You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ch...@apache.org on 2018/07/19 22:47:49 UTC
[03/16] ignite git commit: IGNITE-9021: [ML] Refactor vectors to
dence/sparse
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();
+ }
+ }
+}