You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/04/17 08:21:48 UTC

[26/50] [abbrv] ignite git commit: IGNITE-4572 Machine Learning: Develop distributed algebra support for dense and sparse data sets.

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/MatrixVectorView.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/MatrixVectorView.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/MatrixVectorView.java
new file mode 100644
index 0000000..8f32a89
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/MatrixVectorView.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.impls.vector;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.IndexException;
+import org.apache.ignite.math.impls.storage.vector.MatrixVectorStorage;
+
+/**
+ * Row or column vector view off the matrix.
+ */
+public class MatrixVectorView extends AbstractVector {
+    /** */ private Matrix parent;
+
+    /** */ private int row;
+    /** */ private int col;
+    
+    /** */ private int rowStride;
+    /** */ private int colStride;
+
+    /**
+     *
+     */
+    public MatrixVectorView() {
+        // No-op.
+    }
+
+    /**
+     * @param parent
+     * @param row
+     * @param col
+     * @param rowStride
+     * @param colStride
+     */
+    public MatrixVectorView(Matrix parent, int row, int col, int rowStride, int colStride) {
+        assert parent != null;
+
+        if (row < 0 || row >= parent.rowSize())
+            throw new IndexException(row);
+        if (col < 0 || col >= parent.columnSize())
+            throw new IndexException(col);
+
+        this.parent = parent;
+
+        this.row = row;
+        this.col = col;
+
+        this.rowStride = rowStride;
+        this.colStride = colStride;
+
+        setStorage(new MatrixVectorStorage(parent, row, col, rowStride, colStride));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector copy() {
+        return new MatrixVectorView(parent, row, col, rowStride, colStride);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector like(int crd) {
+        return parent.likeVector(crd);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix likeMatrix(int rows, int cols) {
+        return parent.like(rows, cols);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        super.writeExternal(out);
+
+        out.writeObject(parent);
+        out.writeInt(row);
+        out.writeInt(col);
+        out.writeInt(rowStride);
+        out.writeInt(colStride);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        super.readExternal(in);
+
+        parent = (Matrix)in.readObject();
+        row = in.readInt();
+        col = in.readInt();
+        rowStride = in.readInt();
+        colStride = in.readInt();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + (parent == null ? 0 : parent.hashCode());
+        res = res * 37 + row;
+        res = res * 37 + col;
+        res = res * 37 + rowStride;
+        res = res * 37 + colStride;
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        MatrixVectorView that = (MatrixVectorView)o;
+
+        return (parent != null ? parent.equals(that.parent) : that.parent == null) &&
+            row == that.row &&
+            col == that.col &&
+            rowStride == that.rowStride &&
+            colStride == that.colStride;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/PivotedVectorView.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/PivotedVectorView.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/PivotedVectorView.java
new file mode 100644
index 0000000..cc9e835
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/PivotedVectorView.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.impls.vector;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.math.functions.Functions;
+import org.apache.ignite.math.impls.storage.vector.PivotedVectorStorage;
+
+/**
+ * Pivoted (index mapped) view over another vector.
+ */
+public class PivotedVectorView extends AbstractVector {
+    /** */ private Vector vec;
+
+    /**
+     * @param vec
+     * @param pivot Mapping from external index to internal.
+     * @param unpivot Mapping from internal index to external.
+     */
+    public PivotedVectorView(Vector vec, int[] pivot, int[] unpivot) {
+        setStorage(new PivotedVectorStorage(vec.getStorage(), pivot, unpivot));
+
+        checkCardinality(pivot);
+        checkCardinality(unpivot);
+
+        this.vec = vec;
+    }
+
+    /**
+     * @param vec
+     * @param pivot
+     */
+    public PivotedVectorView(Vector vec, int[] pivot) {
+        setStorage(new PivotedVectorStorage(vec.getStorage(), pivot));
+
+        checkCardinality(pivot);
+
+        this.vec = vec;
+    }
+
+    /**
+     *
+     *
+     */
+    private PivotedVectorStorage storage() {
+        return (PivotedVectorStorage)getStorage();
+    }
+
+    /**
+     *
+     */
+    public PivotedVectorView() {
+        // No-op.
+    }
+
+    /**
+     *
+     *
+     */
+    public Vector getBaseVector() {
+        return vec;
+    }
+
+    /**
+     * @param i
+     */
+    public int pivot(int i) {
+        return storage().pivot()[i];
+    }
+
+    /**
+     * @param i
+     */
+    public int unpivot(int i) {
+        return storage().unpivot()[i];
+    }
+
+    /**
+     * @param idx
+     */
+    protected Vector.Element makeElement(int idx) {
+        checkIndex(idx);
+
+        // External index.
+        int exIdx = storage().pivot()[idx];
+
+        return new Vector.Element() {
+            /** {@inheritDoc */
+            @Override public double get() {
+                return storageGet(idx);
+            }
+
+            /** {@inheritDoc */
+            @Override public int index() {
+                return exIdx;
+            }
+
+            /** {@inheritDoc */
+            @Override public void set(double val) {
+                storageSet(idx, val);
+            }
+        };
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector copy() {
+        PivotedVectorStorage sto = storage();
+
+        return new PivotedVectorView(vec, sto.pivot(), sto.unpivot());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector like(int crd) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix likeMatrix(int rows, int cols) {
+        return vec.likeMatrix(rows, cols);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector times(double x) {
+        if (x == 0.0)
+            return copy().map(Functions.mult(x));
+        else
+            return super.times(x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        super.writeExternal(out);
+
+        out.writeObject(vec);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        super.readExternal(in);
+
+        vec = (Vector)in.readObject();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/RandomVector.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/RandomVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/RandomVector.java
new file mode 100644
index 0000000..c9121c9
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/RandomVector.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.impls.vector;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Map;
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.VectorStorage;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.math.impls.matrix.RandomMatrix;
+import org.apache.ignite.math.impls.storage.vector.RandomVectorStorage;
+
+/**
+ * Random vector. Each value is taken from {-1,0,1} with roughly equal probability. Note
+ * that by default, the value is determined by a relatively simple hash of the index.
+ */
+public class RandomVector extends AbstractReadOnlyVector {
+    /** */ private boolean fastHash;
+
+    /**
+     * @param size Vector cardinality.
+     * @param fastHash
+     */
+    private VectorStorage mkStorage(int size, boolean fastHash) {
+        this.fastHash = fastHash;
+
+        return new RandomVectorStorage(size, fastHash);
+    }
+
+    /**
+     * @param size
+     * @param fastHash
+     */
+    public RandomVector(int size, boolean fastHash) {
+        setStorage(mkStorage(size, fastHash));
+    }
+
+    /**
+     * @param size
+     */
+    public RandomVector(int size) {
+        this(size, true);
+    }
+
+    /**
+     * @param args
+     */
+    public RandomVector(Map<String, Object> args) {
+        assert args != null;
+
+        if (args.containsKey("size") && args.containsKey("fastHash"))
+            setStorage(mkStorage((int)args.get("size"), (boolean)args.get("fastHash")));
+        else if (args.containsKey("size"))
+            setStorage(mkStorage((int)args.get("size"), true));
+        else
+            throw new UnsupportedOperationException("Invalid constructor argument(s).");
+    }
+
+    /** */
+    public RandomVector() {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public org.apache.ignite.math.Vector like(int crd) {
+        return new RandomVector(crd, fastHash);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix likeMatrix(int rows, int cols) {
+        return new RandomMatrix(rows, cols);
+    }
+
+    /** {@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();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + Boolean.hashCode(fastHash);
+        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;
+
+        RandomVector that = (RandomVector)o;
+        VectorStorage sto = getStorage();
+
+        return fastHash == that.fastHash && (sto != null ? sto.equals(that.getStorage()) : that.getStorage() == null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SingleElementVector.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SingleElementVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SingleElementVector.java
new file mode 100644
index 0000000..8d19ee0
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SingleElementVector.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.impls.vector;
+
+import java.util.Map;
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.math.impls.storage.vector.SingleElementVectorStorage;
+
+/**
+ * Read-write vector holding a single non-zero value at some index.
+ */
+public class SingleElementVector extends AbstractVector {
+    /**
+     *
+     */
+    public SingleElementVector() {
+        // No-op
+    }
+
+    /**
+     * @param size
+     * @param idx
+     * @param val
+     */
+    public SingleElementVector(int size, int idx, double val) {
+        super(new SingleElementVectorStorage(size, idx, val));
+    }
+
+    /**
+     * @param args
+     */
+    public SingleElementVector(Map<String, Object> args) {
+        assert args != null;
+
+        if (args.containsKey("size") && args.containsKey("index") && args.containsKey("value")) {
+            int size = (int)args.get("size");
+            int idx = (int)args.get("index");
+            double val = (double)args.get("value");
+
+            setStorage(new SingleElementVectorStorage(size, idx, val));
+        }
+        else
+            throw new UnsupportedOperationException("Invalid constructor argument(s).");
+    }
+
+    /**
+     *
+     *
+     */
+    private SingleElementVectorStorage storage() {
+        return (SingleElementVectorStorage)getStorage();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Element minElement() {
+        return makeElement(storage().index());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Element maxElement() {
+        return makeElement(storage().index());
+    }
+
+    /** {@inheritDoc} */
+    @Override public double sum() {
+        return getX(storage().index());
+    }
+
+    /** {@inheritDoc} */
+    @Override public int nonZeroElements() {
+        return isZero(get(storage().index())) ? 0 : 1;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector like(int crd) {
+        int idx = storage().index();
+
+        return new SingleElementVector(crd, idx, getX(idx));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix likeMatrix(int rows, int cols) {
+        throw new UnsupportedOperationException();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SingleElementVectorView.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SingleElementVectorView.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SingleElementVectorView.java
new file mode 100644
index 0000000..76a1c0a
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SingleElementVectorView.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.math.impls.vector;
+
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.math.functions.Functions;
+import org.apache.ignite.math.impls.storage.vector.SingleElementVectorDelegateStorage;
+
+/**
+ * Single value vector view over another vector.
+ */
+public class SingleElementVectorView extends AbstractVector {
+    /**
+     *
+     */
+    public SingleElementVectorView() {
+        // No-op.
+    }
+
+    /**
+     * @param vec
+     * @param idx
+     */
+    public SingleElementVectorView(Vector vec, int idx) {
+        super(new SingleElementVectorDelegateStorage(vec, idx));
+    }
+
+    /**
+     *
+     *
+     */
+    private SingleElementVectorDelegateStorage storage() {
+        return (SingleElementVectorDelegateStorage)getStorage();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector.Element minElement() {
+        return makeElement(storage().index());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector.Element maxElement() {
+        return makeElement(storage().index());
+    }
+
+    /** {@inheritDoc} */
+    @Override public double sum() {
+        return getX(storage().index());
+    }
+
+    /** {@inheritDoc} */
+    @Override public int nonZeroElements() {
+        return isZero(getX(storage().index())) ? 0 : 1;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector copy() {
+        SingleElementVectorDelegateStorage sto = storage();
+
+        return new SingleElementVectorView(sto.delegate(), sto.index());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector times(double x) {
+        if (x == 0.0)
+            return copy().map(Functions.mult(x));
+        else
+            return super.times(x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector like(int crd) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix likeMatrix(int rows, int cols) {
+        throw new UnsupportedOperationException();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SparseLocalOffHeapVector.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SparseLocalOffHeapVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SparseLocalOffHeapVector.java
new file mode 100644
index 0000000..2fd1c57
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SparseLocalOffHeapVector.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.impls.vector;
+
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.impls.storage.vector.SparseLocalOffHeapVectorStorage;
+
+/**
+ * Implementation for {@link Vector} assuming sparse logic and local offheap JVM storage.
+ * It is suitable for data sets where local, non-distributed execution is satisfactory and on-heap JVM storage
+ * is not enough to keep the entire data set.
+ * <p>See also: <a href="https://en.wikipedia.org/wiki/Sparse_array">Wikipedia article</a>.</p>
+ */
+public class SparseLocalOffHeapVector extends AbstractVector {
+    /**
+     * @param crd Vector cardinality.
+     */
+    public SparseLocalOffHeapVector(int crd) {
+        setStorage(new SparseLocalOffHeapVectorStorage(crd));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector like(int crd) {
+        return new SparseLocalOffHeapVector(crd);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix likeMatrix(int rows, int cols) {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SparseLocalVector.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SparseLocalVector.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SparseLocalVector.java
new file mode 100644
index 0000000..ebb6731
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/SparseLocalVector.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.impls.vector;
+
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.StorageConstants;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.impls.matrix.SparseLocalOnHeapMatrix;
+import org.apache.ignite.math.impls.storage.vector.SparseLocalOnHeapVectorStorage;
+
+/**
+ * Local on-heap sparse vector based on hash map storage.
+ */
+public class SparseLocalVector extends AbstractVector implements StorageConstants {
+    /**
+     *
+     */
+    public SparseLocalVector() {
+        // No-op.
+    }
+
+    /**
+     * @param size
+     * @param acsMode
+     */
+    public SparseLocalVector(int size, int acsMode) {
+        assertAccessMode(acsMode);
+
+        setStorage(new SparseLocalOnHeapVectorStorage(size, acsMode));
+    }
+
+    /** */
+    private SparseLocalOnHeapVectorStorage storage() {
+        return (SparseLocalOnHeapVectorStorage)getStorage();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector like(int crd) {
+        SparseLocalOnHeapVectorStorage sto = storage();
+
+        return new SparseLocalVector(crd, sto.getAccessMode());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix likeMatrix(int rows, int cols) {
+        return new SparseLocalOnHeapMatrix(rows, cols);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector times(double x) {
+        if (x == 0.0)
+            return assign(0);
+        else
+            return super.times(x);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/VectorView.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/VectorView.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/VectorView.java
new file mode 100644
index 0000000..ce51a45
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/VectorView.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.impls.vector;
+
+import java.io.Externalizable;
+import org.apache.ignite.math.Matrix;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.VectorStorage;
+import org.apache.ignite.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.math.impls.storage.vector.DelegateVectorStorage;
+
+/**
+ * Implements the partial view into the parent {@link Vector}.
+ */
+public class VectorView extends AbstractVector {
+    /**
+     * Constructor for {@link Externalizable} interface.
+     */
+    public VectorView() {
+        // No-op.
+    }
+
+    /**
+     * @param parent Backing parent {@link Vector}.
+     * @param off Offset to parent vector.
+     * @param len Size of the view.
+     */
+    public VectorView(Vector parent, int off, int len) {
+        super(new DelegateVectorStorage(parent.getStorage(), off, len));
+    }
+
+    /**
+     * @param sto Backing parent {@link VectorStorage}.
+     * @param off Offset to parent vector.
+     * @param len Size of the view.
+     */
+    public VectorView(VectorStorage sto, int off, int len) {
+        super(new DelegateVectorStorage(sto, off, len));
+    }
+
+    /** */
+    private DelegateVectorStorage storage() {
+        return (DelegateVectorStorage)getStorage();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector copy() {
+        DelegateVectorStorage sto = storage();
+
+        return new VectorView(sto.delegate(), sto.offset(), sto.length());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector like(int crd) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Matrix likeMatrix(int rows, int cols) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        return this == o ||
+            ((o != null)
+                && o.getClass() == getClass()
+                && (getStorage().equals(((VectorView)o).getStorage())));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/vector/package-info.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/vector/package-info.java b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/package-info.java
new file mode 100644
index 0000000..d6ca1f3
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/impls/vector/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 vectors.
+ */
+package org.apache.ignite.math.impls.vector;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/package-info.java
----------------------------------------------------------------------
diff --git a/modules/math/src/main/java/org/apache/ignite/math/package-info.java b/modules/math/src/main/java/org/apache/ignite/math/package-info.java
new file mode 100644
index 0000000..05ce651
--- /dev/null
+++ b/modules/math/src/main/java/org/apache/ignite/math/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 main APIs for distributed code algebra.
+ */
+package org.apache.ignite.math;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/resources/org/apache/ignite/math/d3-matrix-template.html
----------------------------------------------------------------------
diff --git a/modules/math/src/main/resources/org/apache/ignite/math/d3-matrix-template.html b/modules/math/src/main/resources/org/apache/ignite/math/d3-matrix-template.html
new file mode 100644
index 0000000..19a907a
--- /dev/null
+++ b/modules/math/src/main/resources/org/apache/ignite/math/d3-matrix-template.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<!--
+ 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.
+-->
+<meta charset="utf-8">
+<title>IgniteML</title>
+<style>
+    body {
+        margin: 0 15px;
+    }
+
+    p {
+        margin: 10px 0 !important;
+    }
+
+    .name {
+        font-size: 20px;
+        font-weight: 400;
+        font-family: monospace;
+    }
+
+    .swatch {
+        display: inline-block;
+        width: 25px;
+        height: 25px;
+        margin-left: 5px;
+        vertical-align: bottom;
+    }
+</style>
+<body>
+<img style="margin-top: 15px" width="100px" src="https://ignite.apache.org/images/logo3.png">
+<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>
+<script>
+    /*@DATA@*/
+    var data = [[{d: 2.256, r: 198, g: 128, b: 128}, {d: 0.123, r: 218, g: 228, b: 18}], [{
+        d: 2.256,
+        r: 108,
+        g: 28,
+        b: 108
+    }, {d: 0.123, r: 228, g: 228, b: 228}]];
+    /*@MAX@*/
+    var max = {d: 2.256, r: 128, g: 128, b: 128};
+    /*@MIN@*/
+    var min = {d: 0.123, r: 228, g: 228, b: 228};
+    /*@NAME@*/
+    var name = "Matrix";
+
+    var rows = data.length;
+    var cols = data[0].length;
+
+    var range = max.d - min.d;
+
+    var rw, rh;
+    var W, H;
+
+    if (cols > W) {
+        rw = 1;
+        W = cols;
+    }
+    else {
+        W = 1000;
+        rw = Math.min(Math.round(W / cols), 10);
+    }
+
+    if (rows > H) {
+        rh = 1;
+        H = rows;
+    }
+    else {
+        H = 1000;
+        rh = Math.min(Math.round(H / rows), 10);
+    }
+
+    d3.selectAll("body")
+        .append("p")
+        .text(name + " (" + rows + "x" + cols + ")")
+        .attr("class", "name");
+
+    d3.selectAll("body")
+        .append("p")
+        .attr("class", "name")
+        .text("Max: " + max.d)
+        .append("span")
+        .attr("class", "swatch")
+        .attr("style", "background-color: rgb(" + max.r + ", " + max.g + ", " + max.b + ")");
+
+    d3.selectAll("body")
+        .append("p")
+        .attr("class", "name")
+        .text("Min: " + min.d)
+        .append("span")
+        .attr("class", "swatch")
+        .attr("style", "background-color: rgb(" + min.r + ", " + min.g + ", " + min.b + ")");
+
+    var svg = d3.select("body").append("svg")
+        .attr("width", W)
+        .attr("height", H);
+
+    var y = 0;
+
+    for (var row = 0; row < rows; row++)
+        svg.selectAll("div")
+            .data(data[row])
+            .enter()
+            .append("rect")
+            .attr("x", function (d, i) {
+                return i * rw
+            })
+            .attr("y", rh * row)
+            .attr("fill", function (d) {
+                return "rgb(" + d.r + ", " + d.g + ", " + d.b + ")";
+            })
+            .attr("width", rw)
+            .attr("height", rh);
+</script>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/resources/org/apache/ignite/math/d3-vector-template.html
----------------------------------------------------------------------
diff --git a/modules/math/src/main/resources/org/apache/ignite/math/d3-vector-template.html b/modules/math/src/main/resources/org/apache/ignite/math/d3-vector-template.html
new file mode 100644
index 0000000..7644481
--- /dev/null
+++ b/modules/math/src/main/resources/org/apache/ignite/math/d3-vector-template.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+ 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.
+-->
+<meta charset="utf-8">
+<title>IgniteML</title>
+<style>
+    body {
+        margin: 0 15px;
+    }
+
+    p {
+        margin: 10px 0 !important;
+    }
+
+    .name {
+        font-size: 20px;
+        font-weight: 400;
+        font-family: monospace;
+    }
+
+    .swatch {
+        display: inline-block;
+        width: 25px;
+        height: 25px;
+        margin-left: 5px;
+        vertical-align: bottom;
+    }
+</style>
+<body>
+<img style="margin-top: 15px" width="100px" src="https://ignite.apache.org/images/logo3.png">
+<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>
+<script>
+    /*@DATA@*/
+    var data = [{d: 2.256, r: 128, g: 128, b: 128}, {d: 0.123, r: 228, g: 228, b: 228}];
+    /*@MAX@*/
+    var max = {d: 2.256, r: 128, g: 128, b: 128};
+    /*@MIN@*/
+    var min = {d: 0.123, r: 228, g: 228, b: 228};
+    /*@NAME@*/
+    var name = "Vector";
+
+    var W, H = 1000;
+
+    var range = max.d - min.d;
+
+    var rh = 20; // Constant.
+
+    var rw;
+
+    if (data.length > W) {
+        rw = 1;
+        W = data.length;
+    }
+    else {
+        W = 1000;
+        rw = Math.min(Math.round(W / data.length), 5);
+    }
+
+    d3.selectAll("body")
+        .append("p")
+        .text(name + " (size: " + data.length + ")")
+        .attr("class", "name");
+
+    d3.selectAll("body")
+        .append("p")
+        .attr("class", "name")
+        .text("Max: " + max.d)
+        .append("span")
+        .attr("class", "swatch")
+        .attr("style", "background-color: rgb(" + max.r + ", " + max.g + ", " + max.b + ")");
+
+    d3.selectAll("body")
+        .append("p")
+        .attr("class", "name")
+        .text("Min: " + min.d)
+        .append("span")
+        .attr("class", "swatch")
+        .attr("style", "background-color: rgb(" + min.r + ", " + min.g + ", " + min.b + ")");
+
+    var svg = d3.select("body").append("svg")
+        .attr("width", W)
+        .attr("height", H);
+
+    svg.selectAll("rect")
+        .data(data)
+        .enter()
+        .append("rect")
+        .attr("x", function (d, i) {
+            return i * rw
+        })
+        .attr("y", 10)
+        .attr("fill", function (d) {
+            return "rgb(" + d.r + ", " + d.g + ", " + d.b + ")";
+        })
+        .attr("width", rw)
+        .attr("height", rh);
+</script>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/ExternalizeTest.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/ExternalizeTest.java b/modules/math/src/test/java/org/apache/ignite/math/ExternalizeTest.java
new file mode 100644
index 0000000..218b7ff
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/ExternalizeTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import org.apache.ignite.math.impls.MathTestConstants;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Common test for externalization.
+ */
+public abstract class ExternalizeTest<T extends Externalizable & Destroyable> {
+    /** */
+    protected void externalizeTest(T initObj) {
+        T objRestored = null;
+
+        try {
+            ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream();
+            ObjectOutputStream objOutputStream = new ObjectOutputStream(byteArrOutputStream);
+
+            objOutputStream.writeObject(initObj);
+
+            ByteArrayInputStream byteArrInputStream = new ByteArrayInputStream(byteArrOutputStream.toByteArray());
+            ObjectInputStream objInputStream = new ObjectInputStream(byteArrInputStream);
+
+            objRestored = (T)objInputStream.readObject();
+
+            assertTrue(MathTestConstants.VAL_NOT_EQUALS, initObj.equals(objRestored));
+            assertTrue(MathTestConstants.VAL_NOT_EQUALS, Integer.compare(initObj.hashCode(), objRestored.hashCode()) == 0);
+        }
+        catch (ClassNotFoundException | IOException e) {
+            fail(e + " [" + e.getMessage() + "]");
+        }
+        finally {
+            if (objRestored != null)
+                objRestored.destroy();
+        }
+    }
+
+    /** */
+    @Test
+    public abstract void externalizeTest();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/MathImplDistributedTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/MathImplDistributedTestSuite.java b/modules/math/src/test/java/org/apache/ignite/math/MathImplDistributedTestSuite.java
new file mode 100644
index 0000000..318ea95
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/MathImplDistributedTestSuite.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math;
+
+import org.apache.ignite.math.impls.matrix.CacheMatrixTest;
+import org.apache.ignite.math.impls.matrix.SparseDistributedMatrixTest;
+import org.apache.ignite.math.impls.storage.matrix.SparseDistributedMatrixStorageTest;
+import org.apache.ignite.math.impls.vector.CacheVectorTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Test suite for all distributed tests located in org.apache.ignite.math.impls.* package.
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    CacheVectorTest.class,
+    CacheMatrixTest.class,
+    SparseDistributedMatrixStorageTest.class,
+    SparseDistributedMatrixTest.class,
+})
+public class MathImplDistributedTestSuite {
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/MathImplLocalTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/MathImplLocalTestSuite.java b/modules/math/src/test/java/org/apache/ignite/math/MathImplLocalTestSuite.java
new file mode 100644
index 0000000..a652e7f
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/MathImplLocalTestSuite.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math;
+
+import org.apache.ignite.math.decompositions.CholeskyDecompositionTest;
+import org.apache.ignite.math.decompositions.EigenDecompositionTest;
+import org.apache.ignite.math.decompositions.LUDecompositionTest;
+import org.apache.ignite.math.decompositions.QRDecompositionTest;
+import org.apache.ignite.math.decompositions.SingularValueDecompositionTest;
+import org.apache.ignite.math.impls.matrix.DenseLocalOffHeapMatrixConstructorTest;
+import org.apache.ignite.math.impls.matrix.DenseLocalOnHeapMatrixConstructorTest;
+import org.apache.ignite.math.impls.matrix.DiagonalMatrixTest;
+import org.apache.ignite.math.impls.matrix.FunctionMatrixConstructorTest;
+import org.apache.ignite.math.impls.matrix.MatrixAttributeTest;
+import org.apache.ignite.math.impls.matrix.MatrixImplementationsTest;
+import org.apache.ignite.math.impls.matrix.MatrixViewConstructorTest;
+import org.apache.ignite.math.impls.matrix.PivotedMatrixViewConstructorTest;
+import org.apache.ignite.math.impls.matrix.RandomMatrixConstructorTest;
+import org.apache.ignite.math.impls.matrix.SparseLocalOnHeapMatrixConstructorTest;
+import org.apache.ignite.math.impls.matrix.TransposedMatrixViewTest;
+import org.apache.ignite.math.impls.storage.matrix.MatrixArrayStorageTest;
+import org.apache.ignite.math.impls.storage.matrix.MatrixOffHeapStorageTest;
+import org.apache.ignite.math.impls.storage.matrix.MatrixStorageImplementationTest;
+import org.apache.ignite.math.impls.storage.vector.RandomAccessSparseVectorStorageTest;
+import org.apache.ignite.math.impls.storage.vector.SparseLocalOffHeapVectorStorageTest;
+import org.apache.ignite.math.impls.storage.vector.VectorArrayStorageTest;
+import org.apache.ignite.math.impls.storage.vector.VectorOffheapStorageTest;
+import org.apache.ignite.math.impls.vector.AbstractVectorTest;
+import org.apache.ignite.math.impls.vector.ConstantVectorConstructorTest;
+import org.apache.ignite.math.impls.vector.DelegatingVectorConstructorTest;
+import org.apache.ignite.math.impls.vector.DenseLocalOffHeapVectorConstructorTest;
+import org.apache.ignite.math.impls.vector.DenseLocalOnHeapVectorConstructorTest;
+import org.apache.ignite.math.impls.vector.FunctionVectorConstructorTest;
+import org.apache.ignite.math.impls.vector.MatrixVectorViewTest;
+import org.apache.ignite.math.impls.vector.PivotedVectorViewConstructorTest;
+import org.apache.ignite.math.impls.vector.RandomVectorConstructorTest;
+import org.apache.ignite.math.impls.vector.SingleElementVectorConstructorTest;
+import org.apache.ignite.math.impls.vector.SingleElementVectorViewConstructorTest;
+import org.apache.ignite.math.impls.vector.SparseLocalVectorConstructorTest;
+import org.apache.ignite.math.impls.vector.VectorAttributesTest;
+import org.apache.ignite.math.impls.vector.VectorFoldMapTest;
+import org.apache.ignite.math.impls.vector.VectorImplementationsTest;
+import org.apache.ignite.math.impls.vector.VectorIterableTest;
+import org.apache.ignite.math.impls.vector.VectorNormTest;
+import org.apache.ignite.math.impls.vector.VectorToMatrixTest;
+import org.apache.ignite.math.impls.vector.VectorViewTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Test suite for all local tests located in org.apache.ignite.math.impls.* package.
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    // Vector constructors tests.
+    DenseLocalOnHeapVectorConstructorTest.class,
+    DenseLocalOffHeapVectorConstructorTest.class,
+    SparseLocalVectorConstructorTest.class,
+    RandomVectorConstructorTest.class,
+    ConstantVectorConstructorTest.class,
+    FunctionVectorConstructorTest.class,
+    SingleElementVectorConstructorTest.class,
+    PivotedVectorViewConstructorTest.class,
+    SingleElementVectorViewConstructorTest.class,
+    DelegatingVectorConstructorTest.class,
+    // Various vectors tests.
+    AbstractVectorTest.class,
+    VectorImplementationsTest.class,
+    VectorViewTest.class,
+    MatrixVectorViewTest.class,
+    // Vector particular features tests.
+    VectorIterableTest.class,
+    VectorAttributesTest.class,
+    VectorToMatrixTest.class,
+    VectorNormTest.class,
+    VectorFoldMapTest.class,
+    // Vector storage tests
+    VectorArrayStorageTest.class,
+    VectorOffheapStorageTest.class,
+    RandomAccessSparseVectorStorageTest.class,
+    SparseLocalOffHeapVectorStorageTest.class,
+    // Matrix storage tests.
+    MatrixStorageImplementationTest.class,
+    MatrixOffHeapStorageTest.class,
+    MatrixArrayStorageTest.class,
+    // Matrix constructors tests.
+    DenseLocalOnHeapMatrixConstructorTest.class,
+    DenseLocalOffHeapMatrixConstructorTest.class,
+    RandomMatrixConstructorTest.class,
+    FunctionMatrixConstructorTest.class,
+    MatrixViewConstructorTest.class,
+    PivotedMatrixViewConstructorTest.class,
+    SparseLocalOnHeapMatrixConstructorTest.class,
+    // Matrix tests.
+    MatrixImplementationsTest.class,
+    DiagonalMatrixTest.class,
+    MatrixAttributeTest.class,
+    TransposedMatrixViewTest.class,
+    // Decomposes
+    LUDecompositionTest.class,
+    EigenDecompositionTest.class,
+    CholeskyDecompositionTest.class,
+    QRDecompositionTest.class,
+    SingularValueDecompositionTest.class
+})
+public class MathImplLocalTestSuite {
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/MathImplMainTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/MathImplMainTestSuite.java b/modules/math/src/test/java/org/apache/ignite/math/MathImplMainTestSuite.java
new file mode 100644
index 0000000..44fa8e6
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/MathImplMainTestSuite.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Test suite for local and distributed tests
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    MathImplLocalTestSuite.class,
+    MathImplDistributedTestSuite.class
+})
+public class MathImplMainTestSuite {
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/TracerTest.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/TracerTest.java b/modules/math/src/test/java/org/apache/ignite/math/TracerTest.java
new file mode 100644
index 0000000..35d2f60
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/TracerTest.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Optional;
+import org.apache.ignite.math.impls.MathTestConstants;
+import org.apache.ignite.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.math.impls.vector.DenseLocalOnHeapVector;
+import org.junit.Test;
+
+import static java.nio.file.Files.createTempFile;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for {@link Tracer}.
+ */
+public class TracerTest {
+    /** */ private static final String DEFAULT_FORMAT = "%.10f";
+    /** */ private static final double DEFAULT_DELTA = 0.000000001d;
+
+    /**
+     * Color mapper that maps [0, 1] range into three distinct RGB segments.
+     */
+    private static final Tracer.ColorMapper COLOR_MAPPER = new Tracer.ColorMapper() {
+        /** {@inheritDoc} */
+        @Override public Color apply(Double d) {
+            if (d <= 0.33)
+                return Color.RED;
+            else if (d <= 0.66)
+                return Color.GREEN;
+            else
+                return Color.BLUE;
+        }
+    };
+
+    /**
+     * @param size Vector size.
+     */
+    private Vector makeRandomVector(int size) {
+        DenseLocalOnHeapVector vec = new DenseLocalOnHeapVector(size);
+
+        vec.assign((idx) -> Math.random());
+
+        return vec;
+    }
+
+    /**
+     * @param rows Amount of rows in matrix.
+     * @param cols Amount of columns in matrix.
+     */
+    private Matrix makeRandomMatrix(int rows, int cols) {
+        DenseLocalOnHeapMatrix mtx = new DenseLocalOnHeapMatrix(rows, cols);
+
+        // Missing assign(f)?
+        mtx.map((d) -> Math.random());
+
+        return mtx;
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testAsciiVectorTracer() {
+        Vector vec = makeRandomVector(20);
+
+        Tracer.showAscii(vec);
+        Tracer.showAscii(vec, "%2f");
+        Tracer.showAscii(vec, "%.3g");
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testAsciiMatrixTracer() {
+        Matrix mtx = makeRandomMatrix(10, 10);
+
+        Tracer.showAscii(mtx);
+        Tracer.showAscii(mtx, "%2f");
+        Tracer.showAscii(mtx, "%.3g");
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testHtmlVectorTracer() throws IOException {
+        Vector vec1 = makeRandomVector(1000);
+
+        // Default color mapping.
+        Tracer.showHtml(vec1);
+
+        // Custom color mapping.
+        Tracer.showHtml(vec1, COLOR_MAPPER);
+
+        // Default color mapping with sorted vector.
+        Tracer.showHtml(vec1.sort());
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testHtmlMatrixTracer() throws IOException {
+        Matrix mtx1 = makeRandomMatrix(100, 100);
+
+        // Custom color mapping.
+        Tracer.showHtml(mtx1, COLOR_MAPPER);
+
+        Matrix mtx2 = new DenseLocalOnHeapMatrix(100, 100);
+
+        double MAX = (double)(mtx2.rowSize() * mtx2.columnSize());
+
+        mtx2.assign((x, y) -> (double)(x * y) / MAX);
+
+        Tracer.showHtml(mtx2);
+    }
+
+    /** */
+    @Test
+    public void testWriteVectorToCSVFile() throws IOException {
+        DenseLocalOnHeapVector vector = new DenseLocalOnHeapVector(MathTestConstants.STORAGE_SIZE);
+
+        for (int i = 0; i < vector.size(); i++)
+            vector.set(i, Math.random());
+
+        Path file = createTempFile("vector", ".csv");
+
+        Tracer.saveAsCsv(vector, DEFAULT_FORMAT, file.toString());
+
+        System.out.println("Vector exported: " + file.getFileName());
+
+        List<String> strings = Files.readAllLines(file);
+        Optional<String> reduce = strings.stream().reduce((s1, s2) -> s1 + s2);
+        String[] csvVals = reduce.get().split(",");
+
+        for (int i = 0; i < vector.size(); i++) {
+            Double csvVal = Double.valueOf(csvVals[i]);
+
+            assertEquals("Unexpected value.", csvVal, vector.get(i), DEFAULT_DELTA);
+        }
+
+        Files.deleteIfExists(file);
+    }
+
+    /** */
+    @Test
+    public void testWriteMatrixToCSVFile() throws IOException {
+        DenseLocalOnHeapMatrix matrix = new DenseLocalOnHeapMatrix(MathTestConstants.STORAGE_SIZE, MathTestConstants.STORAGE_SIZE);
+
+        for (int i = 0; i < matrix.rowSize(); i++)
+            for (int j = 0; j < matrix.columnSize(); j++)
+                matrix.set(i, j, Math.random());
+
+        Path file = createTempFile("matrix", ".csv");
+
+        Tracer.saveAsCsv(matrix, DEFAULT_FORMAT, file.toString());
+
+        System.out.println("Matrix exported: " + file.getFileName());
+
+        List<String> strings = Files.readAllLines(file);
+        Optional<String> reduce = strings.stream().reduce((s1, s2) -> s1 + s2);
+        String[] csvVals = reduce.get().split(",");
+
+        for (int i = 0; i < matrix.rowSize(); i++)
+            for (int j = 0; j < matrix.columnSize(); j++) {
+                Double csvVal = Double.valueOf(csvVals[i * matrix.rowSize() + j]);
+
+                assertEquals("Unexpected value.", csvVal, matrix.get(i, j), DEFAULT_DELTA);
+            }
+
+        Files.deleteIfExists(file);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/benchmark/MathBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/benchmark/MathBenchmark.java b/modules/math/src/test/java/org/apache/ignite/math/benchmark/MathBenchmark.java
new file mode 100644
index 0000000..4c3718a
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/benchmark/MathBenchmark.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.math.benchmark;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/** Refer {@link MathBenchmarkSelfTest} for usage examples. */
+class MathBenchmark {
+    /** */
+    private final boolean outputToConsole;
+
+    /** */
+    private final String benchmarkName;
+
+    /** */
+    private final int measurementTimes;
+
+    /** */
+    private final int warmUpTimes;
+
+    /** */
+    private final String tag;
+
+    /** */
+    private final String comments;
+
+    /** Constructor strictly for use within this class. */
+    private MathBenchmark(String benchmarkName, boolean outputToConsole, int measurementTimes, int warmUpTimes,
+        String tag, String comments) {
+        this.benchmarkName = benchmarkName;
+        this.outputToConsole = outputToConsole;
+        this.measurementTimes = measurementTimes;
+        this.warmUpTimes = warmUpTimes;
+        this.tag = tag;
+        this.comments = comments;
+        validate();
+    }
+
+    /**
+     * Benchmark with specified name and default parameters, in particular, default output file.
+     *
+     * @param benchmarkName name
+     */
+    MathBenchmark(String benchmarkName) {
+        this(benchmarkName, false, 100, 1, "", "");
+    }
+
+    /**
+     * Executes the code using config of this benchmark.
+     *
+     * @param code code to execute
+     * @throws Exception if something goes wrong
+     */
+    void execute(BenchmarkCode code) throws Exception {
+        System.out.println("Started benchmark [" + benchmarkName + "].");
+
+        for (int cnt = 0; cnt < warmUpTimes; cnt++)
+            code.call();
+
+        final long start = System.currentTimeMillis();
+
+        for (int cnt = 0; cnt < measurementTimes; cnt++)
+            code.call();
+
+        final long end = System.currentTimeMillis();
+
+        writeResults(formatResults(start, end));
+
+        System.out.println("Finished benchmark [" + benchmarkName + "].");
+    }
+
+    /**
+     * Set optional output mode for using stdout.
+     *
+     * @return configured benchmark
+     */
+    MathBenchmark outputToConsole() {
+        return new MathBenchmark(benchmarkName, true, measurementTimes, warmUpTimes, tag, comments);
+    }
+
+    /**
+     * Set optional measurement times.
+     *
+     * @param param times
+     * @return configured benchmark
+     */
+    MathBenchmark measurementTimes(int param) {
+        return new MathBenchmark(benchmarkName, outputToConsole, param, warmUpTimes, tag, comments);
+    }
+
+    /**
+     * Set optional warm-up times.
+     *
+     * @param param times
+     * @return configured benchmark
+     */
+    MathBenchmark warmUpTimes(int param) {
+        return new MathBenchmark(benchmarkName, outputToConsole, measurementTimes, param, tag, comments);
+    }
+
+    /**
+     * Set optional tag to help filtering specific kind of benchmark results.
+     *
+     * @param param name
+     * @return configured benchmark
+     */
+    MathBenchmark tag(String param) {
+        return new MathBenchmark(benchmarkName, outputToConsole, measurementTimes, warmUpTimes, param, comments);
+    }
+
+    /**
+     * Set optional comments.
+     *
+     * @param param name
+     * @return configured benchmark
+     */
+    MathBenchmark comments(String param) {
+        return new MathBenchmark(benchmarkName, outputToConsole, measurementTimes, warmUpTimes, tag, param);
+    }
+
+    /** */
+    private void writeResults(String results) throws Exception {
+        if (outputToConsole) {
+            System.out.println(results);
+
+            return;
+        }
+
+        new ResultsWriter().append(results);
+    }
+
+    /** */
+    private String formatResults(long start, long end) {
+        final String delim = ",";
+
+        assert !formatDouble(1000_000_001.1).contains(delim) : "Formatted results contain [" + delim + "].";
+
+        final String ts = formatTs(start);
+
+        assert !ts.contains(delim) : "Formatted timestamp contains [" + delim + "].";
+
+        return benchmarkName +
+            delim +
+            ts + // IMPL NOTE timestamp
+            delim +
+            formatDouble((double)(end - start) / measurementTimes) +
+            delim +
+            measurementTimes +
+            delim +
+            warmUpTimes +
+            delim +
+            tag +
+            delim +
+            comments;
+    }
+
+    /** */
+    private String formatDouble(double val) {
+        return String.format(Locale.US, "%f", val);
+    }
+
+    /** */
+    private String formatTs(long ts) {
+        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
+
+        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+        return sdf.format(new Date(ts));
+    }
+
+    /** */
+    private void validate() {
+        if (benchmarkName == null || benchmarkName.isEmpty())
+            throw new IllegalArgumentException("Invalid benchmark name: [" + benchmarkName + "].");
+
+        if (measurementTimes < 1)
+            throw new IllegalArgumentException("Invalid measurement times: [" + measurementTimes + "].");
+    }
+
+    /** */
+    interface BenchmarkCode {
+        // todo find out why Callable<Void> failed to work here
+
+        /** */
+        void call() throws Exception;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/benchmark/MathBenchmarkSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/benchmark/MathBenchmarkSelfTest.java b/modules/math/src/test/java/org/apache/ignite/math/benchmark/MathBenchmarkSelfTest.java
new file mode 100644
index 0000000..7a86461
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/benchmark/MathBenchmarkSelfTest.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.benchmark;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+/** */
+public class MathBenchmarkSelfTest {
+    /** */
+    @Test
+    @Ignore("Benchmark tests are intended only for manual execution")
+    public void demoTest() throws Exception {
+        for (int i = 0; i < 2; i++)
+            new MathBenchmark("demo test")
+                .outputToConsole() // IMPL NOTE this is to write output into console instead of a file
+                .tag(null) // IMPL NOTE try null for tag, expect it to be formatted reasonably
+                .comments(null) // IMPL NOTE try null for comments, expect it to be formatted reasonably
+                .execute(() -> {
+                    double seed = 1.1;
+
+                    for (int cnt = 0; cnt < 1000; cnt++) {
+                        seed = Math.pow(seed, 2);
+
+                        assertTrue(seed > 0);
+                    }
+                });
+    }
+
+    /** */
+    @Test
+    @Ignore("Benchmark tests are intended only for manual execution")
+    public void configTest() throws Exception {
+        new MathBenchmark("demo config test")
+            .outputToConsole()
+            .measurementTimes(2)
+            .warmUpTimes(0)
+            .tag("demo tag")
+            .comments("demo comments")
+            .execute(() -> System.out.println("config test"));
+    }
+
+    /** */
+    @Test(expected = IllegalArgumentException.class)
+    @Ignore("Benchmark tests are intended only for manual execution")
+    public void emptyNameTest() throws Exception {
+        new MathBenchmark("")
+            .outputToConsole()
+            .measurementTimes(1)
+            .warmUpTimes(1)
+            .tag("empty name test tag")
+            .comments("empty name test comments")
+            .execute(() -> System.out.println("empty name test"));
+    }
+
+    /** */
+    @Test(expected = IllegalArgumentException.class)
+    @Ignore("Benchmark tests are intended only for manual execution")
+    public void nullDropboxPathTest() throws Exception {
+        new ResultsWriter(null, "whatever", "whatever");
+    }
+
+    /** */
+    @Test(expected = IllegalArgumentException.class)
+    @Ignore("Benchmark tests are intended only for manual execution")
+    public void nullDropboxUrlTest() throws Exception {
+        new ResultsWriter("whatever", null, "whatever");
+    }
+
+    /** */
+    @Test(expected = IllegalArgumentException.class)
+    @Ignore("Benchmark tests are intended only for manual execution")
+    public void nullDropboxTokenTest() throws Exception {
+        new ResultsWriter("whatever", "whatever", null);
+    }
+
+    /** */
+    @Test(expected = IllegalArgumentException.class)
+    @Ignore("Benchmark tests are intended only for manual execution")
+    public void nullResultsTest() throws Exception {
+        new ResultsWriter("whatever", "whatever", "whatever").append(null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/benchmark/ResultsWriter.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/benchmark/ResultsWriter.java b/modules/math/src/test/java/org/apache/ignite/math/benchmark/ResultsWriter.java
new file mode 100644
index 0000000..aeec156
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/benchmark/ResultsWriter.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.benchmark;
+
+import com.dropbox.core.DbxException;
+import com.dropbox.core.DbxRequestConfig;
+import com.dropbox.core.v2.DbxClientV2;
+import com.dropbox.core.v2.files.WriteMode;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.UUID;
+
+/** */
+class ResultsWriter {
+    /** */
+    private static final String DROPBOX_PATH
+        = "/benchmarks/math.benchmark.results.csv";
+
+    /** */
+    private static final String DROPBOX_URL
+        = "https://www.dropbox.com/s/r7tcle31r7gaty8/math.benchmark.results.csv";
+
+    /** */
+    private static final String ACCESS_TOKEN
+        = "1MMmQjEyzGAAAAAAAAAAfDFrQ6oBPPi4NX-iU_VrgmXB2JDXqRHGa125cTkkEQ0V";
+
+    /** */
+    private final String dropboxPath;
+    /** */
+    private final String dropboxUrl;
+    /** */
+    private final String accessTok;
+
+    /** */
+    ResultsWriter(String dropboxPath, String dropboxUrl, String accessTok) {
+        this.dropboxPath = dropboxPath;
+        this.dropboxUrl = dropboxUrl;
+        this.accessTok = accessTok;
+
+        if (dropboxPath == null || dropboxUrl == null || accessTok == null)
+            throw new IllegalArgumentException("Neither of dropbox path, URL, access token can be null.");
+    }
+
+    /** **/
+    ResultsWriter() {
+        this(DROPBOX_PATH, DROPBOX_URL, ACCESS_TOKEN);
+    }
+
+    /** */
+    void append(String res) throws DbxException, IOException {
+        if (res == null)
+            throw new IllegalArgumentException("benchmark result is null");
+
+        if (dropboxPath == null) {
+            System.out.println(res);
+
+            return;
+        }
+
+        append(res, client());
+    }
+
+    /** */
+    private void append(String res, DbxClientV2 client) throws DbxException, IOException {
+        File tmp = createTmpFile();
+
+        try (FileOutputStream out = new FileOutputStream(tmp)) {
+            client.files().download(dropboxPath).download(out);
+        }
+
+        writeResults(res, tmp);
+
+        try (FileInputStream in = new FileInputStream(tmp)) {
+            client.files().uploadBuilder(dropboxPath).withMode(WriteMode.OVERWRITE).uploadAndFinish(in);
+        }
+
+        if (!tmp.delete())
+            System.out.println("Failed to delete " + tmp.getAbsolutePath());
+
+        System.out.println("Uploaded benchmark results to: " + dropboxUrl);
+    }
+
+    /** */
+    private void writeResults(String res, File tmp) throws IOException {
+        final String unixLineSeparator = "\n";
+
+        try (final PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get(tmp.toURI()),
+            StandardOpenOption.APPEND, StandardOpenOption.CREATE))) {
+            writer.write(res + unixLineSeparator);
+        }
+    }
+
+    /** */
+    private File createTmpFile() throws IOException {
+        File tmp = File.createTempFile(UUID.randomUUID().toString(), ".csv");
+
+        tmp.deleteOnExit();
+
+        return tmp;
+    }
+
+    /** */
+    private DbxClientV2 client() {
+        return new DbxClientV2(DbxRequestConfig.newBuilder("dropbox/MathBenchmark").build(), accessTok);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/benchmark/VectorBenchmarkTest.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/benchmark/VectorBenchmarkTest.java b/modules/math/src/test/java/org/apache/ignite/math/benchmark/VectorBenchmarkTest.java
new file mode 100644
index 0000000..1f7b204
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/benchmark/VectorBenchmarkTest.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.benchmark;
+
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import org.apache.ignite.math.Vector;
+import org.apache.ignite.math.impls.vector.DenseLocalOffHeapVector;
+import org.apache.ignite.math.impls.vector.DenseLocalOnHeapVector;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+/** */
+public class VectorBenchmarkTest {
+    // todo add benchmarks for other methods in Vector and for other types of Vector and Matrix
+
+    /** */
+    @Test
+    @Ignore("Benchmark tests are intended only for manual execution")
+    public void testDenseLocalOnHeapVector() throws Exception {
+        benchmark("DenseLocalOnHeapVector basic mix", DenseLocalOnHeapVector::new, this::basicMix);
+
+        benchmark("DenseLocalOnHeapVector fold map", DenseLocalOnHeapVector::new, this::foldMapMix);
+    }
+
+    /** */
+    @Test
+    @Ignore("Benchmark tests are intended only for manual execution")
+    public void testDenseLocalOffHeapVector() throws Exception {
+        benchmark("DenseLocalOffHeapVector basic mix", DenseLocalOffHeapVector::new, this::basicMix);
+
+        benchmark("DenseLocalOffHeapVector fold map", DenseLocalOffHeapVector::new, this::foldMapMix);
+    }
+
+    /** */
+    private void benchmark(String namePrefix, Function<Integer, Vector> constructor,
+        BiConsumer<Integer, Function<Integer, Vector>> consumer) throws Exception {
+        assertNotNull(namePrefix);
+
+        new MathBenchmark(namePrefix + " small sizes").execute(() -> {
+            for (int size : new int[] {2, 3, 4, 5, 6, 7})
+                consumer.accept(size, constructor);
+        });
+
+        new MathBenchmark(namePrefix + " sizes powers of 2").execute(() -> {
+            for (int power : new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14})
+                consumer.accept(1 << power, constructor);
+        });
+
+        new MathBenchmark(namePrefix + " large sizes").execute(() -> {
+            for (int power : new int[] {10, 12, 14, 16})
+                for (int delta : new int[] {-1, 0, 1})
+                    consumer.accept((1 << power) + delta, constructor);
+        });
+
+        new MathBenchmark(namePrefix + " extra large sizes")
+            .measurementTimes(10)
+            .execute(() -> { // IMPL NOTE trying below with power 22 almost killed my IDEA and laptop
+                for (int power : new int[] {17, 18, 19, 20, 21})
+                    for (int delta : new int[] {-1, 0}) // IMPL NOTE delta +1 is not intended for use here
+                        consumer.accept((1 << power) + delta, constructor);
+            });
+    }
+
+    /** */
+    private void basicMix(int size, Function<Integer, Vector> constructor) {
+        final Vector v1 = constructor.apply(size), v2 = constructor.apply(size);
+
+        for (int idx = 0; idx < size; idx++) {
+            v1.set(idx, idx);
+
+            v2.set(idx, size - idx);
+        }
+
+        assertNotNull(v1.sum());
+
+        assertNotNull(v1.copy());
+
+        assertFalse(v1.getLengthSquared() < 0);
+
+        assertNotNull(v1.normalize());
+
+        assertNotNull(v1.logNormalize());
+
+        assertFalse(v1.getDistanceSquared(v2) < 0);
+
+        assertNotNull(v1.divide(2));
+
+        assertNotNull(v1.minus(v2));
+
+        assertNotNull(v1.plus(v2));
+
+        assertNotNull(v1.dot(v2));
+
+        assertNotNull(v1.assign(v2));
+
+        assertNotNull(v1.assign(1)); // IMPL NOTE this would better be last test for it sets all values the same
+    }
+
+    /** */
+    private void foldMapMix(int size, Function<Integer, Vector> constructor) {
+        final Vector v1 = constructor.apply(size), v2 = constructor.apply(size);
+
+        for (int idx = 0; idx < size; idx++) {
+            v1.set(idx, idx);
+
+            v2.set(idx, size - idx);
+        }
+
+        assertNotNull(v1.map((val) -> (val + 1)));
+
+        assertNotNull(v1.map(v2, (one, other) -> one + other / 2.0));
+
+        assertNotNull(v1.map((val, val1) -> (val + val1), 2.0));
+
+        assertNotNull(v1.foldMap((sum, val) -> (val + sum), (val) -> val, 0.0));
+
+        assertNotNull(v1.foldMap(v2, (sum, val) -> (val + sum), (val1, val2) -> val1 + val2, 0.0));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/test/java/org/apache/ignite/math/benchmark/package-info.java
----------------------------------------------------------------------
diff --git a/modules/math/src/test/java/org/apache/ignite/math/benchmark/package-info.java b/modules/math/src/test/java/org/apache/ignite/math/benchmark/package-info.java
new file mode 100644
index 0000000..cbf5d36
--- /dev/null
+++ b/modules/math/src/test/java/org/apache/ignite/math/benchmark/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.math.benchmark;