| /* |
| * Copyright 2017, Yahoo! Inc. |
| * Licensed under the terms of the Apache License 2.0. See LICENSE file at the project root |
| * for terms. |
| */ |
| |
| package com.yahoo.sketches.matrix; |
| |
| import static com.yahoo.sketches.matrix.MatrixPreambleUtil.LS; |
| |
| import org.ojalgo.matrix.store.PrimitiveDenseStore; |
| |
| import com.yahoo.memory.Memory; |
| import com.yahoo.sketches.MatrixFamily; |
| import com.yahoo.sketches.SketchesArgumentException; |
| |
| |
| /** |
| * Provides an implementation-agnostic wrapper around Matrix classes. |
| * |
| * @author Jon Malkin |
| */ |
| public abstract class Matrix { |
| int numRows_; |
| int numCols_; |
| |
| /** |
| * Loads matrix from srcMem, assuming storage in column-major order to ensure portability. |
| * Does not necessarily encode matrix size; do not expect size checks based on passed-in |
| * parameters. |
| * |
| * @param srcMem Memory wrapping the matrix |
| * @param type Matrix implementation type to use |
| * @return The heapified matrix |
| */ |
| public static Matrix heapify(final Memory srcMem, final MatrixBuilder.Algo type) { |
| switch (type) { |
| case OJALGO: |
| return MatrixImplOjAlgo.heapifyInstance(srcMem); |
| default: |
| return null; |
| } |
| } |
| |
| /** |
| * Wraps an object without allocating memory. This method will throw an exception if the mtx |
| * Object is not of the same type as the implementing class's native format. |
| * @param mtx Matrix object to wrap |
| * @return A Matrix object |
| */ |
| public static Matrix wrap(final Object mtx) { |
| if (mtx == null) { |
| return null; |
| } else if (mtx instanceof PrimitiveDenseStore) { |
| return MatrixImplOjAlgo.wrap((PrimitiveDenseStore) mtx); |
| } |
| else { |
| throw new SketchesArgumentException("wrap() does not currently support " |
| + mtx.getClass().toString()); |
| } |
| } |
| |
| /** |
| * Gets a builder to be able to create instances of Matrix objects |
| * @return a MatrixBuilder object |
| */ |
| public static MatrixBuilder builder() { |
| return new MatrixBuilder(); |
| } |
| |
| /** |
| * Returns the raw data object backing this Matrix, as an Object. Must be cast to the |
| * appropriate type (assuming knowledge of the implementation) to be used. |
| * @return An Object pointing to the raw data backing this Matrix |
| */ |
| public abstract Object getRawObject(); |
| |
| /** |
| * Serializes the Matrix in a custom format as a byte array |
| * @return A byte[] conttaining a serialized Matrix |
| */ |
| public abstract byte[] toByteArray(); |
| |
| /** |
| * Serializes a sub-Matrix by storing only the first numRows and numCols rows and columns, |
| * respsectively. |
| * @param numRows Number of rows to write |
| * @param numCols Number of columns to write |
| * @return A byte[] containing the serialized sub-Matrix. |
| */ |
| public abstract byte[] toCompactByteArray(int numRows, int numCols); |
| |
| /** |
| * Returns a single element from the Matrix |
| * @param row Row index of target element (0-based) |
| * @param col Column index of target elemtn (0-based) |
| * @return Matrix value at (row, column) |
| */ |
| public abstract double getElement(int row, int col); |
| |
| /** |
| * Returns a copy of an entire row of the Matrix |
| * @param row Row index to return (0-based) |
| * @return A double[] representing the Matrix row |
| */ |
| public abstract double[] getRow(int row); |
| |
| /** |
| * Returns a copy of an entire column of the Matrix |
| * @param col Column index to return (0-based) |
| * @return A double[] representing the Matrix column |
| */ |
| public abstract double[] getColumn(int col); |
| |
| /** |
| * Sets a single element inthe Matrix |
| * @param row Row index of target element (0-based) |
| * @param col Column index of target element (0-based) |
| * @param value The value to insert into the Matrix at (row, column) |
| */ |
| public abstract void setElement(int row, int col, double value); |
| |
| /** |
| * Sets an entire row of the Matrix, by copying data from the input |
| * @param row Target row index (0-based) |
| * @param values Array of values to write into the Matrix |
| */ |
| public abstract void setRow(int row, double[] values); |
| |
| /** |
| * Sets an entire column of the Matrix, by copying data from the input |
| * @param column Target column index (0-based) |
| * @param values Array of values to write into the Matrix |
| */ |
| public abstract void setColumn(int column, double[] values); |
| |
| /** |
| * Gets the number of rows in the Matrix |
| * @return Configured number of rows in the Matrix |
| */ |
| public long getNumRows() { return numRows_; } |
| |
| /** |
| * Gets the number of columns in the Matrix |
| * @return Configured number of columns in the Matrix |
| */ |
| public long getNumColumns() { return numCols_; } |
| |
| /** |
| * Gets serialized size of the Matrix, in bytes. |
| * @return Number of bytes needed for a serialized Matrix |
| */ |
| public int getSizeBytes() { |
| final int preBytes = MatrixFamily.MATRIX.getMinPreLongs() * Long.BYTES; |
| final int mtxBytes = (numRows_ * numCols_) * Double.BYTES; |
| return preBytes + mtxBytes; |
| } |
| |
| /** |
| * Gets serialized size of the Matrix in cmpact form, in bytes. |
| * @param rows Number of rows to select for writing |
| * @param cols Number of columns to select for writing |
| * @return Number of bytes needed to serialize the first (rows, cols) of this Matrix |
| */ |
| public int getCompactSizeBytes(final int rows, final int cols) { |
| final int nRows = Math.min(rows, numRows_); |
| final int nCols = Math.min(cols, numCols_); |
| |
| if (nRows < 1 || nCols < 1) { |
| return MatrixFamily.MATRIX.getMinPreLongs() * Long.BYTES; |
| } else if (nRows == numRows_ && nCols == numCols_) { |
| return getSizeBytes(); |
| } |
| |
| final int preBytes = MatrixFamily.MATRIX.getMaxPreLongs() * Long.BYTES; |
| final int mtxBytes = (nRows * nCols) * Double.BYTES; |
| return preBytes + mtxBytes; |
| } |
| |
| /** |
| * Writes information about this Matrix to a String. |
| * @return A human-readable representation of a Matrix |
| */ |
| @Override |
| public String toString() { |
| final StringBuilder sb = new StringBuilder(); |
| |
| sb.append(" Matrix data :").append(LS); |
| sb.append(this.getClass().getName()); |
| sb.append(" < ").append(numRows_).append(" x ").append(numCols_).append(" >"); |
| |
| // First element |
| sb.append("\n{ { ").append(getElement(0, 0)); |
| |
| // Rest of the first row |
| for (int j = 1; j < numCols_; j++) { |
| sb.append(",\t").append(getElement(0, j)); |
| } |
| |
| // For each of the remaining rows |
| for (int i = 1; i < numRows_; i++) { |
| |
| // First column |
| sb.append(" },\n{ ").append(getElement(i, 0)); |
| |
| // Remaining columns |
| for (int j = 1; j < numCols_; j++) { |
| sb.append(",\t").append(getElement(i, j)); |
| } |
| } |
| |
| // Finish |
| sb.append(" } }").append(LS); |
| |
| return sb.toString(); |
| } |
| } |