ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From agoncha...@apache.org
Subject [24/50] [abbrv] ignite git commit: IGNITE-5278: BLAS implemented.
Date Tue, 01 Aug 2017 09:27:09 GMT
IGNITE-5278: BLAS implemented.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/de259fff
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/de259fff
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/de259fff

Branch: refs/heads/ignite-5757
Commit: de259fffb7fa5c0f8f6f7eeb84b86f296fe3bde9
Parents: 1318472
Author: Yury Babak <ybabak@gridgain.com>
Authored: Tue Jul 25 20:19:27 2017 +0300
Committer: Igor Sapego <isapego@gridgain.com>
Committed: Tue Jul 25 20:19:27 2017 +0300

----------------------------------------------------------------------
 LICENSE                                         |   7 +
 .../ml/math/matrix/ExampleMatrixStorage.java    |   6 +-
 modules/ml/README.txt                           |   6 +
 modules/ml/licenses/bsd3.txt                    |  51 ++
 modules/ml/pom.xml                              |  22 +
 .../java/org/apache/ignite/ml/math/Blas.java    | 484 +++++++++++++++++++
 .../java/org/apache/ignite/ml/math/Matrix.java  |  31 ++
 .../apache/ignite/ml/math/MatrixStorage.java    |   2 +-
 .../apache/ignite/ml/math/OrderedMatrix.java    |  24 +
 .../java/org/apache/ignite/ml/math/Vector.java  |   8 +
 .../decompositions/CholeskyDecomposition.java   |  11 +-
 .../IgniteIntDoubleToDoubleBiFunction.java      |  27 ++
 .../functions/IgniteIntIntToIntBiFunction.java  |  27 ++
 .../ml/math/functions/IgniteTriFunction.java    |  35 ++
 .../ml/math/impls/matrix/AbstractMatrix.java    |  94 +++-
 .../impls/matrix/DenseLocalOnHeapMatrix.java    |  61 ++-
 .../impls/matrix/SparseLocalOnHeapMatrix.java   |  27 ++
 .../storage/matrix/ArrayMatrixStorage.java      |  78 ++-
 .../matrix/DenseOffHeapMatrixStorage.java       |   2 +-
 .../storage/matrix/MatrixDelegateStorage.java   |   2 +-
 .../matrix/SparseDistributedMatrixStorage.java  |   4 +-
 .../matrix/SparseLocalOnHeapMatrixStorage.java  |  18 +
 .../vector/SparseLocalOnHeapVectorStorage.java  |   6 +
 .../impls/vector/AbstractReadOnlyVector.java    |   6 +
 .../ml/math/impls/vector/AbstractVector.java    |   8 +
 .../ml/math/impls/vector/DelegatingVector.java  |   6 +
 .../ml/math/impls/vector/SparseLocalVector.java |  39 ++
 .../apache/ignite/ml/math/util/MatrixUtil.java  |  48 ++
 .../KMeansDistributedClustererTest.java         |  15 +-
 .../org/apache/ignite/ml/math/BlasTest.java     | 357 ++++++++++++++
 .../ignite/ml/math/MathImplMainTestSuite.java   |   3 +-
 .../impls/matrix/MatrixViewConstructorTest.java |   2 +-
 .../storage/matrix/MatrixArrayStorageTest.java  |   6 +-
 33 files changed, 1475 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index c971434..6e77825 100644
--- a/LICENSE
+++ b/LICENSE
@@ -220,6 +220,13 @@ This product bundles SnapTree, which is available under a
 https://github.com/nbronson/snaptree/blob/master/LICENSE.
 
 ==============================================================================
+For netlib-java:
+==============================================================================
+This product bundles netlib-java, which is available under a
+"3-clause BSD" license.  For details, see
+https://github.com/fommil/netlib-java/blob/master/LICENSE.txt.
+
+==============================================================================
 For JSR 166 classes in "org.jsr166" package
 ==============================================================================
 This product bundles JSR-166 classes which are donated to public domain.

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java
----------------------------------------------------------------------
diff --git a/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java b/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java
index 5dedfbf..1ccb2e2 100644
--- a/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java
+++ b/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java
@@ -23,7 +23,9 @@ import java.io.ObjectOutput;
 import java.util.Arrays;
 
 import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.impls.storage.matrix.ArrayMatrixStorage;
+import org.apache.ignite.ml.math.util.MatrixUtil;
 
 /**
  * Example matrix storage implementation, modeled after {@link ArrayMatrixStorage}.
@@ -117,8 +119,8 @@ class ExampleMatrixStorage implements MatrixStorage {
     }
 
     /** {@inheritDoc} */
-    @Override public double[][] data() {
-        return data;
+    @Override public double[] data() {
+        return MatrixUtil.flatten(data, StorageConstants.ROW_STORAGE_MODE);
     }
 
     /** {@inheritDoc */

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/README.txt
----------------------------------------------------------------------
diff --git a/modules/ml/README.txt b/modules/ml/README.txt
index e0cc093..e85b7a0 100644
--- a/modules/ml/README.txt
+++ b/modules/ml/README.txt
@@ -12,4 +12,10 @@ Based on ideas from Apache Mahout.
 Run from project root:
 mvn clean package -Pml -DskipTests -pl modules/ml -am
 
+Apache binary releases cannot include LGPL dependencies. If you would like to activate native BLAS optimizations
+into your build, you should download the source release
+from Ignite website and do the build with the following maven command:
+
+mvn clean package -Pml,lgpl -DskipTests -pl modules/ml -am
+
 Find generated jars in target folder.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/licenses/bsd3.txt
----------------------------------------------------------------------
diff --git a/modules/ml/licenses/bsd3.txt b/modules/ml/licenses/bsd3.txt
new file mode 100644
index 0000000..d6b30c1
--- /dev/null
+++ b/modules/ml/licenses/bsd3.txt
@@ -0,0 +1,51 @@
+This product binaries redistribute netlib-java which is available under the following license:
+
+Copyright (c) 2013 Samuel Halliday
+Copyright (c) 1992-2011 The University of Tennessee and The University
+                        of Tennessee Research Foundation.  All rights
+                        reserved.
+Copyright (c) 2000-2011 The University of California Berkeley. All
+                        rights reserved.
+Copyright (c) 2006-2011 The University of Colorado Denver.  All rights
+                        reserved.
+
+$COPYRIGHT$
+
+Additional copyrights may follow
+
+$HEADER$
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+- Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer listed
+  in this license in the documentation and/or other materials
+  provided with the distribution.
+
+- Neither the name of the copyright holders nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+The copyright holders provide no reassurances that the source code
+provided does not infringe any patent, copyright, or any other
+intellectual property rights of third parties.  The copyright holders
+disclaim any liability to any recipient for claims brought against
+recipient by any third party for infringement of that parties
+intellectual property rights.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/pom.xml
----------------------------------------------------------------------
diff --git a/modules/ml/pom.xml b/modules/ml/pom.xml
index d619719..478d8c4 100644
--- a/modules/ml/pom.xml
+++ b/modules/ml/pom.xml
@@ -36,6 +36,7 @@
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <netlibjava.version>1.1.2</netlibjava.version>
     </properties>
 
     <dependencies>
@@ -88,6 +89,13 @@
         </dependency>
 
         <dependency>
+            <groupId>com.github.fommil.netlib</groupId>
+            <artifactId>core</artifactId>
+            <version>${netlibjava.version}</version>
+            <type>pom</type>
+        </dependency>
+
+        <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-rng-core</artifactId>
             <version>1.0</version>
@@ -101,6 +109,20 @@
 
     </dependencies>
 
+    <profiles>
+        <profile>
+            <id>lgpl</id>
+
+            <dependencies>
+                <dependency>
+                    <groupId>com.github.fommil.netlib</groupId>
+                    <artifactId>all</artifactId>
+                    <version>${netlibjava.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+
     <build>
         <plugins>
             <plugin>

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/Blas.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/Blas.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/Blas.java
new file mode 100644
index 0000000..57f994e
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/Blas.java
@@ -0,0 +1,484 @@
+/*
+ * 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;
+
+import com.github.fommil.netlib.BLAS;
+import com.github.fommil.netlib.F2jBLAS;
+import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
+import it.unimi.dsi.fastutil.ints.IntIterator;
+import it.unimi.dsi.fastutil.ints.IntSet;
+import java.util.Set;
+import org.apache.ignite.ml.math.exceptions.CardinalityException;
+import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
+import org.apache.ignite.ml.math.exceptions.NonSquareMatrixException;
+import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.ml.math.impls.matrix.SparseLocalOnHeapMatrix;
+import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
+import org.apache.ignite.ml.math.impls.vector.SparseLocalVector;
+
+/**
+ * Useful subset of BLAS operations.
+ * This class is based on 'BLAS' class from Apache Spark MLlib.
+ */
+public class Blas {
+    /** F2J implementation of BLAS. */
+    transient static private BLAS f2jBlas = new F2jBLAS();
+
+    /** Native implementation of BLAS. F2J implementation will be used as fallback if no native implementation is found
+     */
+    transient static private BLAS nativeBlas = BLAS.getInstance();
+
+    /**
+     * Performs y += a * x
+     *
+     * @param a Scalar a.
+     * @param x Vector x.
+     * @param y Vector y.
+     */
+    public static void axpy(Double a, Vector x, Vector y) {
+        if (x.size() != y.size())
+            throw new CardinalityException(x.size(), y.size());
+
+        if (x.isArrayBased() && y.isArrayBased())
+            axpy(a, x.getStorage().data(), y.getStorage().data());
+        else if (x instanceof SparseLocalVector && y.isArrayBased())
+            axpy(a, (SparseLocalVector)x, y.getStorage().data());
+        else
+            throw new MathIllegalArgumentException("Operation 'axpy' doesn't support this combination of parameters [x="
+                + x.getClass().getName() + ", y="+y.getClass().getName()+"].");
+    }
+
+    /** */
+    private static void axpy(Double a, double[] x, double[] y) {
+        f2jBlas.daxpy(x.length, a, x, 1, y, 1);
+    }
+
+    /** */
+    private static void axpy(Double a, SparseLocalVector x, double[] y) {
+        int xSize = x.size();
+
+        if (a == 1.0) {
+            int k = 0;
+
+            while (k < xSize) {
+                y[k] += x.getX(k);
+                k++;
+            }
+        } else {
+            int k = 0;
+
+            while (k < xSize) {
+                y[k] += a * x.getX(k);
+                k++;
+            }
+        }
+    }
+
+    /**
+     * Returns dot product of vectors x and y.
+     *
+     * @param x Vector x.
+     * @param y Vector y.
+     * @return Dot product of x and y.
+     **/
+    public static Double dot(Vector x, Vector y) {
+        return x.dot(y);
+    }
+
+    /**
+     * Copies Vector x into Vector y. (y = x)
+     *
+     * @param x Vector x.
+     * @param y Vector y.
+     */
+    public void copy(Vector x, Vector y) {
+        int n = y.size();
+
+        if (x.size() != n)
+            throw new CardinalityException(x.size(), n);
+
+        if (y.isArrayBased()) {
+            double[] yData = y.getStorage().data();
+
+            if (x.isArrayBased())
+                System.arraycopy(x.getStorage().data(), 0, y.getStorage().data(), 0, n);
+            else {
+                if (y instanceof SparseLocalVector) {
+                    for (int i = 0; i < n; i++)
+                        yData[i] = x.getX(i);
+                }
+            }
+        } else
+            throw new IllegalArgumentException("Vector y must be array based in copy.");
+    }
+
+
+    /**
+     * Performs in-place multiplication of vector x by a real scalar a. (x = a * x)
+     *
+     * @param a Scalar a.
+     * @param x Vector x.
+     **/
+    public static void scal(Double a, Vector x) {
+        if (x.isArrayBased())
+            f2jBlas.dscal(x.size(), a, x.getStorage().data(), 1);
+        else if (x instanceof SparseLocalVector) {
+            Set<Integer> indexes = ((SparseLocalVector)x).indexes();
+
+            for (Integer i : indexes)
+                x.compute(i, (ind, v) -> v * a);
+        } else
+            throw new IllegalArgumentException();
+    }
+
+    /**
+     * Adds alpha * v * v.t to a matrix in-place. This is the same as BLAS's ?SPR.
+     *
+     * @param u the upper triangular part of the matrix in a [[DenseVector]](column major)
+     */
+    public static void spr(Double alpha, DenseLocalOnHeapVector v, DenseLocalOnHeapVector u) {
+        nativeBlas.dspr("U", v.size(), alpha, v.getStorage().data(), 1, u.getStorage().data());
+    }
+
+    /** */
+    public static void spr(Double alpha, SparseLocalVector v, DenseLocalOnHeapVector u) {
+        int prevNonDfltInd = 0;
+        int startInd = 0;
+        double av;
+        double[] uData = u.getStorage().data();
+
+        for (Integer nonDefaultInd : v.indexes()) {
+            startInd += (nonDefaultInd - prevNonDfltInd) * (nonDefaultInd + prevNonDfltInd + 1) / 2;
+            av = alpha * v.get(nonDefaultInd);
+
+            for (Integer i : v.indexes())
+                if (i <= nonDefaultInd)
+                    uData[startInd + i] += av * v.getX(i);
+
+            prevNonDfltInd = nonDefaultInd;
+        }
+    }
+
+    /**
+     * A := alpha * x * x^T + A
+     * @param alpha a real scalar that will be multiplied to x * x^T^.
+     * @param x the vector x that contains the n elements.
+     * @param a the symmetric matrix A. Size of n x n.
+     */
+    void syr(Double alpha, Vector x, DenseLocalOnHeapMatrix a) {
+        int mA = a.rowSize();
+        int nA = a.columnSize();
+
+        if (mA != nA)
+            throw new NonSquareMatrixException(mA, nA);
+
+        if (mA != x.size())
+            throw new CardinalityException(x.size(), mA);
+
+        // TODO: IGNITE-5535, Process DenseLocalOffHeapVector
+        if (x instanceof DenseLocalOnHeapVector)
+            syr(alpha, x, a);
+        else if (x instanceof SparseLocalVector)
+            syr(alpha, x, a);
+        else
+            throw new IllegalArgumentException("Operation 'syr' does not support vector [class="
+                + x.getClass().getName() + "].");
+    }
+
+    /** */
+    static void syr(Double alpha, DenseLocalOnHeapVector x, DenseLocalOnHeapMatrix a) {
+        int nA = a.rowSize();
+        int mA = a.columnSize();
+
+        nativeBlas.dsyr("U", x.size(), alpha, x.getStorage().data(), 1, a.getStorage().data(), nA);
+
+        // Fill lower triangular part of A
+        int i = 0;
+        while (i < mA) {
+            int j = i + 1;
+
+            while (j < nA) {
+                a.setX(i, j, a.getX(j, i));
+                j++;
+            }
+            i++;
+        }
+    }
+
+    /** */
+    public static void syr(Double alpha, SparseLocalVector x, DenseLocalOnHeapMatrix a) {
+        int mA = a.columnSize();
+
+        for (Integer i : x.indexes()) {
+            double mult = alpha * x.getX(i);
+            for (Integer j : x.indexes())
+                a.getStorage().data()[mA * i + j] += mult * x.getX(j);
+        }
+    }
+
+    /**
+     * For the moment we have no flags indicating if matrix is transposed or not. Therefore all dgemm parameters for
+     * transposition are equal to 'N'.
+     */
+    public static void gemm(Double alpha, Matrix a, DenseLocalOnHeapMatrix b, Double beta, DenseLocalOnHeapMatrix c) {
+        if (alpha == 0.0 && beta == 1.0)
+            return;
+        else if (alpha == 0.0)
+            scal(c, beta);
+        else {
+            if (a instanceof SparseLocalOnHeapMatrix)
+                gemm(alpha, (SparseLocalOnHeapMatrix)a, b, beta, c);
+            else if (a instanceof DenseLocalOnHeapMatrix) {
+                double[] fA = a.getStorage().data();
+                double[] fB = b.getStorage().data();
+                double[] fC = c.getStorage().data();
+
+                nativeBlas.dgemm("N", "N", a.rowSize(), b.columnSize(), a.columnSize(), alpha, fA,
+                    a.rowSize(), fB, b.rowSize(), beta, fC, c.rowSize());
+            } else
+                throw new IllegalArgumentException("Operation 'gemm' doesn't support for matrix [class="
+                    + a.getClass().getName() + "].");
+        }
+    }
+
+    /**
+     * C := alpha * A * B + beta * C
+     * For `SparseMatrix` A.
+     */
+    private static void gemm(Double alpha, SparseLocalOnHeapMatrix a, DenseLocalOnHeapMatrix b, Double beta,
+        DenseLocalOnHeapMatrix c) {
+        int mA = a.rowSize();
+        int nB = b.columnSize();
+        int kA = a.columnSize();
+        int kB = b.rowSize();
+
+        if (kA != kB)
+            throw new CardinalityException(kA, kB);
+
+        if (mA != c.rowSize())
+            throw new CardinalityException(mA, c.rowSize());
+
+        if (nB != c.columnSize())
+            throw new CardinalityException(nB, c.columnSize());
+
+        if (beta != 1.0)
+            scal(c, beta);
+
+        Int2ObjectArrayMap<IntSet> im = a.indexesMap();
+        IntIterator rowsIter = im.keySet().iterator();
+        int row;
+        // We use here this form of iteration instead of 'for' because of nextInt.
+        while (rowsIter.hasNext()) {
+            row = rowsIter.nextInt();
+
+            for (int colInd = 0; colInd < nB; colInd++) {
+                double sum = 0.0;
+
+                IntIterator kIter = im.get(row).iterator();
+                int k;
+
+                while (kIter.hasNext()) {
+                    k = kIter.nextInt();
+                    sum += a.get(row, k) * b.get(k, colInd) * alpha;
+                }
+
+                c.setX(row, colInd, c.getX(row, colInd) + sum);
+            }
+        }
+    }
+
+    /**
+     * y := alpha * A * x + beta * y.
+     *
+     * @param alpha Alpha.
+     * @param a Matrix a.
+     * @param x Vector x.
+     * @param beta Beta.
+     * @param y Vector y.
+     */
+    public static void gemv(double alpha, Matrix a, Vector x, double beta, DenseLocalOnHeapVector y) {
+        checkCardinality(a, x);
+        checkCardinality(a, y);
+
+        if (alpha == 0.0 && beta == 1.0)
+            return;
+
+        if (alpha == 0.0) {
+            scal(y, beta);
+            return;
+        }
+
+        if (a instanceof SparseLocalOnHeapMatrix && x instanceof DenseLocalOnHeapVector)
+            gemv(alpha, (SparseLocalOnHeapMatrix)a, (DenseLocalOnHeapVector)x, beta, y);
+        else if (a instanceof SparseLocalOnHeapMatrix && x instanceof SparseLocalVector)
+            gemv(alpha, (SparseLocalOnHeapMatrix)a, (SparseLocalVector)x, beta, y);
+        else if (a instanceof DenseLocalOnHeapMatrix && x instanceof DenseLocalOnHeapVector)
+            gemv(alpha, (DenseLocalOnHeapMatrix)a, (DenseLocalOnHeapVector)x, beta, y);
+        else if (a instanceof DenseLocalOnHeapMatrix && x instanceof SparseLocalVector)
+            gemv(alpha, (DenseLocalOnHeapMatrix)a, (SparseLocalVector)x, beta, y);
+        else
+            throw new IllegalArgumentException("Operation gemv doesn't support running thist input [matrix=" +
+                a.getClass().getSimpleName() + ", vector=" + x.getClass().getSimpleName()+"].");
+    }
+
+    /**
+     * y := alpha * A * x + beta * y.
+     *
+     * @param alpha Alpha.
+     * @param a Matrix a.
+     * @param x Vector x.
+     * @param beta Beta.
+     * @param y Vector y.
+     */
+    private static void gemv(double alpha, SparseLocalOnHeapMatrix a, DenseLocalOnHeapVector x, double beta,
+        DenseLocalOnHeapVector y) {
+
+        if (beta != 1.0)
+            scal(y, beta);
+
+        IntIterator rowIter = a.indexesMap().keySet().iterator();
+        while (rowIter.hasNext()) {
+            int row = rowIter.nextInt();
+
+            double sum = 0.0;
+            IntIterator colIter = a.indexesMap().get(row).iterator();
+            while (colIter.hasNext()) {
+                int col = colIter.nextInt();
+                sum += alpha * a.getX(row, col) * x.getX(col);
+            }
+
+            y.setX(row, y.getX(row) + sum);
+        }
+    }
+
+    /**
+     * y := alpha * A * x + beta * y.
+     *
+     * @param alpha Alpha.
+     * @param a Matrix a.
+     * @param x Vector x.
+     * @param beta Beta.
+     * @param y Vector y.
+     */
+    private static void gemv(double alpha, DenseLocalOnHeapMatrix a, DenseLocalOnHeapVector x, double beta,
+        DenseLocalOnHeapVector y) {
+        nativeBlas.dgemv("N", a.rowSize(), a.columnSize(), alpha, a.getStorage().data(), a.rowSize(), x.getStorage().data(), 1, beta,
+            y.getStorage().data(), 1);
+    }
+
+    /**
+     * y := alpha * A * x + beta * y.
+     *
+     * @param alpha Alpha.
+     * @param a Matrix a.
+     * @param x Vector x.
+     * @param beta Beta.
+     * @param y Vector y.
+     */
+    private static void gemv(double alpha, SparseLocalOnHeapMatrix a, SparseLocalVector x, double beta,
+        DenseLocalOnHeapVector y) {
+
+
+        if (beta != 1.0)
+            scal(y, beta);
+
+        IntIterator rowIter = a.indexesMap().keySet().iterator();
+        while (rowIter.hasNext()) {
+            int row = rowIter.nextInt();
+
+            double sum = 0.0;
+            IntIterator colIter = a.indexesMap().get(row).iterator();
+            while (colIter.hasNext()) {
+                int col = colIter.nextInt();
+
+                sum += alpha * a.getX(row, col) * x.getX(col);
+            }
+
+            y.set(row, y.get(row) + sum);
+        }
+    }
+
+    /**
+     * y := alpha * A * x + beta * y.
+     *
+     * @param alpha Alpha.
+     * @param a Matrix a.
+     * @param x Vector x.
+     * @param beta Beta.
+     * @param y Vector y.
+     */
+    private static void gemv(double alpha, DenseLocalOnHeapMatrix a, SparseLocalVector x, double beta,
+        DenseLocalOnHeapVector y) {
+        int rowCntrForA = 0;
+        int mA = a.rowSize();
+
+        double[] aData = a.getStorage().data();
+
+        IntSet indexes = x.indexes();
+
+        double[] yValues = y.getStorage().data();
+
+        while (rowCntrForA < mA) {
+            double sum = 0.0;
+
+            IntIterator iter = indexes.iterator();
+            while (iter.hasNext()) {
+                int xIdx = iter.nextInt();
+                sum += x.getX(xIdx) * aData[xIdx * mA + rowCntrForA];
+            }
+
+            yValues[rowCntrForA] = sum * alpha + beta * yValues[rowCntrForA];
+            rowCntrForA++;
+        }
+    }
+
+    /**
+     * M := alpha * M.
+     * @param m Matrix M.
+     * @param alpha Aplha.
+     */
+    private static void scal(Matrix m, double alpha) {
+        if (alpha != 1.0)
+            for (int i = 0; i < m.rowSize(); i++)
+                for (int j = 0; j < m.columnSize(); j++)
+                    m.setX(i, j, m.getX(i, j) * alpha);
+
+    }
+
+    /**
+     * v := alpha * v.
+     * @param v Vector v.
+     * @param alpha Aplha.
+     */
+    private static void scal(Vector v, double alpha) {
+        if (alpha != 1.0)
+            for (int i = 0; i < v.size(); i++)
+                v.compute(i, (ind, val) -> val * alpha);
+    }
+
+    /**
+     * Checks if Matrix A can be multiplied by vector v, if not CardinalityException is thrown.
+     *
+     * @param a Matrix A.
+     * @param v Vector v.
+     */
+    public static void checkCardinality(Matrix a, Vector v) throws CardinalityException {
+        if (a.columnSize() != v.size())
+            throw new CardinalityException(a.columnSize(), v.size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java
index 2cf4e63..66de1a1 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.ml.math;
 
 import java.io.Externalizable;
+import java.util.Spliterator;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.ml.math.exceptions.CardinalityException;
 import org.apache.ignite.ml.math.exceptions.IndexException;
@@ -25,6 +26,7 @@ import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
 import org.apache.ignite.ml.math.functions.IgniteBiFunction;
 import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
 import org.apache.ignite.ml.math.functions.IgniteFunction;
+import org.apache.ignite.ml.math.functions.IgniteTriFunction;
 import org.apache.ignite.ml.math.functions.IntIntToDoubleFunction;
 
 /**
@@ -187,6 +189,27 @@ public interface Matrix extends MetaAttributes, Externalizable, StorageOpsMetric
     public Matrix map(Matrix mtx, IgniteBiFunction<Double, Double, Double> fun);
 
     /**
+     * Gets number of non-zero elements in this matrix.
+     *
+     * @return Number of non-zero elements in this matrix.
+     */
+    public int nonZeroElements();
+
+    /**
+     * Gets spliterator for all values in this matrix.
+     *
+     * @return Spliterator for all values.
+     */
+    public Spliterator<Double> allSpliterator();
+
+    /**
+     * Gets spliterator for all non-zero values in this matrix.
+     *
+     * @return Spliterator for all non-zero values.
+     */
+    public Spliterator<Double> nonZeroSpliterator();
+
+    /**
      * Assigns values from given vector to the specified column in this matrix.
      *
      * @param col Column index.
@@ -515,4 +538,12 @@ public interface Matrix extends MetaAttributes, Externalizable, StorageOpsMetric
     public default void destroy() {
         // No-op.
     }
+
+    /**
+     * Replace matrix entry with value oldVal at (row, col) with result of computing f(row, col, oldVal).
+     * @param row Row.
+     * @param col Column.
+     * @param f Function used for replacing.
+     */
+    public void compute(int row, int col, IgniteTriFunction<Integer, Integer, Double, Double> f);
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
index ccfebe5..3b905bc 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
@@ -52,7 +52,7 @@ public interface MatrixStorage extends Externalizable, StorageOpsMetrics, Destro
      *
      * @see StorageOpsMetrics#isArrayBased()
      */
-    default public double[][] data() {
+    default public double[] data() {
         return null;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/OrderedMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/OrderedMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/OrderedMatrix.java
new file mode 100644
index 0000000..2c3acc8
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/OrderedMatrix.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+/** Interface for matrix with particular order for storing entities. */
+public interface OrderedMatrix {
+    /** Get access mode. */
+    public int accessMode();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java
index e1c5df0..5fd39af 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java
@@ -26,6 +26,7 @@ import org.apache.ignite.ml.math.exceptions.IndexException;
 import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
 import org.apache.ignite.ml.math.functions.IgniteBiFunction;
 import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteIntDoubleToDoubleBiFunction;
 
 /**
  * A vector interface.
@@ -496,4 +497,11 @@ public interface Vector extends MetaAttributes, Externalizable, StorageOpsMetric
      * @return Vector GUID.
      */
     public IgniteUuid guid();
+
+    /**
+     * Replace vector entry with value oldVal at i with result of computing f(i, oldVal).
+     * @param i Position.
+     * @param f Function used for replacing.
+     **/
+    public void compute(int i, IgniteIntDoubleToDoubleBiFunction f);
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java
index 84028fe..73fbe2c 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java
@@ -23,6 +23,7 @@ import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.exceptions.CardinalityException;
 import org.apache.ignite.ml.math.exceptions.NonPositiveDefiniteMatrixException;
 import org.apache.ignite.ml.math.exceptions.NonSymmetricMatrixException;
+import org.apache.ignite.ml.math.util.MatrixUtil;
 
 import static org.apache.ignite.ml.math.util.MatrixUtil.like;
 import static org.apache.ignite.ml.math.util.MatrixUtil.likeVector;
@@ -252,7 +253,7 @@ public class CholeskyDecomposition implements Destroyable {
             throw new CardinalityException(b.rowSize(), m);
 
         final int nColB = b.columnSize();
-        final double[][] x = b.getStorage().data();
+        final double[][] x = MatrixUtil.unflatten(b.getStorage().data(), b.columnSize());
 
         // Solve LY = b
         for (int j = 0; j < m; j++) {
@@ -295,15 +296,13 @@ public class CholeskyDecomposition implements Destroyable {
     /** */
     private double[][] toDoubleArr(Matrix mtx) {
         if (mtx.isArrayBased())
-            return mtx.getStorage().data();
+            return MatrixUtil.unflatten(mtx.getStorage().data(), mtx.columnSize());
 
-        double[][] res = new double[mtx.rowSize()][];
+        double[][] res = new double[mtx.rowSize()][mtx.columnSize()];
 
-        for (int row = 0; row < mtx.rowSize(); row++) {
-            res[row] = new double[mtx.columnSize()];
+        for (int row = 0; row < mtx.rowSize(); row++)
             for (int col = 0; col < mtx.columnSize(); col++)
                 res[row][col] = mtx.get(row, col);
-        }
 
         return res;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntDoubleToDoubleBiFunction.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntDoubleToDoubleBiFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntDoubleToDoubleBiFunction.java
new file mode 100644
index 0000000..c9a91ae
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntDoubleToDoubleBiFunction.java
@@ -0,0 +1,27 @@
+/*
+ * 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.functions;
+
+import java.io.Serializable;
+
+/** BiFunction (int, double) -> double. */
+@FunctionalInterface
+public interface IgniteIntDoubleToDoubleBiFunction extends Serializable {
+    /** */
+    public double apply(int x, double d);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntIntToIntBiFunction.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntIntToIntBiFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntIntToIntBiFunction.java
new file mode 100644
index 0000000..bfd472c
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntIntToIntBiFunction.java
@@ -0,0 +1,27 @@
+/*
+ * 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.functions;
+
+import java.io.Serializable;
+
+/** BiFunction (int, int) -> int. */
+@FunctionalInterface
+public interface IgniteIntIntToIntBiFunction extends Serializable {
+    /** */
+    public int apply(int x, int y);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteTriFunction.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteTriFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteTriFunction.java
new file mode 100644
index 0000000..3284a00
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteTriFunction.java
@@ -0,0 +1,35 @@
+/*
+ * 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.functions;
+
+import java.io.Serializable;
+import java.util.Objects;
+import java.util.function.Function;
+
+/** Serializable TriFunction (A, B, C) -> R. */
+@FunctionalInterface
+public interface IgniteTriFunction<A,B,C,R> extends Serializable {
+    /** */
+    R apply(A a, B b, C c);
+
+    /** */
+    default <V> IgniteTriFunction<A, B, C, V> andThen(Function<? super R, ? extends V> after) {
+        Objects.requireNonNull(after);
+        return (A a, B b, C c) -> after.apply(apply(a, b, c));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
index 647ebc6..e1efd0c 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
@@ -24,6 +24,8 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Random;
+import java.util.Spliterator;
+import java.util.function.Consumer;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.MatrixStorage;
@@ -36,6 +38,7 @@ import org.apache.ignite.ml.math.functions.Functions;
 import org.apache.ignite.ml.math.functions.IgniteBiFunction;
 import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
 import org.apache.ignite.ml.math.functions.IgniteFunction;
+import org.apache.ignite.ml.math.functions.IgniteTriFunction;
 import org.apache.ignite.ml.math.functions.IntIntToDoubleFunction;
 import org.apache.ignite.ml.math.impls.vector.MatrixVectorView;
 
@@ -326,8 +329,7 @@ public abstract class AbstractMatrix implements Matrix {
     /** {@inheritDoc} */
     @Override public Matrix assign(double val) {
         if (sto.isArrayBased())
-            for (double[] column : sto.data())
-                Arrays.fill(column, val);
+                Arrays.fill(sto.data(), val);
         else {
             int rows = rowSize();
             int cols = columnSize();
@@ -421,6 +423,85 @@ public abstract class AbstractMatrix implements Matrix {
     }
 
     /** {@inheritDoc} */
+    @Override public Spliterator<Double> allSpliterator() {
+        return new Spliterator<Double>() {
+            /** {@inheritDoc} */
+            @Override public boolean tryAdvance(Consumer<? super Double> act) {
+                int rLen = rowSize();
+                int cLen = columnSize();
+
+                for (int i = 0; i < rLen; i++)
+                    for (int j = 0; j < cLen; j++)
+                        act.accept(storageGet(i, j));
+
+                return true;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Spliterator<Double> trySplit() {
+                return null; // No Splitting.
+            }
+
+            /** {@inheritDoc} */
+            @Override public long estimateSize() {
+                return rowSize() * columnSize();
+            }
+
+            /** {@inheritDoc} */
+            @Override public int characteristics() {
+                return ORDERED | SIZED;
+            }
+        };
+    }
+
+    /** {@inheritDoc} */
+    @Override public int nonZeroElements() {
+        int cnt = 0;
+
+        for (int i = 0; i < rowSize(); i++)
+            for (int j = 0; j < rowSize(); j++)
+                if (get(i, j) != 0.0)
+                    cnt++;
+
+        return cnt;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Spliterator<Double> nonZeroSpliterator() {
+        return new Spliterator<Double>() {
+            /** {@inheritDoc} */
+            @Override public boolean tryAdvance(Consumer<? super Double> act) {
+                int rLen = rowSize();
+                int cLen = columnSize();
+
+                for (int i = 0; i < rLen; i++)
+                    for (int j = 0; j < cLen; j++) {
+                        double val = storageGet(i, j);
+
+                        if (val != 0.0)
+                            act.accept(val);
+                    }
+                return true;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Spliterator<Double> trySplit() {
+                return null; // No Splitting.
+            }
+
+            /** {@inheritDoc} */
+            @Override public long estimateSize() {
+                return nonZeroElements();
+            }
+
+            /** {@inheritDoc} */
+            @Override public int characteristics() {
+                return ORDERED | SIZED;
+            }
+        };
+    }
+
+    /** {@inheritDoc} */
     @Override public Matrix assignColumn(int col, Vector vec) {
         checkColumnIndex(col);
 
@@ -442,7 +523,7 @@ public abstract class AbstractMatrix implements Matrix {
             throw new CardinalityException(cols, vec.size());
 
         if (sto.isArrayBased() && vec.getStorage().isArrayBased())
-            System.arraycopy(vec.getStorage().data(), 0, sto.data()[row], 0, cols);
+            System.arraycopy(vec.getStorage().data(), 0, sto.data(), cols * row, cols);
         else
             for (int y = 0; y < cols; y++)
                 storageSet(row, y, vec.getX(y));
@@ -623,7 +704,7 @@ public abstract class AbstractMatrix implements Matrix {
             throw new CardinalityException(cols, data.length);
 
         if (sto.isArrayBased())
-            System.arraycopy(data, 0, sto.data()[row], 0, cols);
+            System.arraycopy(data, 0, sto.data(), row * cols, cols);
         else
             for (int y = 0; y < cols; y++)
                 setX(row, y, data[y]);
@@ -880,4 +961,9 @@ public abstract class AbstractMatrix implements Matrix {
 
         return (sto != null ? sto.equals(that.getStorage()) : that.getStorage() == null);
     }
+
+    /** {@inheritDoc} */
+    @Override public void compute(int row, int col, IgniteTriFunction<Integer, Integer, Double, Double> f) {
+        setX(row, col, f.apply(row, col, getX(row, col)));
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java
index f95e0cc..393fff6 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java
@@ -18,6 +18,8 @@
 package org.apache.ignite.ml.math.impls.matrix;
 
 import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.OrderedMatrix;
+import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.impls.storage.matrix.ArrayMatrixStorage;
 import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
@@ -30,7 +32,7 @@ import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
  * local, non-distributed execution is satisfactory and on-heap JVM storage is enough
  * to keep the entire data set.
  */
-public class DenseLocalOnHeapMatrix extends AbstractMatrix {
+public class DenseLocalOnHeapMatrix extends AbstractMatrix implements OrderedMatrix {
     /**
      *
      */
@@ -43,44 +45,89 @@ public class DenseLocalOnHeapMatrix extends AbstractMatrix {
      * @param cols Amount of columns in matrix.
      */
     public DenseLocalOnHeapMatrix(int rows, int cols) {
+        this(rows, cols, StorageConstants.ROW_STORAGE_MODE);
+    }
+
+    /**
+     * @param rows Amount of rows in matrix.
+     * @param cols Amount of columns in matrix.
+     * @param acsMode Storage order (row or column-based).
+     */
+    public DenseLocalOnHeapMatrix(int rows, int cols, int acsMode) {
         assert rows > 0;
         assert cols > 0;
 
-        setStorage(new ArrayMatrixStorage(rows, cols));
+        setStorage(new ArrayMatrixStorage(rows, cols, acsMode));
+    }
+
+    /**
+     * @param mtx Backing data array.
+     * @param acsMode Access mode.
+     */
+    public DenseLocalOnHeapMatrix(double[][] mtx, int acsMode) {
+        assert mtx != null;
+
+        setStorage(new ArrayMatrixStorage(mtx, acsMode));
     }
 
     /**
      * @param mtx Backing data array.
      */
     public DenseLocalOnHeapMatrix(double[][] mtx) {
+        this(mtx, StorageConstants.ROW_STORAGE_MODE);
+    }
+
+    /**
+     * @param mtx Backing data array.
+     * @param acsMode Access mode.
+     */
+    public DenseLocalOnHeapMatrix(double[] mtx, int rows, int acsMode) {
         assert mtx != null;
 
-        setStorage(new ArrayMatrixStorage(mtx));
+        setStorage(new ArrayMatrixStorage(mtx, rows, acsMode));
     }
 
     /**
-     * @param orig Original matrix.
+     * Build new matrix from flat raw array.
      */
+    public DenseLocalOnHeapMatrix(double[] mtx, int rows) {
+        this(mtx, StorageConstants.ROW_STORAGE_MODE, rows);
+    }
+
+    /** */
     private DenseLocalOnHeapMatrix(DenseLocalOnHeapMatrix orig) {
+        this(orig, orig.accessMode());
+    }
+
+    /**
+     * @param orig Original matrix.
+     * @param acsMode Access mode.
+     */
+    private DenseLocalOnHeapMatrix(DenseLocalOnHeapMatrix orig, int acsMode) {
         assert orig != null;
 
-        setStorage(new ArrayMatrixStorage(orig.rowSize(), orig.columnSize()));
+        setStorage(new ArrayMatrixStorage(orig.rowSize(), orig.columnSize(), acsMode));
 
         assign(orig);
     }
 
     /** {@inheritDoc} */
     @Override public Matrix copy() {
-        return new DenseLocalOnHeapMatrix(this);
+        return new DenseLocalOnHeapMatrix(this, accessMode());
     }
 
     /** {@inheritDoc} */
     @Override public Matrix like(int rows, int cols) {
-        return new DenseLocalOnHeapMatrix(rows, cols);
+        return new DenseLocalOnHeapMatrix(rows, cols, getStorage() != null ? accessMode() : StorageConstants.ROW_STORAGE_MODE);
     }
 
     /** {@inheritDoc} */
     @Override public Vector likeVector(int crd) {
         return new DenseLocalOnHeapVector(crd);
     }
+
+    /** */
+    @Override public int accessMode() {
+        return ((ArrayMatrixStorage)getStorage()).accessMode();
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/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
index d711295..d0a5937 100644
--- 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
@@ -17,10 +17,14 @@
 
 package org.apache.ignite.ml.math.impls.matrix;
 
+import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
+import it.unimi.dsi.fastutil.ints.IntIterator;
+import it.unimi.dsi.fastutil.ints.IntSet;
 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.functions.IgniteTriFunction;
 import org.apache.ignite.ml.math.impls.storage.matrix.SparseLocalOnHeapMatrixStorage;
 import org.apache.ignite.ml.math.impls.vector.SparseLocalVector;
 
@@ -62,6 +66,24 @@ public class SparseLocalOnHeapMatrix extends AbstractMatrix implements StorageCo
     }
 
     /** {@inheritDoc} */
+    @Override public int nonZeroElements() {
+        int res = 0;
+        IntIterator rowIter = indexesMap().keySet().iterator();
+
+        while (rowIter.hasNext()) {
+            int row = rowIter.nextInt();
+            res += indexesMap().get(row).size();
+        }
+
+        return res;
+    }
+
+    /** */
+    public Int2ObjectArrayMap<IntSet> indexesMap() {
+        return ((SparseLocalOnHeapMatrixStorage)getStorage()).indexesMap();
+    }
+
+    /** {@inheritDoc} */
     @Override public Matrix copy() {
         Matrix cp = like(rowSize(), columnSize());
 
@@ -69,4 +91,9 @@ public class SparseLocalOnHeapMatrix extends AbstractMatrix implements StorageCo
 
         return cp;
     }
+
+    /** {@inheritDoc} */
+    @Override public void compute(int row, int col, IgniteTriFunction<Integer, Integer, Double, Double> f) {
+        ((SparseLocalOnHeapMatrixStorage)getStorage()).compute(row, col, f);
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/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
index 397bf93..1f337fd 100644
--- 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
@@ -22,17 +22,24 @@ import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.Arrays;
 import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.functions.IgniteIntIntToIntBiFunction;
+import org.apache.ignite.ml.math.util.MatrixUtil;
 
 /**
  * Array based {@link MatrixStorage} implementation.
  */
 public class ArrayMatrixStorage implements MatrixStorage {
     /** Backing data array. */
-    private double[][] data;
+    private double[] data;
     /** Amount of rows in the matrix. */
     private int rows;
     /** Amount of columns in the matrix. */
     private int cols;
+    /** Mode specifying if this matrix is row-major or column-major. */
+    private int acsMode;
+    /** Index mapper */
+    private IgniteIntIntToIntBiFunction idxMapper;
 
     /**
      *
@@ -46,32 +53,62 @@ public class ArrayMatrixStorage implements MatrixStorage {
      * @param cols Amount of columns in the matrix.
      */
     public ArrayMatrixStorage(int rows, int cols) {
+        this(rows, cols, StorageConstants.ROW_STORAGE_MODE);
+    }
+
+    /** */
+    public ArrayMatrixStorage(int rows, int cols, int acsMode) {
         assert rows > 0;
         assert cols > 0;
 
-        this.data = new double[rows][cols];
+        this.data = new double[rows * cols];
         this.rows = rows;
         this.cols = cols;
+        idxMapper = indexMapper(acsMode);
+        this.acsMode = acsMode;
+    }
+
+    /**
+     * @param data Backing data array.
+     */
+    public ArrayMatrixStorage(double[][] data, int acsMode) {
+        this(MatrixUtil.flatten(data, acsMode), data.length, acsMode);
     }
 
     /**
      * @param data Backing data array.
      */
     public ArrayMatrixStorage(double[][] data) {
+        this(MatrixUtil.flatten(data, StorageConstants.ROW_STORAGE_MODE), data.length);
+    }
+
+    /**
+     * @param data Backing data array.
+     */
+    public ArrayMatrixStorage(double[] data, int rows, int acsMode) {
         assert data != null;
-        assert data[0] != null;
+        assert data.length % rows == 0;
 
         this.data = data;
-        this.rows = data.length;
-        this.cols = data[0].length;
+        this.rows = rows;
+        this.cols = data.length / rows;
+        idxMapper = indexMapper(acsMode);
+        this.acsMode = acsMode;
 
         assert rows > 0;
         assert cols > 0;
     }
 
+    /**
+     * @param data Backing data array.
+     */
+    public ArrayMatrixStorage(double[] data, int rows) {
+        this(data, rows, StorageConstants.ROW_STORAGE_MODE);
+    }
+
     /** {@inheritDoc} */
     @Override public double get(int x, int y) {
-        return data[x][y];
+        return data[idxMapper.apply(x, y)];
     }
 
     /** {@inheritDoc} */
@@ -96,7 +133,7 @@ public class ArrayMatrixStorage implements MatrixStorage {
 
     /** {@inheritDoc} */
     @Override public void set(int x, int y, double v) {
-        data[x][y] = v;
+        data[idxMapper.apply(x, y)] = v;
     }
 
     /** {@inheritDoc} */
@@ -115,14 +152,25 @@ public class ArrayMatrixStorage implements MatrixStorage {
     }
 
     /** {@inheritDoc} */
-    @Override public double[][] data() {
+    @Override public double[] data() {
         return data;
     }
 
+    /**
+     * Get the index mapper for given access mode.
+     *
+     * @param acsMode Access mode.
+     */
+    private IgniteIntIntToIntBiFunction indexMapper(int acsMode) {
+        return acsMode == StorageConstants.ROW_STORAGE_MODE ? (r, c) -> r * cols + c :
+            (r, c) -> c * rows + r;
+    }
+
     /** {@inheritDoc} */
     @Override public void writeExternal(ObjectOutput out) throws IOException {
         out.writeInt(rows);
         out.writeInt(cols);
+        out.writeInt(acsMode);
 
         out.writeObject(data);
     }
@@ -131,8 +179,15 @@ public class ArrayMatrixStorage implements MatrixStorage {
     @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
         rows = in.readInt();
         cols = in.readInt();
+        acsMode = in.readInt();
+        idxMapper = indexMapper(acsMode);
+
+        data = (double[])in.readObject();
+    }
 
-        data = (double[][])in.readObject();
+    /** Get the access mode of this storage. */
+    public int accessMode() {
+        return acsMode;
     }
 
     /** {@inheritDoc} */
@@ -141,7 +196,8 @@ public class ArrayMatrixStorage implements MatrixStorage {
 
         res += res * 37 + rows;
         res += res * 37 + cols;
-        res += res * 37 + Arrays.deepHashCode(data);
+        res += res * 37 + acsMode;
+        res += res * 37 + Arrays.hashCode(data);
 
         return res;
     }
@@ -156,6 +212,6 @@ public class ArrayMatrixStorage implements MatrixStorage {
 
         ArrayMatrixStorage that = (ArrayMatrixStorage)o;
 
-        return Arrays.deepEquals(data, that.data);
+        return acsMode == that.acsMode && Arrays.equals(data, that.data);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/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
index 7405a4e..f58da65 100644
--- 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
@@ -122,7 +122,7 @@ public class DenseOffHeapMatrixStorage implements MatrixStorage {
     }
 
     /** {@inheritDoc} */
-    @Override public double[][] data() {
+    @Override public double[] data() {
         return null;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/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
index 1f77d0f..f185479 100644
--- 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
@@ -150,7 +150,7 @@ public class MatrixDelegateStorage implements MatrixStorage {
     }
 
     /** {@inheritDoc} */
-    @Override public double[][] data() {
+    @Override public double[] data() {
         return sto.data();
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/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
index 1513502..fc7d969 100644
--- 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
@@ -116,9 +116,7 @@ public class SparseDistributedMatrixStorage extends CacheUtils implements Matrix
         // Random cache name.
         cfg.setName(ML_CACHE_NAME);
 
-        IgniteCache<IgniteBiTuple<Integer, IgniteUuid>, Map<Integer, Double>> cache = Ignition.localIgnite().getOrCreateCache(cfg);
-
-        return cache;
+        return Ignition.localIgnite().getOrCreateCache(cfg);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/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
index b33cb26..daf1d4b 100644
--- 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
@@ -19,6 +19,8 @@ package org.apache.ignite.ml.math.impls.storage.matrix;
 
 import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap;
 import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
+import it.unimi.dsi.fastutil.ints.IntSet;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
@@ -26,6 +28,7 @@ import java.util.HashMap;
 import java.util.Map;
 import org.apache.ignite.ml.math.MatrixStorage;
 import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.functions.IgniteTriFunction;
 
 /**
  * Storage for sparse, local, on-heap matrix.
@@ -225,4 +228,19 @@ public class SparseLocalOnHeapMatrixStorage implements MatrixStorage, StorageCon
         return rows == that.rows && cols == that.cols && acsMode == that.acsMode && stoMode == that.stoMode
             && (sto != null ? sto.equals(that.sto) : that.sto == null);
     }
+
+    /** */
+    public void compute(int row, int col, IgniteTriFunction<Integer, Integer, Double, Double> f) {
+        sto.get(row).compute(col, (c, val) -> f.apply(row, c, val));
+    }
+
+    /** */
+    public Int2ObjectArrayMap<IntSet> indexesMap() {
+        Int2ObjectArrayMap<IntSet> res = new Int2ObjectArrayMap<>();
+
+        for (Integer row : sto.keySet())
+            res.put(row.intValue(), (IntSet)sto.get(row).keySet());
+
+        return res;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java
index deef010..3323a07 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java
@@ -19,6 +19,7 @@ package org.apache.ignite.ml.math.impls.storage.vector;
 
 import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap;
 import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap;
+import it.unimi.dsi.fastutil.ints.IntSet;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
@@ -178,4 +179,9 @@ public class SparseLocalOnHeapVectorStorage implements VectorStorage, StorageCon
 
         return res;
     }
+
+    /** */
+    public IntSet indexes() {
+        return (IntSet)sto.keySet();
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java
index e48542b..1de334f 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java
@@ -22,6 +22,7 @@ import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.VectorStorage;
 import org.apache.ignite.ml.math.functions.IgniteBiFunction;
 import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteIntDoubleToDoubleBiFunction;
 import org.apache.ignite.ml.math.impls.matrix.FunctionMatrix;
 
 /**
@@ -122,4 +123,9 @@ public abstract class AbstractReadOnlyVector extends AbstractVector {
 
         return new FunctionVector(size(), (idx) -> Math.log1p(get(idx)) / denominator);
     }
+
+    /** {@inheritDoc} */
+    @Override public void compute(int idx, IgniteIntDoubleToDoubleBiFunction f) {
+        throw new UnsupportedOperationException();
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java
index 83ac837..131a610 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java
@@ -38,6 +38,7 @@ import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
 import org.apache.ignite.ml.math.functions.Functions;
 import org.apache.ignite.ml.math.functions.IgniteBiFunction;
 import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteIntDoubleToDoubleBiFunction;
 import org.apache.ignite.ml.math.impls.matrix.MatrixView;
 import org.jetbrains.annotations.NotNull;
 
@@ -904,4 +905,11 @@ public abstract class AbstractVector implements Vector {
 
         return (sto != null ? sto.equals(that.sto) : that.sto == null);
     }
+
+    /** {@inheritDoc} */
+    @Override public void compute(int idx, IgniteIntDoubleToDoubleBiFunction f) {
+        storageSet(idx, f.apply(idx, storageGet(idx)));
+        lenSq = 0.0;
+        maxElm = minElm = null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java
index 48fbd06..1df9acc 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java
@@ -30,6 +30,7 @@ import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.VectorStorage;
 import org.apache.ignite.ml.math.functions.IgniteBiFunction;
 import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteIntDoubleToDoubleBiFunction;
 
 /**
  * Convenient class that can be used to add decorations to an existing vector. Subclasses
@@ -367,6 +368,11 @@ public class DelegatingVector implements Vector {
     }
 
     /** {@inheritDoc} */
+    @Override public void compute(int i, IgniteIntDoubleToDoubleBiFunction f) {
+        dlg.compute(i, f);
+    }
+
+    /** {@inheritDoc} */
     @Override public void destroy() {
         dlg.destroy();
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java
index 9e345bb..bc1e59d 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java
@@ -17,7 +17,11 @@
 
 package org.apache.ignite.ml.math.impls.vector;
 
+import it.unimi.dsi.fastutil.ints.IntSet;
 import java.util.Map;
+import java.util.Set;
+import java.util.Spliterator;
+import java.util.function.Consumer;
 import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.Vector;
@@ -77,4 +81,39 @@ public class SparseLocalVector extends AbstractVector implements StorageConstant
         else
             return super.times(x);
     }
+
+    /** Indexes of non-default elements. */
+    public IntSet indexes() {
+        return storage().indexes();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Spliterator<Double> nonZeroSpliterator() {
+        return new Spliterator<Double>() {
+            /** {@inheritDoc} */
+            @Override public boolean tryAdvance(Consumer<? super Double> act) {
+                Set<Integer> indexes = storage().indexes();
+
+                for (Integer index : indexes)
+                    act.accept(storageGet(index));
+
+                return true;
+            }
+
+            /** {@inheritDoc} */
+            @Override public Spliterator<Double> trySplit() {
+                return null; // No Splitting.
+            }
+
+            /** {@inheritDoc} */
+            @Override public long estimateSize() {
+                return storage().indexes().size();
+            }
+
+            /** {@inheritDoc} */
+            @Override public int characteristics() {
+                return ORDERED | SIZED;
+            }
+        };
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
index 752929d..c727e44 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
@@ -20,12 +20,14 @@ package org.apache.ignite.ml.math.util;
 import java.util.List;
 import org.apache.ignite.internal.util.GridArgumentCheck;
 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.impls.matrix.CacheMatrix;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
 import org.apache.ignite.ml.math.impls.matrix.MatrixView;
 import org.apache.ignite.ml.math.impls.matrix.PivotedMatrixView;
 import org.apache.ignite.ml.math.impls.matrix.RandomMatrix;
+import org.apache.ignite.ml.math.impls.matrix.SparseLocalOnHeapMatrix;
 import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
 
 /**
@@ -116,6 +118,18 @@ public class MatrixUtil {
     }
 
     /** */
+    public static DenseLocalOnHeapMatrix asDense(SparseLocalOnHeapMatrix m, int acsMode) {
+        DenseLocalOnHeapMatrix res = new DenseLocalOnHeapMatrix(m.rowSize(), m.columnSize(), acsMode);
+
+        for (Integer row : m.indexesMap().keySet()) {
+            for (Integer col : m.indexesMap().get(row))
+                res.set(row, col, m.get(row, col));
+        }
+
+        return res;
+    }
+
+    /** */
     private static boolean isCopyLikeSupport(Matrix matrix) {
         return matrix instanceof RandomMatrix || matrix instanceof MatrixView || matrix instanceof CacheMatrix ||
             matrix instanceof PivotedMatrixView;
@@ -152,4 +166,38 @@ public class MatrixUtil {
 
         return res;
     }
+
+    /** */
+    public static double[][] unflatten(double[] fArr, int colsCnt) {
+        int rowsCnt = fArr.length / colsCnt;
+
+        double[][] res = new double[rowsCnt][colsCnt];
+
+        for (int i = 0; i < rowsCnt; i++)
+            for (int j = 0; j < colsCnt; j++)
+                res[i][j] = fArr[i * colsCnt + j];
+
+        return res;
+    }
+
+    /** */
+    public static double[] flatten(double[][] arr, int acsMode) {
+        assert arr != null;
+        assert arr[0] != null;
+
+        int size = arr.length * arr[0].length;
+        int rows = acsMode == StorageConstants.ROW_STORAGE_MODE ? arr.length : arr[0].length;
+        int cols = size / rows;
+
+        double[] res = new double[size];
+
+        int iLim = acsMode == StorageConstants.ROW_STORAGE_MODE ? rows : cols;
+        int jLim = acsMode == StorageConstants.ROW_STORAGE_MODE ? cols : rows;
+
+        for (int i = 0; i < iLim; i++)
+            for (int j = 0; j < jLim; j++)
+                res[i * jLim + j] = arr[i][j];
+
+        return res;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java
index cdc2651..a59b7f9 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java
@@ -130,8 +130,8 @@ public class KMeansDistributedClustererTest extends GridCommonAbstractTest {
         Vector[] mc = new Vector[centersCnt];
         Arrays.fill(mc, VectorUtils.zeroes(2));
 
-        int centIndex = 0;
-        int totalCount = 0;
+        int centIdx = 0;
+        int totalCnt = 0;
 
         List<Vector> massCenters = new ArrayList<>();
 
@@ -140,12 +140,12 @@ public class KMeansDistributedClustererTest extends GridCommonAbstractTest {
                 DenseLocalOnHeapVector pnt = (DenseLocalOnHeapVector)new DenseLocalOnHeapVector(2).assign(centers.get(count));
                 // pertrubate point on random value.
                 pnt.map(val -> val + rnd.nextDouble() * squareSideLen / 100);
-                mc[centIndex] = mc[centIndex].plus(pnt);
-                points.assignRow(permutation.get(totalCount), pnt);
-                totalCount++;
+                mc[centIdx] = mc[centIdx].plus(pnt);
+                points.assignRow(permutation.get(totalCnt), pnt);
+                totalCnt++;
             }
-            massCenters.add(mc[centIndex].times(1 / (double)count));
-            centIndex++;
+            massCenters.add(mc[centIdx].times(1 / (double)count));
+            centIdx++;
         }
 
         EuclideanDistance dist = new EuclideanDistance();
@@ -169,6 +169,7 @@ public class KMeansDistributedClustererTest extends GridCommonAbstractTest {
         /** */
         List<Vector> orderedNodes;
 
+        /** */
         public OrderedNodesComparator(Vector[] orderedNodes, DistanceMeasure measure) {
             this.orderedNodes = Arrays.asList(orderedNodes);
             this.measure = measure;


Mime
View raw message