Return-Path: Delivered-To: apmail-lucene-mahout-commits-archive@minotaur.apache.org Received: (qmail 17879 invoked from network); 17 Dec 2009 23:25:08 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 17 Dec 2009 23:25:08 -0000 Received: (qmail 28162 invoked by uid 500); 17 Dec 2009 23:25:08 -0000 Delivered-To: apmail-lucene-mahout-commits-archive@lucene.apache.org Received: (qmail 28098 invoked by uid 500); 17 Dec 2009 23:25:08 -0000 Mailing-List: contact mahout-commits-help@lucene.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: mahout-dev@lucene.apache.org Delivered-To: mailing list mahout-commits@lucene.apache.org Received: (qmail 28089 invoked by uid 99); 17 Dec 2009 23:25:08 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 17 Dec 2009 23:25:08 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 17 Dec 2009 23:24:56 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 21FA82388C79; Thu, 17 Dec 2009 23:23:11 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r891983 [40/47] - in /lucene/mahout/trunk: ./ core/ core/src/main/java/org/apache/mahout/cf/taste/hadoop/item/ core/src/main/java/org/apache/mahout/clustering/ core/src/main/java/org/apache/mahout/clustering/canopy/ core/src/main/java/org/a... Date: Thu, 17 Dec 2009 23:22:41 -0000 To: mahout-commits@lucene.apache.org From: gsingers@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20091217232311.21FA82388C79@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix2D.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix2D.java?rev=891983&view=auto ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix2D.java (added) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix2D.java Thu Dec 17 23:22:16 2009 @@ -0,0 +1,582 @@ +/* +Copyright � 1999 CERN - European Organization for Nuclear Research. +Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose +is hereby granted without fee, provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in supporting documentation. +CERN makes no representations about the suitability of this software for any purpose. +It is provided "as is" without expressed or implied warranty. +*/ +package org.apache.mahout.math.matrix.impl; + +import org.apache.mahout.math.function.DoubleDoubleFunction; +import org.apache.mahout.math.function.DoubleFunction; +import org.apache.mahout.math.function.IntDoubleProcedure; +import org.apache.mahout.math.function.IntIntDoubleFunction; +import org.apache.mahout.math.jet.math.Functions; +import org.apache.mahout.math.jet.math.Mult; +import org.apache.mahout.math.jet.math.PlusMult; +import org.apache.mahout.math.map.AbstractIntDoubleMap; +import org.apache.mahout.math.map.OpenIntDoubleHashMap; +import org.apache.mahout.math.matrix.DoubleMatrix1D; +import org.apache.mahout.math.matrix.DoubleMatrix2D; + +/** @deprecated until unit tests are in place. Until this time, this class/interface is unsupported. */ +@Deprecated +public class SparseDoubleMatrix2D extends DoubleMatrix2D { + /* + * The elements of the matrix. + */ + protected final AbstractIntDoubleMap elements; + protected int dummy; + + /** + * Constructs a matrix with a copy of the given values. values is required to have the form + * values[row][column] and have exactly the same number of columns in every row.

The values are copied. + * So subsequent changes in values are not reflected in the matrix, and vice-versa. + * + * @param values The values to be filled into the new matrix. + * @throws IllegalArgumentException if for any 1 <= row < values.length: values[row].length != + * values[row-1].length. + */ + public SparseDoubleMatrix2D(double[][] values) { + this(values.length, values.length == 0 ? 0 : values[0].length); + assign(values); + } + + /** + * Constructs a matrix with a given number of rows and columns and default memory usage. All entries are initially + * 0. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @throws IllegalArgumentException if rows<0 || columns<0 || (double)columns*rows > Integer.MAX_VALUE. + */ + public SparseDoubleMatrix2D(int rows, int columns) { + this(rows, columns, rows * (columns / 1000), 0.2, 0.5); + } + + /** + * Constructs a matrix with a given number of rows and columns using memory as specified. All entries are initially + * 0. For details related to memory usage see {@link org.apache.mahout.math.map.OpenIntDoubleHashMap}. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param initialCapacity the initial capacity of the hash map. If not known, set initialCapacity=0 or + * small. + * @param minLoadFactor the minimum load factor of the hash map. + * @param maxLoadFactor the maximum load factor of the hash map. + * @throws IllegalArgumentException if initialCapacity < 0 || (minLoadFactor < 0.0 || minLoadFactor >= 1.0) || + * (maxLoadFactor <= 0.0 || maxLoadFactor >= 1.0) || (minLoadFactor >= + * maxLoadFactor). + * @throws IllegalArgumentException if rows<0 || columns<0 || (double)columns*rows > Integer.MAX_VALUE. + */ + public SparseDoubleMatrix2D(int rows, int columns, int initialCapacity, double minLoadFactor, double maxLoadFactor) { + setUp(rows, columns); + this.elements = new OpenIntDoubleHashMap(initialCapacity, minLoadFactor, maxLoadFactor); + } + + /** + * Constructs a view with the given parameters. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param elements the cells. + * @param rowZero the position of the first element. + * @param columnZero the position of the first element. + * @param rowStride the number of elements between two rows, i.e. index(i+1,j)-index(i,j). + * @param columnStride the number of elements between two columns, i.e. index(i,j+1)-index(i,j). + * @throws IllegalArgumentException if rows<0 || columns<0 || (double)columns*rows > Integer.MAX_VALUE or + * flip's are illegal. + */ + protected SparseDoubleMatrix2D(int rows, int columns, AbstractIntDoubleMap elements, int rowZero, int columnZero, + int rowStride, int columnStride) { + setUp(rows, columns, rowZero, columnZero, rowStride, columnStride); + this.elements = elements; + this.isNoView = false; + } + + /** + * Sets all cells to the state specified by value. + * + * @param value the value to be filled into the cells. + * @return this (for convenience only). + */ + @Override + public DoubleMatrix2D assign(double value) { + // overriden for performance only + if (this.isNoView && value == 0) { + this.elements.clear(); + } else { + super.assign(value); + } + return this; + } + + /** + * Assigns the result of a function to each cell; x[row,col] = function(x[row,col]).

Example: + *

+   * matrix = 2 x 2 matrix
+   * 0.5 1.5
+   * 2.5 3.5
+   *
+   * // change each cell to its sine
+   * matrix.assign(Functions.sin);
+   * -->
+   * 2 x 2 matrix
+   * 0.479426  0.997495
+   * 0.598472 -0.350783
+   * 
+ * For further examples, see the package doc. + * + * @param function a function object taking as argument the current cell's value. + * @return this (for convenience only). + * @see org.apache.mahout.math.jet.math.Functions + */ + @Override + public DoubleMatrix2D assign(DoubleFunction function) { + if (this.isNoView && function instanceof Mult) { // x[i] = mult*x[i] + this.elements.assign(function); + } else { + super.assign(function); + } + return this; + } + + /** + * Replaces all cell values of the receiver with the values of another matrix. Both matrices must have the same number + * of rows and columns. If both matrices share the same cells (as is the case if they are views derived from the same + * matrix) and intersect in an ambiguous way, then replaces as if using an intermediate auxiliary deep copy of + * other. + * + * @param source the source matrix to copy from (may be identical to the receiver). + * @return this (for convenience only). + * @throws IllegalArgumentException if columns() != source.columns() || rows() != source.rows() + */ + @Override + public DoubleMatrix2D assign(DoubleMatrix2D source) { + // overriden for performance only + if (!(source instanceof SparseDoubleMatrix2D)) { + return super.assign(source); + } + SparseDoubleMatrix2D other = (SparseDoubleMatrix2D) source; + if (other == this) { + return this; + } // nothing to do + checkShape(other); + + if (this.isNoView && other.isNoView) { // quickest + this.elements.assign(other.elements); + return this; + } + return super.assign(source); + } + + @Override + public DoubleMatrix2D assign(final DoubleMatrix2D y, + DoubleDoubleFunction function) { + if (!this.isNoView) { + return super.assign(y, function); + } + + checkShape(y); + + if (function instanceof PlusMult) { // x[i] = x[i] + alpha*y[i] + final double alpha = ((PlusMult) function).getMultiplicator(); + if (alpha == 0) { + return this; + } // nothing to do + y.forEachNonZero( + new IntIntDoubleFunction() { + @Override + public double apply(int i, int j, double value) { + setQuick(i, j, getQuick(i, j) + alpha * value); + return value; + } + } + ); + return this; + } + + if (function == org.apache.mahout.math.jet.math.Functions.mult) { // x[i] = x[i] * y[i] + this.elements.forEachPair( + new IntDoubleProcedure() { + @Override + public boolean apply(int key, double value) { + int i = key / columns; + int j = key % columns; + double r = value * y.getQuick(i, j); + if (r != value) { + elements.put(key, r); + } + return true; + } + } + ); + } + + if (function == org.apache.mahout.math.jet.math.Functions.div) { // x[i] = x[i] / y[i] + this.elements.forEachPair( + new IntDoubleProcedure() { + @Override + public boolean apply(int key, double value) { + int i = key / columns; + int j = key % columns; + double r = value / y.getQuick(i, j); + if (r != value) { + elements.put(key, r); + } + return true; + } + } + ); + } + + return super.assign(y, function); + } + + /** Returns the number of cells having non-zero values. */ + @Override + public int cardinality() { + if (this.isNoView) { + return this.elements.size(); + } else { + return super.cardinality(); + } + } + + /** + * Ensures that the receiver can hold at least the specified number of non-zero cells without needing to allocate new + * internal memory. If necessary, allocates new internal memory and increases the capacity of the receiver.

This + * method never need be called; it is for performance tuning only. Calling this method before tt>set()ing a large + * number of non-zero values boosts performance, because the receiver will grow only once instead of potentially many + * times and hash collisions get less probable. + * + * @param minCapacity the desired minimum number of non-zero cells. + */ + @Override + public void ensureCapacity(int minCapacity) { + this.elements.ensureCapacity(minCapacity); + } + + @Override + public DoubleMatrix2D forEachNonZero(final org.apache.mahout.math.function.IntIntDoubleFunction function) { + if (this.isNoView) { + this.elements.forEachPair( + new IntDoubleProcedure() { + @Override + public boolean apply(int key, double value) { + int i = key / columns; + int j = key % columns; + double r = function.apply(i, j, value); + if (r != value) { + elements.put(key, r); + } + return true; + } + } + ); + } else { + super.forEachNonZero(function); + } + return this; + } + + /** + * Returns the matrix cell value at coordinate [row,column]. + * + *

Provided with invalid parameters this method may return invalid objects without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): 0 <= column < columns() && 0 <= row < rows(). + * + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + * @return the value at the specified coordinate. + */ + @Override + public double getQuick(int row, int column) { + //if (debug) if (column<0 || column>=columns || row<0 || row>=rows) throw new IndexOutOfBoundsException("row:"+row+", column:"+column); + //return this.elements.get(index(row,column)); + //manually inlined: + return this.elements.get(rowZero + row * rowStride + columnZero + column * columnStride); + } + + /** + * Returns true if both matrices share common cells. More formally, returns true if at least one of + * the following conditions is met

  • the receiver is a view of the other matrix
  • the other matrix is a view + * of the receiver
  • this == other
+ */ + @Override + protected boolean haveSharedCellsRaw(DoubleMatrix2D other) { + if (other instanceof SelectedSparseDoubleMatrix2D) { + SelectedSparseDoubleMatrix2D otherMatrix = (SelectedSparseDoubleMatrix2D) other; + return this.elements == otherMatrix.elements; + } else if (other instanceof SparseDoubleMatrix2D) { + SparseDoubleMatrix2D otherMatrix = (SparseDoubleMatrix2D) other; + return this.elements == otherMatrix.elements; + } + return false; + } + + /** + * Returns the position of the given coordinate within the (virtual or non-virtual) internal 1-dimensional array. + * + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + */ + @Override + protected int index(int row, int column) { + // return super.index(row,column); + // manually inlined for speed: + return rowZero + row * rowStride + columnZero + column * columnStride; + } + + /** + * Construct and returns a new empty matrix of the same dynamic type as the receiver, having the specified + * number of rows and columns. For example, if the receiver is an instance of type DenseDoubleMatrix2D the + * new matrix must also be of type DenseDoubleMatrix2D, if the receiver is an instance of type + * SparseDoubleMatrix2D the new matrix must also be of type SparseDoubleMatrix2D, etc. In general, + * the new matrix should have internal parametrization as similar as possible. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @return a new empty matrix of the same dynamic type. + */ + @Override + public DoubleMatrix2D like(int rows, int columns) { + return new SparseDoubleMatrix2D(rows, columns); + } + + /** + * Construct and returns a new 1-d matrix of the corresponding dynamic type, entirelly independent of the + * receiver. For example, if the receiver is an instance of type DenseDoubleMatrix2D the new matrix must be + * of type DenseDoubleMatrix1D, if the receiver is an instance of type SparseDoubleMatrix2D the new + * matrix must be of type SparseDoubleMatrix1D, etc. + * + * @param size the number of cells the matrix shall have. + * @return a new matrix of the corresponding dynamic type. + */ + @Override + public DoubleMatrix1D like1D(int size) { + return new SparseDoubleMatrix1D(size); + } + + /** + * Construct and returns a new 1-d matrix of the corresponding dynamic type, sharing the same cells. For + * example, if the receiver is an instance of type DenseDoubleMatrix2D the new matrix must be of type + * DenseDoubleMatrix1D, if the receiver is an instance of type SparseDoubleMatrix2D the new matrix + * must be of type SparseDoubleMatrix1D, etc. + * + * @param size the number of cells the matrix shall have. + * @param offset the index of the first element. + * @param stride the number of indexes between any two elements, i.e. index(i+1)-index(i). + * @return a new matrix of the corresponding dynamic type. + */ + @Override + protected DoubleMatrix1D like1D(int size, int offset, int stride) { + return new SparseDoubleMatrix1D(size, this.elements, offset, stride); + } + + /** + * Sets the matrix cell at coordinate [row,column] to the specified value. + * + *

Provided with invalid parameters this method may access illegal indexes without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): 0 <= column < columns() && 0 <= row < rows(). + * + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + * @param value the value to be filled into the specified cell. + */ + @Override + public void setQuick(int row, int column, double value) { + //if (debug) if (column<0 || column>=columns || row<0 || row>=rows) throw new IndexOutOfBoundsException("row:"+row+", column:"+column); + //int index = index(row,column); + //manually inlined: + int index = rowZero + row * rowStride + columnZero + column * columnStride; + + //if (value == 0 || Math.abs(value) < TOLERANCE) + if (value == 0) { + this.elements.removeKey(index); + } else { + this.elements.put(index, value); + } + } + + /** + * Releases any superfluous memory created by explicitly putting zero values into cells formerly having non-zero + * values; An application can use this operation to minimize the storage of the receiver.

Background:

+ * Cells that

  • are never set to non-zero values do not use any memory.
  • switch from zero to non-zero state + * do use memory.
  • switch back from non-zero to zero state also do use memory. However, their memory can be + * reclaimed by calling trimToSize().
A sequence like set(r,c,5); set(r,c,0); sets a cell to + * non-zero state and later back to zero state. Such as sequence generates obsolete memory that is automatically + * reclaimed from time to time or can manually be reclaimed by calling trimToSize(). Putting zeros into cells + * already containing zeros does not generate obsolete memory since no memory was allocated to them in the first + * place. + */ + @Override + public void trimToSize() { + this.elements.trimToSize(); + } + + /** + * Construct and returns a new selection view. + * + * @param rowOffsets the offsets of the visible elements. + * @param columnOffsets the offsets of the visible elements. + * @return a new view. + */ + @Override + protected DoubleMatrix2D viewSelectionLike(int[] rowOffsets, int[] columnOffsets) { + return new SelectedSparseDoubleMatrix2D(this.elements, rowOffsets, columnOffsets, 0); + } + + @Override + public DoubleMatrix1D zMult(DoubleMatrix1D y, DoubleMatrix1D z, double alpha, double beta, final boolean transposeA) { + int m = rows; + int n = columns; + if (transposeA) { + m = columns; + n = rows; + } + + boolean ignore = (z == null); + if (z == null) { + z = new DenseDoubleMatrix1D(m); + } + + if (!(this.isNoView && y instanceof DenseDoubleMatrix1D && z instanceof DenseDoubleMatrix1D)) { + return super.zMult(y, z, alpha, beta, transposeA); + } + + if (n != y.size() || m > z.size()) { + throw new IllegalArgumentException( + "Incompatible args: " + ((transposeA ? viewDice() : this).toStringShort()) + ", " + y.toStringShort() + ", " + + z.toStringShort()); + } + + if (!ignore) { + z.assign(Functions.mult(beta / alpha)); + } + + DenseDoubleMatrix1D zz = (DenseDoubleMatrix1D) z; + final double[] zElements = zz.elements; + final int zStride = zz.stride; + final int zi = z.index(0); + + DenseDoubleMatrix1D yy = (DenseDoubleMatrix1D) y; + final double[] yElements = yy.elements; + final int yStride = yy.stride; + final int yi = y.index(0); + + if (yElements == null || zElements == null) { + throw new InternalError(); + } + + this.elements.forEachPair( + new IntDoubleProcedure() { + @Override + public boolean apply(int key, double value) { + int i = key / columns; + int j = key % columns; + if (transposeA) { + int tmp = i; + i = j; + j = tmp; + } + zElements[zi + zStride * i] += value * yElements[yi + yStride * j]; + //log.info("["+i+","+j+"]-->"+value); + return true; + } + } + ); + + /* + forEachNonZero( + new IntIntDoubleFunction() { + public double apply(int i, int j, double value) { + if (transposeA) { int tmp=i; i=j; j=tmp; } + zElements[zi + zStride*i] += value * yElements[yi + yStride*j]; + //z.setQuick(row,z.getQuick(row) + value * y.getQuick(column)); + //log.info("["+i+","+j+"]-->"+value); + return value; + } + } + ); + */ + + if (alpha != 1) { + z.assign(Functions.mult(alpha)); + } + return z; + } + + @Override + public DoubleMatrix2D zMult(DoubleMatrix2D B, DoubleMatrix2D C, final double alpha, double beta, + final boolean transposeA, boolean transposeB) { + if (!(this.isNoView)) { + return super.zMult(B, C, alpha, beta, transposeA, transposeB); + } + if (transposeB) { + B = B.viewDice(); + } + int m = rows; + int n = columns; + if (transposeA) { + m = columns; + n = rows; + } + int p = B.columns; + boolean ignore = (C == null); + if (C == null) { + C = new DenseDoubleMatrix2D(m, p); + } + + if (B.rows != n) { + throw new IllegalArgumentException("Matrix2D inner dimensions must agree:" + toStringShort() + ", " + + (transposeB ? B.viewDice() : B).toStringShort()); + } + if (C.rows != m || C.columns != p) { + throw new IllegalArgumentException( + "Incompatibel result matrix: " + toStringShort() + ", " + (transposeB ? B.viewDice() : B).toStringShort() + + ", " + C.toStringShort()); + } + if (this == C || B == C) { + throw new IllegalArgumentException("Matrices must not be identical"); + } + + if (!ignore) { + C.assign(Functions.mult(beta)); + } + + // cache views + final DoubleMatrix1D[] Brows = new DoubleMatrix1D[n]; + for (int i = n; --i >= 0;) { + Brows[i] = B.viewRow(i); + } + final DoubleMatrix1D[] Crows = new DoubleMatrix1D[m]; + for (int i = m; --i >= 0;) { + Crows[i] = C.viewRow(i); + } + + final org.apache.mahout.math.jet.math.PlusMult fun = org.apache.mahout.math.jet.math.PlusMult.plusMult(0); + + this.elements.forEachPair( + new IntDoubleProcedure() { + @Override + public boolean apply(int key, double value) { + int i = key / columns; + int j = key % columns; + fun.setMultiplicator(value * alpha); + if (!transposeA) { + Crows[i].assign(Brows[j], fun); + } else { + Crows[j].assign(Brows[i], fun); + } + return true; + } + } + ); + + return C; + } +} Propchange: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix2D.java ------------------------------------------------------------------------------ svn:eol-style = native Added: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix3D.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix3D.java?rev=891983&view=auto ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix3D.java (added) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix3D.java Thu Dec 17 23:22:16 2009 @@ -0,0 +1,283 @@ +/* +Copyright � 1999 CERN - European Organization for Nuclear Research. +Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose +is hereby granted without fee, provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in supporting documentation. +CERN makes no representations about the suitability of this software for any purpose. +It is provided "as is" without expressed or implied warranty. +*/ +package org.apache.mahout.math.matrix.impl; + +import org.apache.mahout.math.map.AbstractIntDoubleMap; +import org.apache.mahout.math.map.OpenIntDoubleHashMap; +import org.apache.mahout.math.matrix.DoubleMatrix2D; +import org.apache.mahout.math.matrix.DoubleMatrix3D; + +/** @deprecated until unit tests are in place. Until this time, this class/interface is unsupported. */ +@Deprecated +public class SparseDoubleMatrix3D extends DoubleMatrix3D { + /* + * The elements of the matrix. + */ + protected AbstractIntDoubleMap elements; + + /** + * Constructs a matrix with a copy of the given values. values is required to have the form + * values[slice][row][column] and have exactly the same number of rows in in every slice and exactly the same + * number of columns in in every row.

The values are copied. So subsequent changes in values are not + * reflected in the matrix, and vice-versa. + * + * @param values The values to be filled into the new matrix. + * @throws IllegalArgumentException if for any 1 <= slice < values.length: values[slice].length != + * values[slice-1].length. + * @throws IllegalArgumentException if for any 1 <= row < values[0].length: values[slice][row].length != + * values[slice][row-1].length. + */ + public SparseDoubleMatrix3D(double[][][] values) { + this(values.length, (values.length == 0 ? 0 : values[0].length), + (values.length == 0 ? 0 : values[0].length == 0 ? 0 : values[0][0].length)); + assign(values); + } + + /** + * Constructs a matrix with a given number of slices, rows and columns and default memory usage. All entries are + * initially 0. + * + * @param slices the number of slices the matrix shall have. + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @throws IllegalArgumentException if (double)slices*columns*rows > Integer.MAX_VALUE. + * @throws IllegalArgumentException if slices<0 || rows<0 || columns<0. + */ + public SparseDoubleMatrix3D(int slices, int rows, int columns) { + this(slices, rows, columns, slices * rows * (columns / 1000), 0.2, 0.5); + } + + /** + * Constructs a matrix with a given number of slices, rows and columns using memory as specified. All entries are + * initially 0. For details related to memory usage see {@link org.apache.mahout.math.map.OpenIntDoubleHashMap}. + * + * @param slices the number of slices the matrix shall have. + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param initialCapacity the initial capacity of the hash map. If not known, set initialCapacity=0 or + * small. + * @param minLoadFactor the minimum load factor of the hash map. + * @param maxLoadFactor the maximum load factor of the hash map. + * @throws IllegalArgumentException if initialCapacity < 0 || (minLoadFactor < 0.0 || minLoadFactor >= 1.0) || + * (maxLoadFactor <= 0.0 || maxLoadFactor >= 1.0) || (minLoadFactor >= + * maxLoadFactor). + * @throws IllegalArgumentException if (double)columns*rows > Integer.MAX_VALUE. + * @throws IllegalArgumentException if slices<0 || rows<0 || columns<0. + */ + public SparseDoubleMatrix3D(int slices, int rows, int columns, int initialCapacity, double minLoadFactor, + double maxLoadFactor) { + setUp(slices, rows, columns); + this.elements = new OpenIntDoubleHashMap(initialCapacity, minLoadFactor, maxLoadFactor); + } + + /** + * Constructs a view with the given parameters. + * + * @param slices the number of slices the matrix shall have. + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param elements the cells. + * @param sliceZero the position of the first element. + * @param rowZero the position of the first element. + * @param columnZero the position of the first element. + * @param sliceStride the number of elements between two slices, i.e. index(k+1,i,j)-index(k,i,j). + * @param rowStride the number of elements between two rows, i.e. index(k,i+1,j)-index(k,i,j). + * @param columnStride the number of elements between two columns, i.e. index(k,i,j+1)-index(k,i,j). + * @throws IllegalArgumentException if (double)slices*columns*rows > Integer.MAX_VALUE. + * @throws IllegalArgumentException if slices<0 || rows<0 || columns<0. + */ + protected SparseDoubleMatrix3D(int slices, int rows, int columns, AbstractIntDoubleMap elements, int sliceZero, + int rowZero, int columnZero, int sliceStride, int rowStride, int columnStride) { + setUp(slices, rows, columns, sliceZero, rowZero, columnZero, sliceStride, rowStride, columnStride); + this.elements = elements; + this.isNoView = false; + } + + /** + * Sets all cells to the state specified by value. + * + * @param value the value to be filled into the cells. + * @return this (for convenience only). + */ + @Override + public DoubleMatrix3D assign(double value) { + // overriden for performance only + if (this.isNoView && value == 0) { + this.elements.clear(); + } else { + super.assign(value); + } + return this; + } + + /** Returns the number of cells having non-zero values. */ + @Override + public int cardinality() { + if (this.isNoView) { + return this.elements.size(); + } else { + return super.cardinality(); + } + } + + /** + * Ensures that the receiver can hold at least the specified number of non-zero cells without needing to allocate new + * internal memory. If necessary, allocates new internal memory and increases the capacity of the receiver.

This + * method never need be called; it is for performance tuning only. Calling this method before tt>set()ing a large + * number of non-zero values boosts performance, because the receiver will grow only once instead of potentially many + * times and hash collisions get less probable. + * + * @param minCapacity the desired minimum number of non-zero cells. + */ + @Override + public void ensureCapacity(int minCapacity) { + this.elements.ensureCapacity(minCapacity); + } + + /** + * Returns the matrix cell value at coordinate [slice,row,column]. + * + *

Provided with invalid parameters this method may return invalid objects without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): slice<0 || slice>=slices() || row<0 || row>=rows() || column<0 || + * column>=column(). + * + * @param slice the index of the slice-coordinate. + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + * @return the value at the specified coordinate. + */ + @Override + public double getQuick(int slice, int row, int column) { + //if (debug) if (slice<0 || slice>=slices || row<0 || row>=rows || column<0 || column>=columns) throw new IndexOutOfBoundsException("slice:"+slice+", row:"+row+", column:"+column); + //return elements.get(index(slice,row,column)); + //manually inlined: + return elements + .get(sliceZero + slice * sliceStride + rowZero + row * rowStride + columnZero + column * columnStride); + } + + /** Returns true if both matrices share at least one identical cell. */ + @Override + protected boolean haveSharedCellsRaw(DoubleMatrix3D other) { + if (other instanceof SelectedSparseDoubleMatrix3D) { + SelectedSparseDoubleMatrix3D otherMatrix = (SelectedSparseDoubleMatrix3D) other; + return this.elements == otherMatrix.elements; + } else if (other instanceof SparseDoubleMatrix3D) { + SparseDoubleMatrix3D otherMatrix = (SparseDoubleMatrix3D) other; + return this.elements == otherMatrix.elements; + } + return false; + } + + /** + * Returns the position of the given coordinate within the (virtual or non-virtual) internal 1-dimensional array. + * + * @param slice the index of the slice-coordinate. + * @param row the index of the row-coordinate. + * @param column the index of the third-coordinate. + */ + @Override + protected int index(int slice, int row, int column) { + //return _sliceOffset(_sliceRank(slice)) + _rowOffset(_rowRank(row)) + _columnOffset(_columnRank(column)); + //manually inlined: + return sliceZero + slice * sliceStride + rowZero + row * rowStride + columnZero + column * columnStride; + } + + /** + * Construct and returns a new empty matrix of the same dynamic type as the receiver, having the specified + * number of slices, rows and columns. For example, if the receiver is an instance of type + * DenseDoubleMatrix3D the new matrix must also be of type DenseDoubleMatrix3D, if the receiver is + * an instance of type SparseDoubleMatrix3D the new matrix must also be of type + * SparseDoubleMatrix3D, etc. In general, the new matrix should have internal parametrization as similar as + * possible. + * + * @param slices the number of slices the matrix shall have. + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @return a new empty matrix of the same dynamic type. + */ + @Override + public DoubleMatrix3D like(int slices, int rows, int columns) { + return new SparseDoubleMatrix3D(slices, rows, columns); + } + + /** + * Construct and returns a new 2-d matrix of the corresponding dynamic type, sharing the same cells. For + * example, if the receiver is an instance of type DenseDoubleMatrix3D the new matrix must also be of type + * DenseDoubleMatrix2D, if the receiver is an instance of type SparseDoubleMatrix3D the new matrix + * must also be of type SparseDoubleMatrix2D, etc. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param rowZero the position of the first element. + * @param columnZero the position of the first element. + * @param rowStride the number of elements between two rows, i.e. index(i+1,j)-index(i,j). + * @param columnStride the number of elements between two columns, i.e. index(i,j+1)-index(i,j). + * @return a new matrix of the corresponding dynamic type. + */ + @Override + protected DoubleMatrix2D like2D(int rows, int columns, int rowZero, int columnZero, int rowStride, int columnStride) { + return new SparseDoubleMatrix2D(rows, columns, this.elements, rowZero, columnZero, rowStride, columnStride); + } + + /** + * Sets the matrix cell at coordinate [slice,row,column] to the specified value. + * + *

Provided with invalid parameters this method may access illegal indexes without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): slice<0 || slice>=slices() || row<0 || row>=rows() || column<0 || + * column>=column(). + * + * @param slice the index of the slice-coordinate. + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + * @param value the value to be filled into the specified cell. + */ + @Override + public void setQuick(int slice, int row, int column, double value) { + //if (debug) if (slice<0 || slice>=slices || row<0 || row>=rows || column<0 || column>=columns) throw new IndexOutOfBoundsException("slice:"+slice+", row:"+row+", column:"+column); + //int index = index(slice,row,column); + //manually inlined: + int index = sliceZero + slice * sliceStride + rowZero + row * rowStride + columnZero + column * columnStride; + if (value == 0) { + this.elements.removeKey(index); + } else { + this.elements.put(index, value); + } + } + + /** + * Releases any superfluous memory created by explicitly putting zero values into cells formerly having non-zero + * values; An application can use this operation to minimize the storage of the receiver.

Background:

+ * Cells that

  • are never set to non-zero values do not use any memory.
  • switch from zero to non-zero state + * do use memory.
  • switch back from non-zero to zero state also do use memory. However, their memory can be + * reclaimed by calling trimToSize().
A sequence like set(s,r,c,5); set(s,r,c,0); sets a cell + * to non-zero state and later back to zero state. Such as sequence generates obsolete memory that is automatically + * reclaimed from time to time or can manually be reclaimed by calling trimToSize(). Putting zeros into cells + * already containing zeros does not generate obsolete memory since no memory was allocated to them in the first + * place. + */ + @Override + public void trimToSize() { + this.elements.trimToSize(); + } + + /** + * Construct and returns a new selection view. + * + * @param sliceOffsets the offsets of the visible elements. + * @param rowOffsets the offsets of the visible elements. + * @param columnOffsets the offsets of the visible elements. + * @return a new view. + */ + @Override + protected DoubleMatrix3D viewSelectionLike(int[] sliceOffsets, int[] rowOffsets, int[] columnOffsets) { + return new SelectedSparseDoubleMatrix3D(this.elements, sliceOffsets, rowOffsets, columnOffsets, 0); + } +} Propchange: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseDoubleMatrix3D.java ------------------------------------------------------------------------------ svn:eol-style = native Added: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix1D.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix1D.java?rev=891983&view=auto ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix1D.java (added) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix1D.java Thu Dec 17 23:22:16 2009 @@ -0,0 +1,226 @@ +/* +Copyright � 1999 CERN - European Organization for Nuclear Research. +Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose +is hereby granted without fee, provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in supporting documentation. +CERN makes no representations about the suitability of this software for any purpose. +It is provided "as is" without expressed or implied warranty. +*/ +package org.apache.mahout.math.matrix.impl; + +import org.apache.mahout.math.map.AbstractIntObjectMap; +import org.apache.mahout.math.map.OpenIntObjectHashMap; +import org.apache.mahout.math.matrix.ObjectMatrix1D; +import org.apache.mahout.math.matrix.ObjectMatrix2D; + +/** @deprecated until unit tests are in place. Until this time, this class/interface is unsupported. */ +@Deprecated +public class SparseObjectMatrix1D extends ObjectMatrix1D { + /* + * The elements of the matrix. + */ + protected final AbstractIntObjectMap elements; + + /** + * Constructs a matrix with a copy of the given values. The values are copied. So subsequent changes in + * values are not reflected in the matrix, and vice-versa. + * + * @param values The values to be filled into the new matrix. + */ + public SparseObjectMatrix1D(Object[] values) { + this(values.length); + assign(values); + } + + /** + * Constructs a matrix with a given number of cells. All entries are initially null. + * + * @param size the number of cells the matrix shall have. + * @throws IllegalArgumentException if size<0. + */ + public SparseObjectMatrix1D(int size) { + this(size, size / 1000, 0.2, 0.5); + } + + /** + * Constructs a matrix with a given number of parameters. All entries are initially null. For details related + * to memory usage see {@link org.apache.mahout.math.map.OpenIntObjectHashMap}. + * + * @param size the number of cells the matrix shall have. + * @param initialCapacity the initial capacity of the hash map. If not known, set initialCapacity=0 or + * small. + * @param minLoadFactor the minimum load factor of the hash map. + * @param maxLoadFactor the maximum load factor of the hash map. + * @throws IllegalArgumentException if initialCapacity < 0 || (minLoadFactor < 0.0 || minLoadFactor >= 1.0) || + * (maxLoadFactor <= 0.0 || maxLoadFactor >= 1.0) || (minLoadFactor >= + * maxLoadFactor). + * @throws IllegalArgumentException if size<0. + */ + public SparseObjectMatrix1D(int size, int initialCapacity, double minLoadFactor, double maxLoadFactor) { + setUp(size); + this.elements = new OpenIntObjectHashMap(initialCapacity, minLoadFactor, maxLoadFactor); + } + + /** + * Constructs a matrix view with a given number of parameters. + * + * @param size the number of cells the matrix shall have. + * @param elements the cells. + * @param offset the index of the first element. + * @param stride the number of indexes between any two elements, i.e. index(i+1)-index(i). + * @throws IllegalArgumentException if size<0. + */ + protected SparseObjectMatrix1D(int size, AbstractIntObjectMap elements, int offset, int stride) { + setUp(size, offset, stride); + this.elements = elements; + this.isNoView = false; + } + + /** Returns the number of cells having non-zero values. */ + @Override + public int cardinality() { + if (this.isNoView) { + return this.elements.size(); + } else { + return super.cardinality(); + } + } + + /** + * Ensures that the receiver can hold at least the specified number of non-zero cells without needing to allocate new + * internal memory. If necessary, allocates new internal memory and increases the capacity of the receiver.

This + * method never need be called; it is for performance tuning only. Calling this method before tt>set()ing a large + * number of non-zero values boosts performance, because the receiver will grow only once instead of potentially many + * times and hash collisions get less probable. + * + * @param minCapacity the desired minimum number of non-zero cells. + */ + @Override + public void ensureCapacity(int minCapacity) { + this.elements.ensureCapacity(minCapacity); + } + + /** + * Returns the matrix cell value at coordinate index. + * + *

Provided with invalid parameters this method may return invalid objects without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): index<0 || index>=size(). + * + * @param index the index of the cell. + * @return the value of the specified cell. + */ + @Override + public Object getQuick(int index) { + //if (debug) if (index<0 || index>=size) checkIndex(index); + //return this.elements.get(index(index)); + // manually inlined: + return elements.get(zero + index * stride); + } + + /** Returns true if both matrices share at least one identical cell. */ + @Override + protected boolean haveSharedCellsRaw(ObjectMatrix1D other) { + if (other instanceof SelectedSparseObjectMatrix1D) { + SelectedSparseObjectMatrix1D otherMatrix = (SelectedSparseObjectMatrix1D) other; + return this.elements == otherMatrix.elements; + } else if (other instanceof SparseObjectMatrix1D) { + SparseObjectMatrix1D otherMatrix = (SparseObjectMatrix1D) other; + return this.elements == otherMatrix.elements; + } + return false; + } + + /** + * Returns the position of the element with the given relative rank within the (virtual or non-virtual) internal + * 1-dimensional array. You may want to override this method for performance. + * + * @param rank the rank of the element. + */ + @Override + protected int index(int rank) { + // overriden for manual inlining only + //return _offset(_rank(rank)); + return zero + rank * stride; + } + + /** + * Construct and returns a new empty matrix of the same dynamic type as the receiver, having the specified + * size. For example, if the receiver is an instance of type DenseObjectMatrix1D the new matrix must also be + * of type DenseObjectMatrix1D, if the receiver is an instance of type SparseObjectMatrix1D the new + * matrix must also be of type SparseObjectMatrix1D, etc. In general, the new matrix should have internal + * parametrization as similar as possible. + * + * @param size the number of cell the matrix shall have. + * @return a new empty matrix of the same dynamic type. + */ + @Override + public ObjectMatrix1D like(int size) { + return new SparseObjectMatrix1D(size); + } + + /** + * Construct and returns a new 2-d matrix of the corresponding dynamic type, entirelly independent of the + * receiver. For example, if the receiver is an instance of type DenseObjectMatrix1D the new matrix must be + * of type DenseObjectMatrix2D, if the receiver is an instance of type SparseObjectMatrix1D the new + * matrix must be of type SparseObjectMatrix2D, etc. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @return a new matrix of the corresponding dynamic type. + */ + @Override + public ObjectMatrix2D like2D(int rows, int columns) { + return new SparseObjectMatrix2D(rows, columns); + } + + /** + * Sets the matrix cell at coordinate index to the specified value. + * + *

Provided with invalid parameters this method may access illegal indexes without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): index<0 || index>=size(). + * + * @param index the index of the cell. + * @param value the value to be filled into the specified cell. + */ + @Override + public void setQuick(int index, Object value) { + //if (debug) if (index<0 || index>=size) checkIndex(index); + //int i = index(index); + // manually inlined: + int i = zero + index * stride; + if (value == null) { + this.elements.removeKey(i); + } else { + this.elements.put(i, value); + } + } + + /** + * Releases any superfluous memory created by explicitly putting zero values into cells formerly having non-zero + * values; An application can use this operation to minimize the storage of the receiver.

Background:

+ * Cells that

  • are never set to non-zero values do not use any memory.
  • switch from zero to non-zero state + * do use memory.
  • switch back from non-zero to zero state also do use memory. However, their memory can be + * reclaimed by calling trimToSize().
A sequence like set(i,5); set(i,0); sets a cell to + * non-zero state and later back to zero state. Such as sequence generates obsolete memory that is automatically + * reclaimed from time to time or can manually be reclaimed by calling trimToSize(). Putting zeros into cells + * already containing zeros does not generate obsolete memory since no memory was allocated to them in the first + * place. + */ + @Override + public void trimToSize() { + this.elements.trimToSize(); + } + + /** + * Construct and returns a new selection view. + * + * @param offsets the offsets of the visible elements. + * @return a new view. + */ + @Override + protected ObjectMatrix1D viewSelectionLike(int[] offsets) { + return new SelectedSparseObjectMatrix1D(this.elements, offsets); + } +} Propchange: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix1D.java ------------------------------------------------------------------------------ svn:eol-style = native Added: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix2D.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix2D.java?rev=891983&view=auto ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix2D.java (added) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix2D.java Thu Dec 17 23:22:16 2009 @@ -0,0 +1,261 @@ +/* +Copyright � 1999 CERN - European Organization for Nuclear Research. +Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose +is hereby granted without fee, provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in supporting documentation. +CERN makes no representations about the suitability of this software for any purpose. +It is provided "as is" without expressed or implied warranty. +*/ +package org.apache.mahout.math.matrix.impl; + +import org.apache.mahout.math.map.AbstractIntObjectMap; +import org.apache.mahout.math.map.OpenIntObjectHashMap; +import org.apache.mahout.math.matrix.ObjectMatrix1D; +import org.apache.mahout.math.matrix.ObjectMatrix2D; + +/** @deprecated until unit tests are in place. Until this time, this class/interface is unsupported. */ +@Deprecated +public class SparseObjectMatrix2D extends ObjectMatrix2D { + /* + * The elements of the matrix. + */ + protected final AbstractIntObjectMap elements; + + /** + * Constructs a matrix with a copy of the given values. values is required to have the form + * values[row][column] and have exactly the same number of columns in every row.

The values are copied. + * So subsequent changes in values are not reflected in the matrix, and vice-versa. + * + * @param values The values to be filled into the new matrix. + * @throws IllegalArgumentException if for any 1 <= row < values.length: values[row].length != + * values[row-1].length. + */ + public SparseObjectMatrix2D(Object[][] values) { + this(values.length, values.length == 0 ? 0 : values[0].length); + assign(values); + } + + /** + * Constructs a matrix with a given number of rows and columns and default memory usage. All entries are initially + * null. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @throws IllegalArgumentException if rows<0 || columns<0 || (double)columns*rows > Integer.MAX_VALUE. + */ + public SparseObjectMatrix2D(int rows, int columns) { + this(rows, columns, rows * (columns / 1000), 0.2, 0.5); + } + + /** + * Constructs a matrix with a given number of rows and columns using memory as specified. All entries are initially + * null. For details related to memory usage see {@link org.apache.mahout.math.map.OpenIntObjectHashMap}. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param initialCapacity the initial capacity of the hash map. If not known, set initialCapacity=0 or + * small. + * @param minLoadFactor the minimum load factor of the hash map. + * @param maxLoadFactor the maximum load factor of the hash map. + * @throws IllegalArgumentException if initialCapacity < 0 || (minLoadFactor < 0.0 || minLoadFactor >= 1.0) || + * (maxLoadFactor <= 0.0 || maxLoadFactor >= 1.0) || (minLoadFactor >= + * maxLoadFactor). + * @throws IllegalArgumentException if rows<0 || columns<0 || (double)columns*rows > Integer.MAX_VALUE. + */ + public SparseObjectMatrix2D(int rows, int columns, int initialCapacity, double minLoadFactor, double maxLoadFactor) { + setUp(rows, columns); + this.elements = new OpenIntObjectHashMap(initialCapacity, minLoadFactor, maxLoadFactor); + } + + /** + * Constructs a view with the given parameters. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param elements the cells. + * @param rowZero the position of the first element. + * @param columnZero the position of the first element. + * @param rowStride the number of elements between two rows, i.e. index(i+1,j)-index(i,j). + * @param columnStride the number of elements between two columns, i.e. index(i,j+1)-index(i,j). + * @throws IllegalArgumentException if rows<0 || columns<0 || (double)columns*rows > Integer.MAX_VALUE or + * flip's are illegal. + */ + protected SparseObjectMatrix2D(int rows, int columns, AbstractIntObjectMap elements, int rowZero, int columnZero, + int rowStride, int columnStride) { + setUp(rows, columns, rowZero, columnZero, rowStride, columnStride); + this.elements = elements; + this.isNoView = false; + } + + /** Returns the number of cells having non-zero values. */ + @Override + public int cardinality() { + if (this.isNoView) { + return this.elements.size(); + } else { + return super.cardinality(); + } + } + + /** + * Ensures that the receiver can hold at least the specified number of non-zero cells without needing to allocate new + * internal memory. If necessary, allocates new internal memory and increases the capacity of the receiver.

This + * method never need be called; it is for performance tuning only. Calling this method before tt>set()ing a large + * number of non-zero values boosts performance, because the receiver will grow only once instead of potentially many + * times and hash collisions get less probable. + * + * @param minCapacity the desired minimum number of non-zero cells. + */ + @Override + public void ensureCapacity(int minCapacity) { + this.elements.ensureCapacity(minCapacity); + } + + /** + * Returns the matrix cell value at coordinate [row,column]. + * + *

Provided with invalid parameters this method may return invalid objects without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): 0 <= column < columns() && 0 <= row < rows(). + * + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + * @return the value at the specified coordinate. + */ + @Override + public Object getQuick(int row, int column) { + //if (debug) if (column<0 || column>=columns || row<0 || row>=rows) throw new IndexOutOfBoundsException("row:"+row+", column:"+column); + //return this.elements.get(index(row,column)); + //manually inlined: + return this.elements.get(rowZero + row * rowStride + columnZero + column * columnStride); + } + + /** + * Returns true if both matrices share common cells. More formally, returns true if at least one of + * the following conditions is met

  • the receiver is a view of the other matrix
  • the other matrix is a view + * of the receiver
  • this == other
+ */ + @Override + protected boolean haveSharedCellsRaw(ObjectMatrix2D other) { + if (other instanceof SelectedSparseObjectMatrix2D) { + SelectedSparseObjectMatrix2D otherMatrix = (SelectedSparseObjectMatrix2D) other; + return this.elements == otherMatrix.elements; + } else if (other instanceof SparseObjectMatrix2D) { + SparseObjectMatrix2D otherMatrix = (SparseObjectMatrix2D) other; + return this.elements == otherMatrix.elements; + } + return false; + } + + /** + * Returns the position of the given coordinate within the (virtual or non-virtual) internal 1-dimensional array. + * + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + */ + @Override + protected int index(int row, int column) { + // return super.index(row,column); + // manually inlined for speed: + return rowZero + row * rowStride + columnZero + column * columnStride; + } + + /** + * Construct and returns a new empty matrix of the same dynamic type as the receiver, having the specified + * number of rows and columns. For example, if the receiver is an instance of type DenseObjectMatrix2D the + * new matrix must also be of type DenseObjectMatrix2D, if the receiver is an instance of type + * SparseObjectMatrix2D the new matrix must also be of type SparseObjectMatrix2D, etc. In general, + * the new matrix should have internal parametrization as similar as possible. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @return a new empty matrix of the same dynamic type. + */ + @Override + public ObjectMatrix2D like(int rows, int columns) { + return new SparseObjectMatrix2D(rows, columns); + } + + /** + * Construct and returns a new 1-d matrix of the corresponding dynamic type, entirelly independent of the + * receiver. For example, if the receiver is an instance of type DenseObjectMatrix2D the new matrix must be + * of type DenseObjectMatrix1D, if the receiver is an instance of type SparseObjectMatrix2D the new + * matrix must be of type SparseObjectMatrix1D, etc. + * + * @param size the number of cells the matrix shall have. + * @return a new matrix of the corresponding dynamic type. + */ + @Override + public ObjectMatrix1D like1D(int size) { + return new SparseObjectMatrix1D(size); + } + + /** + * Construct and returns a new 1-d matrix of the corresponding dynamic type, sharing the same cells. For + * example, if the receiver is an instance of type DenseObjectMatrix2D the new matrix must be of type + * DenseObjectMatrix1D, if the receiver is an instance of type SparseObjectMatrix2D the new matrix + * must be of type SparseObjectMatrix1D, etc. + * + * @param size the number of cells the matrix shall have. + * @param offset the index of the first element. + * @param stride the number of indexes between any two elements, i.e. index(i+1)-index(i). + * @return a new matrix of the corresponding dynamic type. + */ + @Override + protected ObjectMatrix1D like1D(int size, int offset, int stride) { + return new SparseObjectMatrix1D(size, this.elements, offset, stride); + } + + /** + * Sets the matrix cell at coordinate [row,column] to the specified value. + * + *

Provided with invalid parameters this method may access illegal indexes without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): 0 <= column < columns() && 0 <= row < rows(). + * + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + * @param value the value to be filled into the specified cell. + */ + @Override + public void setQuick(int row, int column, Object value) { + //if (debug) if (column<0 || column>=columns || row<0 || row>=rows) throw new IndexOutOfBoundsException("row:"+row+", column:"+column); + //int index = index(row,column); + //manually inlined: + int index = rowZero + row * rowStride + columnZero + column * columnStride; + + if (value == null) { + this.elements.removeKey(index); + } else { + this.elements.put(index, value); + } + } + + /** + * Releases any superfluous memory created by explicitly putting zero values into cells formerly having non-zero + * values; An application can use this operation to minimize the storage of the receiver.

Background:

+ * Cells that

  • are never set to non-zero values do not use any memory.
  • switch from zero to non-zero state + * do use memory.
  • switch back from non-zero to zero state also do use memory. However, their memory can be + * reclaimed by calling trimToSize().
A sequence like set(r,c,5); set(r,c,0); sets a cell to + * non-zero state and later back to zero state. Such as sequence generates obsolete memory that is automatically + * reclaimed from time to time or can manually be reclaimed by calling trimToSize(). Putting zeros into cells + * already containing zeros does not generate obsolete memory since no memory was allocated to them in the first + * place. + */ + @Override + public void trimToSize() { + this.elements.trimToSize(); + } + + /** + * Construct and returns a new selection view. + * + * @param rowOffsets the offsets of the visible elements. + * @param columnOffsets the offsets of the visible elements. + * @return a new view. + */ + @Override + protected ObjectMatrix2D viewSelectionLike(int[] rowOffsets, int[] columnOffsets) { + return new SelectedSparseObjectMatrix2D(this.elements, rowOffsets, columnOffsets, 0); + } +} Propchange: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix2D.java ------------------------------------------------------------------------------ svn:eol-style = native Added: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix3D.java URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix3D.java?rev=891983&view=auto ============================================================================== --- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix3D.java (added) +++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix3D.java Thu Dec 17 23:22:16 2009 @@ -0,0 +1,266 @@ +/* +Copyright � 1999 CERN - European Organization for Nuclear Research. +Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose +is hereby granted without fee, provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in supporting documentation. +CERN makes no representations about the suitability of this software for any purpose. +It is provided "as is" without expressed or implied warranty. +*/ +package org.apache.mahout.math.matrix.impl; + +import org.apache.mahout.math.map.AbstractIntObjectMap; +import org.apache.mahout.math.map.OpenIntObjectHashMap; +import org.apache.mahout.math.matrix.ObjectMatrix2D; +import org.apache.mahout.math.matrix.ObjectMatrix3D; + +/** @deprecated until unit tests are in place. Until this time, this class/interface is unsupported. */ +@Deprecated +public class SparseObjectMatrix3D extends ObjectMatrix3D { + /* + * The elements of the matrix. + */ + protected AbstractIntObjectMap elements; + + /** + * Constructs a matrix with a copy of the given values. values is required to have the form + * values[slice][row][column] and have exactly the same number of rows in in every slice and exactly the same + * number of columns in in every row.

The values are copied. So subsequent changes in values are not + * reflected in the matrix, and vice-versa. + * + * @param values The values to be filled into the new matrix. + * @throws IllegalArgumentException if for any 1 <= slice < values.length: values[slice].length != + * values[slice-1].length. + * @throws IllegalArgumentException if for any 1 <= row < values[0].length: values[slice][row].length != + * values[slice][row-1].length. + */ + public SparseObjectMatrix3D(Object[][][] values) { + this(values.length, (values.length == 0 ? 0 : values[0].length), + (values.length == 0 ? 0 : values[0].length == 0 ? 0 : values[0][0].length)); + assign(values); + } + + /** + * Constructs a matrix with a given number of slices, rows and columns and default memory usage. All entries are + * initially null. + * + * @param slices the number of slices the matrix shall have. + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @throws IllegalArgumentException if (double)slices*columns*rows > Integer.MAX_VALUE. + * @throws IllegalArgumentException if slices<0 || rows<0 || columns<0. + */ + public SparseObjectMatrix3D(int slices, int rows, int columns) { + this(slices, rows, columns, slices * rows * (columns / 1000), 0.2, 0.5); + } + + /** + * Constructs a matrix with a given number of slices, rows and columns using memory as specified. All entries are + * initially null. For details related to memory usage see {@link org.apache.mahout.math.map.OpenIntObjectHashMap}. + * + * @param slices the number of slices the matrix shall have. + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param initialCapacity the initial capacity of the hash map. If not known, set initialCapacity=0 or + * small. + * @param minLoadFactor the minimum load factor of the hash map. + * @param maxLoadFactor the maximum load factor of the hash map. + * @throws IllegalArgumentException if initialCapacity < 0 || (minLoadFactor < 0.0 || minLoadFactor >= 1.0) || + * (maxLoadFactor <= 0.0 || maxLoadFactor >= 1.0) || (minLoadFactor >= + * maxLoadFactor). + * @throws IllegalArgumentException if (double)slices*columns*rows > Integer.MAX_VALUE. + * @throws IllegalArgumentException if slices<0 || rows<0 || columns<0. + */ + public SparseObjectMatrix3D(int slices, int rows, int columns, int initialCapacity, double minLoadFactor, + double maxLoadFactor) { + setUp(slices, rows, columns); + this.elements = new OpenIntObjectHashMap(initialCapacity, minLoadFactor, maxLoadFactor); + } + + /** + * Constructs a view with the given parameters. + * + * @param slices the number of slices the matrix shall have. + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param elements the cells. + * @param sliceZero the position of the first element. + * @param rowZero the position of the first element. + * @param columnZero the position of the first element. + * @param sliceStride the number of elements between two slices, i.e. index(k+1,i,j)-index(k,i,j). + * @param rowStride the number of elements between two rows, i.e. index(k,i+1,j)-index(k,i,j). + * @param columnStride the number of elements between two columns, i.e. index(k,i,j+1)-index(k,i,j). + * @throws IllegalArgumentException if (Object)slices*columns*rows > Integer.MAX_VALUE. + * @throws IllegalArgumentException if slices<0 || rows<0 || columns<0. + */ + protected SparseObjectMatrix3D(int slices, int rows, int columns, AbstractIntObjectMap elements, int sliceZero, + int rowZero, int columnZero, int sliceStride, int rowStride, int columnStride) { + setUp(slices, rows, columns, sliceZero, rowZero, columnZero, sliceStride, rowStride, columnStride); + this.elements = elements; + this.isNoView = false; + } + + /** Returns the number of cells having non-zero values. */ + @Override + public int cardinality() { + if (this.isNoView) { + return this.elements.size(); + } else { + return super.cardinality(); + } + } + + /** + * Ensures that the receiver can hold at least the specified number of non-zero cells without needing to allocate new + * internal memory. If necessary, allocates new internal memory and increases the capacity of the receiver.

This + * method never need be called; it is for performance tuning only. Calling this method before tt>set()ing a large + * number of non-zero values boosts performance, because the receiver will grow only once instead of potentially many + * times and hash collisions get less probable. + * + * @param minCapacity the desired minimum number of non-zero cells. + */ + @Override + public void ensureCapacity(int minCapacity) { + this.elements.ensureCapacity(minCapacity); + } + + /** + * Returns the matrix cell value at coordinate [slice,row,column]. + * + *

Provided with invalid parameters this method may return invalid objects without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): slice<0 || slice>=slices() || row<0 || row>=rows() || column<0 || + * column>=column(). + * + * @param slice the index of the slice-coordinate. + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + * @return the value at the specified coordinate. + */ + @Override + public Object getQuick(int slice, int row, int column) { + //if (debug) if (slice<0 || slice>=slices || row<0 || row>=rows || column<0 || column>=columns) throw new IndexOutOfBoundsException("slice:"+slice+", row:"+row+", column:"+column); + //return elements.get(index(slice,row,column)); + //manually inlined: + return elements + .get(sliceZero + slice * sliceStride + rowZero + row * rowStride + columnZero + column * columnStride); + } + + /** Returns true if both matrices share at least one identical cell. */ + @Override + protected boolean haveSharedCellsRaw(ObjectMatrix3D other) { + if (other instanceof SelectedSparseObjectMatrix3D) { + SelectedSparseObjectMatrix3D otherMatrix = (SelectedSparseObjectMatrix3D) other; + return this.elements == otherMatrix.elements; + } else if (other instanceof SparseObjectMatrix3D) { + SparseObjectMatrix3D otherMatrix = (SparseObjectMatrix3D) other; + return this.elements == otherMatrix.elements; + } + return false; + } + + /** + * Returns the position of the given coordinate within the (virtual or non-virtual) internal 1-dimensional array. + * + * @param slice the index of the slice-coordinate. + * @param row the index of the row-coordinate. + * @param column the index of the third-coordinate. + */ + @Override + protected int index(int slice, int row, int column) { + //return _sliceOffset(_sliceRank(slice)) + _rowOffset(_rowRank(row)) + _columnOffset(_columnRank(column)); + //manually inlined: + return sliceZero + slice * sliceStride + rowZero + row * rowStride + columnZero + column * columnStride; + } + + /** + * Construct and returns a new empty matrix of the same dynamic type as the receiver, having the specified + * number of slices, rows and columns. For example, if the receiver is an instance of type + * DenseObjectMatrix3D the new matrix must also be of type DenseObjectMatrix3D, if the receiver is + * an instance of type SparseObjectMatrix3D the new matrix must also be of type + * SparseObjectMatrix3D, etc. In general, the new matrix should have internal parametrization as similar as + * possible. + * + * @param slices the number of slices the matrix shall have. + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @return a new empty matrix of the same dynamic type. + */ + @Override + public ObjectMatrix3D like(int slices, int rows, int columns) { + return new SparseObjectMatrix3D(slices, rows, columns); + } + + /** + * Construct and returns a new 2-d matrix of the corresponding dynamic type, sharing the same cells. For + * example, if the receiver is an instance of type DenseObjectMatrix3D the new matrix must also be of type + * DenseObjectMatrix2D, if the receiver is an instance of type SparseObjectMatrix3D the new matrix + * must also be of type SparseObjectMatrix2D, etc. + * + * @param rows the number of rows the matrix shall have. + * @param columns the number of columns the matrix shall have. + * @param rowZero the position of the first element. + * @param columnZero the position of the first element. + * @param rowStride the number of elements between two rows, i.e. index(i+1,j)-index(i,j). + * @param columnStride the number of elements between two columns, i.e. index(i,j+1)-index(i,j). + * @return a new matrix of the corresponding dynamic type. + */ + @Override + protected ObjectMatrix2D like2D(int rows, int columns, int rowZero, int columnZero, int rowStride, int columnStride) { + return new SparseObjectMatrix2D(rows, columns, this.elements, rowZero, columnZero, rowStride, columnStride); + } + + /** + * Sets the matrix cell at coordinate [slice,row,column] to the specified value. + * + *

Provided with invalid parameters this method may access illegal indexes without throwing any exception. You + * should only use this method when you are absolutely sure that the coordinate is within bounds. Precondition + * (unchecked): slice<0 || slice>=slices() || row<0 || row>=rows() || column<0 || + * column>=column(). + * + * @param slice the index of the slice-coordinate. + * @param row the index of the row-coordinate. + * @param column the index of the column-coordinate. + * @param value the value to be filled into the specified cell. + */ + @Override + public void setQuick(int slice, int row, int column, Object value) { + //if (debug) if (slice<0 || slice>=slices || row<0 || row>=rows || column<0 || column>=columns) throw new IndexOutOfBoundsException("slice:"+slice+", row:"+row+", column:"+column); + //int index = index(slice,row,column); + //manually inlined: + int index = sliceZero + slice * sliceStride + rowZero + row * rowStride + columnZero + column * columnStride; + if (value == null) { + this.elements.removeKey(index); + } else { + this.elements.put(index, value); + } + } + + /** + * Releases any superfluous memory created by explicitly putting zero values into cells formerly having non-zero + * values; An application can use this operation to minimize the storage of the receiver.

Background:

+ * Cells that

  • are never set to non-zero values do not use any memory.
  • switch from zero to non-zero state + * do use memory.
  • switch back from non-zero to zero state also do use memory. However, their memory can be + * reclaimed by calling trimToSize().
A sequence like set(s,r,c,5); set(s,r,c,0); sets a cell + * to non-zero state and later back to zero state. Such as sequence generates obsolete memory that is automatically + * reclaimed from time to time or can manually be reclaimed by calling trimToSize(). Putting zeros into cells + * already containing zeros does not generate obsolete memory since no memory was allocated to them in the first + * place. + */ + @Override + public void trimToSize() { + this.elements.trimToSize(); + } + + /** + * Construct and returns a new selection view. + * + * @param sliceOffsets the offsets of the visible elements. + * @param rowOffsets the offsets of the visible elements. + * @param columnOffsets the offsets of the visible elements. + * @return a new view. + */ + @Override + protected ObjectMatrix3D viewSelectionLike(int[] sliceOffsets, int[] rowOffsets, int[] columnOffsets) { + return new SelectedSparseObjectMatrix3D(this.elements, sliceOffsets, rowOffsets, columnOffsets, 0); + } +} Propchange: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/impl/SparseObjectMatrix3D.java ------------------------------------------------------------------------------ svn:eol-style = native