http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/PivotedMatrixView.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/PivotedMatrixView.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/PivotedMatrixView.java
new file mode 100644
index 0000000..b9a3b17
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/PivotedMatrixView.java
@@ -0,0 +1,243 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.IndexException;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.impls.storage.matrix.PivotedMatrixStorage;
+import org.apache.ignite.ml.math.impls.vector.PivotedVectorView;
+
+/**
+ * Pivoted (index mapped) view over another matrix implementation.
+ */
+public class PivotedMatrixView extends AbstractMatrix {
+    /** Pivoted matrix. */
+    private Matrix mtx;
+
+    /**
+     *
+     */
+    public PivotedMatrixView() {
+        // No-op.
+    }
+
+    /**
+     * @param mtx
+     * @param rowPivot
+     * @param colPivot
+     */
+    public PivotedMatrixView(Matrix mtx, int[] rowPivot, int[] colPivot) {
+        super(new PivotedMatrixStorage(mtx == null ? null : mtx.getStorage(), 
rowPivot, colPivot));
+
+        this.mtx = mtx;
+    }
+
+    /**
+     * @param mtx
+     */
+    public PivotedMatrixView(Matrix mtx) {
+        super(new PivotedMatrixStorage(mtx == null ? null : mtx.getStorage()));
+
+        this.mtx = mtx;
+    }
+
+    /**
+     * @param mtx
+     * @param pivot
+     */
+    public PivotedMatrixView(Matrix mtx, int[] pivot) {
+        super(new PivotedMatrixStorage(mtx == null ? null : mtx.getStorage(), 
pivot));
+
+        this.mtx = mtx;
+    }
+
+    /**
+     * Swaps indexes {@code i} and {@code j} for both both row and column.
+     *
+     * @param i First index to swap.
+     * @param j Second index to swap.
+     */
+    public Matrix swap(int i, int j) {
+        swapRows(i, j);
+        swapColumns(i, j);
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix swapRows(int i, int j) {
+        if (i < 0 || i >= storage().rowPivot().length)
+            throw new IndexException(i);
+        if (j < 0 || j >= storage().rowPivot().length)
+            throw new IndexException(j);
+
+        storage().swapRows(i, j);
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix swapColumns(int i, int j) {
+        if (i < 0 || i >= storage().columnPivot().length)
+            throw new IndexException(i);
+        if (j < 0 || j >= storage().columnPivot().length)
+            throw new IndexException(j);
+
+        storage().swapColumns(i, j);
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector viewRow(int row) {
+        return new PivotedVectorView(
+            mtx.viewRow(storage().rowPivot()[row]),
+            storage().columnPivot(),
+            storage().columnUnpivot()
+        );
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector viewColumn(int col) {
+        return new PivotedVectorView(
+            mtx.viewColumn(storage().columnPivot()[col]),
+            storage().rowPivot(),
+            storage().rowUnpivot()
+        );
+    }
+
+    /**
+     *
+     *
+     */
+    public Matrix getBaseMatrix() {
+        return mtx;
+    }
+
+    /**
+     *
+     *
+     */
+    public int[] rowPivot() {
+        return storage().rowPivot();
+    }
+
+    /**
+     *
+     *
+     */
+    public int[] columnPivot() {
+        return storage().columnPivot();
+    }
+
+    /**
+     * @param i
+     */
+    public int rowPivot(int i) {
+        return storage().rowPivot()[i];
+    }
+
+    /**
+     * @param i
+     */
+    public int columnPivot(int i) {
+        return storage().columnPivot()[i];
+    }
+
+    /**
+     * @param i
+     */
+    public int rowUnpivot(int i) {
+        return storage().rowUnpivot()[i];
+    }
+
+    /**
+     * @param i
+     */
+    public int columnUnpivot(int i) {
+        return storage().columnUnpivot()[i];
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        super.writeExternal(out);
+
+        out.writeObject(mtx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        super.readExternal(in);
+
+        mtx = (Matrix)in.readObject();
+    }
+
+    /**
+     *
+     *
+     */
+    private PivotedMatrixStorage storage() {
+        return (PivotedMatrixStorage)getStorage();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix copy() {
+        return new PivotedMatrixView(mtx, storage().rowPivot(), 
storage().columnPivot());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix like(int rows, int cols) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector likeVector(int crd) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + mtx.hashCode();
+        res = res * 37 + getStorage().hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        PivotedMatrixView that = (PivotedMatrixView)o;
+
+        MatrixStorage sto = storage();
+
+        return mtx.equals(that.mtx) && sto.equals(that.storage());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/RandomMatrix.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/RandomMatrix.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/RandomMatrix.java
new file mode 100644
index 0000000..ece4ca9
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/RandomMatrix.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.impls.storage.matrix.RandomMatrixStorage;
+import org.apache.ignite.ml.math.impls.vector.RandomVector;
+
+/**
+ * Implementation of {@link Matrix} with random values in the elements.
+ */
+public class RandomMatrix extends AbstractMatrix {
+    /** Whether fast hash is used, see {@link RandomMatrixStorage}. */
+    private boolean fastHash;
+
+    /**
+     * @param rows Amount of rows in the matrix.
+     * @param cols Amount of columns in the matrix.
+     * @param fastHash Whether fast hash is used.
+     */
+    private MatrixStorage mkStorage(int rows, int cols, boolean fastHash) {
+        this.fastHash = fastHash;
+
+        return new RandomMatrixStorage(rows, cols, fastHash);
+    }
+
+    /**
+     * @param rows Amount of rows in the matrix.
+     * @param cols Amount of columns in the matrix.
+     * @param fastHash Whether fast hash is used.
+     */
+    public RandomMatrix(int rows, int cols, boolean fastHash) {
+        setStorage(mkStorage(rows, cols, fastHash));
+    }
+
+    /**
+     * @param rows Amount of rows in the matrix.
+     * @param cols Amount of columns in the matrix.
+     */
+    public RandomMatrix(int rows, int cols) {
+        this(rows, cols, true);
+    }
+
+    /** */
+    public RandomMatrix() {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix copy() {
+        return new RandomMatrix(rowSize(), columnSize(), fastHash);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix like(int rows, int cols) {
+        return new RandomMatrix(rows, cols);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector likeVector(int crd) {
+        return new RandomVector(crd);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        super.writeExternal(out);
+
+        out.writeBoolean(fastHash);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        super.readExternal(in);
+
+        fastHash = in.readBoolean();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java
new file mode 100644
index 0000000..8a7cffe
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java
@@ -0,0 +1,155 @@
+// @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.ml.math.impls.matrix;
+
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteFunction;
+import org.apache.ignite.ml.math.impls.CacheUtils;
+import 
org.apache.ignite.ml.math.impls.storage.matrix.SparseDistributedMatrixStorage;
+
+/**
+ * Sparse distributed matrix implementation based on data grid.
+ *
+ * Unlike {@link CacheMatrix} that is based on existing cache, this 
implementation creates distributed
+ * cache internally and doesn't rely on pre-existing cache.
+ *
+ * You also need to call {@link #destroy()} to remove the underlying cache 
when you no longer need this
+ * matrix.
+ *
+ * <b>Currently fold supports only commutative operations.<b/>
+ */
+public class SparseDistributedMatrix extends AbstractMatrix implements 
StorageConstants {
+    /**
+     *
+     */
+    public SparseDistributedMatrix() {
+        // No-op.
+    }
+
+    /**
+     * @param rows
+     * @param cols
+     * @param stoMode
+     * @param acsMode
+     */
+    public SparseDistributedMatrix(int rows, int cols, int stoMode, int 
acsMode) {
+        assert rows > 0;
+        assert cols > 0;
+        assertAccessMode(acsMode);
+        assertStorageMode(stoMode);
+
+        setStorage(new SparseDistributedMatrixStorage(rows, cols, stoMode, 
acsMode));
+    }
+
+    /**
+     *
+     *
+     */
+    private SparseDistributedMatrixStorage storage() {
+        return (SparseDistributedMatrixStorage)getStorage();
+    }
+
+    /**
+     * Return the same matrix with updates values (broken contract).
+     *
+     * @param d
+     */
+    @Override public Matrix divide(double d) {
+        return mapOverValues((Double v) -> v / d);
+    }
+
+    /**
+     * Return the same matrix with updates values (broken contract).
+     *
+     * @param x
+     */
+    @Override public Matrix plus(double x) {
+        return mapOverValues((Double v) -> v + x);
+    }
+
+    /**
+     * Return the same matrix with updates values (broken contract).
+     *
+     * @param x
+     */
+    @Override public Matrix times(double x) {
+        return mapOverValues((Double v) -> v * x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix assign(double val) {
+        return mapOverValues((Double v) -> val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix map(IgniteDoubleFunction<Double> fun) {
+        return mapOverValues(fun::apply);
+    }
+
+    /**
+     * @param mapper
+     */
+    private Matrix mapOverValues(IgniteFunction<Double, Double> mapper) {
+        CacheUtils.sparseMap(storage().cache().getName(), mapper);
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double sum() {
+        return CacheUtils.sparseSum(storage().cache().getName());
+    }
+
+    /** {@inheritDoc} */
+    @Override public double maxValue() {
+        return CacheUtils.sparseMax(storage().cache().getName());
+    }
+
+    /** {@inheritDoc} */
+    @Override public double minValue() {
+        return CacheUtils.sparseMin(storage().cache().getName());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix copy() {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix like(int rows, int cols) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector likeVector(int crd) {
+        throw new UnsupportedOperationException();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseLocalOnHeapMatrix.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseLocalOnHeapMatrix.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseLocalOnHeapMatrix.java
new file mode 100644
index 0000000..d711295
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseLocalOnHeapMatrix.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.matrix;
+
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.Vector;
+import 
org.apache.ignite.ml.math.impls.storage.matrix.SparseLocalOnHeapMatrixStorage;
+import org.apache.ignite.ml.math.impls.vector.SparseLocalVector;
+
+/**
+ * Sparse local onheap matrix with {@link SparseLocalVector} as rows.
+ */
+public class SparseLocalOnHeapMatrix extends AbstractMatrix implements 
StorageConstants {
+    /**
+     *
+     */
+    public SparseLocalOnHeapMatrix() {
+        // No-op.
+    }
+
+    /**
+     * Construct new {@link SparseLocalOnHeapMatrix}.
+     *
+     * By default storage sets in row optimized mode and in random access mode.
+     */
+    public SparseLocalOnHeapMatrix(int rows, int cols) {
+        setStorage(mkStorage(rows, cols));
+    }
+
+    /**
+     * Create new {@link SparseLocalOnHeapMatrixStorage}.
+     */
+    private MatrixStorage mkStorage(int rows, int cols) {
+        return new SparseLocalOnHeapMatrixStorage(rows, cols, 
StorageConstants.RANDOM_ACCESS_MODE, StorageConstants.ROW_STORAGE_MODE);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix like(int rows, int cols) {
+        return new SparseLocalOnHeapMatrix(rows, cols);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector likeVector(int crd) {
+        return new SparseLocalVector(crd, StorageConstants.RANDOM_ACCESS_MODE);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix copy() {
+        Matrix cp = like(rowSize(), columnSize());
+
+        cp.assign(this);
+
+        return cp;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/TransposedMatrixView.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/TransposedMatrixView.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/TransposedMatrixView.java
new file mode 100644
index 0000000..309570b
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/TransposedMatrixView.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.matrix;
+
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.impls.storage.matrix.MatrixDelegateStorage;
+
+/**
+ * Implements transposed view of the parent {@link Matrix}.
+ */
+public class TransposedMatrixView extends AbstractMatrix {
+    /** */
+    public TransposedMatrixView() {
+        //No-op.
+    }
+
+    /**
+     * @param mtx Parent matrix.
+     */
+    public TransposedMatrixView(Matrix mtx) {
+        this(mtx == null ? null : mtx.getStorage());
+    }
+
+    /** */
+    private TransposedMatrixView(MatrixStorage sto) {
+        super(new MatrixDelegateStorage(sto, 0, 0,
+            sto == null ? 0 : sto.rowSize(), sto == null ? 0 : 
sto.columnSize()));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void storageSet(int row, int col, double v) {
+        super.storageSet(col, row, v);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected double storageGet(int row, int col) {
+        return super.storageGet(col, row);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return getStorage().columnSize();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return getStorage().rowSize();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix copy() {
+        MatrixDelegateStorage sto = (MatrixDelegateStorage)getStorage();
+
+        return new TransposedMatrixView(sto.delegate());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix like(int rows, int cols) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector likeVector(int crd) {
+        throw new UnsupportedOperationException();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/package-info.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/package-info.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/package-info.java
new file mode 100644
index 0000000..9eabf80
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains several matrix implementations.
+ */
+package org.apache.ignite.ml.math.impls.matrix;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/package-info.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/package-info.java 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/package-info.java
new file mode 100644
index 0000000..d531014
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains specific implementations for core algebra.
+ */
+package org.apache.ignite.ml.math.impls;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/ArrayMatrixStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/ArrayMatrixStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/ArrayMatrixStorage.java
new file mode 100644
index 0000000..397bf93
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/ArrayMatrixStorage.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Arrays;
+import org.apache.ignite.ml.math.MatrixStorage;
+
+/**
+ * Array based {@link MatrixStorage} implementation.
+ */
+public class ArrayMatrixStorage implements MatrixStorage {
+    /** Backing data array. */
+    private double[][] data;
+    /** Amount of rows in the matrix. */
+    private int rows;
+    /** Amount of columns in the matrix. */
+    private int cols;
+
+    /**
+     *
+     */
+    public ArrayMatrixStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param rows Amount of rows in the matrix.
+     * @param cols Amount of columns in the matrix.
+     */
+    public ArrayMatrixStorage(int rows, int cols) {
+        assert rows > 0;
+        assert cols > 0;
+
+        this.data = new double[rows][cols];
+        this.rows = rows;
+        this.cols = cols;
+    }
+
+    /**
+     * @param data Backing data array.
+     */
+    public ArrayMatrixStorage(double[][] data) {
+        assert data != null;
+        assert data[0] != null;
+
+        this.data = data;
+        this.rows = data.length;
+        this.cols = data[0].length;
+
+        assert rows > 0;
+        assert cols > 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        return data[x][y];
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        data[x][y] = v;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return rows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double[][] data() {
+        return data;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeInt(rows);
+        out.writeInt(cols);
+
+        out.writeObject(data);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        rows = in.readInt();
+        cols = in.readInt();
+
+        data = (double[][])in.readObject();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res += res * 37 + rows;
+        res += res * 37 + cols;
+        res += res * 37 + Arrays.deepHashCode(data);
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        ArrayMatrixStorage that = (ArrayMatrixStorage)o;
+
+        return Arrays.deepEquals(data, that.data);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/CacheMatrixStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/CacheMatrixStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/CacheMatrixStorage.java
new file mode 100644
index 0000000..510c4cf
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/CacheMatrixStorage.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.ml.math.MatrixKeyMapper;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.ValueMapper;
+
+/**
+ * Matrix storage based on arbitrary cache and key and value mapping functions.
+ */
+public class CacheMatrixStorage<K, V> implements MatrixStorage {
+    /** */ private int rows;
+    /** */  private int cols;
+    /** */ private IgniteCache<K, V> cache;
+    /** */ private MatrixKeyMapper<K> keyMapper;
+    /** */ private ValueMapper<V> valMapper;
+
+    /**
+     *
+     */
+    public CacheMatrixStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param rows
+     * @param cols
+     * @param cache
+     * @param keyMapper
+     * @param valMapper
+     */
+    public CacheMatrixStorage(int rows, int cols, IgniteCache<K, V> cache, 
MatrixKeyMapper<K> keyMapper,
+        ValueMapper<V> valMapper) {
+        assert rows > 0;
+        assert cols > 0;
+        assert cache != null;
+        assert keyMapper != null;
+        assert valMapper != null;
+
+        this.rows = rows;
+        this.cols = cols;
+        this.cache = cache;
+        this.keyMapper = keyMapper;
+        this.valMapper = valMapper;
+    }
+
+    /**
+     * @return Ignite cache.
+     */
+    public IgniteCache<K, V> cache() {
+        return cache;
+    }
+
+    /**
+     * @return Key mapper.
+     */
+    public MatrixKeyMapper<K> keyMapper() {
+        return keyMapper;
+    }
+
+    /**
+     * @return Value mapper.
+     */
+    public ValueMapper<V> valueMapper() {
+        return valMapper;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        return valMapper.toDouble(cache.get(keyMapper.apply(x, y)));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        cache.put(keyMapper.apply(x, y), valMapper.fromDouble(v));
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return rows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeInt(rows);
+        out.writeInt(cols);
+        out.writeUTF(cache.getName());
+        out.writeObject(keyMapper);
+        out.writeObject(valMapper);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"unchecked"})
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        rows = in.readInt();
+        cols = in.readInt();
+        cache = Ignition.localIgnite().getOrCreateCache(in.readUTF());
+        keyMapper = (MatrixKeyMapper<K>)in.readObject();
+        valMapper = (ValueMapper<V>)in.readObject();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + rows;
+        res = res * 37 + cols;
+        res = res * 37 + cache.hashCode();
+        res = res * 37 + keyMapper.hashCode();
+        res = res * 37 + valMapper.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        CacheMatrixStorage that = (CacheMatrixStorage)o;
+
+        return (cache != null ? cache.equals(that.cache) : that.cache == null) 
&&
+            (keyMapper != null ? keyMapper.equals(that.keyMapper) : 
that.keyMapper == null) &&
+            (valMapper != null ? valMapper.equals(that.valMapper) : 
that.valMapper == null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java
new file mode 100644
index 0000000..74952a9
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.ml.math.MatrixStorage;
+
+/**
+ * Local, dense off-heap matrix storage.
+ */
+public class DenseOffHeapMatrixStorage implements MatrixStorage {
+    /** */ private int rows;
+    /** */ private int cols;
+    /** */ private transient long ptr;
+    //TODO: temp solution.
+    /** */ private int ptrInitHash;
+
+    /** */
+    public DenseOffHeapMatrixStorage() {
+        // No-op.
+    }
+
+    /** */
+    public DenseOffHeapMatrixStorage(int rows, int cols) {
+        assert rows > 0;
+        assert cols > 0;
+
+        this.rows = rows;
+        this.cols = cols;
+
+        allocateMemory(rows, cols);
+    }
+
+    /** */
+    public DenseOffHeapMatrixStorage(double[][] data) {
+        assert data != null;
+        assert data[0] != null;
+
+        this.rows = data.length;
+        this.cols = data[0].length;
+
+        assert rows > 0;
+        assert cols > 0;
+
+        allocateMemory(rows, cols);
+
+        for (int i = 0; i < rows; i++)
+            for (int j = 0; j < cols; j++)
+                set(i, j, data[i][j]);
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        return GridUnsafe.getDouble(pointerOffset(x, y));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        GridUnsafe.putDouble(pointerOffset(x, y), v);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return rows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double[][] data() {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeInt(rows);
+        out.writeInt(cols);
+        out.writeInt(ptrInitHash);
+
+        for (int i = 0; i < rows; i++)
+            for (int j = 0; j < cols; j++)
+                out.writeDouble(get(i, j));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        rows = in.readInt();
+        cols = in.readInt();
+
+        allocateMemory(rows, cols);
+
+        ptrInitHash = in.readInt();
+
+        for (int i = 0; i < rows; i++)
+            for (int j = 0; j < cols; j++)
+                set(i, j, in.readDouble());
+    }
+
+    /** {@inheritDoc} */
+    @Override public void destroy() {
+        GridUnsafe.freeMemory(ptr);
+    }
+
+    /** {@inheritDoc} */
+    private long pointerOffset(int x, int y) {
+        return ptr + x * cols * Double.BYTES + y * Double.BYTES;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        return obj != null &&
+            getClass().equals(obj.getClass()) &&
+            (rows == ((DenseOffHeapMatrixStorage)obj).rows) &&
+            (cols == ((DenseOffHeapMatrixStorage)obj).cols) &&
+            (rows == 0 || cols == 0 || ptr == 
((DenseOffHeapMatrixStorage)obj).ptr || 
isMemoryEquals((DenseOffHeapMatrixStorage)obj));
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + rows;
+        res = res * 37 + cols;
+        res = res * 37 + ptrInitHash;
+
+        return res;
+    }
+
+    /** */
+    private boolean isMemoryEquals(DenseOffHeapMatrixStorage otherStorage) {
+        boolean res = true;
+
+        for (int i = 0; i < otherStorage.rows; i++) {
+            for (int j = 0; j < otherStorage.cols; j++) {
+                if (Double.compare(get(i, j), otherStorage.get(i, j)) != 0) {
+                    res = false;
+                    break;
+                }
+            }
+        }
+
+        return res;
+    }
+
+    /** */
+    private void allocateMemory(int rows, int cols) {
+        ptr = GridUnsafe.allocateMemory(rows * cols * Double.BYTES);
+
+        ptrInitHash = Long.hashCode(ptr);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DiagonalMatrixStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DiagonalMatrixStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DiagonalMatrixStorage.java
new file mode 100644
index 0000000..9daacee
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DiagonalMatrixStorage.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+
+/**
+ * {@link MatrixStorage} implementation for diagonal Matrix view.
+ */
+public class DiagonalMatrixStorage implements MatrixStorage {
+    /** Backing vector for matrix diagonal. */
+    private Vector diagonal;
+
+    /**
+     *
+     */
+    public DiagonalMatrixStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param diagonal Backing {@link Vector} for matrix diagonal.
+     */
+    public DiagonalMatrixStorage(Vector diagonal) {
+        assert diagonal != null;
+
+        this.diagonal = diagonal;
+    }
+
+    /**
+     *
+     */
+    public Vector diagonal() {
+        return diagonal;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        return x == y ? diagonal.get(x) : 0.0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        if (x == y)
+            diagonal.set(x, v);
+        else
+            throw new UnsupportedOperationException("Can't set off-diagonal 
element.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return diagonal.size();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return diagonal.size();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(diagonal);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        diagonal = (Vector)in.readObject();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return diagonal.isSequentialAccess();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return diagonal.isDense();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return diagonal.isRandomAccess();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return diagonal.isDistributed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + diagonal.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        DiagonalMatrixStorage that = (DiagonalMatrixStorage)o;
+
+        return diagonal.equals(that.diagonal);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/FunctionMatrixStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/FunctionMatrixStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/FunctionMatrixStorage.java
new file mode 100644
index 0000000..acd7c29
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/FunctionMatrixStorage.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.functions.IntIntDoubleToVoidFunction;
+import org.apache.ignite.ml.math.functions.IntIntToDoubleFunction;
+
+/**
+ * Read-only or read-write function-based matrix storage.
+ */
+public class FunctionMatrixStorage implements MatrixStorage {
+    /** */ private int rows;
+    /** */ private int cols;
+
+    /** */ private IntIntToDoubleFunction getFunc;
+    /** */ private IntIntDoubleToVoidFunction setFunc;
+
+    /**
+     *
+     */
+    public FunctionMatrixStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param rows Amount of rows in the matrix.
+     * @param cols Amount of columns in the matrix.
+     * @param getFunc Function that returns value corresponding to given row 
and column index.
+     * @param setFunc Set function. If {@code null} - this will be a read-only 
matrix.
+     */
+    public FunctionMatrixStorage(int rows, int cols, IntIntToDoubleFunction 
getFunc,
+        IntIntDoubleToVoidFunction setFunc) {
+        assert rows > 0;
+        assert cols > 0;
+        assert getFunc != null;
+
+        this.rows = rows;
+        this.cols = cols;
+        this.getFunc = getFunc;
+        this.setFunc = setFunc;
+    }
+
+    /**
+     * @param rows Amount of rows in the matrix.
+     * @param cols Amount of columns in the matrix.
+     * @param getFunc Function that returns value corresponding to given row 
and column index.
+     */
+    public FunctionMatrixStorage(int rows, int cols, IntIntToDoubleFunction 
getFunc) {
+        this(rows, cols, getFunc, null);
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        return getFunc.apply(x, y);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        if (setFunc != null)
+            setFunc.apply(x, y, v);
+        else
+            throw new UnsupportedOperationException("Cannot set into read-only 
matrix.");
+    }
+
+    /**
+     *
+     */
+    public IntIntToDoubleFunction getFunction() {
+        return getFunc;
+    }
+
+    /**
+     *
+     */
+    public IntIntDoubleToVoidFunction setFunction() {
+        return setFunc;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return rows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(setFunc);
+        out.writeObject(getFunc);
+        out.writeInt(rows);
+        out.writeInt(cols);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        setFunc = (IntIntDoubleToVoidFunction)in.readObject();
+        getFunc = (IntIntToDoubleFunction)in.readObject();
+        rows = in.readInt();
+        cols = in.readInt();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        FunctionMatrixStorage that = (FunctionMatrixStorage)o;
+
+        return rows == that.rows && cols == that.cols
+            && (getFunc != null ? getFunc.equals(that.getFunc) : that.getFunc 
== null)
+            && (setFunc != null ? setFunc.equals(that.setFunc) : that.setFunc 
== null);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = rows;
+
+        res = 31 * res + cols;
+        res = 31 * res + (getFunc != null ? getFunc.hashCode() : 0);
+        res = 31 * res + (setFunc != null ? setFunc.hashCode() : 0);
+
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java
new file mode 100644
index 0000000..1f77d0f
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.ml.math.MatrixStorage;
+
+/**
+ * {@link MatrixStorage} implementation that delegates to parent matrix.
+ */
+public class MatrixDelegateStorage implements MatrixStorage {
+    /** Parent matrix storage. */
+    private MatrixStorage sto;
+
+    /** Row offset in the parent matrix. */
+    private int rowOff;
+    /** Column offset in the parent matrix. */
+    private int colOff;
+
+    /** Amount of rows in the matrix. */
+    private int rows;
+    /** Amount of columns in the matrix. */
+    private int cols;
+
+    /**
+     *
+     */
+    public MatrixDelegateStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param sto Backing parent storage.
+     * @param rowOff Row offset to parent matrix.
+     * @param colOff Column offset to parent matrix.
+     * @param rows Amount of rows in the view.
+     * @param cols Amount of columns in the view.
+     */
+    public MatrixDelegateStorage(MatrixStorage sto, int rowOff, int colOff, 
int rows, int cols) {
+        assert sto != null;
+        assert rowOff >= 0;
+        assert colOff >= 0;
+        assert rows > 0;
+        assert cols > 0;
+
+        this.sto = sto;
+
+        this.rowOff = rowOff;
+        this.colOff = colOff;
+
+        this.rows = rows;
+        this.cols = cols;
+    }
+
+    /**
+     *
+     */
+    public MatrixStorage delegate() {
+        return sto;
+    }
+
+    /**
+     *
+     */
+    public int rowOffset() {
+        return rowOff;
+    }
+
+    /**
+     *
+     */
+    public int columnOffset() {
+        return colOff;
+    }
+
+    /**
+     *
+     */
+    public int rowsLength() {
+        return rows;
+    }
+
+    /**
+     *
+     */
+    public int columnsLength() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        return sto.get(rowOff + x, colOff + y);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        sto.set(rowOff + x, colOff + y, v);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return rows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return sto.isArrayBased() && rowOff == 0 && colOff == 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return sto.isSequentialAccess();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return sto.isDense();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return sto.isRandomAccess();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return sto.isDistributed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public double[][] data() {
+        return sto.data();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(sto);
+
+        out.writeInt(rowOff);
+        out.writeInt(colOff);
+
+        out.writeInt(rows);
+        out.writeInt(cols);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        sto = (MatrixStorage)in.readObject();
+
+        rowOff = in.readInt();
+        colOff = in.readInt();
+
+        rows = in.readInt();
+        cols = in.readInt();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + rows;
+        res = res * 37 + cols;
+        res = res * 37 + rowOff;
+        res = res * 37 + colOff;
+        res = res * 37 + sto.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        MatrixDelegateStorage that = (MatrixDelegateStorage)o;
+
+        return rows == that.rows && cols == that.cols && rowOff == that.rowOff 
&& colOff == that.colOff &&
+            (sto != null ? sto.equals(that.sto) : that.sto == null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/PivotedMatrixStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/PivotedMatrixStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/PivotedMatrixStorage.java
new file mode 100644
index 0000000..ab9b871
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/PivotedMatrixStorage.java
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Arrays;
+import org.apache.ignite.ml.math.MatrixStorage;
+
+/**
+ * Pivoted (index mapped) view over another matrix storage implementation.
+ */
+public class PivotedMatrixStorage implements MatrixStorage {
+    /** Matrix storage. */
+    private MatrixStorage sto;
+
+    /** */
+    private int[] rowPivot;
+    /** */
+    private int[] colPivot;
+    /** */
+    private int[] rowUnpivot;
+    /** */
+    private int[] colUnpivot;
+
+    /**
+     *
+     */
+    public PivotedMatrixStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param sto Matrix storage.
+     * @param rowPivot Pivot array for rows.
+     * @param colPivot Pivot array for columns.
+     */
+    public PivotedMatrixStorage(MatrixStorage sto, int[] rowPivot, int[] 
colPivot) {
+        assert sto != null;
+        assert rowPivot != null;
+        assert colPivot != null;
+
+        this.sto = sto;
+        this.rowPivot = rowPivot;
+        this.colPivot = colPivot;
+
+        rowUnpivot = invert(rowPivot);
+        colUnpivot = invert(colPivot);
+    }
+
+    /**
+     *
+     */
+    public int[] rowPivot() {
+        return rowPivot;
+    }
+
+    /**
+     *
+     */
+    public int[] columnPivot() {
+        return colPivot;
+    }
+
+    /**
+     *
+     */
+    public int[] rowUnpivot() {
+        return rowUnpivot;
+    }
+
+    /**
+     *
+     */
+    public int[] columnUnpivot() {
+        return colUnpivot;
+    }
+
+    /**
+     * @param sto Matrix storage.
+     * @param pivot Pivot array.
+     */
+    public PivotedMatrixStorage(MatrixStorage sto, int[] pivot) {
+        this(sto, pivot, pivot == null ? null : java.util.Arrays.copyOf(pivot, 
pivot.length));
+    }
+
+    /**
+     * @param sto Matrix storage.
+     */
+    public PivotedMatrixStorage(MatrixStorage sto) {
+        this(sto, sto == null ? null : identityPivot(sto.rowSize()), sto == 
null ? null : identityPivot(sto.columnSize()));
+    }
+
+    /**
+     * @param i First row index to swap.
+     * @param j Second row index to swap.
+     */
+    public void swapRows(int i, int j) {
+        if (i != j) {
+            int tmp = rowPivot[i];
+
+            rowPivot[i] = rowPivot[j];
+            rowPivot[j] = tmp;
+
+            rowUnpivot[rowPivot[i]] = i;
+            rowUnpivot[rowPivot[j]] = j;
+        }
+    }
+
+    /**
+     * @param i First column index to swap.
+     * @param j Second column index to swap.
+     */
+    public void swapColumns(int i, int j) {
+        if (i != j) {
+            int tmp = colPivot[i];
+
+            colPivot[i] = colPivot[j];
+            colPivot[j] = tmp;
+
+            colUnpivot[colPivot[i]] = i;
+            colUnpivot[colPivot[j]] = j;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        return sto.get(rowPivot[x], colPivot[y]);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        sto.set(rowPivot[x], colPivot[y], v);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return sto.columnSize();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return sto.rowSize();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(sto);
+        out.writeObject(rowPivot);
+        out.writeObject(colPivot);
+        out.writeObject(rowUnpivot);
+        out.writeObject(colUnpivot);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        sto = (MatrixStorage)in.readObject();
+        rowPivot = (int[])in.readObject();
+        colPivot = (int[])in.readObject();
+        rowUnpivot = (int[])in.readObject();
+        colUnpivot = (int[])in.readObject();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return sto.isSequentialAccess();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return sto.isDense();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return sto.isRandomAccess();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return sto.isDistributed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + sto.hashCode();
+        res = res * 37 + Arrays.hashCode(rowPivot);
+        res = res * 37 + Arrays.hashCode(rowUnpivot);
+        res = res * 37 + Arrays.hashCode(colPivot);
+        res = res * 37 + Arrays.hashCode(colUnpivot);
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        PivotedMatrixStorage that = (PivotedMatrixStorage)obj;
+
+        return Arrays.equals(rowPivot, that.rowPivot) && 
Arrays.equals(rowUnpivot, that.rowUnpivot)
+            && Arrays.equals(colPivot, that.colPivot) && 
Arrays.equals(colUnpivot, that.colUnpivot)
+            && (sto != null ? sto.equals(that.sto) : that.sto == null);
+    }
+
+    /**
+     * @param n Pivot array length.
+     */
+    private static int[] identityPivot(int n) {
+        int[] pivot = new int[n];
+
+        for (int i = 0; i < n; i++)
+            pivot[i] = i;
+
+        return pivot;
+    }
+
+    /**
+     * @param pivot Pivot array to be inverted.
+     */
+    private static int[] invert(int[] pivot) {
+        int[] x = new int[pivot.length];
+
+        for (int i = 0; i < pivot.length; i++)
+            x[pivot[i]] = i;
+
+        return x;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/RandomMatrixStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/RandomMatrixStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/RandomMatrixStorage.java
new file mode 100644
index 0000000..7e0ef27
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/RandomMatrixStorage.java
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.nio.ByteBuffer;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.MurmurHash;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+
+/**
+ * {@link MatrixStorage} implementation with random values in the matrix 
elements.
+ */
+public class RandomMatrixStorage implements MatrixStorage {
+    /** */
+    private static final int PRIME1 = 104047;
+    /** */
+    private static final int PRIME2 = 101377;
+    /** */
+    private static final int PRIME3 = 64661;
+    /** */
+    private static final long SCALE = 1L << 32;
+
+    /** Random generation seed. */
+    private int seed;
+
+    /** Amount of rows in the matrix. */
+    private int rows;
+    /** Amount of columns in the matrix. */
+    private int cols;
+
+    /** Whether fast hash is used, in {@link #get(int, int)}. */
+    private boolean fastHash;
+
+    /**
+     * For externalization.
+     */
+    public RandomMatrixStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param rows Amount of rows in the matrix.
+     * @param cols Amount of columns in the matrix.
+     * @param fastHash Whether fast hash is used.
+     */
+    public RandomMatrixStorage(int rows, int cols, boolean fastHash) {
+        assert rows > 0;
+        assert cols > 0;
+
+        this.rows = rows;
+        this.cols = cols;
+        this.fastHash = fastHash;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        if (!fastHash) {
+            ByteBuffer buf = ByteBuffer.allocate(8);
+
+            buf.putInt(x);
+            buf.putInt(y);
+            buf.flip();
+
+            return (MurmurHash.hash64A(buf, seed) & (SCALE - 1)) / 
(double)SCALE;
+        }
+        else
+            // This isn't a fantastic random number generator, but it is just 
fine for random projections.
+            return ((((x * PRIME1) + y * PRIME2 + x * y * PRIME3) & 8) * 0.25) 
- 1;
+    }
+
+    /**
+     *
+     */
+    public boolean isFastHash() {
+        return fastHash;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        throw new UnsupportedOperationException("Random matrix storage is a 
read-only storage.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return rows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeInt(rows);
+        out.writeInt(cols);
+        out.writeInt(seed);
+        out.writeBoolean(fastHash);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        rows = in.readInt();
+        cols = in.readInt();
+        seed = in.readInt();
+        fastHash = in.readBoolean();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + Boolean.hashCode(fastHash);
+        res = res * 37 + seed;
+        res = res * 37 + cols;
+        res = res * 37 + rows;
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        RandomMatrixStorage that = (RandomMatrixStorage)o;
+
+        return rows == that.rows && cols == that.cols && seed == that.seed && 
fastHash == that.fastHash;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
new file mode 100644
index 0000000..cf200c7
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap;
+import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Map;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.impls.CacheUtils;
+import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
+
+/**
+ * {@link MatrixStorage} implementation for {@link SparseDistributedMatrix}.
+ */
+public class SparseDistributedMatrixStorage extends CacheUtils implements 
MatrixStorage, StorageConstants {
+    /** Amount of rows in the matrix. */
+    private int rows;
+    /** Amount of columns in the matrix. */
+    private int cols;
+
+    /** Row or column based storage mode. */
+    private int stoMode;
+    /** Random or sequential access mode. */
+    private int acsMode;
+
+    /** Actual distributed storage. */
+    private IgniteCache<
+        Integer /* Row or column index. */,
+        Map<Integer, Double> /* Map-based row or column. */
+        > cache = null;
+
+    /**
+     *
+     */
+    public SparseDistributedMatrixStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param rows Amount of rows in the matrix.
+     * @param cols Amount of columns in the matrix.
+     * @param stoMode Row or column based storage mode.
+     * @param acsMode Random or sequential access mode.
+     */
+    public SparseDistributedMatrixStorage(int rows, int cols, int stoMode, int 
acsMode) {
+        assert rows > 0;
+        assert cols > 0;
+        assertAccessMode(acsMode);
+        assertStorageMode(stoMode);
+
+        this.rows = rows;
+        this.cols = cols;
+        this.stoMode = stoMode;
+        this.acsMode = acsMode;
+
+        cache = newCache();
+    }
+
+    /**
+     *
+     *
+     */
+    private IgniteCache<Integer, Map<Integer, Double>> newCache() {
+        CacheConfiguration<Integer, Map<Integer, Double>> cfg = new 
CacheConfiguration<>();
+
+        // Assume 10% density.
+        cfg.setStartSize(Math.max(1024, (rows * cols) / 10));
+
+        // Write to primary.
+        
cfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC);
+
+        // Atomic transactions only.
+        cfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
+
+        // No eviction.
+        cfg.setEvictionPolicy(null);
+
+        // No copying of values.
+        cfg.setCopyOnRead(false);
+
+        // Cache is partitioned.
+        cfg.setCacheMode(CacheMode.PARTITIONED);
+
+        // Random cache name.
+        cfg.setName(new IgniteUuid().shortString());
+
+        return Ignition.localIgnite().getOrCreateCache(cfg);
+    }
+
+    /**
+     *
+     *
+     */
+    public IgniteCache<Integer, Map<Integer, Double>> cache() {
+        return cache;
+    }
+
+    /**
+     *
+     *
+     */
+    public int accessMode() {
+        return acsMode;
+    }
+
+    /**
+     *
+     *
+     */
+    public int storageMode() {
+        return stoMode;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        if (stoMode == ROW_STORAGE_MODE)
+            return matrixGet(cache.getName(), x, y);
+        else
+            return matrixGet(cache.getName(), y, x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        if (stoMode == ROW_STORAGE_MODE)
+            matrixSet(cache.getName(), x, y, v);
+        else
+            matrixSet(cache.getName(), y, x, v);
+    }
+
+    /**
+     * Distributed matrix get.
+     *
+     * @param cacheName Matrix's cache.
+     * @param a Row or column index.
+     * @param b Row or column index.
+     * @return Matrix value at (a, b) index.
+     */
+    private double matrixGet(String cacheName, int a, int b) {
+        // Remote get from the primary node (where given row or column is 
stored locally).
+        return ignite().compute(groupForKey(cacheName, a)).call(() -> {
+            IgniteCache<Integer, Map<Integer, Double>> cache = 
Ignition.localIgnite().getOrCreateCache(cacheName);
+
+            // Local get.
+            Map<Integer, Double> map = cache.localPeek(a, 
CachePeekMode.PRIMARY);
+
+            return (map == null || !map.containsKey(b)) ? 0.0 : map.get(b);
+        });
+    }
+
+    /**
+     * Distributed matrix set.
+     *
+     * @param cacheName Matrix's cache.
+     * @param a Row or column index.
+     * @param b Row or column index.
+     * @param v New value to set.
+     */
+    private void matrixSet(String cacheName, int a, int b, double v) {
+        // Remote set on the primary node (where given row or column is stored 
locally).
+        ignite().compute(groupForKey(cacheName, a)).run(() -> {
+            IgniteCache<Integer, Map<Integer, Double>> cache = 
Ignition.localIgnite().getOrCreateCache(cacheName);
+
+            // Local get.
+            Map<Integer, Double> map = cache.localPeek(a, 
CachePeekMode.PRIMARY);
+
+            if (map == null)
+                map = acsMode == SEQUENTIAL_ACCESS_MODE ? new 
Int2DoubleRBTreeMap() : new Int2DoubleOpenHashMap();
+
+            if (v != 0.0)
+                map.put(b, v);
+            else if (map.containsKey(b))
+                map.remove(b);
+
+            // Local put.
+            cache.put(a, map);
+        });
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return rows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeInt(rows);
+        out.writeInt(cols);
+        out.writeInt(acsMode);
+        out.writeInt(stoMode);
+        out.writeUTF(cache.getName());
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        rows = in.readInt();
+        cols = in.readInt();
+        acsMode = in.readInt();
+        stoMode = in.readInt();
+        cache = ignite().getOrCreateCache(in.readUTF());
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return acsMode == SEQUENTIAL_ACCESS_MODE;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return acsMode == RANDOM_ACCESS_MODE;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** Destroy underlying cache. */
+    @Override public void destroy() {
+        cache.destroy();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + cols;
+        res = res * 37 + rows;
+        res = res * 37 + acsMode;
+        res = res * 37 + stoMode;
+        res = res * 37 + cache.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        SparseDistributedMatrixStorage that = 
(SparseDistributedMatrixStorage)obj;
+
+        return rows == that.rows && cols == that.cols && acsMode == 
that.acsMode && stoMode == that.stoMode
+            && (cache != null ? cache.equals(that.cache) : that.cache == null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java
----------------------------------------------------------------------
diff --git 
a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java
 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java
new file mode 100644
index 0000000..4530900
--- /dev/null
+++ 
b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.impls.storage.matrix;
+
+import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap;
+import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.StorageConstants;
+
+/**
+ * Storage for sparse, local, on-heap matrix.
+ */
+public class SparseLocalOnHeapMatrixStorage implements MatrixStorage, 
StorageConstants {
+    /** Default zero value. */
+    private static final double DEFAULT_VALUE = 0.0;
+
+    /** */ private int rows;
+    /** */ private int cols;
+
+    /** */ private int acsMode;
+    /** */ private int stoMode;
+
+    /** Actual map storage. */
+    private Map<Integer, Map<Integer, Double>> sto;
+
+    /** */
+    public SparseLocalOnHeapMatrixStorage() {
+        // No-op.
+    }
+
+    /** */
+    public SparseLocalOnHeapMatrixStorage(int rows, int cols, int acsMode, int 
stoMode) {
+        assert rows > 0;
+        assert cols > 0;
+        assertAccessMode(acsMode);
+        assertStorageMode(stoMode);
+
+        this.rows = rows;
+        this.cols = cols;
+        this.acsMode = acsMode;
+        this.stoMode = stoMode;
+
+        sto = new HashMap<>();
+    }
+
+    /**
+     *
+     *
+     */
+    public int getStorageMode() {
+        return stoMode;
+    }
+
+    /**
+     *
+     *
+     */
+    public int getAccessMode() {
+        return acsMode;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x, int y) {
+        if (stoMode == ROW_STORAGE_MODE) {
+            Map<Integer, Double> row = sto.get(x);
+
+            if (row != null) {
+                Double val = row.get(y);
+
+                if (val != null)
+                    return val;
+            }
+
+            return DEFAULT_VALUE;
+        }
+        else {
+            Map<Integer, Double> col = sto.get(y);
+
+            if (col != null) {
+                Double val = col.get(x);
+
+                if (val != null)
+                    return val;
+            }
+
+            return DEFAULT_VALUE;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, int y, double v) {
+        // Ignore default values (currently 0.0).
+        if (v != DEFAULT_VALUE) {
+            if (stoMode == ROW_STORAGE_MODE) {
+                Map<Integer, Double> row = sto.computeIfAbsent(x, k ->
+                    acsMode == SEQUENTIAL_ACCESS_MODE ? new 
Int2DoubleRBTreeMap() : new Int2DoubleOpenHashMap());
+
+                row.put(y, v);
+            }
+            else {
+                Map<Integer, Double> col = sto.computeIfAbsent(y, k ->
+                    acsMode == SEQUENTIAL_ACCESS_MODE ? new 
Int2DoubleRBTreeMap() : new Int2DoubleOpenHashMap());
+
+                col.put(x, v);
+            }
+        }
+        else {
+            if (stoMode == ROW_STORAGE_MODE) {
+                if (sto.containsKey(x)) {
+                    Map<Integer, Double> row = sto.get(x);
+
+                    if (row.containsKey(y))
+                        row.remove(y);
+                }
+
+            }
+            else {
+                if (sto.containsKey(y)) {
+                    Map<Integer, Double> col = sto.get(y);
+
+                    if (col.containsKey(x))
+                        col.remove(x);
+                }
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public int columnSize() {
+        return cols;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int rowSize() {
+        return rows;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeInt(rows);
+        out.writeInt(cols);
+        out.writeInt(acsMode);
+        out.writeInt(stoMode);
+        out.writeObject(sto);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"unchecked"})
+    @Override public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
+        rows = in.readInt();
+        cols = in.readInt();
+        acsMode = in.readInt();
+        stoMode = in.readInt();
+        sto = (Map<Integer, Map<Integer, Double>>)in.readObject();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return acsMode == SEQUENTIAL_ACCESS_MODE;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return acsMode == RANDOM_ACCESS_MODE;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + rows;
+        res = res * 37 + cols;
+        res = res * 37 + sto.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        SparseLocalOnHeapMatrixStorage that = 
(SparseLocalOnHeapMatrixStorage)o;
+
+        return rows == that.rows && cols == that.cols && acsMode == 
that.acsMode && stoMode == that.stoMode
+            && (sto != null ? sto.equals(that.sto) : that.sto == null);
+    }
+}

Reply via email to