http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/DiagonalMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/DiagonalMatrixStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/DiagonalMatrixStorage.java new file mode 100644 index 0000000..099db38 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/DiagonalMatrixStorage.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; + +/** + * {@link MatrixStorage} implementation for diagonal Matrix view. + */ +public class DiagonalMatrixStorage implements MatrixStorage { + /** Backing vector for matrix diagonal. */ + private Vector diagonal; + + /** + * + */ + public DiagonalMatrixStorage() { + // No-op. + } + + /** + * @param diagonal Backing {@link Vector} for matrix diagonal. + */ + public DiagonalMatrixStorage(Vector diagonal) { + assert diagonal != null; + + this.diagonal = diagonal; + } + + /** + * + */ + public Vector diagonal() { + return diagonal; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return x == y ? diagonal.get(x) : 0.0; + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + if (x == y) + diagonal.set(x, v); + else + throw new UnsupportedOperationException("Can't set off-diagonal element."); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return diagonal.size(); + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return diagonal.size(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(diagonal); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + diagonal = (Vector)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return diagonal.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return diagonal.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return diagonal.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return diagonal.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + diagonal.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + DiagonalMatrixStorage that = (DiagonalMatrixStorage)o; + + return diagonal.equals(that.diagonal); + } +}
http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/FunctionMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/FunctionMatrixStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/FunctionMatrixStorage.java new file mode 100644 index 0000000..6b0c6b4 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/FunctionMatrixStorage.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.functions.IntIntDoubleToVoidFunction; +import org.apache.ignite.math.functions.IntIntToDoubleFunction; + +/** + * Read-only or read-write function-based matrix storage. + */ +public class FunctionMatrixStorage implements MatrixStorage { + /** */ private int rows; + /** */ private int cols; + + /** */ private IntIntToDoubleFunction getFunc; + /** */ private IntIntDoubleToVoidFunction setFunc; + + /** + * + */ + public FunctionMatrixStorage() { + // No-op. + } + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param getFunc Function that returns value corresponding to given row and column index. + * @param setFunc Set function. If {@code null} - this will be a read-only matrix. + */ + public FunctionMatrixStorage(int rows, int cols, IntIntToDoubleFunction getFunc, + IntIntDoubleToVoidFunction setFunc) { + assert rows > 0; + assert cols > 0; + assert getFunc != null; + + this.rows = rows; + this.cols = cols; + this.getFunc = getFunc; + this.setFunc = setFunc; + } + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param getFunc Function that returns value corresponding to given row and column index. + */ + public FunctionMatrixStorage(int rows, int cols, IntIntToDoubleFunction getFunc) { + this(rows, cols, getFunc, null); + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return getFunc.apply(x, y); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + if (setFunc != null) + setFunc.apply(x, y, v); + else + throw new UnsupportedOperationException("Cannot set into read-only matrix."); + } + + /** + * + */ + public IntIntToDoubleFunction getFunction() { + return getFunc; + } + + /** + * + */ + public IntIntDoubleToVoidFunction setFunction() { + return setFunc; + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(setFunc); + out.writeObject(getFunc); + out.writeInt(rows); + out.writeInt(cols); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + setFunc = (IntIntDoubleToVoidFunction)in.readObject(); + getFunc = (IntIntToDoubleFunction)in.readObject(); + rows = in.readInt(); + cols = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + FunctionMatrixStorage that = (FunctionMatrixStorage)o; + + return rows == that.rows && cols == that.cols + && (getFunc != null ? getFunc.equals(that.getFunc) : that.getFunc == null) + && (setFunc != null ? setFunc.equals(that.setFunc) : that.setFunc == null); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = rows; + + res = 31 * res + cols; + res = 31 * res + (getFunc != null ? getFunc.hashCode() : 0); + res = 31 * res + (setFunc != null ? setFunc.hashCode() : 0); + + return res; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/MatrixDelegateStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/MatrixDelegateStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/MatrixDelegateStorage.java new file mode 100644 index 0000000..2e1fc12 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/MatrixDelegateStorage.java @@ -0,0 +1,205 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.MatrixStorage; + +/** + * {@link MatrixStorage} implementation that delegates to parent matrix. + */ +public class MatrixDelegateStorage implements MatrixStorage { + /** Parent matrix storage. */ + private MatrixStorage sto; + + /** Row offset in the parent matrix. */ + private int rowOff; + /** Column offset in the parent matrix. */ + private int colOff; + + /** Amount of rows in the matrix. */ + private int rows; + /** Amount of columns in the matrix. */ + private int cols; + + /** + * + */ + public MatrixDelegateStorage() { + // No-op. + } + + /** + * @param sto Backing parent storage. + * @param rowOff Row offset to parent matrix. + * @param colOff Column offset to parent matrix. + * @param rows Amount of rows in the view. + * @param cols Amount of columns in the view. + */ + public MatrixDelegateStorage(MatrixStorage sto, int rowOff, int colOff, int rows, int cols) { + assert sto != null; + assert rowOff >= 0; + assert colOff >= 0; + assert rows > 0; + assert cols > 0; + + this.sto = sto; + + this.rowOff = rowOff; + this.colOff = colOff; + + this.rows = rows; + this.cols = cols; + } + + /** + * + */ + public MatrixStorage delegate() { + return sto; + } + + /** + * + */ + public int rowOffset() { + return rowOff; + } + + /** + * + */ + public int columnOffset() { + return colOff; + } + + /** + * + */ + public int rowsLength() { + return rows; + } + + /** + * + */ + public int columnsLength() { + return cols; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return sto.get(rowOff + x, colOff + y); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + sto.set(rowOff + x, colOff + y, v); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return sto.isArrayBased() && rowOff == 0 && colOff == 0; + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return sto.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return sto.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return sto.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return sto.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public double[][] data() { + return sto.data(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + + out.writeInt(rowOff); + out.writeInt(colOff); + + out.writeInt(rows); + out.writeInt(cols); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (MatrixStorage)in.readObject(); + + rowOff = in.readInt(); + colOff = in.readInt(); + + rows = in.readInt(); + cols = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + rows; + res = res * 37 + cols; + res = res * 37 + rowOff; + res = res * 37 + colOff; + res = res * 37 + sto.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + MatrixDelegateStorage that = (MatrixDelegateStorage)o; + + return rows == that.rows && cols == that.cols && rowOff == that.rowOff && colOff == that.colOff && + (sto != null ? sto.equals(that.sto) : that.sto == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/PivotedMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/PivotedMatrixStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/PivotedMatrixStorage.java new file mode 100644 index 0000000..32c8624 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/PivotedMatrixStorage.java @@ -0,0 +1,256 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import org.apache.ignite.math.MatrixStorage; + +/** + * Pivoted (index mapped) view over another matrix storage implementation. + */ +public class PivotedMatrixStorage implements MatrixStorage { + /** Matrix storage. */ + private MatrixStorage sto; + + /** */ + private int[] rowPivot; + /** */ + private int[] colPivot; + /** */ + private int[] rowUnpivot; + /** */ + private int[] colUnpivot; + + /** + * + */ + public PivotedMatrixStorage() { + // No-op. + } + + /** + * @param sto Matrix storage. + * @param rowPivot Pivot array for rows. + * @param colPivot Pivot array for columns. + */ + public PivotedMatrixStorage(MatrixStorage sto, int[] rowPivot, int[] colPivot) { + assert sto != null; + assert rowPivot != null; + assert colPivot != null; + + this.sto = sto; + this.rowPivot = rowPivot; + this.colPivot = colPivot; + + rowUnpivot = invert(rowPivot); + colUnpivot = invert(colPivot); + } + + /** + * + */ + public int[] rowPivot() { + return rowPivot; + } + + /** + * + */ + public int[] columnPivot() { + return colPivot; + } + + /** + * + */ + public int[] rowUnpivot() { + return rowUnpivot; + } + + /** + * + */ + public int[] columnUnpivot() { + return colUnpivot; + } + + /** + * @param sto Matrix storage. + * @param pivot Pivot array. + */ + public PivotedMatrixStorage(MatrixStorage sto, int[] pivot) { + this(sto, pivot, pivot == null ? null : java.util.Arrays.copyOf(pivot, pivot.length)); + } + + /** + * @param sto Matrix storage. + */ + public PivotedMatrixStorage(MatrixStorage sto) { + this(sto, sto == null ? null : identityPivot(sto.rowSize()), sto == null ? null : identityPivot(sto.columnSize())); + } + + /** + * @param i First row index to swap. + * @param j Second row index to swap. + */ + public void swapRows(int i, int j) { + if (i != j) { + int tmp = rowPivot[i]; + + rowPivot[i] = rowPivot[j]; + rowPivot[j] = tmp; + + rowUnpivot[rowPivot[i]] = i; + rowUnpivot[rowPivot[j]] = j; + } + } + + /** + * @param i First column index to swap. + * @param j Second column index to swap. + */ + public void swapColumns(int i, int j) { + if (i != j) { + int tmp = colPivot[i]; + + colPivot[i] = colPivot[j]; + colPivot[j] = tmp; + + colUnpivot[colPivot[i]] = i; + colUnpivot[colPivot[j]] = j; + } + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return sto.get(rowPivot[x], colPivot[y]); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + sto.set(rowPivot[x], colPivot[y], v); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return sto.columnSize(); + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return sto.rowSize(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + out.writeObject(rowPivot); + out.writeObject(colPivot); + out.writeObject(rowUnpivot); + out.writeObject(colUnpivot); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (MatrixStorage)in.readObject(); + rowPivot = (int[])in.readObject(); + colPivot = (int[])in.readObject(); + rowUnpivot = (int[])in.readObject(); + colUnpivot = (int[])in.readObject(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return sto.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return sto.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return sto.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return sto.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + sto.hashCode(); + res = res * 37 + Arrays.hashCode(rowPivot); + res = res * 37 + Arrays.hashCode(rowUnpivot); + res = res * 37 + Arrays.hashCode(colPivot); + res = res * 37 + Arrays.hashCode(colUnpivot); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null || getClass() != obj.getClass()) + return false; + + PivotedMatrixStorage that = (PivotedMatrixStorage)obj; + + return Arrays.equals(rowPivot, that.rowPivot) && Arrays.equals(rowUnpivot, that.rowUnpivot) + && Arrays.equals(colPivot, that.colPivot) && Arrays.equals(colUnpivot, that.colUnpivot) + && (sto != null ? sto.equals(that.sto) : that.sto == null); + } + + /** + * @param n Pivot array length. + */ + private static int[] identityPivot(int n) { + int[] pivot = new int[n]; + + for (int i = 0; i < n; i++) + pivot[i] = i; + + return pivot; + } + + /** + * @param pivot Pivot array to be inverted. + */ + private static int[] invert(int[] pivot) { + int[] x = new int[pivot.length]; + + for (int i = 0; i < pivot.length; i++) + x[pivot[i]] = i; + + return x; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/RandomMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/RandomMatrixStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/RandomMatrixStorage.java new file mode 100644 index 0000000..8283201 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/RandomMatrixStorage.java @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.nio.ByteBuffer; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.MurmurHash; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; + +/** + * {@link MatrixStorage} implementation with random values in the matrix elements. + */ +public class RandomMatrixStorage implements MatrixStorage { + /** */ + private static final int PRIME1 = 104047; + /** */ + private static final int PRIME2 = 101377; + /** */ + private static final int PRIME3 = 64661; + /** */ + private static final long SCALE = 1L << 32; + + /** Random generation seed. */ + private int seed; + + /** Amount of rows in the matrix. */ + private int rows; + /** Amount of columns in the matrix. */ + private int cols; + + /** Whether fast hash is used, in {@link #get(int, int)}. */ + private boolean fastHash; + + /** + * For externalization. + */ + public RandomMatrixStorage() { + // No-op. + } + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param fastHash Whether fast hash is used. + */ + public RandomMatrixStorage(int rows, int cols, boolean fastHash) { + assert rows > 0; + assert cols > 0; + + this.rows = rows; + this.cols = cols; + this.fastHash = fastHash; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + if (!fastHash) { + ByteBuffer buf = ByteBuffer.allocate(8); + + buf.putInt(x); + buf.putInt(y); + buf.flip(); + + return (MurmurHash.hash64A(buf, seed) & (SCALE - 1)) / (double)SCALE; + } + else + // This isn't a fantastic random number generator, but it is just fine for random projections. + return ((((x * PRIME1) + y * PRIME2 + x * y * PRIME3) & 8) * 0.25) - 1; + } + + /** + * + */ + public boolean isFastHash() { + return fastHash; + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + throw new UnsupportedOperationException("Random matrix storage is a read-only storage."); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(rows); + out.writeInt(cols); + out.writeInt(seed); + out.writeBoolean(fastHash); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + rows = in.readInt(); + cols = in.readInt(); + seed = in.readInt(); + fastHash = in.readBoolean(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + Boolean.hashCode(fastHash); + res = res * 37 + seed; + res = res * 37 + cols; + res = res * 37 + rows; + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + RandomMatrixStorage that = (RandomMatrixStorage)o; + + return rows == that.rows && cols == that.cols && seed == that.seed && fastHash == that.fastHash; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/SparseDistributedMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/SparseDistributedMatrixStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/SparseDistributedMatrixStorage.java new file mode 100644 index 0000000..936f893 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/SparseDistributedMatrixStorage.java @@ -0,0 +1,283 @@ +// @java.file.header + +/* _________ _____ __________________ _____ + * __ ____/___________(_)______ /__ ____/______ ____(_)_______ + * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \ + * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / / + * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/ + */ + +package org.apache.ignite.math.impls.storage.matrix; + +import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Map; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.Ignition; +import org.apache.ignite.cache.CacheAtomicWriteOrderMode; +import org.apache.ignite.cache.CacheAtomicityMode; +import org.apache.ignite.cache.CacheMode; +import org.apache.ignite.cache.CachePeekMode; +import org.apache.ignite.cache.CacheWriteSynchronizationMode; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.lang.IgniteUuid; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.StorageConstants; +import org.apache.ignite.math.impls.CacheUtils; + +/** + * {@link MatrixStorage} implementation for {@link org.apache.ignite.math.impls.matrix.SparseDistributedMatrix}. + */ +public class SparseDistributedMatrixStorage extends CacheUtils implements MatrixStorage, StorageConstants { + /** Amount of rows in the matrix. */ + private int rows; + /** Amount of columns in the matrix. */ + private int cols; + + /** Row or column based storage mode. */ + private int stoMode; + /** Random or sequential access mode. */ + private int acsMode; + + /** Actual distributed storage. */ + private IgniteCache< + Integer /* Row or column index. */, + Map<Integer, Double> /* Map-based row or column. */ + > cache = null; + + /** + * + */ + public SparseDistributedMatrixStorage() { + // No-op. + } + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param stoMode Row or column based storage mode. + * @param acsMode Random or sequential access mode. + */ + public SparseDistributedMatrixStorage(int rows, int cols, int stoMode, int acsMode) { + assert rows > 0; + assert cols > 0; + assertAccessMode(acsMode); + assertStorageMode(stoMode); + + this.rows = rows; + this.cols = cols; + this.stoMode = stoMode; + this.acsMode = acsMode; + + cache = newCache(); + } + + /** + * + * + */ + private IgniteCache<Integer, Map<Integer, Double>> newCache() { + CacheConfiguration<Integer, Map<Integer, Double>> cfg = new CacheConfiguration<>(); + + // Assume 10% density. + cfg.setStartSize(Math.max(1024, (rows * cols) / 10)); + + // Write to primary. + cfg.setAtomicWriteOrderMode(CacheAtomicWriteOrderMode.PRIMARY); + cfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC); + + // Atomic transactions only. + cfg.setAtomicityMode(CacheAtomicityMode.ATOMIC); + + // No eviction. + cfg.setEvictionPolicy(null); + + // No copying of values. + cfg.setCopyOnRead(false); + + // Cache is partitioned. + cfg.setCacheMode(CacheMode.PARTITIONED); + + // Random cache name. + cfg.setName(new IgniteUuid().shortString()); + + return Ignition.localIgnite().getOrCreateCache(cfg); + } + + /** + * + * + */ + public IgniteCache<Integer, Map<Integer, Double>> cache() { + return cache; + } + + /** + * + * + */ + public int accessMode() { + return acsMode; + } + + /** + * + * + */ + public int storageMode() { + return stoMode; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + if (stoMode == ROW_STORAGE_MODE) + return matrixGet(cache.getName(), x, y); + else + return matrixGet(cache.getName(), y, x); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + if (stoMode == ROW_STORAGE_MODE) + matrixSet(cache.getName(), x, y, v); + else + matrixSet(cache.getName(), y, x, v); + } + + /** + * Distributed matrix get. + * + * @param cacheName Matrix's cache. + * @param a Row or column index. + * @param b Row or column index. + * @return Matrix value at (a, b) index. + */ + private double matrixGet(String cacheName, int a, int b) { + // Remote get from the primary node (where given row or column is stored locally). + return ignite().compute(groupForKey(cacheName, a)).call(() -> { + IgniteCache<Integer, Map<Integer, Double>> cache = Ignition.localIgnite().getOrCreateCache(cacheName); + + // Local get. + Map<Integer, Double> map = cache.localPeek(a, CachePeekMode.PRIMARY); + + return (map == null || !map.containsKey(b)) ? 0.0 : map.get(b); + }); + } + + /** + * Distributed matrix set. + * + * @param cacheName Matrix's cache. + * @param a Row or column index. + * @param b Row or column index. + * @param v New value to set. + */ + private void matrixSet(String cacheName, int a, int b, double v) { + // Remote set on the primary node (where given row or column is stored locally). + ignite().compute(groupForKey(cacheName, a)).run(() -> { + IgniteCache<Integer, Map<Integer, Double>> cache = Ignition.localIgnite().getOrCreateCache(cacheName); + + // Local get. + Map<Integer, Double> map = cache.localPeek(a, CachePeekMode.PRIMARY); + + if (map == null) + map = acsMode == SEQUENTIAL_ACCESS_MODE ? new Int2DoubleRBTreeMap() : new Int2DoubleOpenHashMap(); + + if (v != 0.0) + map.put(b, v); + else if (map.containsKey(b)) + map.remove(b); + + // Local put. + cache.put(a, map); + }); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(rows); + out.writeInt(cols); + out.writeInt(acsMode); + out.writeInt(stoMode); + out.writeUTF(cache.getName()); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + rows = in.readInt(); + cols = in.readInt(); + acsMode = in.readInt(); + stoMode = in.readInt(); + cache = ignite().getOrCreateCache(in.readUTF()); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return acsMode == SEQUENTIAL_ACCESS_MODE; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return acsMode == RANDOM_ACCESS_MODE; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** Destroy underlying cache. */ + @Override public void destroy() { + cache.destroy(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + cols; + res = res * 37 + rows; + res = res * 37 + acsMode; + res = res * 37 + stoMode; + res = res * 37 + cache.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null || getClass() != obj.getClass()) + return false; + + SparseDistributedMatrixStorage that = (SparseDistributedMatrixStorage)obj; + + return rows == that.rows && cols == that.cols && acsMode == that.acsMode && stoMode == that.stoMode + && (cache != null ? cache.equals(that.cache) : that.cache == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java new file mode 100644 index 0000000..e72da70 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java @@ -0,0 +1,226 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.matrix; + +import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.HashMap; +import java.util.Map; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.StorageConstants; + +/** + * Storage for sparse, local, on-heap matrix. + */ +public class SparseLocalOnHeapMatrixStorage implements MatrixStorage, StorageConstants { + /** Default zero value. */ + private static final double DEFAULT_VALUE = 0.0; + + /** */ private int rows; + /** */ private int cols; + + /** */ private int acsMode; + /** */ private int stoMode; + + /** Actual map storage. */ + private Map<Integer, Map<Integer, Double>> sto; + + /** */ + public SparseLocalOnHeapMatrixStorage() { + // No-op. + } + + /** */ + public SparseLocalOnHeapMatrixStorage(int rows, int cols, int acsMode, int stoMode) { + assert rows > 0; + assert cols > 0; + assertAccessMode(acsMode); + assertStorageMode(stoMode); + + this.rows = rows; + this.cols = cols; + this.acsMode = acsMode; + this.stoMode = stoMode; + + sto = new HashMap<>(); + } + + /** + * + * + */ + public int getStorageMode() { + return stoMode; + } + + /** + * + * + */ + public int getAccessMode() { + return acsMode; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + if (stoMode == ROW_STORAGE_MODE) { + Map<Integer, Double> row = sto.get(x); + + if (row != null) { + Double val = row.get(y); + + if (val != null) + return val; + } + + return DEFAULT_VALUE; + } + else { + Map<Integer, Double> col = sto.get(y); + + if (col != null) { + Double val = col.get(x); + + if (val != null) + return val; + } + + return DEFAULT_VALUE; + } + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + // Ignore default values (currently 0.0). + if (v != DEFAULT_VALUE) { + if (stoMode == ROW_STORAGE_MODE) { + Map<Integer, Double> row = sto.computeIfAbsent(x, k -> + acsMode == SEQUENTIAL_ACCESS_MODE ? new Int2DoubleRBTreeMap() : new Int2DoubleOpenHashMap()); + + row.put(y, v); + } + else { + Map<Integer, Double> col = sto.computeIfAbsent(y, k -> + acsMode == SEQUENTIAL_ACCESS_MODE ? new Int2DoubleRBTreeMap() : new Int2DoubleOpenHashMap()); + + col.put(x, v); + } + } + else { + if (stoMode == ROW_STORAGE_MODE) { + if (sto.containsKey(x)) { + Map<Integer, Double> row = sto.get(x); + + if (row.containsKey(y)) + row.remove(y); + } + + } + else { + if (sto.containsKey(y)) { + Map<Integer, Double> col = sto.get(y); + + if (col.containsKey(x)) + col.remove(x); + } + } + } + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(rows); + out.writeInt(cols); + out.writeInt(acsMode); + out.writeInt(stoMode); + out.writeObject(sto); + } + + /** {@inheritDoc} */ + @SuppressWarnings({"unchecked"}) + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + rows = in.readInt(); + cols = in.readInt(); + acsMode = in.readInt(); + stoMode = in.readInt(); + sto = (Map<Integer, Map<Integer, Double>>)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return acsMode == SEQUENTIAL_ACCESS_MODE; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return acsMode == RANDOM_ACCESS_MODE; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + rows; + res = res * 37 + cols; + res = res * 37 + sto.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + SparseLocalOnHeapMatrixStorage that = (SparseLocalOnHeapMatrixStorage)o; + + return rows == that.rows && cols == that.cols && acsMode == that.acsMode && stoMode == that.stoMode + && (sto != null ? sto.equals(that.sto) : that.sto == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/package-info.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/package-info.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/package-info.java new file mode 100644 index 0000000..aba47db --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/matrix/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * <!-- Package description. --> + * Contains specific implementations for matrix storage models. + */ +package org.apache.ignite.math.impls.storage.matrix; \ 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/impls/storage/vector/ArrayVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/ArrayVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/ArrayVectorStorage.java new file mode 100644 index 0000000..ef59c62 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/ArrayVectorStorage.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import org.apache.ignite.math.VectorStorage; + +/** + * Array based {@link VectorStorage} implementation. + */ +public class ArrayVectorStorage implements VectorStorage { + /** Backing data array. */ + private double[] data; + + /** + * IMPL NOTE required by {@link Externalizable}. + */ + public ArrayVectorStorage() { + // No-op. + } + + /** + * @param size Vector size. + */ + public ArrayVectorStorage(int size) { + assert size > 0; + + data = new double[size]; + } + + /** + * @param data Backing data array. + */ + public ArrayVectorStorage(double[] data) { + assert data != null; + + this.data = data; + } + + /** {@inheritDoc} */ + @Override public int size() { + return data == null ? 0 : data.length; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return data[i]; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + data[i] = v; + } + + /** {@inheritDoc}} */ + @Override public boolean isArrayBased() { + return true; + } + + /** {@inheritDoc} */ + @Override public double[] data() { + return data; + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(data); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + data = (double[])in.readObject(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + Arrays.hashCode(data); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null || getClass() != obj.getClass()) + return false; + + ArrayVectorStorage that = (ArrayVectorStorage)obj; + + return Arrays.equals(data, (that.data)); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/CacheVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/CacheVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/CacheVectorStorage.java new file mode 100644 index 0000000..670deef --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/CacheVectorStorage.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.Ignition; +import org.apache.ignite.math.ValueMapper; +import org.apache.ignite.math.VectorKeyMapper; +import org.apache.ignite.math.VectorStorage; + +/** + * Vector storage based on existing cache and index and value mapping functions. + */ +public class CacheVectorStorage<K, V> implements VectorStorage { + /** Storage size. */ + private int size; + /** Key mapper. */ + private VectorKeyMapper<K> keyMapper; + /** Value mapper. */ + private ValueMapper<V> valMapper; + /** Underlying ignite cache. */ + private IgniteCache<K, V> cache; + + /** + * + */ + public CacheVectorStorage() { + // No-op. + } + + /** + * @param size + * @param cache + * @param keyMapper + * @param valMapper + */ + public CacheVectorStorage(int size, IgniteCache<K, V> cache, VectorKeyMapper<K> keyMapper, + ValueMapper<V> valMapper) { + assert size > 0; + assert cache != null; + assert keyMapper != null; + assert valMapper != null; + + this.size = size; + this.cache = cache; + this.keyMapper = keyMapper; + this.valMapper = valMapper; + } + + /** + * + * + */ + public IgniteCache<K, V> cache() { + return cache; + } + + /** + * + * + */ + public VectorKeyMapper<K> keyMapper() { + return keyMapper; + } + + /** + * + * + */ + public ValueMapper<V> valueMapper() { + return valMapper; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return valMapper.toDouble(cache.get(keyMapper.apply(i))); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + cache.put(keyMapper.apply(i), valMapper.fromDouble(v)); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeObject(keyMapper); + out.writeObject(valMapper); + out.writeUTF(cache.getName()); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + keyMapper = (VectorKeyMapper<K>)in.readObject(); + valMapper = (ValueMapper<V>)in.readObject(); + cache = Ignition.localIgnite().getOrCreateCache(in.readUTF()); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + size(); + res = res * 37 + keyMapper.hashCode(); + res = res * 37 + valMapper.hashCode(); + res = res * 37 + cache.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null || getClass() != obj.getClass()) + return false; + + CacheVectorStorage that = (CacheVectorStorage)obj; + + return size == that.size + && (keyMapper != null ? keyMapper.getClass().equals(that.keyMapper.getClass()) : that.keyMapper == null) + && (valMapper != null ? valMapper.getClass().equals(that.valMapper.getClass()) : that.valMapper == null) + && (cache != null ? cache.equals(that.cache) : that.cache == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/ConstantVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/ConstantVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/ConstantVectorStorage.java new file mode 100644 index 0000000..ff5ab26 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/ConstantVectorStorage.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; + +/** + * Constant read-only vector storage. + */ +public class ConstantVectorStorage implements VectorStorage { + /** */ private int size; + /** */ private double val; + + /** + * + */ + public ConstantVectorStorage() { + // No-op. + } + + /** + * @param size Vector size. + * @param val Value to set for vector elements. + */ + public ConstantVectorStorage(int size, double val) { + assert size > 0; + + this.size = size; + this.val = val; + } + + /** + * + * + */ + public double constant() { + return val; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return val; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + throw new UnsupportedOperationException("Can't set value into constant vector."); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeDouble(val); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + val = in.readDouble(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + size; + res = res * 37 + Double.hashCode(val); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + ConstantVectorStorage that = (ConstantVectorStorage)o; + + return size == that.size && val == that.val; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/DelegateVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/DelegateVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/DelegateVectorStorage.java new file mode 100644 index 0000000..aa6018c --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/DelegateVectorStorage.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.VectorStorage; + +/** + * {@link VectorStorage} implementation that delegates to parent matrix. + */ +public class DelegateVectorStorage implements VectorStorage { + /** Parent vector storage. */ + private VectorStorage sto; + + /** Offset in the parent vector. */ + private int off; + + /** Size of the vector. */ + private int len; + + /** + * + */ + public DelegateVectorStorage() { + // No-op. + } + + /** + * @param sto Vector storage to delegate to. + * @param off Offset in the parent vector. + * @param len Size of the vector. + */ + public DelegateVectorStorage(VectorStorage sto, int off, int len) { + assert sto != null; + assert off >= 0; + assert len > 0; + + this.sto = sto; + this.off = off; + this.len = len; + } + + /** */ + public VectorStorage delegate() { + return sto; + } + + /** */ + public int offset() { + return off; + } + + /** */ + public int length() { + return len; + } + + /** {@inheritDoc} */ + @Override public int size() { + return len; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return sto.get(off + i); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + sto.set(off + i, v); + } + + /** {@inheritDoc} */ + @Override public double[] data() { + return sto.data(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return sto.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return sto.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return sto.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return sto.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return sto.isArrayBased(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + out.writeInt(off); + out.writeInt(len); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (VectorStorage)in.readObject(); + off = in.readInt(); + len = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + DelegateVectorStorage that = (DelegateVectorStorage)o; + + return len == that.len && off == that.off && (sto != null ? sto.equals(that.sto) : that.sto == null); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + off; + res = res * 37 + len; + res = res * 37 + sto.hashCode(); + + return res; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/DenseLocalOffHeapVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/DenseLocalOffHeapVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/DenseLocalOffHeapVectorStorage.java new file mode 100644 index 0000000..2e7cdc9 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/DenseLocalOffHeapVectorStorage.java @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.stream.IntStream; +import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.math.VectorStorage; + +/** + * Local, dense off-heap vector storage. + */ +public class DenseLocalOffHeapVectorStorage implements VectorStorage { + /** Vector size. */ + private int size; + + /** */ + private transient long ptr; + //TODO: temp solution. + /** */ + private int ptrInitHash; + + /** + * + */ + public DenseLocalOffHeapVectorStorage() { + // No-op. + } + + /** + * @param size Vector size. + */ + public DenseLocalOffHeapVectorStorage(int size) { + assert size > 0; + + this.size = size; + + allocateMemory(size); + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return GridUnsafe.getDouble(pointerOffset(i)); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + GridUnsafe.putDouble(pointerOffset(i), v); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public double[] data() { + return null; + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeInt(ptrInitHash); + + for (int i = 0; i < size; i++) + out.writeDouble(get(i)); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + + allocateMemory(size); + + ptrInitHash = in.readInt(); + + for (int i = 0; i < size; i++) + set(i, in.readDouble()); + } + + /** {@inheritDoc} */ + @Override public void destroy() { + GridUnsafe.freeMemory(ptr); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + size; + res = res * 37 + ptrInitHash; + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + DenseLocalOffHeapVectorStorage that = (DenseLocalOffHeapVectorStorage)o; + + return size == that.size && isMemoryEquals(that); + } + + /** */ + private boolean isMemoryEquals(DenseLocalOffHeapVectorStorage otherStorage) { + return IntStream.range(0, size).parallel().noneMatch(idx -> Double.compare(get(idx), otherStorage.get(idx)) != 0); + } + + /** + * Pointer offset for specific index. + * + * @param i Offset index. + */ + private long pointerOffset(int i) { + return ptr + i * Double.BYTES; + } + + /** */ + private void allocateMemory(int size) { + ptr = GridUnsafe.allocateMemory(size * Double.BYTES); + + ptrInitHash = Long.hashCode(ptr); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/FunctionVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/FunctionVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/FunctionVectorStorage.java new file mode 100644 index 0000000..df8fa12 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/FunctionVectorStorage.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.functions.IgniteFunction; +import org.apache.ignite.math.functions.IntDoubleToVoidFunction; + +/** + * Read-only or read-write function-based vector storage. + */ +public class FunctionVectorStorage implements VectorStorage { + /** */ private IgniteFunction<Integer, Double> getFunc; + /** */ private IntDoubleToVoidFunction setFunc; + /** */ private int size; + + /** + * + */ + public FunctionVectorStorage() { + // No-op. + } + + /** + * Creates read-only or read-write storage. + * + * @param size Cardinality of this vector storage. + * @param getFunc Get function. + * @param setFunc Optional set function ({@code null} for read-only storage). + */ + public FunctionVectorStorage(int size, IgniteFunction<Integer, Double> getFunc, IntDoubleToVoidFunction setFunc) { + assert size > 0; + assert getFunc != null; // At least get function is required. + + this.size = size; + this.getFunc = getFunc; + this.setFunc = setFunc; + } + + /** + * + * + */ + public IgniteFunction<Integer, Double> getFunction() { + return getFunc; + } + + /** + * + * + */ + public IntDoubleToVoidFunction setFunction() { + return setFunc; + } + + /** + * Creates read-only storage. + * + * @param size Cardinality of this vector storage. + * @param getFunc Get function. + */ + public FunctionVectorStorage(int size, IgniteFunction<Integer, Double> getFunc) { + this(size, getFunc, null); + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return getFunc.apply(i); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (setFunc != null) + setFunc.accept(i, v); + else + throw new UnsupportedOperationException("Cannot set into read-only vector."); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(setFunc); + out.writeObject(getFunc); + out.writeInt(size); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + setFunc = (IntDoubleToVoidFunction)in.readObject(); + getFunc = (IgniteFunction<Integer, Double>)in.readObject(); + size = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/MatrixVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/MatrixVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/MatrixVectorStorage.java new file mode 100644 index 0000000..ece0003 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/MatrixVectorStorage.java @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.VectorStorage; +import org.apache.ignite.math.exceptions.IndexException; + +/** + * Row, column or diagonal vector-based view of the matrix + */ +public class MatrixVectorStorage implements VectorStorage { + /** */ private Matrix parent; + + /** */ private int row; + /** */ private int col; + + /** */ private int rowStride; + /** */ private int colStride; + + /** */ private int size; + + /** + * + */ + public MatrixVectorStorage() { + // No-op. + } + + /** + * @param parent + * @param row + * @param col + * @param rowStride + * @param colStride + */ + public MatrixVectorStorage(Matrix parent, int row, int col, int rowStride, int colStride) { + assert parent != null; + assert rowStride >= 0; + assert colStride >= 0; + assert rowStride > 0 || colStride > 0; + + 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; + + this.size = getSize(); + } + + /** + * + * + */ + int row() { + return row; + } + + /** + * + * + */ + int column() { + return col; + } + + /** + * + * + */ + int rowStride() { + return rowStride; + } + + /** + * + * + */ + int columnStride() { + return colStride; + } + + /** + * + * + */ + private int getSize() { + if (rowStride != 0 && colStride != 0) { + int n1 = (parent.rowSize() - row) / rowStride; + int n2 = (parent.columnSize() - col) / colStride; + + return Math.min(n1, n2); + } + else if (rowStride > 0) + return (parent.rowSize() - row) / rowStride; + else + return (parent.columnSize() - col) / colStride; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return parent.get(row + i * rowStride, col + i * colStride); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + parent.set(row + i * rowStride, col + i * colStride, v); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return parent.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return parent.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return parent.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return parent.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + 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 { + parent = (Matrix)in.readObject(); + row = in.readInt(); + col = in.readInt(); + rowStride = in.readInt(); + colStride = in.readInt(); + + size = getSize(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/acd21fb8/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/PivotedVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/PivotedVectorStorage.java b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/PivotedVectorStorage.java new file mode 100644 index 0000000..f69e959 --- /dev/null +++ b/modules/math/src/main/java/org/apache/ignite/math/impls/storage/vector/PivotedVectorStorage.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.math.impls.storage.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import org.apache.ignite.math.VectorStorage; + +/** + * Pivoted (index mapped) view over another vector storage implementation. + */ +public class PivotedVectorStorage implements VectorStorage { + /** */ private VectorStorage sto; + + /** */ private int[] pivot; + /** */ private int[] unpivot; + + /** + * @param pivot Pivot array. + */ + private static int[] reverse(int[] pivot) { + int[] res = new int[pivot.length]; + + for (int i = 0; i < pivot.length; i++) + res[pivot[i]] = i; + + return res; + } + + /** + * + * + */ + public int[] pivot() { + return pivot; + } + + /** + * + * + */ + public int[] unpivot() { + return unpivot; + } + + /** + * @param sto Backing vector storage. + * @param pivot Mapping from external index to internal. + * @param unpivot Mapping from internal index to external. + */ + public PivotedVectorStorage(VectorStorage sto, int[] pivot, int[] unpivot) { + assert sto != null; + assert pivot != null; + assert unpivot != null; + + this.sto = sto; + this.pivot = pivot; + this.unpivot = unpivot; + } + + /** + * @param sto Backing vector storage. + * @param pivot Mapping from external index to internal. + */ + public PivotedVectorStorage(VectorStorage sto, int[] pivot) { + this(sto, pivot, reverse(pivot)); + } + + /** + * + */ + public PivotedVectorStorage() { + // No-op. + } + + /** {@inheritDoc} */ + @Override public int size() { + return sto.size(); + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return sto.get(pivot[i]); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + sto.set(pivot[i], v); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + out.writeObject(pivot); + out.writeObject(unpivot); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (VectorStorage)in.readObject(); + pivot = (int[])in.readObject(); + unpivot = (int[])in.readObject(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return sto.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return sto.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return sto.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return sto.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return sto.isArrayBased(); + } + + /** {@inheritDoc} */ + @Override public double[] data() { + return isArrayBased() ? sto.data() : null; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + PivotedVectorStorage that = (PivotedVectorStorage)o; + + return (sto != null ? sto.equals(that.sto) : that.sto == null) && Arrays.equals(pivot, that.pivot) + && Arrays.equals(unpivot, that.unpivot); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = sto != null ? sto.hashCode() : 0; + + res = 31 * res + Arrays.hashCode(pivot); + res = 31 * res + Arrays.hashCode(unpivot); + + return res; + } +}
