http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/AbstractVectorTest.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/AbstractVectorTest.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/AbstractVectorTest.java
new file mode 100644
index 0000000..2550c6f
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/AbstractVectorTest.java
@@ -0,0 +1,542 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import java.util.Arrays;
+import java.util.stream.StreamSupport;
+import org.apache.ignite.ml.math.primitives.matrix.Matrix;
+import org.apache.ignite.ml.math.exceptions.IndexException;
+import org.apache.ignite.ml.math.functions.Functions;
+import org.apache.ignite.ml.math.primitives.MathTestConstants;
+import org.apache.ignite.ml.math.primitives.vector.storage.DenseVectorStorage;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit test for {@link AbstractVector}.
+ */
+public class AbstractVectorTest {
+    /** */
+    private AbstractVector testVector;
+
+    /** */
+    @Before
+    public void setUp() {
+        testVector = getAbstractVector();
+    }
+
+    /** */
+    @Test
+    public void setStorage() {
+        testVector.setStorage(createStorage());
+
+        assertTrue(testVector.size() == MathTestConstants.STORAGE_SIZE);
+    }
+
+    /** */
+    @Test
+    public void size() {
+        testVector.setStorage(createStorage());
+        assertTrue(testVector.size() == MathTestConstants.STORAGE_SIZE);
+
+        testVector.setStorage(new 
DenseVectorStorage(MathTestConstants.STORAGE_SIZE + 
MathTestConstants.STORAGE_SIZE));
+        assertTrue(testVector.size() == MathTestConstants.STORAGE_SIZE + 
MathTestConstants.STORAGE_SIZE);
+
+        testVector = getAbstractVector(createStorage());
+        assertTrue(testVector.size() == MathTestConstants.STORAGE_SIZE);
+    }
+
+    /** */
+    @Test
+    public void getPositive() {
+        testVector = getAbstractVector(createStorage());
+
+        for (int i = 0; i < MathTestConstants.STORAGE_SIZE; i++)
+            assertNotNull(MathTestConstants.NULL_VALUES, testVector.get(i));
+
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void getNegative0() {
+        testVector.get(0);
+    }
+
+    /** */
+    @Test(expected = IndexException.class)
+    public void getNegative1() {
+        testVector.setStorage(createStorage());
+
+        testVector.get(-1);
+    }
+
+    /** */
+    @Test(expected = IndexException.class)
+    public void getNegative2() {
+        testVector.setStorage(createStorage());
+
+        testVector.get(testVector.size() + 1);
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void getXNegative0() {
+        testVector.getX(0);
+    }
+
+    /** */
+    @Test(expected = ArrayIndexOutOfBoundsException.class)
+    public void getXNegative1() {
+        testVector.setStorage(createStorage());
+
+        testVector.getX(-1);
+    }
+
+    /** */
+    @Test(expected = ArrayIndexOutOfBoundsException.class)
+    public void getXNegative2() {
+        testVector.setStorage(createStorage());
+
+        testVector.getX(MathTestConstants.STORAGE_SIZE + 1);
+    }
+
+    /** */
+    @Test
+    public void set() {
+        double[] data = initVector();
+
+        for (int i = 0; i < MathTestConstants.STORAGE_SIZE; i++)
+            testVector.set(i, Math.exp(data[i]));
+
+        for (int i = 0; i < MathTestConstants.STORAGE_SIZE; i++)
+            assertEquals(MathTestConstants.VAL_NOT_EQUALS, testVector.get(i), 
Math.exp(data[i]), MathTestConstants.NIL_DELTA);
+    }
+
+    /** */
+    @Test(expected = IndexException.class)
+    public void setNegative0() {
+        testVector.set(-1, -1);
+    }
+
+    /** */
+    @Test(expected = IndexException.class)
+    public void setNegative1() {
+        initVector();
+
+        testVector.set(-1, -1);
+    }
+
+    /** */
+    @Test(expected = IndexException.class)
+    public void setNegative2() {
+        initVector();
+
+        testVector.set(MathTestConstants.STORAGE_SIZE + 1, -1);
+    }
+
+    /** */
+    @Test(expected = IndexOutOfBoundsException.class)
+    public void setXNegative0() {
+        initVector();
+
+        testVector.setX(-1, -1);
+    }
+
+    /** */
+    @Test(expected = IndexOutOfBoundsException.class)
+    public void setXNegative1() {
+        initVector();
+
+        testVector.setX(MathTestConstants.STORAGE_SIZE + 1, -1);
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void setXNegative2() {
+        testVector.setX(-1, -1);
+    }
+
+    /** */
+    @Test
+    public void isZero() {
+        assertTrue(MathTestConstants.UNEXPECTED_VAL, testVector.isZero(0d));
+
+        assertFalse(MathTestConstants.UNEXPECTED_VAL, testVector.isZero(1d));
+    }
+
+    /** */
+    @Test
+    public void guid() {
+        assertNotNull(MathTestConstants.NULL_GUID, testVector.guid());
+
+        assertEquals(MathTestConstants.UNEXPECTED_GUID_VAL, testVector.guid(), 
testVector.guid());
+
+        assertFalse(MathTestConstants.EMPTY_GUID, 
testVector.guid().toString().isEmpty());
+
+        testVector = getAbstractVector(createStorage());
+
+        assertNotNull(MathTestConstants.NULL_GUID, testVector.guid());
+
+        assertEquals(MathTestConstants.UNEXPECTED_GUID_VAL, testVector.guid(), 
testVector.guid());
+
+        assertFalse(MathTestConstants.EMPTY_GUID, 
testVector.guid().toString().isEmpty());
+    }
+
+    /** */
+    @Test
+    public void equalsTest() {
+        VectorStorage storage = createStorage();
+
+        AbstractVector testVector1 = getAbstractVector();
+
+        testVector1.setStorage(storage);
+
+        AbstractVector testVector2 = getAbstractVector();
+
+        assertEquals(MathTestConstants.VAL_NOT_EQUALS, testVector, testVector);
+
+        testVector2.setStorage(storage);
+
+        assertTrue(MathTestConstants.VAL_NOT_EQUALS, 
testVector1.equals(testVector2));
+
+        assertFalse(MathTestConstants.VALUES_SHOULD_BE_NOT_EQUALS, 
testVector1.equals(testVector));
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void all() {
+        assertNotNull(MathTestConstants.NULL_VAL, testVector.all());
+
+        assertNotNull(MathTestConstants.NULL_VAL, 
getAbstractVector(createStorage()).all());
+
+        getAbstractVector().all().iterator().next();
+    }
+
+    /** */
+    @Test
+    public void nonZeroElements() {
+        VectorStorage storage = createStorage();
+
+        double[] data = storage.data();
+
+        testVector = getAbstractVector(storage);
+
+        assertEquals(MathTestConstants.VAL_NOT_EQUALS, 
testVector.nonZeroElements(), Arrays.stream(data).filter(x -> x != 0d).count());
+
+        addNilValues(data);
+
+        assertEquals(MathTestConstants.VAL_NOT_EQUALS, 
testVector.nonZeroElements(), Arrays.stream(data).filter(x -> x != 0d).count());
+    }
+
+    /** */
+    @Test
+    public void foldMapWithSecondVector() {
+        double[] data0 = initVector();
+
+        VectorStorage storage1 = createStorage();
+
+        double[] data1 = storage1.data().clone();
+
+        AbstractVector testVector1 = getAbstractVector(storage1);
+
+        StringBuilder testVal = new StringBuilder();
+
+        for (int i = 0; i < data0.length; i++)
+            testVal.append(data0[i] + data1[i]);
+
+        assertEquals(MathTestConstants.VAL_NOT_EQUALS, 
testVector.foldMap(testVector1, (string, xi) -> string.concat(xi.toString()), 
Functions.PLUS, ""), testVal.toString());
+    }
+
+    /** */
+    @Test
+    public void nonZeroes() {
+        assertNotNull(MathTestConstants.NULL_VAL, testVector.nonZeroes());
+
+        double[] data = initVector();
+
+        assertNotNull(MathTestConstants.NULL_VAL, testVector.nonZeroes());
+
+        Assert.assertEquals(MathTestConstants.VAL_NOT_EQUALS, 
StreamSupport.stream(testVector.nonZeroes().spliterator(), false).count(), 
Arrays.stream(data).filter(x -> x != 0d).count());
+
+        addNilValues(data);
+
+        Assert.assertEquals(MathTestConstants.VAL_NOT_EQUALS, 
StreamSupport.stream(testVector.nonZeroes().spliterator(), false).count(), 
Arrays.stream(data).filter(x -> x != 0d).count());
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void nonZeroesEmpty() {
+        testVector.nonZeroes().iterator().next();
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void assign() {
+        testVector.assign(MathTestConstants.TEST_VAL);
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void assignArr() {
+        testVector.assign(new double[1]);
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void assignArrEmpty() {
+        testVector.assign(new double[0]);
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void dotNegative() {
+        testVector.dot(getAbstractVector(createEmptyStorage()));
+    }
+
+    /** */
+    @Test
+    public void dotSelf() {
+        double[] data = initVector();
+
+        assertEquals(MathTestConstants.VAL_NOT_EQUALS, testVector.dotSelf(), 
Arrays.stream(data).reduce(0, (x, y) -> x + y * y), 
MathTestConstants.NIL_DELTA);
+    }
+
+    /** */
+    @Test
+    public void getStorage() {
+        assertNotNull(MathTestConstants.NULL_VAL, 
getAbstractVector(createEmptyStorage()));
+        assertNotNull(MathTestConstants.NULL_VAL, 
getAbstractVector(createStorage()));
+        testVector.setStorage(createStorage());
+        assertNotNull(MathTestConstants.NULL_VAL, testVector.getStorage());
+    }
+
+    /** */
+    @Test
+    public void getElement() {
+        double[] data = initVector();
+
+        for (int i = 0; i < data.length; i++) {
+            assertNotNull(MathTestConstants.NULL_VAL, 
testVector.getElement(i));
+
+            assertEquals(MathTestConstants.UNEXPECTED_VAL, 
testVector.getElement(i).get(), data[i], MathTestConstants.NIL_DELTA);
+
+            testVector.getElement(i).set(++data[i]);
+
+            assertEquals(MathTestConstants.UNEXPECTED_VAL, 
testVector.getElement(i).get(), data[i], MathTestConstants.NIL_DELTA);
+        }
+    }
+
+    /**
+     * Create {@link AbstractVector} with storage for tests.
+     *
+     * @param storage {@link VectorStorage}
+     * @return AbstractVector.
+     */
+    @SuppressWarnings("ClassWithoutNoArgConstructor")
+    private AbstractVector getAbstractVector(VectorStorage storage) {
+        return new AbstractVector(storage) { // TODO: IGNTIE-5723, find out 
how to fix warning about missing constructor
+            /** {@inheritDoc} */
+            @Override public boolean isDense() {
+                return false;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean isSequentialAccess() {
+                return false;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Matrix likeMatrix(int rows, int cols) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector copy() {
+                return getAbstractVector(this.getStorage());
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector like(int crd) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector normalize() {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector normalize(double power) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector logNormalize() {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector logNormalize(double power) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector viewPart(int off, int len) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean isRandomAccess() {
+                return true;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean isDistributed() {
+                return false;
+            }
+        };
+    }
+
+    /**
+     * Create empty {@link AbstractVector} for tests.
+     *
+     * @return AbstractVector.
+     */
+    private AbstractVector getAbstractVector() {
+        return new AbstractVector() { // TODO: IGNTIE-5723, find out how to 
fix warning about missing constructor
+            /** {@inheritDoc} */
+            @Override public boolean isDense() {
+                return false;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Matrix likeMatrix(int rows, int cols) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean isSequentialAccess() {
+                return false;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector copy() {
+                return getAbstractVector(this.getStorage());
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector like(int crd) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector normalize() {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector normalize(double power) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector logNormalize() {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector logNormalize(double power) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Vector viewPart(int off, int len) {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean isRandomAccess() {
+                return true;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean isDistributed() {
+                return false;
+            }
+        };
+    }
+
+    /**
+     * Create {@link VectorStorage} for tests.
+     *
+     * @return VectorStorage
+     */
+    private VectorStorage createEmptyStorage() {
+        return new DenseVectorStorage(MathTestConstants.STORAGE_SIZE);
+    }
+
+    /**
+     * Create filled {@link VectorStorage} for tests.
+     *
+     * @return VectorStorage.
+     */
+    private VectorStorage createStorage() {
+        DenseVectorStorage storage = new 
DenseVectorStorage(MathTestConstants.STORAGE_SIZE);
+
+        for (int i = 0; i < MathTestConstants.STORAGE_SIZE; i++)
+            storage.set(i, Math.random());
+
+        return storage;
+    }
+
+    /**
+     * Init vector and return initialized values.
+     *
+     * @return Initial values.
+     */
+    private double[] initVector() {
+        VectorStorage storage = createStorage();
+        double[] data = storage.data().clone();
+
+        testVector = getAbstractVector(storage);
+        return data;
+    }
+
+    /**
+     * Add some zeroes to vector elements.
+     */
+    private void addNilValues() {
+        testVector.set(10, 0);
+        testVector.set(50, 0);
+    }
+
+    /**
+     * Add some zeroes to vector elements. Also set zeroes to the same 
elements in reference array data
+     */
+    private void addNilValues(double[] testRef) {
+        addNilValues();
+        testRef[10] = 0;
+        testRef[50] = 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/DelegatingVectorConstructorTest.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/DelegatingVectorConstructorTest.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/DelegatingVectorConstructorTest.java
new file mode 100644
index 0000000..f5033e3
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/DelegatingVectorConstructorTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import org.apache.ignite.ml.math.primitives.vector.impl.DenseVector;
+import org.apache.ignite.ml.math.primitives.vector.impl.DelegatingVector;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/** */
+public class DelegatingVectorConstructorTest {
+    /** */
+    private static final int IMPOSSIBLE_SIZE = -1;
+
+    /** */
+    @Test
+    public void basicTest() {
+        final Vector parent = new DenseVector(new double[] {0, 1});
+
+        final Vector delegate = new DelegatingVector(parent);
+
+        final int size = parent.size();
+
+        assertEquals("Delegate size differs from expected.", size, 
delegate.size());
+
+        for (int idx = 0; idx < size; idx++)
+            assertDelegate(parent, delegate, idx);
+    }
+
+    /** */
+    private void assertDelegate(Vector parent, Vector delegate, int idx) {
+        assertValue(parent, delegate, idx);
+
+        parent.set(idx, parent.get(idx) + 1);
+
+        assertValue(parent, delegate, idx);
+
+        delegate.set(idx, delegate.get(idx) + 2);
+
+        assertValue(parent, delegate, idx);
+    }
+
+    /** */
+    private void assertValue(Vector parent, Vector delegate, int idx) {
+        assertEquals("Unexpected value at index " + idx, parent.get(idx), 
delegate.get(idx), 0d);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/DenseVectorConstructorTest.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/DenseVectorConstructorTest.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/DenseVectorConstructorTest.java
new file mode 100644
index 0000000..24e4460
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/DenseVectorConstructorTest.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.primitives.vector.impl.DenseVector;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/** */
+public class DenseVectorConstructorTest {
+    /** */
+    private static final int IMPOSSIBLE_SIZE = -1;
+
+    /** */
+    @Test(expected = UnsupportedOperationException.class)
+    public void mapInvalidArgsTest() {
+        assertEquals("Expect exception due to invalid args.", IMPOSSIBLE_SIZE,
+            new DenseVector(new HashMap<String, Object>() {{
+                put("invalid", 99);
+            }}).size());
+    }
+
+    /** */
+    @Test(expected = UnsupportedOperationException.class)
+    public void mapMissingArgsTest() {
+        final Map<String, Object> test = new HashMap<String, Object>() {{
+            put("arr", new double[0]);
+            put("shallowCopyMissing", "whatever");
+        }};
+
+        assertEquals("Expect exception due to missing args.", IMPOSSIBLE_SIZE,
+            new DenseVector(test).size());
+    }
+
+    /** */
+    @Test(expected = ClassCastException.class)
+    public void mapInvalidArrTypeTest() {
+        final Map<String, Object> test = new HashMap<String, Object>() {{
+            put("size", "whatever");
+        }};
+
+        assertEquals("Expect exception due to invalid arr type.", 
IMPOSSIBLE_SIZE,
+            new DenseVector(test).size());
+    }
+
+    /** */
+    @Test(expected = UnsupportedOperationException.class)
+    public void mapInvalidCopyTypeTest() {
+        final Map<String, Object> test = new HashMap<String, Object>() {{
+            put("arr", new double[0]);
+            put("shallowCopy", 0);
+        }};
+
+        assertEquals("Expect exception due to invalid copy type.", 
IMPOSSIBLE_SIZE,
+            new DenseVector(test).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void mapNullTest() {
+        //noinspection ConstantConditions
+        assertEquals("Null map args.", IMPOSSIBLE_SIZE,
+            new DenseVector((Map<String, Object>)null).size());
+    }
+
+    /** */
+    @Test
+    public void mapTest() {
+        assertEquals("Size from args.", 99,
+            new DenseVector(new HashMap<String, Object>() {{
+                put("size", 99);
+            }}).size());
+
+        final double[] test = new double[99];
+
+        assertEquals("Size from array in args.", test.length,
+            new DenseVector(new HashMap<String, Object>() {{
+                put("arr", test);
+                put("copy", false);
+            }}).size());
+
+        assertEquals("Size from array in args, shallow copy.", test.length,
+            new DenseVector(new HashMap<String, Object>() {{
+                put("arr", test);
+                put("copy", true);
+            }}).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void negativeSizeTest() {
+        assertEquals("Negative size.", IMPOSSIBLE_SIZE,
+            new DenseVector(-1).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void nullCopyTest() {
+        assertEquals("Null array to non-shallow copy.", IMPOSSIBLE_SIZE,
+            new DenseVector(null, false).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void nullDefaultCopyTest() {
+        assertEquals("Null array default copy.", IMPOSSIBLE_SIZE,
+            new DenseVector((double[])null).size());
+    }
+
+    /** */
+    @Test(expected = NullPointerException.class)
+    public void defaultConstructorTest() {
+        assertEquals("Default constructor.", IMPOSSIBLE_SIZE,
+            new DenseVector().size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void nullArrShallowCopyTest() {
+        assertEquals("Null array shallow copy.", IMPOSSIBLE_SIZE,
+            new DenseVector(null, true).size());
+    }
+
+    /** */
+    @Test
+    public void primitiveTest() {
+        assertEquals("0 size shallow copy.", 0,
+            new DenseVector(new double[0], true).size());
+
+        assertEquals("0 size.", 0,
+            new DenseVector(new double[0], false).size());
+
+        assertEquals("1 size shallow copy.", 1,
+            new DenseVector(new double[1], true).size());
+
+        assertEquals("1 size.", 1,
+            new DenseVector(new double[1], false).size());
+
+        assertEquals("0 size default copy.", 0,
+            new DenseVector(new double[0]).size());
+
+        assertEquals("1 size default copy.", 1,
+            new DenseVector(new double[1]).size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/MatrixVectorViewTest.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/MatrixVectorViewTest.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/MatrixVectorViewTest.java
new file mode 100644
index 0000000..b978729
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/MatrixVectorViewTest.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import org.apache.ignite.ml.math.primitives.matrix.Matrix;
+import org.apache.ignite.ml.math.exceptions.IndexException;
+import org.apache.ignite.ml.math.primitives.matrix.impl.DenseMatrix;
+import org.apache.ignite.ml.math.primitives.vector.impl.VectorizedViewMatrix;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link VectorizedViewMatrix}.
+ */
+public class MatrixVectorViewTest {
+    /** */
+    private static final String UNEXPECTED_VALUE = "Unexpected value";
+    /** */
+    private static final int SMALL_SIZE = 3;
+    /** */
+    private static final int IMPOSSIBLE_SIZE = -1;
+
+    /** */
+    private Matrix parent;
+
+    /** */
+    @Before
+    public void setup() {
+        parent = newMatrix(SMALL_SIZE, SMALL_SIZE);
+    }
+
+    /** */
+    @Test
+    public void testDiagonal() {
+        Vector vector = parent.viewDiagonal();
+
+        for (int i = 0; i < SMALL_SIZE; i++)
+            assertView(i, i, vector, i);
+    }
+
+    /** */
+    @Test
+    public void testRow() {
+        for (int i = 0; i < SMALL_SIZE; i++) {
+            Vector viewRow = parent.viewRow(i);
+
+            for (int j = 0; j < SMALL_SIZE; j++)
+                assertView(i, j, viewRow, j);
+        }
+    }
+
+    /** */
+    @Test
+    public void testCols() {
+        for (int i = 0; i < SMALL_SIZE; i++) {
+            Vector viewCol = parent.viewColumn(i);
+
+            for (int j = 0; j < SMALL_SIZE; j++)
+                assertView(j, i, viewCol, j);
+        }
+    }
+
+    /** */
+    @Test
+    public void basicTest() {
+        for (int rowSize : new int[] {1, 2, 3, 4})
+            for (int colSize : new int[] {1, 2, 3, 4})
+                for (int row = 0; row < rowSize; row++)
+                    for (int col = 0; col < colSize; col++)
+                        for (int rowStride = 0; rowStride < rowSize; 
rowStride++)
+                            for (int colStride = 0; colStride < colSize; 
colStride++)
+                                if (rowStride != 0 || colStride != 0)
+                                    assertMatrixVectorView(newMatrix(rowSize, 
colSize), row, col, rowStride, colStride);
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void parentNullTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(null, 1, 1, 1, 1).size());
+    }
+
+    /** */
+    @Test(expected = IndexException.class)
+    public void rowNegativeTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(parent, -1, 1, 1, 1).size());
+    }
+
+    /** */
+    @Test(expected = IndexException.class)
+    public void colNegativeTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(parent, 1, -1, 1, 1).size());
+    }
+
+    /** */
+    @Test(expected = IndexException.class)
+    public void rowTooLargeTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(parent, parent.rowSize() + 1, 1, 1, 
1).size());
+    }
+
+    /** */
+    @Test(expected = IndexException.class)
+    public void colTooLargeTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(parent, 1, parent.columnSize() + 1, 1, 
1).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void rowStrideNegativeTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(parent, 1, 1, -1, 1).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void colStrideNegativeTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(parent, 1, 1, 1, -1).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void rowStrideTooLargeTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(parent, 1, 1, parent.rowSize() + 1, 
1).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void colStrideTooLargeTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(parent, 1, 1, 1, parent.columnSize() + 
1).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void bothStridesZeroTest() {
+        //noinspection ConstantConditions
+        assertEquals(IMPOSSIBLE_SIZE,
+            new VectorizedViewMatrix(parent, 1, 1, 0, 0).size());
+    }
+
+    /** */
+    private void assertMatrixVectorView(Matrix parent, int row, int col, int 
rowStride, int colStride) {
+        VectorizedViewMatrix view = new VectorizedViewMatrix(parent, row, col, 
rowStride, colStride);
+
+        String desc = "parent [" + parent.rowSize() + "x" + 
parent.columnSize() + "], view ["
+            + row + "x" + col + "], strides [" + rowStride + ", " + colStride 
+ "]";
+
+        final int size = view.size();
+
+        final int sizeByRows = rowStride == 0 ? IMPOSSIBLE_SIZE : 
(parent.rowSize() - row) / rowStride;
+        final int sizeByCols = colStride == 0 ? IMPOSSIBLE_SIZE : 
(parent.columnSize() - col) / colStride;
+
+        assertTrue("Size " + size + " differs from expected for " + desc,
+            size == sizeByRows || size == sizeByCols);
+
+        for (int idx = 0; idx < size; idx++) {
+            final int rowIdx = row + idx * rowStride;
+            final int colIdx = col + idx * colStride;
+
+            assertEquals(UNEXPECTED_VALUE + " at view index " + idx + desc,
+                parent.get(rowIdx, colIdx), view.get(idx), 0d);
+        }
+    }
+
+    /** */
+    private Matrix newMatrix(int rowSize, int colSize) {
+        Matrix res = new DenseMatrix(rowSize, colSize);
+
+        for (int i = 0; i < res.rowSize(); i++)
+            for (int j = 0; j < res.columnSize(); j++)
+                res.set(i, j, i * res.rowSize() + j);
+
+        return res;
+    }
+
+    /** */
+    private void assertView(int row, int col, Vector view, int viewIdx) {
+        assertValue(row, col, view, viewIdx);
+
+        parent.set(row, col, parent.get(row, col) + 1);
+
+        assertValue(row, col, view, viewIdx);
+
+        view.set(viewIdx, view.get(viewIdx) + 2);
+
+        assertValue(row, col, view, viewIdx);
+    }
+
+    /** */
+    private void assertValue(int row, int col, Vector view, int viewIdx) {
+        assertEquals(UNEXPECTED_VALUE + " at row " + row + " col " + col, 
parent.get(row, col), view.get(viewIdx), 0d);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/SparseVectorConstructorTest.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/SparseVectorConstructorTest.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/SparseVectorConstructorTest.java
new file mode 100644
index 0000000..b53a952
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/SparseVectorConstructorTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.primitives.vector.impl.SparseVector;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/** */
+public class SparseVectorConstructorTest {
+    /** */
+    private static final int IMPOSSIBLE_SIZE = -1;
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void negativeSizeTest() {
+        assertEquals("Negative size.", IMPOSSIBLE_SIZE,
+            new SparseVector(-1, 1).size());
+    }
+
+    /** */
+    @Test(expected = AssertionError.class)
+    public void zeroSizeTest() {
+        assertEquals("0 size.", IMPOSSIBLE_SIZE,
+            new SparseVector(0, 1).size());
+    }
+
+    /** */
+    @Test
+    public void primitiveTest() {
+        assertEquals("1 size, random access.", 1,
+            new SparseVector(1, StorageConstants.RANDOM_ACCESS_MODE).size());
+
+        assertEquals("1 size, sequential access.", 1,
+            new SparseVector(1, 
StorageConstants.SEQUENTIAL_ACCESS_MODE).size());
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorArrayStorageTest.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorArrayStorageTest.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorArrayStorageTest.java
new file mode 100644
index 0000000..f0a847a
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorArrayStorageTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import java.util.Arrays;
+import org.apache.ignite.ml.math.primitives.MathTestConstants;
+import org.apache.ignite.ml.math.primitives.vector.storage.DenseVectorStorage;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit test for {@link DenseVectorStorage}.
+ */
+public class VectorArrayStorageTest extends 
VectorBaseStorageTest<DenseVectorStorage> {
+    /** */
+    @Override public void setUp() {
+        storage = new DenseVectorStorage(MathTestConstants.STORAGE_SIZE);
+    }
+
+    /** */
+    @Test
+    public void isArrayBased() throws Exception {
+        assertTrue(MathTestConstants.WRONG_ATTRIBUTE_VAL, 
storage.isArrayBased());
+
+        assertTrue(MathTestConstants.WRONG_ATTRIBUTE_VAL, new 
DenseVectorStorage().isArrayBased());
+    }
+
+    /** */
+    @Test
+    public void data() throws Exception {
+        assertNotNull(MathTestConstants.NULL_DATA_STORAGE, storage.data());
+
+        assertEquals(MathTestConstants.WRONG_DATA_SIZE, storage.data().length, 
MathTestConstants.STORAGE_SIZE);
+
+        assertTrue(MathTestConstants.UNEXPECTED_DATA_VAL, 
Arrays.equals(storage.data(), new double[MathTestConstants.STORAGE_SIZE]));
+
+        assertNull(MathTestConstants.UNEXPECTED_DATA_VAL, new 
DenseVectorStorage().data());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorAttributesTest.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorAttributesTest.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorAttributesTest.java
new file mode 100644
index 0000000..691eeb1
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorAttributesTest.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import org.apache.ignite.ml.math.primitives.matrix.impl.DenseMatrix;
+import org.apache.ignite.ml.math.primitives.vector.impl.DenseVector;
+import org.apache.ignite.ml.math.primitives.vector.impl.SparseVector;
+import org.apache.ignite.ml.math.primitives.vector.impl.DelegatingVector;
+import org.apache.ignite.ml.math.primitives.vector.impl.VectorizedViewMatrix;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/** */
+public class VectorAttributesTest {
+    /** */
+    private final List<AttrCfg> attrCfgs = Arrays.asList(
+        new AttrCfg("isDense", Vector::isDense,
+            DenseVector.class),
+        new AttrCfg("isArrayBased", Vector::isArrayBased,
+            DenseVector.class),
+        new AttrCfg("isSequentialAccess", Vector::isSequentialAccess,
+            DenseVector.class, SparseLocalVectorSequentialAccess.class),
+        new AttrCfg("guidNotNull", v -> v.guid() == null), // IMPL NOTE this 
is somewhat artificial
+        new AttrCfg("isRandomAccess", Vector::isRandomAccess,
+            DenseVector.class, SparseLocalVectorSequentialAccess.class, 
SparseLocalVectorRandomAccess.class),
+        new AttrCfg("isDistributed", Vector::isDistributed));
+
+    /** */
+    private final List<Specification> specFixture = Arrays.asList(
+        new Specification(new DenseVector(1)),
+        new Specification(new DelegatingVector(new DenseVector(1)),
+            DenseVector.class, "isDense", "isArrayBased", "isSequentialAccess",
+            "isRandomAccess", "isDistributed"),
+        new Specification(new SparseLocalVectorSequentialAccess(1)),
+        new Specification(new SparseLocalVectorRandomAccess(1)),
+        new Specification(new VectorizedViewMatrix(new DenseMatrix(1, 1), 0, 
0, 1, 1),
+            DenseVector.class, "isDense",
+            "isRandomAccess", "isDistributed")); // TODO: IGNTIE-5723, find 
out why "isSequentialAccess" fails here
+
+    /** */
+    @Test
+    public void isDenseTest() {
+        assertAttribute("isDense");
+    }
+
+    /** */
+    @Test
+    public void isArrayBasedTest() {
+        assertAttribute("isArrayBased");
+    }
+
+    /** */
+    @Test
+    public void isSequentialAccessTest() {
+        assertAttribute("isSequentialAccess");
+    }
+
+    /** */
+    @Test
+    public void guidTest() {
+        assertAttribute("guidNotNull");
+    }
+
+    /** */
+    @Test
+    public void isRandomAccessTest() {
+        assertAttribute("isRandomAccess");
+    }
+
+    /** */
+    @Test
+    public void isDistributedTest() {
+        assertAttribute("isDistributed");
+    }
+
+    /** */
+    private void assertAttribute(String name) {
+        final AttrCfg attr = attrCfg(name);
+
+        for (Specification spec : specFixture)
+            spec.verify(attr);
+    }
+
+    /** */
+    private AttrCfg attrCfg(String name) {
+        for (AttrCfg attr : attrCfgs)
+            if (attr.name.equals(name))
+                return attr;
+
+        throw new IllegalArgumentException("Undefined attribute " + name);
+    }
+
+    /** See http://en.wikipedia.org/wiki/Specification_pattern */
+    private static class Specification {
+        /** */
+        private final Vector v;
+        /** */
+        private final Class<? extends Vector> underlyingType;
+        /** */
+        private final List<String> attrsFromUnderlying;
+        /** */
+        final String desc;
+
+        /** */
+        Specification(Vector v, Class<? extends Vector> underlyingType, 
String... attrsFromUnderlying) {
+            this.v = v;
+            this.underlyingType = underlyingType;
+            this.attrsFromUnderlying = Arrays.asList(attrsFromUnderlying);
+            final Class<? extends Vector> clazz = v.getClass();
+            desc = clazz.getSimpleName() + (clazz.equals(underlyingType)
+                ? "" : " (underlying type " + underlyingType.getSimpleName() + 
")");
+        }
+
+        /** */
+        Specification(Vector v) {
+            this(v, v.getClass());
+        }
+
+        /** */
+        void verify(AttrCfg attr) {
+            final boolean obtained = attr.obtain.apply(v);
+
+            final Class<? extends Vector> typeToCheck
+                = attrsFromUnderlying.contains(attr.name) ? underlyingType : 
v.getClass();
+
+            final boolean exp = attr.trueInTypes.contains(typeToCheck);
+
+            assertEquals("Unexpected " + attr.name + " value for " + desc, 
exp, obtained);
+        }
+    }
+
+    /** */
+    private static class AttrCfg {
+        /** */
+        final String name;
+        /** */
+        final Function<Vector, Boolean> obtain;
+        /** */
+        final List<Class> trueInTypes;
+
+        /** */
+        AttrCfg(String name, Function<Vector, Boolean> obtain, Class... 
trueInTypes) {
+            this.name = name;
+            this.obtain = obtain;
+            this.trueInTypes = Arrays.asList(trueInTypes);
+        }
+    }
+
+    /** */
+    private static class SparseLocalVectorSequentialAccess extends 
SparseVector {
+        /** */
+        public SparseLocalVectorSequentialAccess() {
+            // No-op.
+        }
+
+        /** */
+        SparseLocalVectorSequentialAccess(int size) {
+            super(size, SEQUENTIAL_ACCESS_MODE);
+        }
+    }
+
+    /** */
+    private static class SparseLocalVectorRandomAccess extends SparseVector {
+        /** */
+        public SparseLocalVectorRandomAccess() {
+            // No-op.
+        }
+
+        /** */
+        SparseLocalVectorRandomAccess(int size) {
+            super(size, RANDOM_ACCESS_MODE);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorBaseStorageTest.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorBaseStorageTest.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorBaseStorageTest.java
new file mode 100644
index 0000000..b6c9721
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorBaseStorageTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import org.apache.ignite.ml.math.ExternalizeTest;
+import org.apache.ignite.ml.math.primitives.vector.VectorStorage;
+import org.apache.ignite.ml.math.primitives.MathTestConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Abstract class with base tests for each vector storage.
+ */
+public abstract class VectorBaseStorageTest<T extends VectorStorage> extends 
ExternalizeTest<T> {
+    /** */
+    protected T storage;
+
+    /** */
+    @Before
+    public abstract void setUp();
+
+    /** */
+    @After
+    public void tearDown() throws Exception {
+        storage.destroy();
+    }
+
+    /** */
+    @Test
+    public void getSet() throws Exception {
+        for (int i = 0; i < MathTestConstants.STORAGE_SIZE; i++) {
+            double random = Math.random();
+
+            storage.set(i, random);
+
+            assertEquals(MathTestConstants.WRONG_DATA_ELEMENT, storage.get(i), 
random, MathTestConstants.NIL_DELTA);
+        }
+    }
+
+    /** */
+    @Test
+    public void size() {
+        assertTrue(MathTestConstants.UNEXPECTED_VAL, storage.size() == 
MathTestConstants.STORAGE_SIZE);
+    }
+
+    /** */
+    @Override public void externalizeTest() {
+        super.externalizeTest(storage);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorFoldMapTest.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorFoldMapTest.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorFoldMapTest.java
new file mode 100644
index 0000000..770340a
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorFoldMapTest.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import java.util.Arrays;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.ignite.ml.math.functions.Functions;
+import org.junit.Test;
+
+import static java.util.function.DoubleUnaryOperator.identity;
+import static org.junit.Assert.assertTrue;
+
+/** See also: {@link AbstractVectorTest} and {@link VectorToMatrixTest}. */
+public class VectorFoldMapTest {
+    /** */
+    @Test
+    public void mapVectorTest() {
+        operationVectorTest((operand1, operand2) -> operand1 + operand2, 
(Vector v1, Vector v2) -> v1.map(v2, Functions.PLUS));
+    }
+
+    /** */
+    @Test
+    public void mapDoubleFunctionTest() {
+        consumeSampleVectors((v, desc) -> operatorTest(v, desc,
+            (vec) -> vec.map(Functions.INV), (val) -> 1.0 / val));
+    }
+
+    /** */
+    @Test
+    public void mapBiFunctionTest() {
+        consumeSampleVectors((v, desc) -> operatorTest(v, desc,
+            (vec) -> vec.map(Functions.PLUS, 1.0), (val) -> 1.0 + val));
+    }
+
+    /** */
+    @Test
+    public void foldMapTest() {
+        toDoubleTest(
+            ref -> Arrays.stream(ref).map(identity()).sum(),
+            (v) -> v.foldMap(Functions.PLUS, Functions.IDENTITY, 0.0));
+    }
+
+    /** */
+    @Test
+    public void foldMapVectorTest() {
+        toDoubleTest(
+            ref -> 2.0 * Arrays.stream(ref).sum(),
+            (v) -> v.foldMap(v, Functions.PLUS, Functions.PLUS, 0.0));
+
+    }
+
+    /** */
+    private void operatorTest(Vector v, String desc, Function<Vector, Vector> 
op, Function<Double, Double> refOp) {
+        final int size = v.size();
+        final double[] ref = new double[size];
+
+        VectorImplementationsTest.ElementsChecker checker = new 
VectorImplementationsTest.ElementsChecker(v, ref, desc);
+
+        Vector actual = op.apply(v);
+
+        for (int idx = 0; idx < size; idx++)
+            ref[idx] = refOp.apply(ref[idx]);
+
+        checker.assertCloseEnough(actual, ref);
+    }
+
+    /** */
+    private void toDoubleTest(Function<double[], Double> calcRef, 
Function<Vector, Double> calcVec) {
+        consumeSampleVectors((v, desc) -> {
+            final int size = v.size();
+            final double[] ref = new double[size];
+
+            new VectorImplementationsTest.ElementsChecker(v, ref, desc); // 
IMPL NOTE this initialises vector and reference array
+
+            final VectorImplementationsTest.Metric metric = new 
VectorImplementationsTest.Metric(calcRef.apply(ref), calcVec.apply(v));
+
+            assertTrue("Not close enough at " + desc
+                + ", " + metric, metric.closeEnough());
+        });
+    }
+
+    /** */
+    private void operationVectorTest(BiFunction<Double, Double, Double> 
operation,
+        BiFunction<Vector, Vector, Vector> vecOperation) {
+        consumeSampleVectors((v, desc) -> {
+            // TODO: IGNTIE-5723, find out if more elaborate testing scenario 
is needed or it's okay as is.
+            final int size = v.size();
+            final double[] ref = new double[size];
+
+            final VectorImplementationsTest.ElementsChecker checker = new 
VectorImplementationsTest.ElementsChecker(v, ref, desc);
+            final Vector operand = v.copy();
+
+            for (int idx = 0; idx < size; idx++)
+                ref[idx] = operation.apply(ref[idx], ref[idx]);
+
+            checker.assertCloseEnough(vecOperation.apply(v, operand), ref);
+        });
+    }
+
+    /** */
+    private void consumeSampleVectors(BiConsumer<Vector, String> consumer) {
+        new VectorImplementationsFixtures().consumeSampleVectors(null, 
consumer);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/26e40528/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorImplementationsFixtures.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorImplementationsFixtures.java
 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorImplementationsFixtures.java
new file mode 100644
index 0000000..549a5f8
--- /dev/null
+++ 
b/modules/ml/src/test/java/org/apache/ignite/ml/math/primitives/vector/VectorImplementationsFixtures.java
@@ -0,0 +1,424 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.primitives.vector;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import org.apache.ignite.ml.math.primitives.matrix.Matrix;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.primitives.matrix.impl.DenseMatrix;
+import org.apache.ignite.ml.math.primitives.vector.impl.DenseVector;
+import org.apache.ignite.ml.math.primitives.vector.impl.SparseVector;
+import org.apache.ignite.ml.math.primitives.vector.impl.DelegatingVector;
+import org.apache.ignite.ml.math.primitives.vector.impl.VectorizedViewMatrix;
+import org.jetbrains.annotations.NotNull;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/** */
+class VectorImplementationsFixtures {
+    /** */
+    private static final List<Supplier<Iterable<Vector>>> suppliers = 
Arrays.asList(
+        (Supplier<Iterable<Vector>>)DenseLocalOnHeapVectorFixture::new,
+        (Supplier<Iterable<Vector>>)SparseLocalVectorFixture::new,
+        (Supplier<Iterable<Vector>>)DelegatingVectorFixture::new,
+        (Supplier<Iterable<Vector>>)MatrixVectorViewFixture::new
+    );
+
+    /** */
+    void consumeSampleVectors(Consumer<Integer> paramsConsumer, 
BiConsumer<Vector, String> consumer) {
+        for (Supplier<Iterable<Vector>> fixtureSupplier : 
VectorImplementationsFixtures.suppliers) {
+            final Iterable<Vector> fixture = fixtureSupplier.get();
+
+            for (Vector v : fixture) {
+                if (paramsConsumer != null)
+                    paramsConsumer.accept(v.size());
+
+                consumer.accept(v, fixture.toString());
+            }
+        }
+    }
+
+    /** */
+    private static class DenseLocalOnHeapVectorFixture extends 
VectorSizesExtraFixture<Boolean> {
+        /** */
+        DenseLocalOnHeapVectorFixture() {
+            super("DenseLocalOnHeapVector",
+                (size, shallowCp) -> new DenseVector(new double[size], 
shallowCp),
+                "shallow copy", new Boolean[] {false, true, null});
+        }
+    }
+
+    /** */
+    private static class SparseLocalVectorFixture extends 
VectorSizesExtraFixture<Integer> {
+        /** */
+        SparseLocalVectorFixture() {
+            super("SparseLocalVector", SparseVector::new, "access mode",
+                new Integer[] {StorageConstants.SEQUENTIAL_ACCESS_MODE, 
StorageConstants.RANDOM_ACCESS_MODE, null});
+        }
+    }
+
+    /** */
+    private static class MatrixVectorViewFixture extends 
VectorSizesExtraFixture<Integer> {
+        /** */
+        MatrixVectorViewFixture() {
+            super("MatrixVectorView",
+                MatrixVectorViewFixture::newView,
+                "stride kind", new Integer[] {0, 1, 2, null});
+        }
+
+        /** */
+        private static Vector newView(int size, int strideKind) {
+            final Matrix parent = new DenseMatrix(size, size);
+
+            return new VectorizedViewMatrix(parent, 0, 0, strideKind != 1 ? 1 
: 0, strideKind != 0 ? 1 : 0);
+        }
+    }
+
+    /** */
+    private static class VectorSizesExtraFixture<T> implements 
Iterable<Vector> {
+        /** */
+        private final Supplier<VectorSizesExtraIterator<T>> iter;
+
+        /** */
+        private final AtomicReference<String> ctxDescrHolder = new 
AtomicReference<>("Iterator not started.");
+
+        /** */
+        VectorSizesExtraFixture(String vectorKind, BiFunction<Integer, T, 
Vector> ctor, String extraParamName,
+            T[] extras) {
+            iter = () -> new VectorSizesExtraIterator<>(vectorKind, ctor, 
ctxDescrHolder::set, extraParamName, extras);
+        }
+
+        /** {@inheritDoc} */
+        @NotNull
+        @Override public Iterator<Vector> iterator() {
+            return iter.get();
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            // IMPL NOTE index within bounds is expected to be guaranteed by 
proper code in this class
+            return ctxDescrHolder.get();
+        }
+    }
+
+    /** */
+    private static abstract class VectorSizesFixture implements 
Iterable<Vector> {
+        /** */
+        private final Supplier<VectorSizesIterator> iter;
+
+        /** */
+        private final AtomicReference<String> ctxDescrHolder = new 
AtomicReference<>("Iterator not started.");
+
+        /** */
+        VectorSizesFixture(String vectorKind, Function<Integer, Vector> ctor) {
+            iter = () -> new VectorSizesIterator(vectorKind, ctor, 
ctxDescrHolder::set);
+        }
+
+        /** {@inheritDoc} */
+        @NotNull
+        @Override public Iterator<Vector> iterator() {
+            return iter.get();
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            // IMPL NOTE index within bounds is expected to be guaranteed by 
proper code in this class
+            return ctxDescrHolder.get();
+        }
+    }
+
+    /** */
+    private static class VectorSizesExtraIterator<T> extends 
VectorSizesIterator {
+        /** */
+        private final T[] extras;
+        /** */
+        private int extraIdx = 0;
+        /** */
+        private final BiFunction<Integer, T, Vector> ctor;
+        /** */
+        private final String extraParamName;
+
+        /**
+         * @param vectorKind Descriptive name to use for context logging.
+         * @param ctor Constructor for objects to iterate over.
+         * @param ctxDescrConsumer Context logging consumer.
+         * @param extraParamName Name of extra parameter to iterate over.
+         * @param extras Array of extra parameter values to iterate over.
+         */
+        VectorSizesExtraIterator(String vectorKind, BiFunction<Integer, T, 
Vector> ctor,
+            Consumer<String> ctxDescrConsumer, String extraParamName, T[] 
extras) {
+            super(vectorKind, null, ctxDescrConsumer);
+
+            this.ctor = ctor;
+            this.extraParamName = extraParamName;
+            this.extras = extras;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean hasNext() {
+            return super.hasNext() && hasNextExtra(extraIdx);
+        }
+
+        /** {@inheritDoc} */
+        @Override void nextIdx() {
+            assert extras[extraIdx] != null
+                : "Index(es) out of bound at " + VectorSizesExtraIterator.this;
+
+            if (hasNextExtra(extraIdx + 1)) {
+                extraIdx++;
+
+                return;
+            }
+
+            extraIdx = 0;
+
+            super.nextIdx();
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            // IMPL NOTE index within bounds is expected to be guaranteed by 
proper code in this class
+            return "{" + super.toString() +
+                ", " + extraParamName + "=" + extras[extraIdx] +
+                '}';
+        }
+
+        /** {@inheritDoc} */
+        @Override BiFunction<Integer, Integer, Vector> ctor() {
+            return (size, delta) -> ctor.apply(size + delta, extras[extraIdx]);
+        }
+
+        /** */
+        void selfTest() {
+            final Set<Integer> extraIdxs = new HashSet<>();
+
+            int cnt = 0;
+
+            while (hasNext()) {
+                assertNotNull("Expect not null vector at " + this, next());
+
+                if (extras[extraIdx] != null)
+                    extraIdxs.add(extraIdx);
+
+                cnt++;
+            }
+
+            assertEquals("Extra param tested", extraIdxs.size(), extras.length 
- 1);
+
+            assertEquals("Combinations tested mismatch.",
+                7 * 3 * (extras.length - 1), cnt);
+        }
+
+        /** */
+        private boolean hasNextExtra(int idx) {
+            return extras[idx] != null;
+        }
+    }
+
+    /** */
+    private static class VectorSizesIterator extends 
TwoParamsIterator<Integer, Integer> {
+        /** */
+        private final Function<Integer, Vector> ctor;
+
+        /** */
+        VectorSizesIterator(String vectorKind, Function<Integer, Vector> ctor, 
Consumer<String> ctxDescrConsumer) {
+            super(vectorKind, null, ctxDescrConsumer,
+                "size", new Integer[] {2, 4, 8, 16, 32, 64, 128, null},
+                "size delta", new Integer[] {-1, 0, 1, null});
+
+            this.ctor = ctor;
+        }
+
+        /** {@inheritDoc} */
+        @Override BiFunction<Integer, Integer, Vector> ctor() {
+            return (size, delta) -> ctor.apply(size + delta);
+        }
+    }
+
+    /** */
+    private static class TwoParamsIterator<T, U> implements Iterator<Vector> {
+        /** */
+        private final T params1[];
+
+        /** */
+        private final U params2[];
+
+        /** */
+        private final String vectorKind;
+
+        /** */
+        private final String param1Name;
+
+        /** */
+        private final String param2Name;
+
+        /** */
+        private final BiFunction<T, U, Vector> ctor;
+
+        /** */
+        private final Consumer<String> ctxDescrConsumer;
+
+        /** */
+        private int param1Idx = 0;
+
+        /** */
+        private int param2Idx = 0;
+
+        /** */
+        TwoParamsIterator(String vectorKind, BiFunction<T, U, Vector> ctor,
+            Consumer<String> ctxDescrConsumer, String param1Name, T[] params1, 
String param2Name, U[] params2) {
+            this.param1Name = param1Name;
+            this.params1 = params1;
+
+            this.param2Name = param2Name;
+            this.params2 = params2;
+
+            this.vectorKind = vectorKind;
+
+            this.ctor = ctor;
+
+            this.ctxDescrConsumer = ctxDescrConsumer;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean hasNext() {
+            return hasNextParam1(param1Idx) && hasNextParam2(param2Idx);
+        }
+
+        /** {@inheritDoc} */
+        @Override public Vector next() {
+            if (!hasNext())
+                throw new 
NoSuchElementException(TwoParamsIterator.this.toString());
+
+            if (ctxDescrConsumer != null)
+                ctxDescrConsumer.accept(toString());
+
+            Vector res = ctor().apply(params1[param1Idx], params2[param2Idx]);
+
+            nextIdx();
+
+            return res;
+        }
+
+        /** */
+        void selfTest() {
+            final Set<Integer> sizeIdxs = new HashSet<>(), deltaIdxs = new 
HashSet<>();
+
+            int cnt = 0;
+
+            while (hasNext()) {
+                assertNotNull("Expect not null vector at " + this, next());
+
+                if (params1[param1Idx] != null)
+                    sizeIdxs.add(param1Idx);
+
+                if (params2[param2Idx] != null)
+                    deltaIdxs.add(param2Idx);
+
+                cnt++;
+            }
+
+            assertEquals("Sizes tested mismatch.", sizeIdxs.size(), 
params1.length - 1);
+
+            assertEquals("Deltas tested", deltaIdxs.size(), params2.length - 
1);
+
+            assertEquals("Combinations tested mismatch.",
+                (params1.length - 1) * (params2.length - 1), cnt);
+        }
+
+        /** IMPL NOTE override in subclasses if needed */
+        void nextIdx() {
+            assert params1[param1Idx] != null && params2[param2Idx] != null
+                : "Index(es) out of bound at " + TwoParamsIterator.this;
+
+            if (hasNextParam2(param2Idx + 1)) {
+                param2Idx++;
+
+                return;
+            }
+
+            param2Idx = 0;
+
+            param1Idx++;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            // IMPL NOTE index within bounds is expected to be guaranteed by 
proper code in this class
+            return vectorKind + "{" + param1Name + "=" + params1[param1Idx] +
+                ", " + param2Name + "=" + params2[param2Idx] +
+                '}';
+        }
+
+        /** IMPL NOTE override in subclasses if needed */
+        BiFunction<T, U, Vector> ctor() {
+            return ctor;
+        }
+
+        /** */
+        private boolean hasNextParam1(int idx) {
+            return params1[idx] != null;
+        }
+
+        /** */
+        private boolean hasNextParam2(int idx) {
+            return params2[idx] != null;
+        }
+    }
+
+    /** Delegating vector with dense local onheap vector */
+    private static class DelegatingVectorFixture implements Iterable<Vector> {
+
+        /** */
+        private final Supplier<VectorSizesExtraIterator<Boolean>> iter;
+
+        /** */
+        private final AtomicReference<String> ctxDescrHolder = new 
AtomicReference<>("Iterator not started.");
+
+        /** */
+        DelegatingVectorFixture() {
+            iter = () -> new VectorSizesExtraIterator<>("DelegatingVector with 
DenseLocalOnHeapVector",
+                (size, shallowCp) -> new DelegatingVector(new DenseVector(new 
double[size], shallowCp)),
+                ctxDescrHolder::set, "shallow copy", new Boolean[] {false, 
true, null});
+        }
+
+        /** {@inheritDoc} */
+        @NotNull
+        @Override public Iterator<Vector> iterator() {
+            return iter.get();
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            // IMPL NOTE index within bounds is expected to be guaranteed by 
proper code in this class
+            return ctxDescrHolder.get();
+        }
+    }
+}

Reply via email to