You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2017/04/18 13:45:47 UTC
[02/62] [abbrv] ignite git commit: IGNITE-5000 Rename Ignite Math
module to Ignite ML module
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/MatrixVectorViewTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/MatrixVectorViewTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/MatrixVectorViewTest.java
new file mode 100644
index 0000000..b7e390e
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/MatrixVectorViewTest.java
@@ -0,0 +1,209 @@
+package org.apache.ignite.math.impls.vector;
+
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.IndexException;
+import org.apache.ignite.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link MatrixVectorView}.
+ */
+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 MatrixVectorView(null, 1, 1, 1, 1).size());
+ }
+
+ /** */
+ @Test(expected = IndexException.class)
+ public void rowNegativeTest() {
+ //noinspection ConstantConditions
+ assertEquals(IMPOSSIBLE_SIZE,
+ new MatrixVectorView(parent, -1, 1, 1, 1).size());
+ }
+
+ /** */
+ @Test(expected = IndexException.class)
+ public void colNegativeTest() {
+ //noinspection ConstantConditions
+ assertEquals(IMPOSSIBLE_SIZE,
+ new MatrixVectorView(parent, 1, -1, 1, 1).size());
+ }
+
+ /** */
+ @Test(expected = IndexException.class)
+ public void rowTooLargeTest() {
+ //noinspection ConstantConditions
+ assertEquals(IMPOSSIBLE_SIZE,
+ new MatrixVectorView(parent, parent.rowSize() + 1, 1, 1, 1).size());
+ }
+
+ /** */
+ @Test(expected = IndexException.class)
+ public void colTooLargeTest() {
+ //noinspection ConstantConditions
+ assertEquals(IMPOSSIBLE_SIZE,
+ new MatrixVectorView(parent, 1, parent.columnSize() + 1, 1, 1).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void rowStrideNegativeTest() {
+ //noinspection ConstantConditions
+ assertEquals(IMPOSSIBLE_SIZE,
+ new MatrixVectorView(parent, 1, 1, -1, 1).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void colStrideNegativeTest() {
+ //noinspection ConstantConditions
+ assertEquals(IMPOSSIBLE_SIZE,
+ new MatrixVectorView(parent, 1, 1, 1, -1).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void rowStrideTooLargeTest() {
+ //noinspection ConstantConditions
+ assertEquals(IMPOSSIBLE_SIZE,
+ new MatrixVectorView(parent, 1, 1, parent.rowSize() + 1, 1).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void colStrideTooLargeTest() {
+ //noinspection ConstantConditions
+ assertEquals(IMPOSSIBLE_SIZE,
+ new MatrixVectorView(parent, 1, 1, 1, parent.columnSize() + 1).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void bothStridesZeroTest() {
+ //noinspection ConstantConditions
+ assertEquals(IMPOSSIBLE_SIZE,
+ new MatrixVectorView(parent, 1, 1, 0, 0).size());
+ }
+
+ /** */
+ private void assertMatrixVectorView(Matrix parent, int row, int col, int rowStride, int colStride) {
+ MatrixVectorView view = new MatrixVectorView(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 DenseLocalOnHeapMatrix(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/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/PivotedVectorViewConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/PivotedVectorViewConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/PivotedVectorViewConstructorTest.java
new file mode 100644
index 0000000..91650dc
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/PivotedVectorViewConstructorTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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.math.impls.vector;
+
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.CardinalityException;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+/** */
+public class PivotedVectorViewConstructorTest {
+ /** */
+ private static final int IMPOSSIBLE_SIZE = -1;
+
+ /** */
+ private static final SampleParams sampleParams = new SampleParams();
+
+ /** */
+ @Test(expected = NullPointerException.class)
+ public void nullVecParamTest() {
+ assertEquals("Expect exception due to null vector param.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(null, sampleParams.pivot).size());
+ }
+
+ /** */
+ @Test(expected = NullPointerException.class)
+ public void nullVecParam2Test() {
+ assertEquals("Expect exception due to null vector param, with unpivot.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(null, sampleParams.pivot, sampleParams.unpivot).size());
+ }
+
+ /** */
+ @Test(expected = NullPointerException.class)
+ public void nullPivotParamTest() {
+ assertEquals("Expect exception due to null pivot param.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(sampleParams.vec, null).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void nullPivotParam2Test() {
+ assertEquals("Expect exception due to null pivot param, with unpivot.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(sampleParams.vec, null, sampleParams.unpivot).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void nullUnpivotParam2Test() {
+ assertEquals("Expect exception due to null unpivot param.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(sampleParams.vec, sampleParams.pivot, null).size());
+ }
+
+ /** */
+ @Test(expected = CardinalityException.class)
+ public void emptyPivotTest() {
+ assertEquals("Expect exception due to empty pivot param.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(sampleParams.vec, new int[] {}).size());
+ }
+
+ /** */
+ @Test(expected = CardinalityException.class)
+ public void emptyPivot2Test() {
+ assertEquals("Expect exception due to empty pivot param, with unpivot.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(sampleParams.vec, new int[] {}, sampleParams.unpivot).size());
+ }
+
+ /** */
+ @Test(expected = CardinalityException.class)
+ public void wrongPivotTest() {
+ assertEquals("Expect exception due to wrong pivot param.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(sampleParams.vec, new int[] {0}).size());
+ }
+
+ /** */
+ @Test(expected = CardinalityException.class)
+ public void wrongPivot2Test() {
+ assertEquals("Expect exception due to wrong pivot param, with unpivot.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(sampleParams.vec, new int[] {0}, sampleParams.unpivot).size());
+ }
+
+ /** */
+ @Test(expected = CardinalityException.class)
+ public void emptyUnpivotTest() {
+ assertEquals("Expect exception due to empty unpivot param.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(sampleParams.vec, sampleParams.pivot, new int[] {}).size());
+ }
+
+ /** */
+ @Test(expected = CardinalityException.class)
+ public void wrongUnpivotTest() {
+ assertEquals("Expect exception due to wrong unpivot param, with unpivot.", IMPOSSIBLE_SIZE,
+ new PivotedVectorView(sampleParams.vec, sampleParams.pivot, new int[] {0}).size());
+ }
+
+ /** */
+ @Test
+ public void basicPivotTest() {
+ final PivotedVectorView pvv = new PivotedVectorView(sampleParams.vec, sampleParams.pivot);
+
+ final int size = sampleParams.vec.size();
+
+ assertEquals("View size differs from expected.", size, pvv.size());
+
+ assertSame("Base vector differs from expected.", sampleParams.vec, pvv.getBaseVector());
+
+ for (int idx = 0; idx < size; idx++) {
+ assertEquals("Sample pivot and unpivot differ from expected",
+ idx, sampleParams.unpivot[sampleParams.pivot[idx]]);
+
+ assertEquals("Pivot differs from expected at index " + idx,
+ sampleParams.pivot[idx], pvv.pivot(idx));
+
+ assertEquals("Default unpivot differs from expected at index " + idx,
+ sampleParams.unpivot[idx], pvv.unpivot(idx));
+
+ final Metric metric = new Metric(sampleParams.vec.get(idx), pvv.get(pvv.pivot(idx)));
+
+ assertTrue("Not close enough at index " + idx + ", " + metric, metric.closeEnough());
+ }
+
+ for (int idx = 0; idx < size; idx++) {
+ sampleParams.vec.set(idx, sampleParams.vec.get(idx) + idx + 1);
+
+ final Metric metric = new Metric(sampleParams.vec.get(idx), pvv.get(pvv.pivot(idx)));
+
+ assertTrue("Modified value not close enough at index " + idx + ", " + metric, metric.closeEnough());
+ }
+ }
+
+ /** */
+ @Test
+ public void basicUnpivotTest() {
+ final PivotedVectorView pvv = new PivotedVectorView(sampleParams.vec, sampleParams.pivot, sampleParams.unpivot);
+
+ final int size = sampleParams.vec.size();
+
+ assertEquals("View size differs from expected.", size, pvv.size());
+
+ for (int idx = 0; idx < size; idx++) {
+ assertEquals("Unpivot differs from expected at index " + idx,
+ sampleParams.unpivot[idx], pvv.unpivot(idx));
+
+ final Metric metric = new Metric(sampleParams.vec.get(idx), pvv.get(pvv.unpivot(idx)));
+
+ assertTrue("Not close enough at index " + idx + ", " + metric, metric.closeEnough());
+ }
+ }
+
+ /** */
+ private static class SampleParams {
+ /** */
+ final double[] data = new double[] {0, 1};
+ /** */
+ final Vector vec = new DenseLocalOnHeapVector(data);
+ /** */
+ final int[] pivot = new int[] {1, 0};
+ /** */
+ final int[] unpivot = new int[] {1, 0};
+ }
+
+ /** */
+ private static class Metric { // todo consider if softer tolerance (like say 0.1 or 0.01) would make sense here
+ /** */
+ private final double exp;
+
+ /** */
+ private final double obtained;
+
+ /** **/
+ Metric(double exp, double obtained) {
+ this.exp = exp;
+ this.obtained = obtained;
+ }
+
+ /** */
+ boolean closeEnough() {
+ return new Double(exp).equals(obtained) || closeEnoughToZero();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "Metric{" + "expected=" + exp +
+ ", obtained=" + obtained +
+ '}';
+ }
+
+ /** */
+ private boolean closeEnoughToZero() {
+ return (new Double(exp).equals(0.0) && new Double(obtained).equals(-0.0))
+ || (new Double(exp).equals(-0.0) && new Double(obtained).equals(0.0));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/RandomVectorConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/RandomVectorConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/RandomVectorConstructorTest.java
new file mode 100644
index 0000000..6d4e4f1
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/RandomVectorConstructorTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.math.impls.vector;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/** */
+public class RandomVectorConstructorTest {
+ /** */
+ private static final int IMPOSSIBLE_SIZE = -1;
+
+ /** */
+ @Test(expected = org.apache.ignite.math.exceptions.UnsupportedOperationException.class)
+ public void mapInvalidArgsTest() {
+ assertEquals("Expect exception due to invalid args.", IMPOSSIBLE_SIZE,
+ new RandomVector(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("paramMissing", "whatever");
+ }};
+
+ assertEquals("Expect exception due to missing args.",
+ -1, new RandomVector(test).size());
+ }
+
+ /** */
+ @Test(expected = ClassCastException.class)
+ public void mapInvalidParamTypeTest() {
+ final Map<String, Object> test = new HashMap<String, Object>() {{
+ put("size", "whatever");
+ put("fastHash", true);
+ }};
+
+ assertEquals("Expect exception due to invalid param type.", IMPOSSIBLE_SIZE,
+ new RandomVector(test).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void mapNullTest() {
+ //noinspection ConstantConditions
+ assertEquals("Null map args.", IMPOSSIBLE_SIZE,
+ new RandomVector(null).size());
+ }
+
+ /** */
+ @Test
+ public void mapTest() {
+ assertEquals("Size from args.", 99,
+ new RandomVector(new HashMap<String, Object>() {{
+ put("size", 99);
+ }}).size());
+
+ final int test = 99;
+
+ assertEquals("Size from args with fastHash false.", test,
+ new RandomVector(new HashMap<String, Object>() {{
+ put("size", test);
+ put("fastHash", false);
+ }}).size());
+
+ assertEquals("Size from args with fastHash true.", test,
+ new RandomVector(new HashMap<String, Object>() {{
+ put("size", test);
+ put("fastHash", true);
+ }}).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void negativeSizeTest() {
+ assertEquals("Negative size.", IMPOSSIBLE_SIZE,
+ new RandomVector(-1).size());
+ }
+
+ /** */
+ @Test
+ public void basicTest() {
+ final int basicSize = 3;
+
+ Vector v1 = new RandomVector(basicSize);
+
+ //noinspection EqualsWithItself
+ assertTrue("Expect vector to be equal to self", v1.equals(v1));
+
+ //noinspection ObjectEqualsNull
+ assertFalse("Expect vector to be not equal to null", v1.equals(null));
+
+ assertEquals("Size differs from expected", basicSize, v1.size());
+
+ verifyValues(v1);
+
+ Vector v2 = new RandomVector(basicSize, true);
+
+ assertEquals("Size differs from expected", basicSize, v2.size());
+
+ verifyValues(v2);
+
+ Vector v3 = new RandomVector(basicSize, false);
+
+ assertEquals("Size differs from expected", basicSize, v3.size());
+
+ verifyValues(v3);
+ }
+
+ /** */
+ private void verifyValues(Vector v) {
+ for (Vector.Element e : v.all()) {
+ double val = e.get();
+
+ assertTrue("Value too small: " + val + " at index " + e.index(), -1d <= val);
+
+ assertTrue("Value too large: " + val + " at index " + e.index(), val <= 1d);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SingleElementVectorConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SingleElementVectorConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SingleElementVectorConstructorTest.java
new file mode 100644
index 0000000..69e22e0
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SingleElementVectorConstructorTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.math.impls.vector;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/** */
+public class SingleElementVectorConstructorTest {
+ /** */
+ private static final int IMPOSSIBLE_SIZE = -1;
+
+ /** */
+ @Test(expected = UnsupportedOperationException.class)
+ public void mapInvalidArgsTest() {
+ assertEquals("Expect exception due to invalid args.", IMPOSSIBLE_SIZE,
+ new SingleElementVector(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("size", 1);
+
+ put("paramMissing", "whatever");
+ }};
+
+ assertEquals("Expect exception due to missing args.",
+ -1, new SingleElementVector(test).size());
+ }
+
+ /** */
+ @Test(expected = ClassCastException.class)
+ public void mapInvalidParamTypeTest() {
+ final Map<String, Object> test = new HashMap<String, Object>() {{
+ put("size", "whatever");
+
+ put("index", 0);
+ put("value", 1.0);
+ }};
+
+ assertEquals("Expect exception due to invalid param type.", IMPOSSIBLE_SIZE,
+ new SingleElementVector(test).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void mapNullTest() {
+ //noinspection ConstantConditions
+ assertEquals("Null map args.", IMPOSSIBLE_SIZE,
+ new SingleElementVector(null).size());
+ }
+
+ /** */
+ @Test
+ public void mapTest() {
+ assertEquals("Size from array in args.", 99,
+ new SingleElementVector(new HashMap<String, Object>() {{
+ put("size", 99);
+ put("index", 0);
+ put("value", 1.0);
+ }}).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void negativeSizeTest() {
+ assertEquals("Negative size.", IMPOSSIBLE_SIZE,
+ new SingleElementVector(-1, 0, 1.0).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void zeroSizeTest() {
+ assertEquals("Zero size.", IMPOSSIBLE_SIZE,
+ new SingleElementVector(0, 0, 1.0).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void wrongIndexTest() {
+ //noinspection ConstantConditions
+ assertEquals("Wrong index.", IMPOSSIBLE_SIZE,
+ new SingleElementVector(1, 2, 1.0).size());
+ }
+
+ /** */
+ @Test
+ public void basicTest() {
+ final int[] sizes = new int[] {1, 4, 8};
+
+ for (int size : sizes)
+ for (int idx = 0; idx < size; idx++)
+ basicTest(size, idx);
+ }
+
+ /** */
+ private void basicTest(int size, int idx) {
+ final Double expVal = (double)(size - idx);
+
+ Vector v = new SingleElementVector(size, idx, expVal);
+
+ assertTrue("Expect value " + expVal + " at index " + idx + " for size " + size,
+ expVal.equals(v.get(idx)));
+
+ final double delta = 1.0;
+
+ v.set(idx, expVal - delta);
+
+ assertTrue("Expect value " + expVal + " at index " + idx + " for size " + size,
+ expVal.equals(v.get(idx) + delta));
+
+ final Double zero = 0.0;
+
+ for (int i = 0; i < size; i++) {
+ if (i == idx)
+ continue;
+
+ assertTrue("Expect zero at index " + i + " for size " + size,
+ zero.equals(v.get(i)));
+
+ boolean eCaught = false;
+
+ try {
+ v.set(i, 1.0);
+ }
+ catch (UnsupportedOperationException uoe) {
+ eCaught = true;
+ }
+
+ assertTrue("Expect " + java.lang.UnsupportedOperationException.class.getSimpleName()
+ + " at index " + i + " for size " + size, eCaught);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SingleElementVectorViewConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SingleElementVectorViewConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SingleElementVectorViewConstructorTest.java
new file mode 100644
index 0000000..957f3b7
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SingleElementVectorViewConstructorTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.math.impls.vector;
+
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/** */
+public class SingleElementVectorViewConstructorTest {
+ /** */
+ private static final int IMPOSSIBLE_SIZE = -1;
+
+ /** */
+ private static final SampleHelper helper = new SampleHelper();
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void nullVecParamTest() {
+ assertEquals("Expect exception due to null vector param.", IMPOSSIBLE_SIZE,
+ new SingleElementVectorView(null, helper.idx).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void negativeIdxParamTest() {
+ assertEquals("Expect exception due to negative index param.", IMPOSSIBLE_SIZE,
+ new SingleElementVectorView(helper.vec, -1).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void tooLargeIdxParamTest() {
+ assertEquals("Expect exception due to too large index param.", IMPOSSIBLE_SIZE,
+ new SingleElementVectorView(helper.vec, helper.vec.size()).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void emptyVecParamTest() {
+ assertEquals("Expect exception due to empty vector param.", IMPOSSIBLE_SIZE,
+ new SingleElementVectorView(helper.vecEmpty, 0).size());
+ }
+
+ /** */
+ @Test
+ public void basicTest() {
+ final int[] sizes = new int[] {1, 4, 8};
+
+ for (int size : sizes)
+ for (int idx = 0; idx < size; idx++)
+ basicTest(size, idx);
+ }
+
+ /** */
+ private void basicTest(int size, int idx) {
+ final Double expVal = (double)(size - idx);
+
+ Vector orig = helper.newSample(size, idx, expVal);
+
+ SingleElementVectorView svv = new SingleElementVectorView(orig, idx);
+
+ assertEquals("Size differs from expected", size, svv.size());
+
+ assertTrue("Expect value " + expVal + " at index " + idx + " for size " + size,
+ expVal.equals(svv.get(idx)));
+
+ final double delta = 1.0;
+
+ svv.set(idx, expVal - delta);
+
+ assertTrue("Expect value " + expVal + " at index " + idx + " for size " + size,
+ expVal.equals(orig.get(idx) + delta));
+
+ final Double zero = 0.0;
+
+ for (int i = 0; i < size; i++) {
+ if (i == idx)
+ continue;
+
+ assertTrue("Expect zero at index " + i + " for size " + size,
+ zero.equals(svv.get(i)));
+
+ boolean eCaught = false;
+
+ try {
+ svv.set(i, 1.0);
+ }
+ catch (UnsupportedOperationException uoe) {
+ eCaught = true;
+ }
+
+ assertTrue("Expect " + UnsupportedOperationException.class.getSimpleName()
+ + " at index " + i + " for size " + size, eCaught);
+ }
+ }
+
+ /** */
+ private static class SampleHelper {
+ /** */
+ final double[] data = new double[] {0, 1};
+ /** */
+ final Vector vec = new DenseLocalOnHeapVector(data);
+ /** */
+ final Vector vecEmpty = new DenseLocalOnHeapVector(new double[] {});
+ /** */
+ final int idx = 0;
+
+ /** */
+ Vector newSample(int size, int idx, double expVal) {
+ final Vector v = new DenseLocalOnHeapVector(size);
+
+ for (int i = 0; i < size; i++)
+ v.set(i, i == idx ? expVal : i);
+
+ return v;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SparseLocalVectorConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SparseLocalVectorConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SparseLocalVectorConstructorTest.java
new file mode 100644
index 0000000..2be4a10
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/SparseLocalVectorConstructorTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.math.impls.vector;
+
+import org.apache.ignite.math.StorageConstants;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/** */
+public class SparseLocalVectorConstructorTest {
+ /** */
+ private static final int IMPOSSIBLE_SIZE = -1;
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void negativeSizeTest() {
+ assertEquals("Negative size.", IMPOSSIBLE_SIZE,
+ new SparseLocalVector(-1, 1).size());
+ }
+
+ /** */
+ @Test(expected = AssertionError.class)
+ public void zeroSizeTest() {
+ assertEquals("0 size.", IMPOSSIBLE_SIZE,
+ new SparseLocalVector(0, 1).size());
+ }
+
+ /** */
+ @Test
+ public void primitiveTest() {
+ assertEquals("1 size, random access.", 1,
+ new SparseLocalVector(1, StorageConstants.RANDOM_ACCESS_MODE).size());
+
+ assertEquals("1 size, sequential access.", 1,
+ new SparseLocalVector(1, StorageConstants.SEQUENTIAL_ACCESS_MODE).size());
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorAttributesTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorAttributesTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorAttributesTest.java
new file mode 100644
index 0000000..992018a
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorAttributesTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.math.impls.vector;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.impls.matrix.DenseLocalOffHeapMatrix;
+import org.apache.ignite.math.impls.matrix.DenseLocalOnHeapMatrix;
+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,
+ DenseLocalOnHeapVector.class, DenseLocalOffHeapVector.class, RandomVector.class, ConstantVector.class,
+ SingleElementVector.class),
+ new AttrCfg("isArrayBased", Vector::isArrayBased,
+ DenseLocalOnHeapVector.class),
+ new AttrCfg("isSequentialAccess", Vector::isSequentialAccess,
+ DenseLocalOnHeapVector.class, DenseLocalOffHeapVector.class, SparseLocalVectorSequentialAccess.class,
+ RandomVector.class, ConstantVector.class, SingleElementVector.class),
+ new AttrCfg("guidNotNull", v -> v.guid() == null), // IMPL NOTE this is somewhat artificial
+ new AttrCfg("isRandomAccess", Vector::isRandomAccess,
+ DenseLocalOnHeapVector.class, DenseLocalOffHeapVector.class, RandomVector.class, ConstantVector.class,
+ SingleElementVector.class, SparseLocalVectorSequentialAccess.class, SparseLocalVectorRandomAccess.class),
+ new AttrCfg("isDistributed", Vector::isDistributed));
+
+ /** */
+ private final List<Specification> specFixture = Arrays.asList(
+ new Specification(new DenseLocalOnHeapVector(1)),
+ new Specification(new DenseLocalOffHeapVector(1)),
+ new Specification(new DelegatingVector(new DenseLocalOnHeapVector(1)),
+ DenseLocalOnHeapVector.class, "isDense", "isArrayBased", "isSequentialAccess",
+ "isRandomAccess", "isDistributed"),
+ new Specification(new DelegatingVector(new DenseLocalOffHeapVector(1)),
+ DenseLocalOffHeapVector.class, "isDense", "isArrayBased", "isSequentialAccess",
+ "isRandomAccess", "isDistributed"),
+ new Specification(new SparseLocalVectorSequentialAccess(1)),
+ new Specification(new SparseLocalVectorRandomAccess(1)),
+ new Specification(new RandomVector(1)),
+ new Specification(new ConstantVector(1, 1.0)),
+ new Specification(new FunctionVector(1, idx -> (double)idx)),
+ new Specification(new SingleElementVector(1, 0, 1.0)),
+ new Specification(new PivotedVectorView(new DenseLocalOnHeapVector(1), new int[] {0}),
+ DenseLocalOnHeapVector.class, "isDense", "isArrayBased", "isSequentialAccess",
+ "isRandomAccess", "isDistributed"),
+ new Specification(new PivotedVectorView(new DenseLocalOffHeapVector(1), new int[] {0}),
+ DenseLocalOffHeapVector.class, "isDense", "isArrayBased", "isSequentialAccess",
+ "isRandomAccess", "isDistributed"),
+ new Specification(new SingleElementVectorView(new DenseLocalOnHeapVector(1), 0),
+ DenseLocalOnHeapVector.class, "isDense", "isSequentialAccess",
+ "isRandomAccess", "isDistributed"),
+ new Specification(new SingleElementVectorView(new DenseLocalOffHeapVector(1), 0),
+ DenseLocalOffHeapVector.class, "isDense", "isSequentialAccess",
+ "isRandomAccess", "isDistributed"),
+ new Specification(new MatrixVectorView(new DenseLocalOnHeapMatrix(1, 1), 0, 0, 1, 1),
+ DenseLocalOnHeapVector.class, "isDense",
+ "isRandomAccess", "isDistributed"), // todo find out why "isSequentialAccess" fails here
+ new Specification(new MatrixVectorView(new DenseLocalOffHeapMatrix(1, 1), 0, 0, 1, 1),
+ DenseLocalOffHeapVector.class, "isDense",
+ "isRandomAccess", "isDistributed"));
+
+ /** */
+ @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 SparseLocalVector {
+ /** */
+ public SparseLocalVectorSequentialAccess() {
+ // No-op.
+ }
+
+ /** */
+ SparseLocalVectorSequentialAccess(int size) {
+ super(size, SEQUENTIAL_ACCESS_MODE);
+ }
+ }
+
+ /** */
+ private static class SparseLocalVectorRandomAccess extends SparseLocalVector {
+ /** */
+ public SparseLocalVectorRandomAccess() {
+ // No-op.
+ }
+
+ /** */
+ SparseLocalVectorRandomAccess(int size) {
+ super(size, RANDOM_ACCESS_MODE);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorFoldMapTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorFoldMapTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorFoldMapTest.java
new file mode 100644
index 0000000..67eb8ba
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorFoldMapTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.math.impls.vector;
+
+import java.util.Arrays;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.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 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/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorImplementationsFixtures.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorImplementationsFixtures.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorImplementationsFixtures.java
new file mode 100644
index 0000000..5a46218
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorImplementationsFixtures.java
@@ -0,0 +1,655 @@
+/*
+ * 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.math.impls.vector;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+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.math.Matrix;
+import org.apache.ignite.math.StorageConstants;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.math.impls.storage.vector.FunctionVectorStorage;
+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>>)DenseLocalOffHeapVectorFixture::new,
+ (Supplier<Iterable<Vector>>)SparseLocalVectorFixture::new,
+ (Supplier<Iterable<Vector>>)RandomVectorFixture::new,
+ (Supplier<Iterable<Vector>>)ConstantVectorFixture::new,
+ (Supplier<Iterable<Vector>>)DelegatingVectorFixture::new,
+ (Supplier<Iterable<Vector>>)FunctionVectorFixture::new,
+ (Supplier<Iterable<Vector>>)SingleElementVectorFixture::new,
+ (Supplier<Iterable<Vector>>)PivotedVectorViewFixture::new,
+ (Supplier<Iterable<Vector>>)SingleElementVectorViewFixture::new,
+ (Supplier<Iterable<Vector>>)MatrixVectorViewFixture::new,
+ (Supplier<Iterable<Vector>>)SparseLocalOffHeapVectorFixture::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());
+ }
+ }
+ }
+
+ /** */
+ void selfTest() {
+ new VectorSizesExtraIterator<>("VectorSizesExtraIterator test",
+ (size, shallowCp) -> new DenseLocalOnHeapVector(new double[size], shallowCp),
+ null, "shallow copy", new Boolean[] {false, true, null}).selfTest();
+
+ new VectorSizesIterator("VectorSizesIterator test", DenseLocalOffHeapVector::new, null).selfTest();
+ }
+
+ /** */
+ private static class DenseLocalOnHeapVectorFixture extends VectorSizesExtraFixture<Boolean> {
+ /** */
+ DenseLocalOnHeapVectorFixture() {
+ super("DenseLocalOnHeapVector",
+ (size, shallowCp) -> new DenseLocalOnHeapVector(new double[size], shallowCp),
+ "shallow copy", new Boolean[] {false, true, null});
+ }
+ }
+
+ /** */
+ private static class DenseLocalOffHeapVectorFixture extends VectorSizesFixture {
+ /** */
+ DenseLocalOffHeapVectorFixture() {
+ super("DenseLocalOffHeapVector", DenseLocalOffHeapVector::new);
+ }
+ }
+
+ /** */
+ private static class SparseLocalVectorFixture extends VectorSizesExtraFixture<Integer> {
+ /** */
+ SparseLocalVectorFixture() {
+ super("SparseLocalVector", SparseLocalVector::new, "access mode",
+ new Integer[] {StorageConstants.SEQUENTIAL_ACCESS_MODE, StorageConstants.RANDOM_ACCESS_MODE, null});
+ }
+ }
+
+ /** */
+ private static class RandomVectorFixture extends VectorSizesFixture {
+ /** */
+ RandomVectorFixture() {
+ super("RandomVector", RandomVector::new);
+ }
+ }
+
+ /** */
+ private static class ConstantVectorFixture extends VectorSizesExtraFixture<Double> {
+ /** */
+ ConstantVectorFixture() {
+ super("ConstantVector", ConstantVector::new,
+ "value", new Double[] {-1.0, 0.0, 0.5, 1.0, 2.0, null});
+ }
+ }
+
+ /** */
+ private static class FunctionVectorFixture extends VectorSizesExtraFixture<Double> {
+ /** */
+ FunctionVectorFixture() {
+ super("FunctionVector",
+ (size, scale) -> new FunctionVectorForTest(new double[size], scale),
+ "scale", new Double[] {0.5, 1.0, 2.0, null});
+ }
+ }
+
+ /** */
+ private static class SingleElementVectorFixture implements Iterable<Vector> {
+ /** */
+ private final Supplier<TwoParamsIterator<Integer, Double>> iter;
+
+ /** */
+ private final AtomicReference<String> ctxDescrHolder = new AtomicReference<>("Iterator not started.");
+
+ /** */
+ SingleElementVectorFixture() {
+ iter = () -> new TwoParamsIterator<Integer, Double>("SingleElementVector",
+ null, ctxDescrHolder::set,
+ "size", new Integer[] {1, null},
+ "value", new Double[] {-1.0, 0.0, 0.5, 1.0, 2.0, null}) {
+
+ /** {@inheritDoc} */
+ @Override BiFunction<Integer, Double, Vector> ctor() {
+ return (size, value) -> new SingleElementVector(size, 0, value);
+ }
+ };
+ }
+
+ /** {@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 PivotedVectorViewFixture extends VectorSizesFixture {
+ /** */
+ PivotedVectorViewFixture() {
+ super("PivotedVectorView", PivotedVectorViewFixture::pivotedVectorView);
+ }
+
+ /** */
+ private static PivotedVectorView pivotedVectorView(int size) {
+ final DenseLocalOnHeapVector vec = new DenseLocalOnHeapVector(size);
+
+ final int[] pivot = new int[size];
+
+ for (int idx = 0; idx < size; idx++)
+ pivot[idx] = size - 1 - idx;
+
+ PivotedVectorView tmp = new PivotedVectorView(vec, pivot);
+
+ final int[] unpivot = new int[size];
+
+ for (int idx = 0; idx < size; idx++)
+ unpivot[idx] = tmp.unpivot(idx);
+
+ final int[] idxRecovery = new int[size];
+
+ for (int idx = 0; idx < size; idx++)
+ idxRecovery[idx] = idx;
+
+ return new PivotedVectorView(new PivotedVectorView(tmp, unpivot), idxRecovery);
+ }
+ }
+
+ /** */
+ private static class SingleElementVectorViewFixture implements Iterable<Vector> {
+ /** */
+ private final Supplier<TwoParamsIterator<Integer, Double>> iter;
+
+ /** */
+ private final AtomicReference<String> ctxDescrHolder = new AtomicReference<>("Iterator not started.");
+
+ /** */
+ SingleElementVectorViewFixture() {
+ iter = () -> new TwoParamsIterator<Integer, Double>("SingleElementVectorView",
+ null, ctxDescrHolder::set,
+ "size", new Integer[] {1, null},
+ "value", new Double[] {-1.0, 0.0, 0.5, 1.0, 2.0, null}) {
+
+ /** {@inheritDoc} */
+ @Override BiFunction<Integer, Double, Vector> ctor() {
+ return (size, value) -> new SingleElementVectorView(new SingleElementVector(size, 0, value), 0);
+ }
+ };
+ }
+
+ /** {@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 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 DenseLocalOnHeapMatrix(size, size);
+
+ return new MatrixVectorView(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 DenseLocalOnHeapVector(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();
+ }
+ }
+
+ /** Subclass tweaked for serialization */
+ private static class FunctionVectorForTest extends FunctionVector {
+ /** */
+ double[] arr;
+
+ /** */
+ double scale;
+
+ /** */
+ public FunctionVectorForTest() {
+ // No-op.
+ }
+
+ /** */
+ FunctionVectorForTest(double[] arr, double scale) {
+ super(arr.length, idx -> arr[idx] * scale, (idx, value) -> arr[idx] = value / scale);
+
+ this.arr = arr;
+
+ this.scale = scale;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+
+ out.writeObject(arr);
+
+ out.writeDouble(scale);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+
+ arr = (double[])in.readObject();
+
+ scale = in.readDouble();
+
+ setStorage(new FunctionVectorStorage(arr.length, idx -> arr[idx] * scale, (idx, value) -> arr[idx] = value / scale));
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = 1;
+
+ res = res * 37 + Double.hashCode(scale);
+ res = res * 37 + Integer.hashCode(getStorage().size());
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ FunctionVectorForTest that = (FunctionVectorForTest)o;
+
+ return new Double(scale).equals(that.scale)
+ && (arr != null ? Arrays.equals(arr, that.arr) : that.arr == null);
+ }
+ }
+
+ /** */
+ private static class SparseLocalOffHeapVectorFixture extends VectorSizesFixture {
+
+ /** */
+ SparseLocalOffHeapVectorFixture() {
+ super("SparseLocalOffHeapVector", SparseLocalOffHeapVector::new);
+ }
+ }
+}