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:49 UTC
[04/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/matrix/MatrixImplementationFixtures.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixImplementationFixtures.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixImplementationFixtures.java
new file mode 100644
index 0000000..88aa4fe
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixImplementationFixtures.java
@@ -0,0 +1,381 @@
+/*
+ * 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.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.impls.storage.matrix.FunctionMatrixStorage;
+import org.jetbrains.annotations.NotNull;
+
+/** */
+class MatrixImplementationFixtures {
+ /** */
+ private static final List<Supplier<Iterable<Matrix>>> suppliers = Arrays.asList(
+ (Supplier<Iterable<Matrix>>)DenseLocalOnHeapMatrixFixture::new,
+ (Supplier<Iterable<Matrix>>)DenseLocalOffHeapMatrixFixture::new,
+ (Supplier<Iterable<Matrix>>)RandomMatrixFixture::new,
+ (Supplier<Iterable<Matrix>>)SparseLocalOnHeapMatrixFixture::new,
+ (Supplier<Iterable<Matrix>>)PivotedMatrixViewFixture::new,
+ (Supplier<Iterable<Matrix>>)MatrixViewFixture::new,
+ (Supplier<Iterable<Matrix>>)FunctionMatrixFixture::new,
+ (Supplier<Iterable<Matrix>>)DiagonalMatrixFixture::new,
+ (Supplier<Iterable<Matrix>>)TransposedMatrixViewFixture::new
+ );
+
+ /** */
+ void consumeSampleMatrix(BiConsumer<Matrix, String> consumer) {
+ for (Supplier<Iterable<Matrix>> fixtureSupplier : suppliers) {
+ final Iterable<Matrix> fixture = fixtureSupplier.get();
+
+ for (Matrix matrix : fixture) {
+ consumer.accept(matrix, fixture.toString());
+
+ matrix.destroy();
+ }
+ }
+ }
+
+ /** */
+ private static class DenseLocalOnHeapMatrixFixture extends MatrixSizeIterator {
+ /** */
+ DenseLocalOnHeapMatrixFixture() {
+ super(DenseLocalOnHeapMatrix::new, "DenseLocalOnHeapMatrix");
+ }
+ }
+
+ /** */
+ private static class DenseLocalOffHeapMatrixFixture extends MatrixSizeIterator {
+ /** */
+ DenseLocalOffHeapMatrixFixture() {
+ super(DenseLocalOffHeapMatrix::new, "DenseLocalOffHeapMatrix");
+ }
+ }
+
+ /** */
+ private static class RandomMatrixFixture extends MatrixSizeIterator {
+ /** */
+ RandomMatrixFixture() {
+ super(RandomMatrix::new, "RandomMatrix");
+ }
+ }
+
+ /** */
+ private static class SparseLocalOnHeapMatrixFixture extends MatrixSizeIterator {
+ /** */
+ SparseLocalOnHeapMatrixFixture() {
+ super(SparseLocalOnHeapMatrix::new, "SparseLocalOnHeapMatrix");
+ }
+ }
+
+ /** */
+ private static class PivotedMatrixViewFixture extends WrapperMatrixIterator {
+ /** */
+ PivotedMatrixViewFixture() {
+ super(PivotedMatrixView::new, "PivotedMatrixView over DenseLocalOnHeapMatrix");
+ }
+ }
+
+ /** */
+ private static class MatrixViewFixture extends WrapperMatrixIterator {
+ /** */
+ MatrixViewFixture() {
+ super((matrix) -> new MatrixView(matrix, 0, 0, matrix.rowSize(), matrix.columnSize()),
+ "MatrixView over DenseLocalOnHeapMatrix");
+ }
+ }
+
+ /** */
+ private static class FunctionMatrixFixture extends WrapperMatrixIterator {
+ /** */
+ FunctionMatrixFixture() {
+ super(FunctionMatrixForTest::new, "FunctionMatrix wrapping DenseLocalOnHeapMatrix");
+ }
+ }
+
+ /** */
+ private static class DiagonalMatrixFixture extends DiagonalIterator {
+ /** */
+ DiagonalMatrixFixture() {
+ super(DenseLocalOnHeapMatrix::new, "DiagonalMatrix over DenseLocalOnHeapMatrix");
+ }
+
+ /** {@inheritDoc} */
+ @NotNull
+ @Override public Iterator<Matrix> iterator() {
+ return new Iterator<Matrix>() {
+ /** {@inheritDoc} */
+ @Override public boolean hasNext() {
+ return hasNextSize(getSizeIdx());
+ }
+
+ /** {@inheritDoc} */
+ @Override public Matrix next() {
+ assert getSize(getSizeIdx()) == 1 : "Only size 1 allowed for diagonal matrix fixture.";
+
+ Matrix matrix = getConstructor().apply(getSize(getSizeIdx()), getSize(getSizeIdx()));
+
+ nextIdx();
+
+ return new DiagonalMatrix(matrix);
+ }
+ };
+ }
+ }
+
+ /** */
+ private static class TransposedMatrixViewFixture extends WrapperMatrixIterator {
+ /** */
+ TransposedMatrixViewFixture() {
+ super(TransposedMatrixView::new, "TransposedMatrixView over DenseLocalOnHeapMatrix");
+ }
+ }
+
+ /** */
+ private static abstract class DiagonalIterator implements Iterable<Matrix> {
+ /** */
+ private final Integer[] sizes = new Integer[] {1, null};
+ /** */
+ private int sizeIdx = 0;
+
+ /** */
+ private BiFunction<Integer, Integer, ? extends Matrix> constructor;
+ /** */
+ private String desc;
+
+ /** */
+ DiagonalIterator(BiFunction<Integer, Integer, ? extends Matrix> constructor, String desc) {
+ this.constructor = constructor;
+ this.desc = desc;
+ }
+
+ /** */
+ public BiFunction<Integer, Integer, ? extends Matrix> getConstructor() {
+ return constructor;
+ }
+
+ /** */
+ int getSizeIdx() {
+ return sizeIdx;
+ }
+
+ /** */
+ @Override public String toString() {
+ return desc + "{rows=" + sizes[sizeIdx] + ", cols=" + sizes[sizeIdx] + "}";
+ }
+
+ /** */
+ boolean hasNextSize(int idx) {
+ return sizes[idx] != null;
+ }
+
+ /** */
+ Integer getSize(int idx) {
+ return sizes[idx];
+ }
+
+ /** */
+ void nextIdx() {
+ sizeIdx++;
+ }
+ }
+
+ /** */
+ private static class WrapperMatrixIterator extends MatrixSizeIterator {
+ /** */
+ private final Function<Matrix, Matrix> wrapperCtor;
+
+ /** */
+ WrapperMatrixIterator(Function<Matrix, Matrix> wrapperCtor, String desc) {
+ super(DenseLocalOnHeapMatrix::new, desc);
+
+ this.wrapperCtor = wrapperCtor;
+ }
+
+ /** {@inheritDoc} */
+ @NotNull
+ @Override public Iterator<Matrix> iterator() {
+ return new Iterator<Matrix>() {
+ /** {@inheritDoc} */
+ @Override public boolean hasNext() {
+ return hasNextCol(getSizeIdx()) && hasNextRow(getSizeIdx());
+ }
+
+ /** {@inheritDoc} */
+ @Override public Matrix next() {
+ Matrix matrix = getConstructor().apply(getRow(getSizeIdx()), getCol(getSizeIdx()));
+
+ nextIdx();
+
+ return wrapperCtor.apply(matrix);
+ }
+ };
+ }
+ }
+
+ /** */
+ private static class MatrixSizeIterator implements Iterable<Matrix> {
+ /** */
+ private final Integer[] rows = new Integer[] {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 512, 1024, null};
+ /** */
+ private final Integer[] cols = new Integer[] {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 1024, 512, null};
+ /** */
+ private int sizeIdx = 0;
+
+ /** */
+ private BiFunction<Integer, Integer, ? extends Matrix> constructor;
+ /** */
+ private String desc;
+
+ /** */
+ MatrixSizeIterator(BiFunction<Integer, Integer, ? extends Matrix> constructor, String desc) {
+ this.constructor = constructor;
+ this.desc = desc;
+ }
+
+ /** */
+ public BiFunction<Integer, Integer, ? extends Matrix> getConstructor() {
+ return constructor;
+ }
+
+ /** */
+ int getSizeIdx() {
+ return sizeIdx;
+ }
+
+ /** */
+ @Override public String toString() {
+ return desc + "{rows=" + rows[sizeIdx] + ", cols=" + cols[sizeIdx] + "}";
+ }
+
+ /** */
+ boolean hasNextRow(int idx) {
+ return rows[idx] != null;
+ }
+
+ /** */
+ boolean hasNextCol(int idx) {
+ return cols[idx] != null;
+ }
+
+ /** */
+ Integer getRow(int idx) {
+ return rows[idx];
+ }
+
+ /** */
+ int getCol(int idx) {
+ return cols[idx];
+ }
+
+ /** {@inheritDoc} */
+ @NotNull
+ @Override public Iterator<Matrix> iterator() {
+ return new Iterator<Matrix>() {
+ /** {@inheritDoc} */
+ @Override public boolean hasNext() {
+ return hasNextCol(sizeIdx) && hasNextRow(sizeIdx);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Matrix next() {
+ Matrix matrix = constructor.apply(rows[sizeIdx], cols[sizeIdx]);
+
+ nextIdx();
+
+ return matrix;
+ }
+ };
+ }
+
+ /** */
+ void nextIdx() {
+ sizeIdx++;
+ }
+ }
+
+ /** Subclass tweaked for serialization */
+ private static class FunctionMatrixForTest extends FunctionMatrix {
+ /** */
+ Matrix underlying;
+
+ /** */
+ public FunctionMatrixForTest() {
+ // No-op.
+ }
+
+ /** */
+ FunctionMatrixForTest(Matrix underlying) {
+ super(underlying.rowSize(), underlying.columnSize(), underlying::get, underlying::set);
+
+ this.underlying = underlying;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Matrix copy() {
+ return new FunctionMatrixForTest(underlying);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+
+ out.writeObject(underlying);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+
+ underlying = (Matrix)in.readObject();
+
+ setStorage(new FunctionMatrixStorage(underlying.rowSize(), underlying.columnSize(),
+ underlying::get, underlying::set));
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = 1;
+
+ res = res * 37 + underlying.hashCode();
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ FunctionMatrixForTest that = (FunctionMatrixForTest)o;
+
+ return underlying != null ? underlying.equals(that.underlying) : that.underlying == null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixImplementationsTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixImplementationsTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixImplementationsTest.java
new file mode 100644
index 0000000..28abab7
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixImplementationsTest.java
@@ -0,0 +1,1113 @@
+/*
+ * 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.matrix;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Supplier;
+import org.apache.ignite.math.ExternalizeTest;
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.CardinalityException;
+import org.apache.ignite.math.exceptions.ColumnIndexException;
+import org.apache.ignite.math.exceptions.IndexException;
+import org.apache.ignite.math.exceptions.RowIndexException;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.math.impls.vector.DenseLocalOffHeapVector;
+import org.apache.ignite.math.impls.vector.DenseLocalOnHeapVector;
+import org.apache.ignite.math.impls.vector.RandomVector;
+import org.apache.ignite.math.impls.vector.SparseLocalVector;
+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;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests for {@link Matrix} implementations.
+ */
+public class MatrixImplementationsTest extends ExternalizeTest<Matrix> {
+ /** */
+ private static final double DEFAULT_DELTA = 0.000000001d;
+
+ /** */
+ private void consumeSampleMatrix(BiConsumer<Matrix, String> consumer) {
+ new MatrixImplementationFixtures().consumeSampleMatrix(consumer);
+ }
+
+ /** */
+ @Test
+ public void externalizeTest() {
+ consumeSampleMatrix((m, desc) -> externalizeTest(m));
+ }
+
+ /** */
+ @Test
+ public void testLike() {
+ consumeSampleMatrix((m, desc) -> {
+ Class<? extends Matrix> cls = likeMatrixType(m);
+
+ if (cls != null) {
+ Matrix like = m.like(m.rowSize(), m.columnSize());
+
+ assertEquals("Wrong \"like\" matrix for " + desc + "; Unexpected rows.", like.rowSize(), m.rowSize());
+ assertEquals("Wrong \"like\" matrix for " + desc + "; Unexpected columns.", like.columnSize(), m.columnSize());
+
+ assertEquals("Wrong \"like\" matrix for " + desc
+ + "; Unexpected class: " + like.getClass().toString(),
+ cls,
+ like.getClass());
+
+ return;
+ }
+
+ boolean expECaught = false;
+
+ try {
+ m.like(1, 1);
+ }
+ catch (UnsupportedOperationException uoe) {
+ expECaught = true;
+ }
+
+ assertTrue("Expected exception was not caught for " + desc, expECaught);
+ });
+ }
+
+ /** */
+ @Test
+ public void testCopy() {
+ consumeSampleMatrix((m, desc) -> {
+ Matrix cp = m.copy();
+ assertTrue("Incorrect copy for empty matrix " + desc, cp.equals(m));
+
+ if (!readOnly(m))
+ fillMatrix(m);
+
+ cp = m.copy();
+
+ assertTrue("Incorrect copy for matrix " + desc, cp.equals(m));
+ });
+ }
+
+ /** */
+ @Test
+ public void testHaveLikeVector() throws InstantiationException, IllegalAccessException {
+ for (Class<? extends Matrix> key : likeVectorTypesMap().keySet()) {
+ Class<? extends Vector> val = likeVectorTypesMap().get(key);
+
+ if (val == null && !ignore(key))
+ System.out.println("Missing test for implementation of likeMatrix for " + key.getSimpleName());
+ }
+ }
+
+ /** */
+ @Test
+ public void testLikeVector() {
+ consumeSampleMatrix((m, desc) -> {
+ if (likeVectorTypesMap().containsKey(m.getClass())) {
+ Vector likeVector = m.likeVector(m.columnSize());
+
+ assertNotNull(likeVector);
+ assertEquals("Unexpected value for " + desc, likeVector.size(), m.columnSize());
+
+ return;
+ }
+
+ boolean expECaught = false;
+
+ try {
+ m.likeVector(1);
+ }
+ catch (UnsupportedOperationException uoe) {
+ expECaught = true;
+ }
+
+ assertTrue("Expected exception was not caught for " + desc, expECaught);
+ });
+ }
+
+ /** */
+ @Test
+ public void testAssignSingleElement() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ final double assignVal = Math.random();
+
+ m.assign(assignVal);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ assignVal, m.get(i, j), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testAssignArray() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ double[][] data = new double[m.rowSize()][m.columnSize()];
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ data[i][j] = Math.random();
+
+ m.assign(data);
+
+ for (int i = 0; i < m.rowSize(); i++) {
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ data[i][j], m.get(i, j), 0d);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testAssignFunction() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ m.assign((i, j) -> (double)(i * m.columnSize() + j));
+
+ for (int i = 0; i < m.rowSize(); i++) {
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ (double)(i * m.columnSize() + j), m.get(i, j), 0d);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testPlus() {
+ consumeSampleMatrix((m, desc) -> {
+ if (readOnly(m))
+ return;
+
+ double[][] data = fillAndReturn(m);
+
+ double plusVal = Math.random();
+
+ Matrix plus = m.plus(plusVal);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ data[i][j] + plusVal, plus.get(i, j), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testPlusMatrix() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ double[][] data = fillAndReturn(m);
+
+ Matrix plus = m.plus(m);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ data[i][j] * 2.0, plus.get(i, j), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testMinusMatrix() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ Matrix minus = m.minus(m);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ 0.0, minus.get(i, j), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testTimes() {
+ consumeSampleMatrix((m, desc) -> {
+ if (readOnly(m))
+ return;
+
+ double[][] data = fillAndReturn(m);
+
+ double timeVal = Math.random();
+ Matrix times = m.times(timeVal);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ data[i][j] * timeVal, times.get(i, j), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testTimesVector() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ double[][] data = fillAndReturn(m);
+
+ double[] arr = fillArray(m.columnSize());
+
+ Vector times = m.times(new DenseLocalOnHeapVector(arr));
+
+ assertEquals("Unexpected vector size for " + desc, times.size(), m.rowSize());
+
+ for (int i = 0; i < m.rowSize(); i++) {
+ double exp = 0.0;
+
+ for (int j = 0; j < m.columnSize(); j++)
+ exp += arr[j] * data[i][j];
+
+ assertEquals("Unexpected value for " + desc + " at " + i,
+ times.get(i), exp, 0d);
+ }
+
+ testInvalidCardinality(() -> m.times(new DenseLocalOnHeapVector(m.columnSize() + 1)), desc);
+ });
+ }
+
+ /** */
+ @Test
+ public void testTimesMatrix() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ double[][] data = fillAndReturn(m);
+
+ double[] arr = fillArray(m.columnSize());
+
+ Matrix mult = new DenseLocalOnHeapMatrix(m.columnSize(), 1);
+
+ mult.setColumn(0, arr);
+
+ Matrix times = m.times(mult);
+
+ assertEquals("Unexpected rows for " + desc, times.rowSize(), m.rowSize());
+
+ assertEquals("Unexpected cols for " + desc, times.columnSize(), 1);
+
+ for (int i = 0; i < m.rowSize(); i++) {
+ double exp = 0.0;
+
+ for (int j = 0; j < m.columnSize(); j++)
+ exp += arr[j] * data[i][j];
+
+ assertEquals("Unexpected value for " + desc + " at " + i,
+ exp, times.get(i, 0), 0d);
+ }
+
+ testInvalidCardinality(() -> m.times(new DenseLocalOnHeapMatrix(m.columnSize() + 1, 1)), desc);
+ });
+ }
+
+ /** */
+ @Test
+ public void testDivide() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ double[][] data = fillAndReturn(m);
+
+ double divVal = Math.random();
+
+ Matrix divide = m.divide(divVal);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ data[i][j] / divVal, divide.get(i, j), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testTranspose() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ Matrix transpose = m.transpose();
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ m.get(i, j), transpose.get(j, i), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testDeterminant() {
+ consumeSampleMatrix((m, desc) -> {
+ if (m.rowSize() != m.columnSize())
+ return;
+
+ if (ignore(m.getClass()))
+ return;
+
+ double[][] doubles = fillIntAndReturn(m);
+
+ if (m.rowSize() == 1) {
+ assertEquals("Unexpected value " + desc, m.determinant(), doubles[0][0], 0d);
+
+ return;
+ }
+
+ if (m.rowSize() == 2) {
+ double det = doubles[0][0] * doubles[1][1] - doubles[0][1] * doubles[1][0];
+ assertEquals("Unexpected value " + desc, m.determinant(), det, 0d);
+
+ return;
+ }
+
+ if (m.rowSize() > 512)
+ return; // IMPL NOTE if row size >= 30000 it takes unacceptably long for normal test run.
+
+ Matrix diagMtx = m.like(m.rowSize(), m.columnSize());
+
+ diagMtx.assign(0);
+ for (int i = 0; i < m.rowSize(); i++)
+ diagMtx.set(i, i, m.get(i, i));
+
+ double det = 1;
+
+ for (int i = 0; i < diagMtx.rowSize(); i++)
+ det *= diagMtx.get(i, i);
+
+ try {
+ assertEquals("Unexpected value " + desc, det, diagMtx.determinant(), DEFAULT_DELTA);
+ }
+ catch (Exception e) {
+ System.out.println(desc);
+ throw e;
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testInverse() {
+ consumeSampleMatrix((m, desc) -> {
+ if (m.rowSize() != m.columnSize())
+ return;
+
+ if (ignore(m.getClass()))
+ return;
+
+ if (m.rowSize() > 256)
+ return; // IMPL NOTE this is for quicker test run.
+
+ fillNonSingularMatrix(m);
+
+ assertTrue("Unexpected zero determinant " + desc, Math.abs(m.determinant()) > 0d);
+
+ Matrix inverse = m.inverse();
+
+ Matrix mult = m.times(inverse);
+
+ final double delta = 0.001d;
+
+ assertEquals("Unexpected determinant " + desc, 1d, mult.determinant(), delta);
+
+ assertEquals("Unexpected top left value " + desc, 1d, mult.get(0, 0), delta);
+
+ if (m.rowSize() == 1)
+ return;
+
+ assertEquals("Unexpected center value " + desc,
+ 1d, mult.get(m.rowSize() / 2, m.rowSize() / 2), delta);
+
+ assertEquals("Unexpected bottom right value " + desc,
+ 1d, mult.get(m.rowSize() - 1, m.rowSize() - 1), delta);
+
+ assertEquals("Unexpected top right value " + desc,
+ 0d, mult.get(0, m.rowSize() - 1), delta);
+
+ assertEquals("Unexpected bottom left value " + desc,
+ 0d, mult.get(m.rowSize() - 1, 0), delta);
+ });
+ }
+
+ /** */
+ @Test
+ public void testMap() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ m.map(x -> 10d);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ 10d, m.get(i, j), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testMapMatrix() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ double[][] doubles = fillAndReturn(m);
+
+ testMapMatrixWrongCardinality(m, desc);
+
+ Matrix cp = m.copy();
+
+ m.map(cp, (m1, m2) -> m1 + m2);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ m.get(i, j), doubles[i][j] * 2, 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testViewRow() {
+ consumeSampleMatrix((m, desc) -> {
+ if (!readOnly(m))
+ fillMatrix(m);
+
+ for (int i = 0; i < m.rowSize(); i++) {
+ Vector vector = m.viewRow(i);
+ assert vector != null;
+
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ m.get(i, j), vector.get(j), 0d);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testViewCol() {
+ consumeSampleMatrix((m, desc) -> {
+ if (!readOnly(m))
+ fillMatrix(m);
+
+ for (int i = 0; i < m.columnSize(); i++) {
+ Vector vector = m.viewColumn(i);
+ assert vector != null;
+
+ for (int j = 0; j < m.rowSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at (" + i + "," + j + ")",
+ m.get(j, i), vector.get(j), 0d);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testFoldRow() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ Vector foldRows = m.foldRows(Vector::sum);
+
+ for (int i = 0; i < m.rowSize(); i++) {
+ Double locSum = 0d;
+
+ for (int j = 0; j < m.columnSize(); j++)
+ locSum += m.get(i, j);
+
+ assertEquals("Unexpected value for " + desc + " at " + i,
+ foldRows.get(i), locSum, 0d);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testFoldCol() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ Vector foldCols = m.foldColumns(Vector::sum);
+
+ for (int j = 0; j < m.columnSize(); j++) {
+ Double locSum = 0d;
+
+ for (int i = 0; i < m.rowSize(); i++)
+ locSum += m.get(i, j);
+
+ assertEquals("Unexpected value for " + desc + " at " + j,
+ foldCols.get(j), locSum, 0d);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testSum() {
+ consumeSampleMatrix((m, desc) -> {
+ double[][] data = fillAndReturn(m);
+
+ double sum = m.sum();
+
+ double rawSum = 0;
+ for (double[] anArr : data)
+ for (int j = 0; j < data[0].length; j++)
+ rawSum += anArr[j];
+
+ assertEquals("Unexpected value for " + desc,
+ rawSum, sum, 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testMax() {
+ consumeSampleMatrix((m, desc) -> {
+ double[][] doubles = fillAndReturn(m);
+ double max = Double.NEGATIVE_INFINITY;
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ max = max < doubles[i][j] ? doubles[i][j] : max;
+
+ assertEquals("Unexpected value for " + desc, m.maxValue(), max, 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testMin() {
+ consumeSampleMatrix((m, desc) -> {
+ double[][] doubles = fillAndReturn(m);
+ double min = Double.MAX_VALUE;
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ min = min > doubles[i][j] ? doubles[i][j] : min;
+
+ assertEquals("Unexpected value for " + desc, m.minValue(), min, 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testGetElement() {
+ consumeSampleMatrix((m, desc) -> {
+ if (!(readOnly(m)))
+ fillMatrix(m);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++) {
+ final Matrix.Element e = m.getElement(i, j);
+
+ final String details = desc + " at [" + i + "," + j + "]";
+
+ assertEquals("Unexpected element row " + details, i, e.row());
+ assertEquals("Unexpected element col " + details, j, e.column());
+
+ final double val = m.get(i, j);
+
+ assertEquals("Unexpected value for " + details, val, e.get(), 0d);
+
+ boolean expECaught = false;
+
+ final double newVal = val * 2.0;
+
+ try {
+ e.set(newVal);
+ }
+ catch (UnsupportedOperationException uoe) {
+ if (!(readOnly(m)))
+ throw uoe;
+
+ expECaught = true;
+ }
+
+ if (readOnly(m)) {
+ if (!expECaught)
+ fail("Expected exception was not caught for " + details);
+
+ continue;
+ }
+
+ assertEquals("Unexpected value set for " + details, newVal, m.get(i, j), 0d);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testGetX() {
+ consumeSampleMatrix((m, desc) -> {
+ if (!(readOnly(m)))
+ fillMatrix(m);
+
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ assertEquals("Unexpected value for " + desc + " at [" + i + "," + j + "]",
+ m.get(i, j), m.getX(i, j), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testGetMetaStorage() {
+ consumeSampleMatrix((m, desc) -> assertNotNull("Null meta storage in " + desc, m.getMetaStorage()));
+ }
+
+ /** */
+ @Test
+ public void testGuid() {
+ consumeSampleMatrix((m, desc) -> assertNotNull("Null guid in " + desc, m.guid()));
+ }
+
+ /** */
+ @Test
+ public void testSwapRows() {
+ consumeSampleMatrix((m, desc) -> {
+ if (readOnly(m))
+ return;
+
+ double[][] doubles = fillAndReturn(m);
+
+ final int swap_i = m.rowSize() == 1 ? 0 : 1;
+ final int swap_j = 0;
+
+ Matrix swap = m.swapRows(swap_i, swap_j);
+
+ for (int col = 0; col < m.columnSize(); col++) {
+ assertEquals("Unexpected value for " + desc + " at col " + col + ", swap_i " + swap_i,
+ swap.get(swap_i, col), doubles[swap_j][col], 0d);
+
+ assertEquals("Unexpected value for " + desc + " at col " + col + ", swap_j " + swap_j,
+ swap.get(swap_j, col), doubles[swap_i][col], 0d);
+ }
+
+ testInvalidRowIndex(() -> m.swapRows(-1, 0), desc + " negative first swap index");
+ testInvalidRowIndex(() -> m.swapRows(0, -1), desc + " negative second swap index");
+ testInvalidRowIndex(() -> m.swapRows(m.rowSize(), 0), desc + " too large first swap index");
+ testInvalidRowIndex(() -> m.swapRows(0, m.rowSize()), desc + " too large second swap index");
+ });
+ }
+
+ /** */
+ @Test
+ public void testSwapColumns() {
+ consumeSampleMatrix((m, desc) -> {
+ if (readOnly(m))
+ return;
+
+ double[][] doubles = fillAndReturn(m);
+
+ final int swap_i = m.columnSize() == 1 ? 0 : 1;
+ final int swap_j = 0;
+
+ Matrix swap = m.swapColumns(swap_i, swap_j);
+
+ for (int row = 0; row < m.rowSize(); row++) {
+ assertEquals("Unexpected value for " + desc + " at row " + row + ", swap_i " + swap_i,
+ swap.get(row, swap_i), doubles[row][swap_j], 0d);
+
+ assertEquals("Unexpected value for " + desc + " at row " + row + ", swap_j " + swap_j,
+ swap.get(row, swap_j), doubles[row][swap_i], 0d);
+ }
+
+ testInvalidColIndex(() -> m.swapColumns(-1, 0), desc + " negative first swap index");
+ testInvalidColIndex(() -> m.swapColumns(0, -1), desc + " negative second swap index");
+ testInvalidColIndex(() -> m.swapColumns(m.columnSize(), 0), desc + " too large first swap index");
+ testInvalidColIndex(() -> m.swapColumns(0, m.columnSize()), desc + " too large second swap index");
+ });
+ }
+
+ /** */
+ @Test
+ public void testSetRow() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ int rowIdx = m.rowSize() / 2;
+
+ double[] newValues = fillArray(m.columnSize());
+
+ m.setRow(rowIdx, newValues);
+
+ for (int col = 0; col < m.columnSize(); col++)
+ assertEquals("Unexpected value for " + desc + " at " + col,
+ newValues[col], m.get(rowIdx, col), 0d);
+
+ testInvalidCardinality(() -> m.setRow(rowIdx, new double[m.columnSize() + 1]), desc);
+ });
+ }
+
+ /** */
+ @Test
+ public void testSetColumn() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ int colIdx = m.columnSize() / 2;
+
+ double[] newValues = fillArray(m.rowSize());
+
+ m.setColumn(colIdx, newValues);
+
+ for (int row = 0; row < m.rowSize(); row++)
+ assertEquals("Unexpected value for " + desc + " at " + row,
+ newValues[row], m.get(row, colIdx), 0d);
+
+ testInvalidCardinality(() -> m.setColumn(colIdx, new double[m.rowSize() + 1]), desc);
+ });
+ }
+
+ /** */
+ @Test
+ public void testViewPart() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ int rowOff = m.rowSize() < 3 ? 0 : 1;
+ int rows = m.rowSize() < 3 ? 1 : m.rowSize() - 2;
+ int colOff = m.columnSize() < 3 ? 0 : 1;
+ int cols = m.columnSize() < 3 ? 1 : m.columnSize() - 2;
+
+ Matrix view1 = m.viewPart(rowOff, rows, colOff, cols);
+ Matrix view2 = m.viewPart(new int[] {rowOff, colOff}, new int[] {rows, cols});
+
+ String details = desc + " view [" + rowOff + ", " + rows + ", " + colOff + ", " + cols + "]";
+
+ for (int i = 0; i < rows; i++)
+ for (int j = 0; j < cols; j++) {
+ assertEquals("Unexpected view1 value for " + details + " at (" + i + "," + j + ")",
+ m.get(i + rowOff, j + colOff), view1.get(i, j), 0d);
+
+ assertEquals("Unexpected view2 value for " + details + " at (" + i + "," + j + ")",
+ m.get(i + rowOff, j + colOff), view2.get(i, j), 0d);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testDensity() {
+ consumeSampleMatrix((m, desc) -> {
+ if (!readOnly(m))
+ fillMatrix(m);
+
+ assertTrue("Unexpected density with threshold 0 for " + desc, m.density(0.0));
+
+ assertFalse("Unexpected density with threshold 1 for " + desc, m.density(1.0));
+ });
+ }
+
+ /** */
+ @Test
+ public void testMaxAbsRowSumNorm() {
+ consumeSampleMatrix((m, desc) -> {
+ if (!readOnly(m))
+ fillMatrix(m);
+
+ assertEquals("Unexpected value for " + desc,
+ maxAbsRowSumNorm(m), m.maxAbsRowSumNorm(), 0d);
+ });
+ }
+
+ /** */
+ @Test
+ public void testAssignRow() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ int rowIdx = m.rowSize() / 2;
+
+ double[] newValues = fillArray(m.columnSize());
+
+ m.assignRow(rowIdx, new DenseLocalOnHeapVector(newValues));
+
+ for (int col = 0; col < m.columnSize(); col++)
+ assertEquals("Unexpected value for " + desc + " at " + col,
+ newValues[col], m.get(rowIdx, col), 0d);
+
+ testInvalidCardinality(() -> m.assignRow(rowIdx, new DenseLocalOnHeapVector(m.columnSize() + 1)), desc);
+ });
+ }
+
+ /** */
+ @Test
+ public void testAssignColumn() {
+ consumeSampleMatrix((m, desc) -> {
+ if (ignore(m.getClass()))
+ return;
+
+ fillMatrix(m);
+
+ int colIdx = m.columnSize() / 2;
+
+ double[] newValues = fillArray(m.rowSize());
+
+ m.assignColumn(colIdx, new DenseLocalOnHeapVector(newValues));
+
+ for (int row = 0; row < m.rowSize(); row++)
+ assertEquals("Unexpected value for " + desc + " at " + row,
+ newValues[row], m.get(row, colIdx), 0d);
+ });
+ }
+
+ /** */
+ private double[] fillArray(int len) {
+ double[] newValues = new double[len];
+
+ for (int i = 0; i < newValues.length; i++)
+ newValues[i] = newValues.length - i;
+ return newValues;
+ }
+
+ /** */
+ private double maxAbsRowSumNorm(Matrix m) {
+ double max = 0.0;
+
+ for (int x = 0; x < m.rowSize(); x++) {
+ double sum = 0;
+
+ for (int y = 0; y < m.columnSize(); y++)
+ sum += Math.abs(m.getX(x, y));
+
+ if (sum > max)
+ max = sum;
+ }
+
+ return max;
+ }
+
+ /** */
+ private void testInvalidRowIndex(Supplier<Matrix> supplier, String desc) {
+ try {
+ supplier.get();
+ }
+ catch (RowIndexException | IndexException ie) {
+ return;
+ }
+
+ fail("Expected exception was not caught for " + desc);
+ }
+
+ /** */
+ private void testInvalidColIndex(Supplier<Matrix> supplier, String desc) {
+ try {
+ supplier.get();
+ }
+ catch (ColumnIndexException | IndexException ie) {
+ return;
+ }
+
+ fail("Expected exception was not caught for " + desc);
+ }
+
+ /** */
+ private void testMapMatrixWrongCardinality(Matrix m, String desc) {
+ for (int rowDelta : new int[] {-1, 0, 1})
+ for (int colDelta : new int[] {-1, 0, 1}) {
+ if (rowDelta == 0 && colDelta == 0)
+ continue;
+
+ int rowNew = m.rowSize() + rowDelta;
+ int colNew = m.columnSize() + colDelta;
+
+ if (rowNew < 1 || colNew < 1)
+ continue;
+
+ testInvalidCardinality(() -> m.map(new DenseLocalOnHeapMatrix(rowNew, colNew), (m1, m2) -> m1 + m2),
+ desc + " wrong cardinality when mapping to size " + rowNew + "x" + colNew);
+ }
+ }
+
+ /** */
+ private void testInvalidCardinality(Supplier<Object> supplier, String desc) {
+ try {
+ supplier.get();
+ }
+ catch (CardinalityException ce) {
+ return;
+ }
+
+ fail("Expected exception was not caught for " + desc);
+ }
+
+ /** */
+ private boolean readOnly(Matrix m) {
+ return m instanceof RandomMatrix;
+ }
+
+ /** */
+ private double[][] fillIntAndReturn(Matrix m) {
+ double[][] data = new double[m.rowSize()][m.columnSize()];
+
+ if (readOnly(m)) {
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ data[i][j] = m.get(i, j);
+
+ }
+ else {
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ data[i][j] = i * m.rowSize() + j + 1;
+
+ m.assign(data);
+ }
+ return data;
+ }
+
+ /** */
+ private double[][] fillAndReturn(Matrix m) {
+ double[][] data = new double[m.rowSize()][m.columnSize()];
+
+ if (readOnly(m)) {
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ data[i][j] = m.get(i, j);
+
+ }
+ else {
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ data[i][j] = -0.5d + Math.random();
+
+ m.assign(data);
+ }
+ return data;
+ }
+
+ /** */
+ private void fillNonSingularMatrix(Matrix m) {
+ for (int i = 0; i < m.rowSize(); i++) {
+ m.set(i, i, 10);
+
+ for (int j = 0; j < m.columnSize(); j++)
+ if (j != i)
+ m.set(i, j, 0.01d);
+ }
+ }
+
+ /** */
+ private void fillMatrix(Matrix m) {
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ m.set(i, j, Math.random());
+ }
+
+ /** Ignore test for given matrix type. */
+ private boolean ignore(Class<? extends Matrix> clazz) {
+ List<Class<? extends Matrix>> ignoredClasses = Arrays.asList(RandomMatrix.class, PivotedMatrixView.class,
+ MatrixView.class, FunctionMatrix.class, TransposedMatrixView.class);
+
+ for (Class<? extends Matrix> ignoredClass : ignoredClasses)
+ if (ignoredClass.isAssignableFrom(clazz))
+ return true;
+
+ return false;
+ }
+
+ /** */
+ private Class<? extends Matrix> likeMatrixType(Matrix m) {
+ for (Class<? extends Matrix> clazz : likeTypesMap().keySet())
+ if (clazz.isAssignableFrom(m.getClass()))
+ return likeTypesMap().get(clazz);
+
+ return null;
+ }
+
+ /** */
+ private static Map<Class<? extends Matrix>, Class<? extends Vector>> likeVectorTypesMap() {
+ return new LinkedHashMap<Class<? extends Matrix>, Class<? extends Vector>>() {{
+ put(DenseLocalOnHeapMatrix.class, DenseLocalOnHeapVector.class);
+ put(DenseLocalOffHeapMatrix.class, DenseLocalOffHeapVector.class);
+ put(RandomMatrix.class, RandomVector.class);
+ put(SparseLocalOnHeapMatrix.class, SparseLocalVector.class);
+ put(DenseLocalOnHeapMatrix.class, DenseLocalOnHeapVector.class);
+ put(DiagonalMatrix.class, DenseLocalOnHeapVector.class); // IMPL NOTE per fixture
+ // IMPL NOTE check for presence of all implementations here will be done in testHaveLikeMatrix via Fixture
+ }};
+ }
+
+ /** */
+ private static Map<Class<? extends Matrix>, Class<? extends Matrix>> likeTypesMap() {
+ return new LinkedHashMap<Class<? extends Matrix>, Class<? extends Matrix>>() {{
+ put(DenseLocalOnHeapMatrix.class, DenseLocalOnHeapMatrix.class);
+ put(DenseLocalOffHeapMatrix.class, DenseLocalOffHeapMatrix.class);
+ put(RandomMatrix.class, RandomMatrix.class);
+ put(SparseLocalOnHeapMatrix.class, SparseLocalOnHeapMatrix.class);
+ put(DenseLocalOnHeapMatrix.class, DenseLocalOnHeapMatrix.class);
+ put(DiagonalMatrix.class, DenseLocalOnHeapMatrix.class); // IMPL NOTE per fixture
+ put(FunctionMatrix.class, FunctionMatrix.class);
+ // IMPL NOTE check for presence of all implementations here will be done in testHaveLikeMatrix via Fixture
+ }};
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixKeyMapperForTests.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixKeyMapperForTests.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixKeyMapperForTests.java
new file mode 100644
index 0000000..90fbec4
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixKeyMapperForTests.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.math.impls.matrix;
+
+import org.apache.ignite.math.MatrixKeyMapper;
+
+/** */
+public class MatrixKeyMapperForTests implements MatrixKeyMapper<Integer> {
+ /** */ private int rows;
+ /** */ private int cols;
+
+ /** */
+ public MatrixKeyMapperForTests() {
+ // No-op.
+ }
+
+ /** */
+ public MatrixKeyMapperForTests(int rows, int cols) {
+ this.rows = rows;
+ this.cols = cols;
+ }
+
+ /** */
+ @Override public Integer apply(int x, int y) {
+ return x * cols + y;
+ }
+
+ /** */
+ @Override public boolean isValid(Integer integer) {
+ return (rows * cols) > integer;
+ }
+
+ /** */
+ @Override public int hashCode() {
+ int hash = 1;
+
+ hash += hash * 31 + rows;
+ hash += hash * 31 + cols;
+
+ return hash;
+ }
+
+ /** */
+ @Override public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+
+ MatrixKeyMapperForTests that = (MatrixKeyMapperForTests)obj;
+
+ return rows == that.rows && cols == that.cols;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixViewConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixViewConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixViewConstructorTest.java
new file mode 100644
index 0000000..01278da
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/MatrixViewConstructorTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.matrix;
+
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.impls.storage.matrix.MatrixDelegateStorage;
+import org.junit.Test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+/** */
+public class MatrixViewConstructorTest {
+ /** */
+ @Test
+ public void invalidArgsTest() {
+ Matrix m = new DenseLocalOnHeapMatrix(1, 1);
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new MatrixView((Matrix)null, 0, 0, 1, 1),
+ "Null parent matrix.");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new MatrixView(m, -1, 0, 1, 1),
+ "Invalid row offset.");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new MatrixView(m, 0, -1, 1, 1),
+ "Invalid col offset.");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new MatrixView(m, 0, 0, 0, 1),
+ "Invalid rows.");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new MatrixView(m, 0, 0, 1, 0),
+ "Invalid cols.");
+ }
+
+ /** */
+ @Test
+ public void basicTest() {
+ for (Matrix m : new Matrix[] {
+ new DenseLocalOnHeapMatrix(3, 3),
+ new DenseLocalOnHeapMatrix(3, 4), new DenseLocalOnHeapMatrix(4, 3)})
+ for (int rowOff : new int[] {0, 1})
+ for (int colOff : new int[] {0, 1})
+ for (int rows : new int[] {1, 2})
+ for (int cols : new int[] {1, 2})
+ basicTest(m, rowOff, colOff, rows, cols);
+ }
+
+ /** */
+ private void basicTest(Matrix parent, int rowOff, int colOff, int rows, int cols) {
+ for (int row = 0; row < parent.rowSize(); row++)
+ for (int col = 0; col < parent.columnSize(); col++)
+ parent.set(row, col, row * parent.columnSize() + col + 1);
+
+ Matrix view = new MatrixView(parent, rowOff, colOff, rows, cols);
+
+ assertEquals("Rows in view.", rows, view.rowSize());
+ assertEquals("Cols in view.", cols, view.columnSize());
+
+ for (int row = 0; row < rows; row++)
+ for (int col = 0; col < cols; col++)
+ assertEquals("Unexpected value at " + row + "x" + col,
+ parent.get(row + rowOff, col + colOff), view.get(row, col), 0d);
+
+ for (int row = 0; row < rows; row++)
+ for (int col = 0; col < cols; col++)
+ view.set(row, col, 0d);
+
+ for (int row = 0; row < rows; row++)
+ for (int col = 0; col < cols; col++)
+ assertEquals("Unexpected value set at " + row + "x" + col,
+ 0d, parent.get(row + rowOff, col + colOff), 0d);
+ }
+
+ /** */
+ @Test
+ public void attributeTest() {
+ for (Matrix m : new Matrix[] {
+ new DenseLocalOnHeapMatrix(3, 3),
+ new DenseLocalOnHeapMatrix(3, 4), new DenseLocalOnHeapMatrix(4, 3)}) {
+ MatrixView matrixView = new MatrixView(m, 0, 0, m.rowSize(), m.columnSize());
+
+ MatrixDelegateStorage delegateStorage = (MatrixDelegateStorage)matrixView.getStorage();
+
+ assertEquals(m.rowSize(), matrixView.rowSize());
+ assertEquals(m.columnSize(), matrixView.columnSize());
+
+ assertEquals(m.rowSize(), (delegateStorage).rowsLength());
+ assertEquals(m.columnSize(), (delegateStorage).columnsLength());
+
+ assertEquals(m.isSequentialAccess(), delegateStorage.isSequentialAccess());
+ assertEquals(m.isRandomAccess(), delegateStorage.isRandomAccess());
+ assertEquals(m.isDistributed(), delegateStorage.isDistributed());
+ assertEquals(m.isDense(), delegateStorage.isDense());
+ assertEquals(m.isArrayBased(), delegateStorage.isArrayBased());
+
+ assertArrayEquals(m.getStorage().data(), delegateStorage.data());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/PivotedMatrixViewConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/PivotedMatrixViewConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/PivotedMatrixViewConstructorTest.java
new file mode 100644
index 0000000..a495745
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/PivotedMatrixViewConstructorTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.matrix;
+
+import java.util.Arrays;
+import org.apache.ignite.math.Matrix;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/** */
+public class PivotedMatrixViewConstructorTest {
+ /** */
+ @Test
+ public void invalidArgsTest() {
+ Matrix m = new DenseLocalOnHeapMatrix(1, 1);
+
+ int[] pivot = new int[] {0};
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new PivotedMatrixView(null),
+ "Null parent matrix.");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new PivotedMatrixView(null, pivot),
+ "Null parent matrix, with pivot.");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new PivotedMatrixView(m, null),
+ "Null pivot.");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new PivotedMatrixView(m, null, pivot),
+ "Null row pivot.");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new PivotedMatrixView(m, pivot, null),
+ "Null col pivot.");
+ }
+
+ /** */
+ @Test
+ public void basicTest() {
+ Matrix m = new DenseLocalOnHeapMatrix(2, 2);
+
+ int[] pivot = new int[] {0, 1};
+
+ PivotedMatrixView view = new PivotedMatrixView(m, pivot);
+
+ assertEquals("Rows in view.", m.rowSize(), view.rowSize());
+ assertEquals("Cols in view.", m.columnSize(), view.columnSize());
+
+ assertTrue("Row pivot array in view.", Arrays.equals(pivot, view.rowPivot()));
+ assertTrue("Col pivot array in view.", Arrays.equals(pivot, view.columnPivot()));
+
+ assertEquals("Base matrix in view.", m, view.getBaseMatrix());
+
+ assertEquals("Row pivot value in view.", 0, view.rowPivot(0));
+ assertEquals("Col pivot value in view.", 0, view.columnPivot(0));
+
+ assertEquals("Row unpivot value in view.", 0, view.rowUnpivot(0));
+ assertEquals("Col unpivot value in view.", 0, view.columnUnpivot(0));
+
+ Matrix swap = view.swap(1, 1);
+
+ for (int row = 0; row < view.rowSize(); row++)
+ for (int col = 0; col < view.columnSize(); col++)
+ assertEquals("Unexpected swap value set at (" + row + "," + col + ").",
+ view.get(row, col), swap.get(row, col), 0d);
+
+ //noinspection EqualsWithItself
+ assertTrue("View is expected to be equal to self.", view.equals(view));
+ //noinspection ObjectEqualsNull
+ assertFalse("View is expected to be not equal to null.", view.equals(null));
+ }
+
+ /** */
+ @Test
+ public void pivotTest() {
+ int[] pivot = new int[] {2, 1, 0, 3};
+
+ for (Matrix m : new Matrix[] {
+ new DenseLocalOnHeapMatrix(3, 3),
+ new DenseLocalOnHeapMatrix(3, 4), new DenseLocalOnHeapMatrix(4, 3)})
+ pivotTest(m, pivot);
+ }
+
+ /** */
+ private void pivotTest(Matrix parent, int[] pivot) {
+ for (int row = 0; row < parent.rowSize(); row++)
+ for (int col = 0; col < parent.columnSize(); col++)
+ parent.set(row, col, row * parent.columnSize() + col + 1);
+
+ Matrix view = new PivotedMatrixView(parent, pivot);
+
+ int rows = parent.rowSize();
+ int cols = parent.columnSize();
+
+ assertEquals("Rows in view.", rows, view.rowSize());
+ assertEquals("Cols in view.", cols, view.columnSize());
+
+ for (int row = 0; row < rows; row++)
+ for (int col = 0; col < cols; col++)
+ assertEquals("Unexpected value at " + row + "x" + col,
+ parent.get(pivot[row], pivot[col]), view.get(row, col), 0d);
+
+ int min = rows < cols ? rows : cols;
+
+ for (int idx = 0; idx < min; idx++)
+ view.set(idx, idx, 0d);
+
+ for (int idx = 0; idx < min; idx++)
+ assertEquals("Unexpected value set at " + idx,
+ 0d, parent.get(pivot[idx], pivot[idx]), 0d);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/RandomMatrixConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/RandomMatrixConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/RandomMatrixConstructorTest.java
new file mode 100644
index 0000000..e19cfa3
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/RandomMatrixConstructorTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.matrix;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/** */
+public class RandomMatrixConstructorTest {
+ /** */
+ @Test
+ public void invalidArgsTest() {
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new RandomMatrix(0, 1), "invalid row parameter");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new RandomMatrix(1, 0), "invalid col parameter");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new RandomMatrix(0, 1, true), "invalid row parameter, fastHash true");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new RandomMatrix(1, 0, true), "invalid col parameter, fastHash true");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new RandomMatrix(0, 1, false), "invalid row parameter, fastHash false");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new RandomMatrix(1, 0, false), "invalid col parameter, fastHash false");
+ }
+
+ /** */
+ @Test
+ public void basicTest() {
+ assertEquals("Expected number of rows, int parameters.", 1,
+ new RandomMatrix(1, 2).rowSize());
+
+ assertEquals("Expected number of cols, int parameters.", 1,
+ new RandomMatrix(2, 1).columnSize());
+
+ assertEquals("Expected number of rows, int parameters, fastHash true.", 1,
+ new RandomMatrix(1, 2, true).rowSize());
+
+ assertEquals("Expected number of cols, int parameters, fastHash true.", 1,
+ new RandomMatrix(2, 1, true).columnSize());
+
+ assertEquals("Expected number of rows, int parameters, fastHash false.", 1,
+ new RandomMatrix(1, 2, false).rowSize());
+
+ assertEquals("Expected number of cols, int parameters, fastHash false.", 1,
+ new RandomMatrix(2, 1, false).columnSize());
+
+ RandomMatrix m = new RandomMatrix(1, 1);
+ //noinspection EqualsWithItself
+ assertTrue("Matrix is expected to be equal to self.", m.equals(m));
+ //noinspection ObjectEqualsNull
+ assertFalse("Matrix is expected to be not equal to null.", m.equals(null));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/SparseDistributedMatrixTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/SparseDistributedMatrixTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/SparseDistributedMatrixTest.java
new file mode 100644
index 0000000..8218a12
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/SparseDistributedMatrixTest.java
@@ -0,0 +1,265 @@
+// @java.file.header
+
+/* _________ _____ __________________ _____
+ * __ ____/___________(_)______ /__ ____/______ ____(_)_______
+ * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \
+ * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / /
+ * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/
+ */
+
+/*
+ * 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.matrix;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.StorageConstants;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.math.impls.MathTestConstants;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+
+import static org.apache.ignite.math.impls.MathTestConstants.UNEXPECTED_VAL;
+
+/**
+ * Tests for {@link SparseDistributedMatrix}.
+ */
+@GridCommonTest(group = "Distributed Models")
+public class SparseDistributedMatrixTest extends GridCommonAbstractTest {
+ /** Number of nodes in grid */
+ private static final int NODE_COUNT = 3;
+ /** Cache name. */
+ private static final String CACHE_NAME = "test-cache";
+ /** Precision. */
+ private static final double PRECISION = 0.0;
+ /** Grid instance. */
+ private Ignite ignite;
+ /** Matrix rows */
+ private final int rows = MathTestConstants.STORAGE_SIZE;
+ /** Matrix cols */
+ private final int cols = MathTestConstants.STORAGE_SIZE;
+ /** Matrix for tests */
+ private SparseDistributedMatrix cacheMatrix;
+
+ /**
+ * Default constructor.
+ */
+ public SparseDistributedMatrixTest() {
+ super(false);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ for (int i = 1; i <= NODE_COUNT; i++)
+ startGrid(i);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override protected void beforeTest() throws Exception {
+ ignite = grid(NODE_COUNT);
+
+ ignite.configuration().setPeerClassLoadingEnabled(true);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ ignite.destroyCache(CACHE_NAME);
+
+ if (cacheMatrix != null) {
+ cacheMatrix.destroy();
+ cacheMatrix = null;
+ }
+ }
+
+ /** */
+ public void testGetSet() throws Exception {
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < cols; j++) {
+ double v = Math.random();
+ cacheMatrix.set(i, j, v);
+
+ assert Double.compare(v, cacheMatrix.get(i, j)) == 0;
+ }
+ }
+ }
+
+ /** */
+ public void testExternalize() throws IOException, ClassNotFoundException {
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
+
+ cacheMatrix.set(1, 1, 1.0);
+
+ ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream();
+ ObjectOutputStream objOutputStream = new ObjectOutputStream(byteArrOutputStream);
+
+ objOutputStream.writeObject(cacheMatrix);
+
+ ByteArrayInputStream byteArrInputStream = new ByteArrayInputStream(byteArrOutputStream.toByteArray());
+ ObjectInputStream objInputStream = new ObjectInputStream(byteArrInputStream);
+
+ SparseDistributedMatrix objRestored = (SparseDistributedMatrix)objInputStream.readObject();
+
+ assertTrue(MathTestConstants.VAL_NOT_EQUALS, cacheMatrix.equals(objRestored));
+ assertEquals(MathTestConstants.VAL_NOT_EQUALS, objRestored.get(1, 1), 1.0, 0.0);
+ }
+
+ /** Test simple math. */
+ public void testMath() {
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
+ initMtx(cacheMatrix);
+
+ cacheMatrix.assign(2.0);
+ for (int i = 0; i < cacheMatrix.rowSize(); i++)
+ for (int j = 0; j < cacheMatrix.columnSize(); j++)
+ assertEquals(UNEXPECTED_VAL, 2.0, cacheMatrix.get(i, j), PRECISION);
+
+ cacheMatrix.plus(3.0);
+ for (int i = 0; i < cacheMatrix.rowSize(); i++)
+ for (int j = 0; j < cacheMatrix.columnSize(); j++)
+ assertEquals(UNEXPECTED_VAL, 5.0, cacheMatrix.get(i, j), PRECISION);
+
+ cacheMatrix.times(2.0);
+ for (int i = 0; i < cacheMatrix.rowSize(); i++)
+ for (int j = 0; j < cacheMatrix.columnSize(); j++)
+ assertEquals(UNEXPECTED_VAL, 10.0, cacheMatrix.get(i, j), PRECISION);
+
+ cacheMatrix.divide(10.0);
+ for (int i = 0; i < cacheMatrix.rowSize(); i++)
+ for (int j = 0; j < cacheMatrix.columnSize(); j++)
+ assertEquals(UNEXPECTED_VAL, 1.0, cacheMatrix.get(i, j), PRECISION);
+
+ assertEquals(UNEXPECTED_VAL, cacheMatrix.rowSize() * cacheMatrix.columnSize(), cacheMatrix.sum(), PRECISION);
+ }
+
+ /** */
+ public void testMinMax() {
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
+
+ for (int i = 0; i < cacheMatrix.rowSize(); i++)
+ for (int j = 0; j < cacheMatrix.columnSize(); j++)
+ cacheMatrix.set(i, j, i * cols + j + 1);
+
+ assertEquals(UNEXPECTED_VAL, 1.0, cacheMatrix.minValue(), PRECISION);
+ assertEquals(UNEXPECTED_VAL, rows * cols, cacheMatrix.maxValue(), PRECISION);
+
+ for (int i = 0; i < cacheMatrix.rowSize(); i++)
+ for (int j = 0; j < cacheMatrix.columnSize(); j++)
+ cacheMatrix.set(i, j, -1.0 * (i * cols + j + 1));
+
+ assertEquals(UNEXPECTED_VAL, -rows * cols, cacheMatrix.minValue(), PRECISION);
+ assertEquals(UNEXPECTED_VAL, -1.0, cacheMatrix.maxValue(), PRECISION);
+
+ for (int i = 0; i < cacheMatrix.rowSize(); i++)
+ for (int j = 0; j < cacheMatrix.columnSize(); j++)
+ cacheMatrix.set(i, j, i * cols + j);
+
+ assertEquals(UNEXPECTED_VAL, 1.0, cacheMatrix.minValue(), PRECISION);
+ assertEquals(UNEXPECTED_VAL, rows * cols - 1.0, cacheMatrix.maxValue(), PRECISION);
+ }
+
+ /** */
+ public void testMap() {
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
+ initMtx(cacheMatrix);
+
+ cacheMatrix.map(i -> 100.0);
+ for (int i = 0; i < cacheMatrix.rowSize(); i++)
+ for (int j = 0; j < cacheMatrix.columnSize(); j++)
+ assertEquals(UNEXPECTED_VAL, 100.0, cacheMatrix.get(i, j), PRECISION);
+ }
+
+ /** */
+ public void testCopy() {
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
+
+ try {
+ cacheMatrix.copy();
+ fail("UnsupportedOperationException expected.");
+ }
+ catch (UnsupportedOperationException e) {
+ return;
+ }
+ fail("UnsupportedOperationException expected.");
+ }
+
+ /** */
+ public void testLike() {
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
+
+ try {
+ cacheMatrix.like(1, 1);
+ fail("UnsupportedOperationException expected.");
+ }
+ catch (UnsupportedOperationException e) {
+ return;
+ }
+ fail("UnsupportedOperationException expected.");
+ }
+
+ /** */
+ public void testLikeVector() {
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
+
+ try {
+ cacheMatrix.likeVector(1);
+ fail("UnsupportedOperationException expected.");
+ }
+ catch (UnsupportedOperationException e) {
+ return;
+ }
+ fail("UnsupportedOperationException expected.");
+ }
+
+ /** */
+ private void initMtx(Matrix m) {
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ m.set(i, j, 1.0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/SparseLocalOnHeapMatrixConstructorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/SparseLocalOnHeapMatrixConstructorTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/SparseLocalOnHeapMatrixConstructorTest.java
new file mode 100644
index 0000000..fc675c1
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/SparseLocalOnHeapMatrixConstructorTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.matrix;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/** */
+public class SparseLocalOnHeapMatrixConstructorTest {
+ /** */
+ @Test
+ public void invalidArgsTest() {
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new SparseLocalOnHeapMatrix(0, 1),
+ "invalid row parameter");
+
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new SparseLocalOnHeapMatrix(1, 0),
+ "invalid col parameter");
+ }
+
+ /** */
+ @Test
+ public void basicTest() {
+ assertEquals("Expected number of rows.", 1,
+ new SparseLocalOnHeapMatrix(1, 2).rowSize());
+
+ assertEquals("Expected number of cols, int parameters.", 1,
+ new SparseLocalOnHeapMatrix(2, 1).columnSize());
+
+ SparseLocalOnHeapMatrix m = new SparseLocalOnHeapMatrix(1, 1);
+ //noinspection EqualsWithItself
+ assertTrue("Matrix is expected to be equal to self.", m.equals(m));
+ //noinspection ObjectEqualsNull
+ assertFalse("Matrix is expected to be not equal to null.", m.equals(null));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/TransposedMatrixViewTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/TransposedMatrixViewTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/TransposedMatrixViewTest.java
new file mode 100644
index 0000000..5eacfea
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/matrix/TransposedMatrixViewTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.matrix;
+
+import org.apache.ignite.math.ExternalizeTest;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.math.impls.MathTestConstants;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for {@link TransposedMatrixView}.
+ */
+public class TransposedMatrixViewTest extends ExternalizeTest<TransposedMatrixView> {
+ /** */
+ private static final String UNEXPECTED_VALUE = "Unexpected value";
+ /** */
+ private TransposedMatrixView testMatrix;
+ /** */
+ private DenseLocalOnHeapMatrix parent;
+
+ /** */
+ @Before
+ public void setup() {
+ parent = new DenseLocalOnHeapMatrix(MathTestConstants.STORAGE_SIZE, MathTestConstants.STORAGE_SIZE);
+ fillMatrix(parent);
+ testMatrix = new TransposedMatrixView(parent);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void externalizeTest() {
+ externalizeTest(testMatrix);
+ }
+
+ /** */
+ @Test
+ public void testView() {
+ assertEquals(UNEXPECTED_VALUE, parent.rowSize(), testMatrix.columnSize());
+ assertEquals(UNEXPECTED_VALUE, parent.columnSize(), testMatrix.rowSize());
+
+ for (int i = 0; i < parent.rowSize(); i++)
+ for (int j = 0; j < parent.columnSize(); j++)
+ assertEquals(UNEXPECTED_VALUE, parent.get(i, j), testMatrix.get(j, i), 0d);
+ }
+
+ /** */
+ @Test
+ public void testNullParams() {
+ DenseLocalOnHeapMatrixConstructorTest.verifyAssertionError(() -> new TransposedMatrixView(null), "Null Matrix parameter");
+ }
+
+ /** */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testLike() {
+ testMatrix.like(0, 0);
+ }
+
+ /** */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testLikeVector() {
+ testMatrix.likeVector(0);
+ }
+
+ /** */
+ private void fillMatrix(DenseLocalOnHeapMatrix mtx) {
+ for (int i = 0; i < mtx.rowSize(); i++)
+ for (int j = 0; j < mtx.columnSize(); j++)
+ mtx.setX(i, j, i * mtx.rowSize() + j);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/test/java/org/apache/ignite/math/impls/storage/matrix/MatrixArrayStorageTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/storage/matrix/MatrixArrayStorageTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/storage/matrix/MatrixArrayStorageTest.java
new file mode 100644
index 0000000..817dd49
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/math/impls/storage/matrix/MatrixArrayStorageTest.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.math.impls.storage.matrix;
+
+import org.apache.ignite.math.impls.MathTestConstants;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit tests for {@link ArrayMatrixStorage}.
+ */
+public class MatrixArrayStorageTest extends MatrixBaseStorageTest<ArrayMatrixStorage> {
+ /** {@inheritDoc} */
+ @Override public void setUp() {
+ storage = new ArrayMatrixStorage(MathTestConstants.STORAGE_SIZE, MathTestConstants.STORAGE_SIZE);
+ }
+
+ /** */
+ @Test
+ public void isSequentialAccess() throws Exception {
+ assertFalse(MathTestConstants.UNEXPECTED_VAL, storage.isSequentialAccess());
+ }
+
+ /** */
+ @Test
+ public void isDense() throws Exception {
+ assertTrue(MathTestConstants.UNEXPECTED_VAL, storage.isDense());
+ }
+
+ /** */
+ @Test
+ public void isArrayBased() throws Exception {
+ assertTrue(MathTestConstants.UNEXPECTED_VAL, storage.isArrayBased());
+ }
+
+ /** */
+ @Test
+ public void data() throws Exception {
+ double[][] data = storage.data();
+ assertNotNull(MathTestConstants.NULL_VAL, data);
+ assertTrue(MathTestConstants.UNEXPECTED_VAL, data.length == MathTestConstants.STORAGE_SIZE);
+ assertTrue(MathTestConstants.UNEXPECTED_VAL, data[0].length == MathTestConstants.STORAGE_SIZE);
+ }
+
+}