You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mahout.apache.org by gs...@apache.org on 2009/11/23 16:14:38 UTC

svn commit: r883365 [34/47] - in /lucene/mahout/trunk: ./ examples/ matrix/ matrix/src/ matrix/src/main/ matrix/src/main/java/ matrix/src/main/java/org/ matrix/src/main/java/org/apache/ matrix/src/main/java/org/apache/mahout/ matrix/src/main/java/org/a...

Added: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Sorting.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Sorting.java?rev=883365&view=auto
==============================================================================
--- lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Sorting.java (added)
+++ lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Sorting.java Mon Nov 23 15:14:26 2009
@@ -0,0 +1,767 @@
+/*
+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.colt.matrix.doublealgo;
+
+import org.apache.mahout.colt.function.IntComparator;
+import org.apache.mahout.colt.matrix.DoubleFactory2D;
+import org.apache.mahout.colt.matrix.DoubleFactory3D;
+import org.apache.mahout.colt.matrix.DoubleMatrix1D;
+import org.apache.mahout.colt.matrix.DoubleMatrix2D;
+import org.apache.mahout.colt.matrix.DoubleMatrix3D;
+import org.apache.mahout.colt.matrix.impl.DenseDoubleMatrix1D;
+/**
+Matrix quicksorts and mergesorts.
+Use idioms like <tt>Sorting.quickSort.sort(...)</tt> and <tt>Sorting.mergeSort.sort(...)</tt>.
+<p>
+This is another case demonstrating one primary goal of this library: Delivering easy to use, yet very efficient APIs.
+The sorts return convenient <i>sort views</i>.
+This enables the usage of algorithms which scale well with the problem size:
+For example, sorting a 1000000 x 10000 or a 1000000 x 100 x 100 matrix performs just as fast as sorting a 1000000 x 1 matrix.
+This is so, because internally the algorithms only move around integer indexes, they do not physically move around entire rows or slices.
+The original matrix is left unaffected.
+<p>
+The quicksort is a derivative of the JDK 1.2 V1.26 algorithms (which are, in turn, based on Bentley's and McIlroy's fine work).
+The mergesort is a derivative of the JAL algorithms, with optimisations taken from the JDK algorithms.
+Mergesort is <i>stable</i> (by definition), while quicksort is not.
+A stable sort is, for example, helpful, if matrices are sorted successively 
+by multiple columns. It preserves the relative position of equal elements.
+ 
+@see org.apache.mahout.colt.GenericSorting
+@see org.apache.mahout.colt.Sorting
+@see java.util.Arrays
+
+@author wolfgang.hoschek@cern.ch
+@version 1.1, 25/May/2000
+*/
+/** 
+ * @deprecated until unit tests are in place.  Until this time, this class/interface is unsupported.
+ */
+@Deprecated
+public class Sorting extends org.apache.mahout.colt.PersistentObject {
+	/**
+	 * A prefabricated quicksort.
+	 */
+	public static final Sorting quickSort = new Sorting(); // already has quicksort implemented
+
+	/**
+	 * A prefabricated mergesort.
+	 */
+	public static final Sorting mergeSort = new Sorting() { // override quicksort with mergesort
+		protected void runSort(int[] a, int fromIndex, int toIndex, IntComparator c) {
+			org.apache.mahout.colt.Sorting.mergeSort(a,fromIndex,toIndex,c);
+		}
+		protected void runSort(int fromIndex, int toIndex, IntComparator c, org.apache.mahout.colt.Swapper swapper) {
+			org.apache.mahout.colt.GenericSorting.mergeSort(fromIndex, toIndex, c, swapper);
+		}
+	};
+/**
+ * Makes this class non instantiable, but still let's others inherit from it.
+ */
+protected Sorting() {}
+/**
+ * Compare two values, one of which is assumed to be Double.NaN
+ */
+private static final int compareNaN(double a, double b) {
+	if (a!=a) {
+		if (b!=b) return 0; // NaN equals NaN
+		else return 1; // e.g. NaN > 5
+	}
+	return -1; // e.g. 5 < NaN
+}
+protected void runSort(int[] a, int fromIndex, int toIndex, IntComparator c) {
+	org.apache.mahout.colt.Sorting.quickSort(a,fromIndex,toIndex,c);
+}
+protected void runSort(int fromIndex, int toIndex, IntComparator c, org.apache.mahout.colt.Swapper swapper) {
+	org.apache.mahout.colt.GenericSorting.quickSort(fromIndex, toIndex, c, swapper);
+}
+/**
+Sorts the vector into ascending order, according to the <i>natural ordering</i>.
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+To sort ranges use sub-ranging views. To sort descending, use flip views ...
+<p>
+<b>Example:</b> 
+<table border="1" cellspacing="0">
+  <tr nowrap> 
+	<td valign="top"><tt> 7, 1, 3, 1<br>
+	  </tt></td>
+	<td valign="top"> 
+	  <p><tt> ==&gt; 1, 1, 3, 7<br>
+		The vector IS NOT SORTED.<br>
+		The new VIEW IS SORTED.</tt></p>
+	</td>
+  </tr>
+</table>
+
+@param vector the vector to be sorted.
+@return a new sorted vector (matrix) view. 
+		<b>Note that the original matrix is left unaffected.</b>
+*/
+public DoubleMatrix1D sort(final DoubleMatrix1D vector) {
+	int[] indexes = new int[vector.size()]; // row indexes to reorder instead of matrix itself
+	for (int i=indexes.length; --i >= 0; ) indexes[i] = i;
+
+	IntComparator comp = new IntComparator() {  
+		public int compare(int a, int b) {
+			double av = vector.getQuick(a);
+			double bv = vector.getQuick(b);
+			if (av!=av || bv!=bv) return compareNaN(av,bv); // swap NaNs to the end
+			return av<bv ? -1 : (av==bv ? 0 : 1);
+		}
+	};
+
+	runSort(indexes,0,indexes.length,comp);
+
+	return vector.viewSelection(indexes);
+}
+/**
+Sorts the vector into ascending order, according to the order induced by the specified comparator.
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+The algorithm compares two cells at a time, determinining whether one is smaller, equal or larger than the other.
+To sort ranges use sub-ranging views. To sort descending, use flip views ...
+<p>
+<b>Example:</b>
+<pre>
+// sort by sinus of cells
+DoubleComparator comp = new DoubleComparator() {
+&nbsp;&nbsp;&nbsp;public int compare(double a, double b) {
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double as = Math.sin(a); double bs = Math.sin(b);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return as < bs ? -1 : as == bs ? 0 : 1;
+&nbsp;&nbsp;&nbsp;}
+};
+sorted = quickSort(vector,comp);
+</pre>
+
+@param vector the vector to be sorted.
+@param c the comparator to determine the order.
+@return a new matrix view sorted as specified.
+		<b>Note that the original vector (matrix) is left unaffected.</b>
+*/
+public DoubleMatrix1D sort(final DoubleMatrix1D vector, final org.apache.mahout.colt.function.DoubleComparator c) {
+	int[] indexes = new int[vector.size()]; // row indexes to reorder instead of matrix itself
+	for (int i=indexes.length; --i >= 0; ) indexes[i] = i;
+
+	IntComparator comp = new IntComparator() {  
+		public int compare(int a, int b) {
+			return c.compare(vector.getQuick(a), vector.getQuick(b));
+		}
+	};
+
+	runSort(indexes,0,indexes.length,comp);
+
+	return vector.viewSelection(indexes);
+}
+/**
+Sorts the matrix rows into ascending order, according to the <i>natural ordering</i> of the matrix values in the virtual column <tt>aggregates</tt>;
+Particularly efficient when comparing expensive aggregates, because aggregates need not be recomputed time and again, as is the case for comparator based sorts.
+Essentially, this algorithm makes expensive comparisons cheap.
+Normally each element of <tt>aggregates</tt> is a summary measure of a row.
+Speedup over comparator based sorting = <tt>2*log(rows)</tt>, on average.
+For this operation, quicksort is usually faster.
+<p>
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+To sort ranges use sub-ranging views. To sort columns by rows, use dice views. To sort descending, use flip views ...
+<p>
+<b>Example:</b>
+Each aggregate is the sum of a row
+<table border="1" cellspacing="0">
+  <tr nowrap> 
+	<td valign="top"><tt>4 x 2 matrix: <br>
+	  1, 1<br>
+	  5, 4<br>
+	  3, 0<br>
+	  4, 4 <br>
+	  </tt></td>
+	<td align="left" valign="top"> 
+	  <tt>aggregates=<br>
+	  2<br>
+	  9<br>
+	  3<br>
+	  8<br>
+	  ==></tt></td>
+	<td valign="top"> 
+	  <p><tt>4 x 2 matrix:<br>
+		1, 1<br>
+		3, 0<br>
+		4, 4<br>
+		5, 4</tt><br>
+		The matrix IS NOT SORTED.<br>
+		The new VIEW IS SORTED.</p>
+	  </td>
+  </tr>
+</table>
+
+<table>
+<td class="PRE"> 
+<pre>
+// sort 10000 x 1000 matrix by sum of logarithms in a row (i.e. by geometric mean)
+DoubleMatrix2D matrix = new DenseDoubleMatrix2D(10000,1000);
+matrix.assign(new org.apache.mahout.jet.random.engine.MersenneTwister()); // initialized randomly
+org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions; // alias for convenience
+
+// THE QUICK VERSION (takes some 3 secs)
+// aggregates[i] = Sum(log(row));
+double[] aggregates = new double[matrix.rows()];
+for (int i = matrix.rows(); --i >= 0; ) aggregates[i] = matrix.viewRow(i).aggregate(F.plus, F.log);
+DoubleMatrix2D sorted = quickSort(matrix,aggregates);
+
+// THE SLOW VERSION (takes some 90 secs)
+DoubleMatrix1DComparator comparator = new DoubleMatrix1DComparator() {
+&nbsp;&nbsp;&nbsp;public int compare(DoubleMatrix1D x, DoubleMatrix1D y) {
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a = x.aggregate(F.plus,F.log);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double b = y.aggregate(F.plus,F.log);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return a < b ? -1 : a==b ? 0 : 1;
+&nbsp;&nbsp;&nbsp;}
+};
+DoubleMatrix2D sorted = quickSort(matrix,comparator);
+</pre>
+</td>
+</table>
+
+@param matrix the matrix to be sorted.
+@param aggregates the values to sort on. (As a side effect, this array will also get sorted).
+@return a new matrix view having rows sorted.
+		<b>Note that the original matrix is left unaffected.</b>
+@throws IndexOutOfBoundsException if <tt>aggregates.length != matrix.rows()</tt>.
+*/
+public DoubleMatrix2D sort(DoubleMatrix2D matrix, final double[] aggregates) {
+	int rows = matrix.rows();
+	if (aggregates.length != rows) throw new IndexOutOfBoundsException("aggregates.length != matrix.rows()");
+	
+	// set up index reordering
+	final int[] indexes = new int[rows];
+	for (int i=rows; --i >= 0; ) indexes[i] = i;
+
+	// compares two aggregates at a time
+	org.apache.mahout.colt.function.IntComparator comp = new org.apache.mahout.colt.function.IntComparator() {
+		public int compare(int x, int y) {
+			double a = aggregates[x];
+			double b = aggregates[y];
+			if (a!=a || b!=b) return compareNaN(a,b); // swap NaNs to the end
+			return a < b ? -1 : (a==b) ? 0 : 1;
+		}
+	};
+	// swaps aggregates and reorders indexes
+	org.apache.mahout.colt.Swapper swapper = new org.apache.mahout.colt.Swapper() {
+		public void swap(int x, int y) {
+			int t1;	double t2;
+			t1 = indexes[x]; indexes[x] = indexes[y]; indexes[y] = t1;		
+			t2 = aggregates[x]; aggregates[x] = aggregates[y]; aggregates[y] = t2;
+		}
+	};
+
+	// sort indexes and aggregates
+	runSort(0,rows,comp,swapper);
+
+	// view the matrix according to the reordered row indexes
+	// take all columns in the original order
+	return matrix.viewSelection(indexes,null);
+}
+/**
+Sorts the matrix rows into ascending order, according to the <i>natural ordering</i> of the matrix values in the given column.
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+To sort ranges use sub-ranging views. To sort columns by rows, use dice views. To sort descending, use flip views ...
+<p>
+<b>Example:</b> 
+<table border="1" cellspacing="0">
+  <tr nowrap> 
+	<td valign="top"><tt>4 x 2 matrix: <br>
+	  7, 6<br>
+	  5, 4<br>
+	  3, 2<br>
+	  1, 0 <br>
+	  </tt></td>
+	<td align="left" valign="top"> 
+	  <p><tt>column = 0;<br>
+		view = quickSort(matrix,column);<br>
+		System.out.println(view); </tt><tt><br>
+		==> </tt></p>
+	  </td>
+	<td valign="top"> 
+	  <p><tt>4 x 2 matrix:<br>
+		1, 0<br>
+		3, 2<br>
+		5, 4<br>
+		7, 6</tt><br>
+		The matrix IS NOT SORTED.<br>
+		The new VIEW IS SORTED.</p>
+	  </td>
+  </tr>
+</table>
+
+@param matrix the matrix to be sorted.
+@param column the index of the column inducing the order.
+@return a new matrix view having rows sorted by the given column.
+		<b>Note that the original matrix is left unaffected.</b>
+@throws IndexOutOfBoundsException if <tt>column < 0 || column >= matrix.columns()</tt>.
+*/
+public DoubleMatrix2D sort(DoubleMatrix2D matrix, int column) {
+	if (column < 0 || column >= matrix.columns()) throw new IndexOutOfBoundsException("column="+column+", matrix="+Formatter.shape(matrix));
+
+	int[] rowIndexes = new int[matrix.rows()]; // row indexes to reorder instead of matrix itself
+	for (int i=rowIndexes.length; --i >= 0; ) rowIndexes[i] = i;
+
+	final DoubleMatrix1D col = matrix.viewColumn(column);
+	IntComparator comp = new IntComparator() {  
+		public int compare(int a, int b) {
+			double av = col.getQuick(a);
+			double bv = col.getQuick(b);
+			if (av!=av || bv!=bv) return compareNaN(av,bv); // swap NaNs to the end
+			return av<bv ? -1 : (av==bv ? 0 : 1);
+		}
+	};
+
+	runSort(rowIndexes,0,rowIndexes.length,comp);
+
+	// view the matrix according to the reordered row indexes
+	// take all columns in the original order
+	return matrix.viewSelection(rowIndexes,null);
+}
+/**
+Sorts the matrix rows according to the order induced by the specified comparator.
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+The algorithm compares two rows (1-d matrices) at a time, determinining whether one is smaller, equal or larger than the other.
+To sort ranges use sub-ranging views. To sort columns by rows, use dice views. To sort descending, use flip views ...
+<p>
+<b>Example:</b>
+<pre>
+// sort by sum of values in a row
+DoubleMatrix1DComparator comp = new DoubleMatrix1DComparator() {
+&nbsp;&nbsp;&nbsp;public int compare(DoubleMatrix1D a, DoubleMatrix1D b) {
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double as = a.zSum(); double bs = b.zSum();
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return as < bs ? -1 : as == bs ? 0 : 1;
+&nbsp;&nbsp;&nbsp;}
+};
+sorted = quickSort(matrix,comp);
+</pre>
+
+@param matrix the matrix to be sorted.
+@param c the comparator to determine the order.
+@return a new matrix view having rows sorted as specified.
+		<b>Note that the original matrix is left unaffected.</b>
+*/
+public DoubleMatrix2D sort(final DoubleMatrix2D matrix, final DoubleMatrix1DComparator c) {
+	int[] rowIndexes = new int[matrix.rows()]; // row indexes to reorder instead of matrix itself
+	for (int i=rowIndexes.length; --i >= 0; ) rowIndexes[i] = i;
+
+	final DoubleMatrix1D[] views = new DoubleMatrix1D[matrix.rows()]; // precompute views for speed
+	for (int i=views.length; --i >= 0; ) views[i] = matrix.viewRow(i);
+
+	IntComparator comp = new IntComparator() {  
+		public int compare(int a, int b) {
+			//return c.compare(matrix.viewRow(a), matrix.viewRow(b));
+			return c.compare(views[a], views[b]);
+		}
+	};
+
+	runSort(rowIndexes,0,rowIndexes.length,comp);
+
+	// view the matrix according to the reordered row indexes
+	// take all columns in the original order
+	return matrix.viewSelection(rowIndexes,null);
+}
+/**
+Sorts the matrix rows into ascending order, according to the <i>natural ordering</i> of the values computed by applying the given aggregation function to each row;
+Particularly efficient when comparing expensive aggregates, because aggregates need not be recomputed time and again, as is the case for comparator based sorts.
+Essentially, this algorithm makes expensive comparisons cheap.
+Normally <tt>aggregates</tt> defines a summary measure of a row.
+Speedup over comparator based sorting = <tt>2*log(rows)</tt>, on average.
+<p>
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+To sort ranges use sub-ranging views. To sort columns by rows, use dice views. To sort descending, use flip views ...
+<p>
+<b>Example:</b>
+Each aggregate is the sum of a row
+<table border="1" cellspacing="0">
+  <tr nowrap> 
+	<td valign="top"><tt>4 x 2 matrix: <br>
+	  1, 1<br>
+	  5, 4<br>
+	  3, 0<br>
+	  4, 4 <br>
+	  </tt></td>
+	<td align="left" valign="top"> 
+	  <tt>aggregates=<br>
+	  hep.aida.bin.BinFunctions1D.sum<br>
+	  ==></tt></td>
+	<td valign="top"> 
+	  <p><tt>4 x 2 matrix:<br>
+		1, 1<br>
+		3, 0<br>
+		4, 4<br>
+		5, 4</tt><br>
+		The matrix IS NOT SORTED.<br>
+		The new VIEW IS SORTED.</p>
+	  </td>
+  </tr>
+</table>
+
+<table>
+<td class="PRE"> 
+<pre>
+// sort 10000 x 1000 matrix by median or by sum of logarithms in a row (i.e. by geometric mean)
+DoubleMatrix2D matrix = new DenseDoubleMatrix2D(10000,1000);
+matrix.assign(new org.apache.mahout.jet.random.engine.MersenneTwister()); // initialized randomly
+org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions; // alias for convenience
+
+// THE QUICK VERSION (takes some 10 secs)
+DoubleMatrix2D sorted = quickSort(matrix,hep.aida.bin.BinFunctions1D.median);
+//DoubleMatrix2D sorted = quickSort(matrix,hep.aida.bin.BinFunctions1D.sumOfLogarithms);
+
+// THE SLOW VERSION (takes some 300 secs)
+DoubleMatrix1DComparator comparator = new DoubleMatrix1DComparator() {
+&nbsp;&nbsp;&nbsp;public int compare(DoubleMatrix1D x, DoubleMatrix1D y) {
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double a = org.apache.mahout.colt.matrix.doublealgo.Statistic.bin(x).median();
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double b = org.apache.mahout.colt.matrix.doublealgo.Statistic.bin(y).median();
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// double a = x.aggregate(F.plus,F.log);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// double b = y.aggregate(F.plus,F.log);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return a < b ? -1 : a==b ? 0 : 1;
+&nbsp;&nbsp;&nbsp;}
+};
+DoubleMatrix2D sorted = quickSort(matrix,comparator);
+</pre>
+</td>
+</table>
+
+@param matrix the matrix to be sorted.
+@param aggregate the function to sort on; aggregates values in a row.
+@return a new matrix view having rows sorted.
+		<b>Note that the original matrix is left unaffected.</b>
+
+public DoubleMatrix2D sort(DoubleMatrix2D matrix, hep.aida.bin.BinFunction1D aggregate) {
+	// precompute aggregates over rows, as defined by "aggregate"
+
+	// a bit clumsy, because Statistic.aggregate(...) is defined on columns, so we need to transpose views
+	DoubleMatrix2D tmp = matrix.like(1,matrix.rows());
+	hep.aida.bin.BinFunction1D[] func = {aggregate};
+	Statistic.aggregate(matrix.viewDice(), func, tmp);
+	double[] aggr = tmp.viewRow(0).toArray();
+	return sort(matrix,aggr);
+}
+*/
+/**
+Sorts the matrix slices into ascending order, according to the <i>natural ordering</i> of the matrix values in the given <tt>[row,column]</tt> position.
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+To sort ranges use sub-ranging views. To sort by other dimensions, use dice views. To sort descending, use flip views ...
+<p>
+The algorithm compares two 2-d slices at a time, determinining whether one is smaller, equal or larger than the other.
+Comparison is based on the cell <tt>[row,column]</tt> within a slice.
+Let <tt>A</tt> and <tt>B</tt> be two 2-d slices. Then we have the following rules
+<ul>
+<li><tt>A &lt;  B  iff A.get(row,column) &lt;  B.get(row,column)</tt>
+<li><tt>A == B iff A.get(row,column) == B.get(row,column)</tt>
+<li><tt>A &gt;  B  iff A.get(row,column) &gt;  B.get(row,column)</tt>
+</ul>
+
+@param matrix the matrix to be sorted.
+@param row the index of the row inducing the order.
+@param column the index of the column inducing the order.
+@return a new matrix view having slices sorted by the values of the slice view <tt>matrix.viewRow(row).viewColumn(column)</tt>.
+		<b>Note that the original matrix is left unaffected.</b>
+@throws IndexOutOfBoundsException if <tt>row < 0 || row >= matrix.rows() || column < 0 || column >= matrix.columns()</tt>.
+*/
+public DoubleMatrix3D sort(DoubleMatrix3D matrix, int row, int column) {
+	if (row < 0 || row >= matrix.rows()) throw new IndexOutOfBoundsException("row="+row+", matrix="+Formatter.shape(matrix));
+	if (column < 0 || column >= matrix.columns()) throw new IndexOutOfBoundsException("column="+column+", matrix="+Formatter.shape(matrix));
+
+	int[] sliceIndexes = new int[matrix.slices()]; // indexes to reorder instead of matrix itself
+	for (int i=sliceIndexes.length; --i >= 0; ) sliceIndexes[i] = i;
+
+	final DoubleMatrix1D sliceView = matrix.viewRow(row).viewColumn(column);
+	IntComparator comp = new IntComparator() {  
+		public int compare(int a, int b) {
+			double av = sliceView.getQuick(a);
+			double bv = sliceView.getQuick(b);
+			if (av!=av || bv!=bv) return compareNaN(av,bv); // swap NaNs to the end
+			return av<bv ? -1 : (av==bv ? 0 : 1);
+		}
+	};
+
+	runSort(sliceIndexes,0,sliceIndexes.length,comp);
+
+	// view the matrix according to the reordered slice indexes
+	// take all rows and columns in the original order
+	return matrix.viewSelection(sliceIndexes,null,null);
+}
+/**
+Sorts the matrix slices according to the order induced by the specified comparator.
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+The algorithm compares two slices (2-d matrices) at a time, determinining whether one is smaller, equal or larger than the other.
+To sort ranges use sub-ranging views. To sort by other dimensions, use dice views. To sort descending, use flip views ...
+<p>
+<b>Example:</b>
+<pre>
+// sort by sum of values in a slice
+DoubleMatrix2DComparator comp = new DoubleMatrix2DComparator() {
+&nbsp;&nbsp;&nbsp;public int compare(DoubleMatrix2D a, DoubleMatrix2D b) {
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double as = a.zSum(); double bs = b.zSum();
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return as < bs ? -1 : as == bs ? 0 : 1;
+&nbsp;&nbsp;&nbsp;}
+};
+sorted = quickSort(matrix,comp);
+</pre>
+
+@param matrix the matrix to be sorted.
+@param c the comparator to determine the order.
+@return a new matrix view having slices sorted as specified.
+		<b>Note that the original matrix is left unaffected.</b>
+*/
+public DoubleMatrix3D sort(final DoubleMatrix3D matrix, final DoubleMatrix2DComparator c) {
+	int[] sliceIndexes = new int[matrix.slices()]; // indexes to reorder instead of matrix itself
+	for (int i=sliceIndexes.length; --i >= 0; ) sliceIndexes[i] = i;
+
+	final DoubleMatrix2D[] views = new DoubleMatrix2D[matrix.slices()]; // precompute views for speed
+	for (int i=views.length; --i >= 0; ) views[i] = matrix.viewSlice(i);
+
+	IntComparator comp = new IntComparator() {  
+		public int compare(int a, int b) {
+			//return c.compare(matrix.viewSlice(a), matrix.viewSlice(b));
+			return c.compare(views[a], views[b]);
+		}
+	};
+
+	runSort(sliceIndexes,0,sliceIndexes.length,comp);
+
+	// view the matrix according to the reordered slice indexes
+	// take all rows and columns in the original order
+	return matrix.viewSelection(sliceIndexes,null,null);
+}
+/**
+ * Demonstrates advanced sorting.
+ * Sorts by sum of row.
+ */
+public static void zdemo1() {
+	Sorting sort = quickSort;
+	DoubleMatrix2D matrix = DoubleFactory2D.dense.descending(4,3);
+	DoubleMatrix1DComparator comp = new DoubleMatrix1DComparator() {
+		public int compare(DoubleMatrix1D a, DoubleMatrix1D b) {
+			double as = a.zSum(); double bs = b.zSum();
+			return as < bs ? -1 : as == bs ? 0 : 1;
+		}
+	};
+	System.out.println("unsorted:"+matrix);
+	System.out.println("sorted  :"+sort.sort(matrix,comp));
+}
+/**
+ * Demonstrates advanced sorting.
+ * Sorts by sum of slice.
+ */
+public static void zdemo2() {
+	Sorting sort = quickSort;
+	DoubleMatrix3D matrix = DoubleFactory3D.dense.descending(4,3,2);
+	DoubleMatrix2DComparator comp = new DoubleMatrix2DComparator() {
+		public int compare(DoubleMatrix2D a, DoubleMatrix2D b) {
+			double as = a.zSum();
+			double bs = b.zSum();
+			return as < bs ? -1 : as == bs ? 0 : 1;
+		}
+	};
+	System.out.println("unsorted:"+matrix);
+	System.out.println("sorted  :"+sort.sort(matrix,comp));
+}
+/**
+ * Demonstrates advanced sorting.
+ * Sorts by sinus of cell values.
+ */
+public static void zdemo3() {
+	Sorting sort = quickSort;
+	double[] values = {0.5, 1.5, 2.5, 3.5};
+	DoubleMatrix1D matrix = new DenseDoubleMatrix1D(values);
+	org.apache.mahout.colt.function.DoubleComparator comp = new org.apache.mahout.colt.function.DoubleComparator() {
+		public int compare(double a, double b) {
+			double as = Math.sin(a); double bs = Math.sin(b);
+			return as < bs ? -1 : as == bs ? 0 : 1;
+		}
+	};
+	System.out.println("unsorted:"+matrix);
+	
+	DoubleMatrix1D sorted = sort.sort(matrix,comp);
+	System.out.println("sorted  :"+sorted);
+
+	// check whether it is really sorted
+	sorted.assign(org.apache.mahout.jet.math.Functions.sin);
+	/*
+	sorted.assign(
+		new org.apache.mahout.colt.function.DoubleFunction() {
+			public double apply(double arg) { return Math.sin(arg); }
+		}
+	);
+	*/
+	System.out.println("sined  :"+sorted);
+}
+/**
+ * Demonstrates applying functions.
+ */
+protected static void zdemo4() {
+	double[] values1 = {0, 1, 2, 3};
+	double[] values2 = {0, 2, 4, 6};
+	DoubleMatrix1D matrix1 = new DenseDoubleMatrix1D(values1);
+	DoubleMatrix1D matrix2 = new DenseDoubleMatrix1D(values2);
+	System.out.println("m1:"+matrix1);
+	System.out.println("m2:"+matrix2);
+	
+	matrix1.assign(matrix2, org.apache.mahout.jet.math.Functions.pow);
+	
+	/*
+	matrix1.assign(matrix2,
+		new org.apache.mahout.colt.function.DoubleDoubleFunction() {
+			public double apply(double x, double y) { return Math.pow(x,y); }
+		}
+	);
+	*/
+	
+	System.out.println("applied:"+matrix1);
+}
+/**
+ * Demonstrates sorting with precomputation of aggregates (median and sum of logarithms).
+ *
+public static void zdemo5(int rows, int columns, boolean print) {
+	Sorting sort = quickSort;
+	// for reliable benchmarks, call this method twice: once with small dummy parameters to "warm up" the jitter, then with your real work-load
+		
+	System.out.println("\n\n");
+	System.out.print("now initializing... ");
+	org.apache.mahout.colt.Timer timer = new org.apache.mahout.colt.Timer().start();
+		
+	final org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+	DoubleMatrix2D A = org.apache.mahout.colt.matrix.DoubleFactory2D.dense.make(rows,columns);
+	A.assign(new org.apache.mahout.jet.random.engine.DRand()); // initialize randomly
+	timer.stop().display();
+
+	// also benchmark copying in its several implementation flavours
+	DoubleMatrix2D B = A.like();
+	timer.reset().start();
+	System.out.print("now copying... ");
+	B.assign(A);
+	timer.stop().display();
+
+	timer.reset().start();
+	System.out.print("now copying subrange... ");
+	B.viewPart(0,0,rows,columns).assign(A.viewPart(0,0,rows,columns));
+	timer.stop().display();
+	//System.out.println(A);
+
+	timer.reset().start();
+	System.out.print("now copying selected... ");
+	B.viewSelection(null,null).assign(A.viewSelection(null,null));
+	timer.stop().display();
+
+	System.out.print("now sorting - quick version with precomputation... ");
+	timer.reset().start();
+	// THE QUICK VERSION (takes some 10 secs)
+	A = sort.sort(A,hep.aida.bin.BinFunctions1D.median);
+	//A = sort.sort(A,hep.aida.bin.BinFunctions1D.sumLog);
+	timer.stop().display();
+
+	// check results for correctness
+	// WARNING: be sure NOT TO PRINT huge matrices unless you have tons of main memory and time!!
+	// so we just show the first 5 rows
+	if (print) {
+		int r = Math.min(rows,5);
+		hep.aida.bin.BinFunction1D[] funs = {hep.aida.bin.BinFunctions1D.median, hep.aida.bin.BinFunctions1D.sumLog, hep.aida.bin.BinFunctions1D.geometricMean};
+		String[] rowNames = new String[r];
+		String[] columnNames = new String[columns];
+		for (int i=columns; --i >= 0; ) columnNames[i] = Integer.toString(i);
+		for (int i=r; --i >= 0; ) rowNames[i] = Integer.toString(i);
+		System.out.println("first part of sorted result = \n"+new org.apache.mahout.colt.matrix.doublealgo.Formatter("%G").toTitleString(
+			A.viewPart(0,0,r,columns), rowNames, columnNames, null, null, null, funs
+		));
+	}
+
+
+	System.out.print("now sorting - slow version... ");
+	A = B;	
+	org.apache.mahout.colt.matrix.doublealgo.DoubleMatrix1DComparator fun = new org.apache.mahout.colt.matrix.doublealgo.DoubleMatrix1DComparator() {
+		public int compare(DoubleMatrix1D x, DoubleMatrix1D y) {
+			double a = org.apache.mahout.colt.matrix.doublealgo.Statistic.bin(x).median();
+			double b = org.apache.mahout.colt.matrix.doublealgo.Statistic.bin(y).median();
+			//double a = x.aggregate(F.plus,F.log);
+			//double b = y.aggregate(F.plus,F.log);
+			return a < b ? -1 : (a==b) ? 0 : 1;
+		}
+	};
+	timer.reset().start();
+	A = sort.sort(A,fun);
+	timer.stop().display();
+}
+*/
+/**
+ * Demonstrates advanced sorting.
+ * Sorts by sum of row.
+ */
+public static void zdemo6() {
+	Sorting sort = quickSort;
+	double[][] values = {
+		{ 3,7,0 },
+		{ 2,1,0 },
+		{ 2,2,0 },
+		{ 1,8,0 },
+		{ 2,5,0 },
+		{ 7,0,0 },
+		{ 2,3,0 },
+		{ 1,0,0 },
+		{ 4,0,0 },
+		{ 2,0,0 }
+	};
+	DoubleMatrix2D A = DoubleFactory2D.dense.make(values);
+	DoubleMatrix2D B,C;
+	/*
+	DoubleMatrix1DComparator comp = new DoubleMatrix1DComparator() {
+		public int compare(DoubleMatrix1D a, DoubleMatrix1D b) {
+			double as = a.zSum(); double bs = b.zSum();
+			return as < bs ? -1 : as == bs ? 0 : 1;
+		}
+	};
+	*/
+	System.out.println("\n\nunsorted:"+A);
+	B = quickSort.sort(A,1);
+	C = quickSort.sort(B,0);	
+	System.out.println("quick sorted  :"+C);
+	
+	B = mergeSort.sort(A,1);
+	C = mergeSort.sort(B,0);	
+	System.out.println("merge sorted  :"+C);
+	
+}
+/**
+ * Demonstrates sorting with precomputation of aggregates, comparing mergesort with quicksort.
+ */
+public static void zdemo7(int rows, int columns, boolean print) {
+	// for reliable benchmarks, call this method twice: once with small dummy parameters to "warm up" the jitter, then with your real work-load
+		
+	System.out.println("\n\n");
+	System.out.println("now initializing... ");
+		
+	final org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+	DoubleMatrix2D A = org.apache.mahout.colt.matrix.DoubleFactory2D.dense.make(rows,columns);
+	A.assign(new org.apache.mahout.jet.random.engine.DRand()); // initialize randomly
+	DoubleMatrix2D B = A.copy();
+
+	double[] v1 = A.viewColumn(0).toArray();
+	double[] v2 = A.viewColumn(0).toArray();
+	System.out.print("now quick sorting... ");
+	org.apache.mahout.colt.Timer timer = new org.apache.mahout.colt.Timer().start();
+	quickSort.sort(A,0);
+	timer.stop().display();
+
+	System.out.print("now merge sorting... ");
+	timer.reset().start();
+	mergeSort.sort(A,0);
+	timer.stop().display();
+
+	System.out.print("now quick sorting with simple aggregation... ");
+	timer.reset().start();
+	quickSort.sort(A,v1);
+	timer.stop().display();
+
+	System.out.print("now merge sorting with simple aggregation... ");
+	timer.reset().start();
+	mergeSort.sort(A,v2);
+	timer.stop().display();
+}
+}

Propchange: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Sorting.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Statistic.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Statistic.java?rev=883365&view=auto
==============================================================================
--- lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Statistic.java (added)
+++ lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Statistic.java Mon Nov 23 15:14:26 2009
@@ -0,0 +1,856 @@
+/*
+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.colt.matrix.doublealgo;
+
+import org.apache.mahout.colt.function.DoubleDoubleFunction;
+import org.apache.mahout.colt.matrix.DoubleFactory2D;
+import org.apache.mahout.colt.matrix.DoubleMatrix1D;
+import org.apache.mahout.colt.matrix.DoubleMatrix2D;
+import org.apache.mahout.colt.matrix.DoubleMatrix3D;
+import org.apache.mahout.jet.random.engine.RandomEngine;
+/**
+Basic statistics operations on matrices.
+Computation of covariance, correlation, distance matrix.
+Random sampling views.
+Conversion to histograms with and without OLAP cube operators.
+Conversion to bins with retrieval of statistical bin measures.
+Also see {@link org.apache.mahout.jet.stat} and {@link hep.aida.bin}, in particular {@link hep.aida.bin.DynamicBin1D}.
+<p>
+Examples:
+<table border="1" cellspacing="0" dwcopytype="CopyTableRow">
+  <tr valign="top" align="center"> 
+	<td><tt>A</tt></td>
+	<td><tt>covariance(A)</tt></td>
+	<td><tt>correlation(covariance(A))</tt></td>
+	<td><tt>distance(A,EUCLID)</tt></td>
+  </tr>
+  <tr valign="top"> 
+	<td><tt> 4&nbsp;x&nbsp;3&nbsp;matrix<br>
+	  1&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;3<br>
+	  2&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;6<br>
+	  3&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;9<br>
+	  4&nbsp;-8&nbsp;-10 </tt> </td>
+	<td><tt> 3&nbsp;x&nbsp;3&nbsp;matrix<br>
+	  &nbsp;1.25&nbsp;-3.5&nbsp;-4.5<br>
+	  -3.5&nbsp;&nbsp;29&nbsp;&nbsp;&nbsp;39&nbsp;&nbsp;<br>
+	  -4.5&nbsp;&nbsp;39&nbsp;&nbsp;&nbsp;52.5 </tt></td>
+	<td><tt> 3&nbsp;x&nbsp;3&nbsp;matrix<br>
+	  &nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-0.581318&nbsp;-0.555492<br>
+	  -0.581318&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.999507<br>
+	  -0.555492&nbsp;&nbsp;0.999507&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+	  </tt></td>
+	<td><tt> 3&nbsp;x&nbsp;3&nbsp;matrix<br>
+	  &nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12.569805&nbsp;15.874508<br>
+	  12.569805&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.242641<br>
+	  15.874508&nbsp;&nbsp;4.242641&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+	  </tt> <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </tt></td>
+  </tr>
+</table>
+
+@author wolfgang.hoschek@cern.ch
+@version 1.0, 09/24/99
+*/
+/** 
+ * @deprecated until unit tests are in place.  Until this time, this class/interface is unsupported.
+ */
+@Deprecated
+public class Statistic extends Object {
+	private static final org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+	/**
+	 * Euclidean distance function; <tt>Sqrt(Sum( (x[i]-y[i])^2 ))</tt>.
+	 */ 
+	public static final VectorVectorFunction EUCLID = new VectorVectorFunction() {
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {
+			return Math.sqrt(a.aggregate(b, F.plus, F.chain(F.square,F.minus)));
+		}
+	};
+
+	/**
+	 * Bray-Curtis distance function; <tt>Sum( abs(x[i]-y[i]) )  /  Sum( x[i]+y[i] )</tt>.
+	 */ 
+	public static final VectorVectorFunction BRAY_CURTIS = new VectorVectorFunction() {
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {	
+			return a.aggregate(b, F.plus, F.chain(F.abs,F.minus)) / a.aggregate(b, F.plus, F.plus);
+		}
+	};
+
+	/**
+	 * Canberra distance function; <tt>Sum( abs(x[i]-y[i]) / abs(x[i]+y[i]) )</tt>.
+	 */ 
+	public static final VectorVectorFunction CANBERRA = new VectorVectorFunction() {
+		DoubleDoubleFunction fun = new DoubleDoubleFunction() {
+			public final double apply(double a, double b) {
+				return Math.abs(a-b) / Math.abs(a+b);
+			}
+		};
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {	
+			return a.aggregate(b, F.plus, fun);
+		}
+	};
+
+	/**
+	 * Maximum distance function; <tt>Max( abs(x[i]-y[i]) )</tt>.
+	 */ 
+	public static final VectorVectorFunction MAXIMUM = new VectorVectorFunction() {
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {	
+			return a.aggregate(b, F.max, F.chain(F.abs,F.minus));
+		}
+	};
+
+	/**
+	 * Manhattan distance function; <tt>Sum( abs(x[i]-y[i]) )</tt>.
+	 */ 
+	public static final VectorVectorFunction MANHATTAN = new VectorVectorFunction() {
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {	
+			return a.aggregate(b, F.plus, F.chain(F.abs,F.minus));
+		}
+	};
+
+
+
+
+/**
+ * Interface that represents a function object: a function that takes 
+ * two argument vectors and returns a single value.
+ */
+/** 
+ * @deprecated until unit tests are in place.  Until this time, this class/interface is unsupported.
+ */
+@Deprecated
+public interface VectorVectorFunction {
+/**
+ * Applies a function to two argument vectors.
+ *
+ * @param x   the first argument vector passed to the function.
+ * @param y   the second argument vector passed to the function.
+ * @return the result of the function.
+ */
+abstract public double apply(org.apache.mahout.colt.matrix.DoubleMatrix1D x, org.apache.mahout.colt.matrix.DoubleMatrix1D y);
+}
+
+/**
+ * Makes this class non instantiable, but still let's others inherit from it.
+ */
+protected Statistic() {}
+/**
+ * Applies the given aggregation functions to each column and stores the results in a the result matrix.
+ * If matrix has shape <tt>m x n</tt>, then result must have shape <tt>aggr.length x n</tt>.
+ * Tip: To do aggregations on rows use dice views (transpositions), as in <tt>aggregate(matrix.viewDice(),aggr,result.viewDice())</tt>.
+ * 
+ * @param matrix any matrix; a column holds the values of a given variable.
+ * @param aggr the aggregation functions to be applied to each column.
+ * @param result the matrix to hold the aggregation results.
+ * @return <tt>result</tt> (for convenience only).
+ * @see Formatter
+ * @see hep.aida.bin.BinFunction1D
+ * @see hep.aida.bin.BinFunctions1D
+ *
+public static DoubleMatrix2D aggregate(DoubleMatrix2D matrix, hep.aida.bin.BinFunction1D[] aggr, DoubleMatrix2D result) {
+	DynamicBin1D bin = new DynamicBin1D();
+	double[] elements = new double[matrix.rows()];
+	org.apache.mahout.colt.list.DoubleArrayList values = new org.apache.mahout.colt.list.DoubleArrayList(elements);
+	for (int column=matrix.columns(); --column >= 0; ) {
+		matrix.viewColumn(column).toArray(elements); // copy column into values
+		bin.clear();
+		bin.addAllOf(values);
+		for (int i=aggr.length; --i >= 0; ) {
+			result.set(i, column, aggr[i].apply(bin));
+		}
+	}
+	return result;
+}
+*/
+/**
+Fills all cell values of the given vector into a bin from which statistics measures can be retrieved efficiently.
+Cells values are copied.
+<br>
+Tip: Use <tt>System.out.println(bin(vector))</tt> to print most measures computed by the bin. Example:
+<table>
+<td class="PRE"> 
+<pre>
+Size: 20000
+Sum: 299858.02350278624
+SumOfSquares: 5399184.154095971
+Min: 0.8639113139711261
+Max: 59.75331890541892
+Mean: 14.992901175139313
+RMS: 16.43043540825375
+Variance: 45.17438077634358
+Standard deviation: 6.721188940681818
+Standard error: 0.04752598277592142
+Geometric mean: 13.516615397064466
+Product: Infinity
+Harmonic mean: 11.995174297952191
+Sum of inversions: 1667.337172700724
+Skew: 0.8922838940067878
+Kurtosis: 1.1915828121825598
+Sum of powers(3): 1.1345828465808412E8
+Sum of powers(4): 2.7251055344494686E9
+Sum of powers(5): 7.367125643433887E10
+Sum of powers(6): 2.215370909100143E12
+Moment(0,0): 1.0
+Moment(1,0): 14.992901175139313
+Moment(2,0): 269.95920770479853
+Moment(3,0): 5672.914232904206
+Moment(4,0): 136255.27672247344
+Moment(5,0): 3683562.8217169433
+Moment(6,0): 1.1076854545500715E8
+Moment(0,mean()): 1.0
+Moment(1,mean()): -2.0806734113421045E-14
+Moment(2,mean()): 45.172122057305664
+Moment(3,mean()): 270.92018671421
+Moment(4,mean()): 8553.8664869067
+Moment(5,mean()): 153357.41712233616
+Moment(6,mean()): 4273757.570142922
+25%, 50% and 75% Quantiles: 10.030074811938091, 13.977982089912224,
+18.86124362967137
+quantileInverse(mean): 0.559163335012079
+Distinct elements & frequencies not printed (too many).
+</pre>
+</td>
+</table>
+
+@param vector the vector to analyze.
+@return a bin holding the statistics measures of the vector.
+*
+public static DynamicBin1D bin(DoubleMatrix1D vector) {
+	DynamicBin1D bin = new DynamicBin1D();
+	bin.addAllOf(DoubleFactory1D.dense.toList(vector));
+	return bin;
+}
+*/
+/**
+ * Modifies the given covariance matrix to be a correlation matrix (in-place).
+ * The correlation matrix is a square, symmetric matrix consisting of nothing but correlation coefficients.
+ * The rows and the columns represent the variables, the cells represent correlation coefficients. 
+ * The diagonal cells (i.e. the correlation between a variable and itself) will equal 1, for the simple reason that the correlation coefficient of a variable with itself equals 1. 
+ * The correlation of two column vectors x and y is given by <tt>corr(x,y) = cov(x,y) / (stdDev(x)*stdDev(y))</tt> (Pearson's correlation coefficient).
+ * A correlation coefficient varies between -1 (for a perfect negative relationship) to +1 (for a perfect positive relationship). 
+ * See the <A HREF="http://www.cquest.utoronto.ca/geog/ggr270y/notes/not05efg.html"> math definition</A>
+ * and <A HREF="http://www.stat.berkeley.edu/users/stark/SticiGui/Text/gloss.htm#correlation_coef"> another def</A>.
+ * Compares two column vectors at a time. Use dice views to compare two row vectors at a time.
+ * 
+ * @param covariance a covariance matrix, as, for example, returned by method {@link #covariance(DoubleMatrix2D)}.
+ * @return the modified covariance, now correlation matrix (for convenience only).
+ */
+public static DoubleMatrix2D correlation(DoubleMatrix2D covariance) {
+	for (int i=covariance.columns(); --i >= 0; ) {
+		for (int j=i; --j >= 0; ) {
+			double stdDev1 = Math.sqrt(covariance.getQuick(i,i));
+			double stdDev2 = Math.sqrt(covariance.getQuick(j,j));
+			double cov = covariance.getQuick(i,j);
+			double corr = cov / (stdDev1*stdDev2);
+			
+			covariance.setQuick(i,j,corr);
+			covariance.setQuick(j,i,corr); // symmetric
+		}
+	}
+	for (int i=covariance.columns(); --i >= 0; ) covariance.setQuick(i,i,1);
+
+	return covariance;	
+}
+/**
+ * Constructs and returns the covariance matrix of the given matrix.
+ * The covariance matrix is a square, symmetric matrix consisting of nothing but covariance coefficients. 
+ * The rows and the columns represent the variables, the cells represent covariance coefficients. 
+ * The diagonal cells (i.e. the covariance between a variable and itself) will equal the variances.
+ * The covariance of two column vectors x and y is given by <tt>cov(x,y) = (1/n) * Sum((x[i]-mean(x)) * (y[i]-mean(y)))</tt>.
+ * See the <A HREF="http://www.cquest.utoronto.ca/geog/ggr270y/notes/not05efg.html"> math definition</A>.
+ * Compares two column vectors at a time. Use dice views to compare two row vectors at a time.
+ * 
+ * @param matrix any matrix; a column holds the values of a given variable.
+ * @return the covariance matrix (<tt>n x n, n=matrix.columns</tt>).
+ */
+public static DoubleMatrix2D covariance(DoubleMatrix2D matrix) {
+	int rows = matrix.rows();
+	int columns = matrix.columns();
+	DoubleMatrix2D covariance = new org.apache.mahout.colt.matrix.impl.DenseDoubleMatrix2D(columns,columns);
+	
+	double[] sums = new double[columns];
+	DoubleMatrix1D[] cols = new DoubleMatrix1D[columns];
+	for (int i=columns; --i >= 0; ) {
+		cols[i] = matrix.viewColumn(i);
+		sums[i] = cols[i].zSum();
+	}
+
+	for (int i=columns; --i >= 0; ) {
+		for (int j=i+1; --j >= 0; ) {
+			double sumOfProducts = cols[i].zDotProduct(cols[j]);
+			double cov = (sumOfProducts - sums[i]*sums[j]/rows) / rows;
+			covariance.setQuick(i,j,cov);
+			covariance.setQuick(j,i,cov); // symmetric
+		}
+	}
+	return covariance;	
+}
+/**
+2-d OLAP cube operator; Fills all cells of the given vectors into the given histogram.
+If you use hep.aida.ref.Converter.toString(histo) on the result, the OLAP cube of x-"column" vs. y-"column" , summing the weights "column" will be printed.
+For example, aggregate sales by product by region.
+<p>
+Computes the distinct values of x and y, yielding histogram axes that capture one distinct value per bin.
+Then fills the histogram.
+<p>
+Example output:
+<table>
+<td class="PRE"> 
+<pre>
+Cube:
+&nbsp;&nbsp;&nbsp;Entries=5000, ExtraEntries=0
+&nbsp;&nbsp;&nbsp;MeanX=4.9838, RmsX=NaN
+&nbsp;&nbsp;&nbsp;MeanY=2.5304, RmsY=NaN
+&nbsp;&nbsp;&nbsp;xAxis: Min=0, Max=10, Bins=11
+&nbsp;&nbsp;&nbsp;yAxis: Min=0, Max=5, Bins=6
+Heights:
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| X
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 0   1   2   3   4   5   6   7   8   9   10  | Sum 
+----------------------------------------------------------
+Y 5   |  30  53  51  52  57  39  65  61  55  49  22 |  534
+&nbsp;&nbsp;4   |  43 106 112  96  92  94 107  98  98 110  47 | 1003
+&nbsp;&nbsp;3   |  39 134  87  93 102 103 110  90 114  98  51 | 1021
+&nbsp;&nbsp;2   |  44  81 113  96 101  86 109  83 111  93  42 |  959
+&nbsp;&nbsp;1   |  54  94 103  99 115  92  98  97 103  90  44 |  989
+&nbsp;&nbsp;0   |  24  54  52  44  42  56  46  47  56  53  20 |  494
+----------------------------------------------------------
+&nbsp;&nbsp;Sum | 234 522 518 480 509 470 535 476 537 493 226 |     
+</pre>
+</td>
+</table>
+@return the histogram containing the cube.
+@throws IllegalArgumentException if <tt>x.size() != y.size() || y.size() != weights.size()</tt>.
+*
+public static hep.aida.IHistogram2D cube(DoubleMatrix1D x, DoubleMatrix1D y, DoubleMatrix1D weights) {
+	if (x.size() != y.size() || y.size() != weights.size()) throw new IllegalArgumentException("vectors must have same size");
+	
+	double epsilon = 1.0E-9;
+	org.apache.mahout.colt.list.DoubleArrayList distinct = new org.apache.mahout.colt.list.DoubleArrayList();
+	double[] vals = new double[x.size()];
+	org.apache.mahout.colt.list.DoubleArrayList sorted = new org.apache.mahout.colt.list.DoubleArrayList(vals);
+
+	// compute distinct values of x
+	x.toArray(vals); // copy x into vals
+	sorted.sort();
+	org.apache.mahout.jet.stat.Descriptive.frequencies(sorted, distinct, null);
+	// since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin
+	if (distinct.size()>0) distinct.add(distinct.get(distinct.size()-1) + epsilon);
+	distinct.trimToSize();
+	hep.aida.IAxis xaxis = new hep.aida.ref.VariableAxis(distinct.elements());
+
+	// compute distinct values of y
+	y.toArray(vals);
+	sorted.sort();
+	org.apache.mahout.jet.stat.Descriptive.frequencies(sorted, distinct, null);
+	// since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin
+	if (distinct.size()>0) distinct.add(distinct.get(distinct.size()-1) + epsilon);
+	distinct.trimToSize();
+	hep.aida.IAxis yaxis = new hep.aida.ref.VariableAxis(distinct.elements());
+
+	hep.aida.IHistogram2D histo = new hep.aida.ref.Histogram2D("Cube",xaxis,yaxis);
+	return histogram(histo,x,y,weights);
+}
+*/
+/**
+3-d OLAP cube operator; Fills all cells of the given vectors into the given histogram.
+If you use hep.aida.ref.Converter.toString(histo) on the result, the OLAP cube of x-"column" vs. y-"column" vs. z-"column", summing the weights "column" will be printed.
+For example, aggregate sales by product by region by time.
+<p>
+Computes the distinct values of x and y and z, yielding histogram axes that capture one distinct value per bin.
+Then fills the histogram.
+@return the histogram containing the cube.
+@throws IllegalArgumentException if <tt>x.size() != y.size() || x.size() != z.size() || x.size() != weights.size()</tt>.
+*
+public static hep.aida.IHistogram3D cube(DoubleMatrix1D x, DoubleMatrix1D y, DoubleMatrix1D z, DoubleMatrix1D weights) {
+	if (x.size() != y.size() || x.size() != z.size() || x.size() != weights.size()) throw new IllegalArgumentException("vectors must have same size");
+	
+	double epsilon = 1.0E-9;
+	org.apache.mahout.colt.list.DoubleArrayList distinct = new org.apache.mahout.colt.list.DoubleArrayList();
+	double[] vals = new double[x.size()];
+	org.apache.mahout.colt.list.DoubleArrayList sorted = new org.apache.mahout.colt.list.DoubleArrayList(vals);
+
+	// compute distinct values of x
+	x.toArray(vals); // copy x into vals
+	sorted.sort();
+	org.apache.mahout.jet.stat.Descriptive.frequencies(sorted, distinct, null);
+	// since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin
+	if (distinct.size()>0) distinct.add(distinct.get(distinct.size()-1) + epsilon);
+	distinct.trimToSize();
+	hep.aida.IAxis xaxis = new hep.aida.ref.VariableAxis(distinct.elements());
+
+	// compute distinct values of y
+	y.toArray(vals);
+	sorted.sort();
+	org.apache.mahout.jet.stat.Descriptive.frequencies(sorted, distinct, null);
+	// since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin
+	if (distinct.size()>0) distinct.add(distinct.get(distinct.size()-1) + epsilon);
+	distinct.trimToSize();
+	hep.aida.IAxis yaxis = new hep.aida.ref.VariableAxis(distinct.elements());
+
+	// compute distinct values of z
+	z.toArray(vals);
+	sorted.sort();
+	org.apache.mahout.jet.stat.Descriptive.frequencies(sorted, distinct, null);
+	// since bins are right-open [from,to) we need an additional dummy bin so that the last distinct value does not fall into the overflow bin
+	if (distinct.size()>0) distinct.add(distinct.get(distinct.size()-1) + epsilon);
+	distinct.trimToSize();
+	hep.aida.IAxis zaxis = new hep.aida.ref.VariableAxis(distinct.elements());
+
+	hep.aida.IHistogram3D histo = new hep.aida.ref.Histogram3D("Cube",xaxis,yaxis,zaxis);
+	return histogram(histo,x,y,z,weights);
+}
+*/
+/**
+ * Demonstrates usage of this class.
+ */
+public static void demo1() {
+double[][] values = {
+	{ 1, 2, 3 },
+	{ 2, 4, 6 },
+	{ 3, 6, 9 },
+	{ 4, -8, -10 }
+};
+DoubleFactory2D factory = DoubleFactory2D.dense;
+DoubleMatrix2D A = factory.make(values);
+System.out.println("\n\nmatrix="+A);
+System.out.println("\ncovar1="+covariance(A));
+//System.out.println(correlation(covariance(A)));
+//System.out.println(distance(A,EUCLID));
+
+
+//System.out.println(org.apache.mahout.colt.matrixpattern.Converting.toHTML(A.toString()));
+//System.out.println(org.apache.mahout.colt.matrixpattern.Converting.toHTML(covariance(A).toString()));
+//System.out.println(org.apache.mahout.colt.matrixpattern.Converting.toHTML(correlation(covariance(A)).toString()));
+//System.out.println(org.apache.mahout.colt.matrixpattern.Converting.toHTML(distance(A,EUCLID).toString()));
+}
+/**
+ * Demonstrates usage of this class.
+ */
+public static void demo2(int rows, int columns, boolean print) {
+System.out.println("\n\ninitializing...");
+DoubleFactory2D factory = DoubleFactory2D.dense;
+DoubleMatrix2D A = factory.ascending(rows,columns);
+//double value = 1;
+//DoubleMatrix2D A = factory.make(rows,columns);
+//A.assign(value);
+
+System.out.println("benchmarking correlation...");
+
+org.apache.mahout.colt.Timer timer = new org.apache.mahout.colt.Timer().start();
+DoubleMatrix2D corr = correlation(covariance(A));
+timer.stop().display();
+
+if (print) {
+	System.out.println("printing result...");
+	System.out.println(corr);
+}
+System.out.println("done.");
+}
+/**
+ * Demonstrates usage of this class.
+ */
+public static void demo3(VectorVectorFunction norm) {
+double[][] values = {
+	{ -0.9611052, -0.25421095 },
+	{ 0.4308269, -0.69932648 },
+	{ -1.2071029,  0.62030596 },
+	{ 1.5345166,  0.02135884},
+	{-1.1341542,  0.20388430}
+};
+
+System.out.println("\n\ninitializing...");
+DoubleFactory2D factory = DoubleFactory2D.dense;
+DoubleMatrix2D A = factory.make(values).viewDice();
+
+System.out.println("\nA="+A.viewDice());
+System.out.println("\ndist="+distance(A,norm).viewDice());
+}
+/**
+ * Constructs and returns the distance matrix of the given matrix.
+ * The distance matrix is a square, symmetric matrix consisting of nothing but distance coefficients. 
+ * The rows and the columns represent the variables, the cells represent distance coefficients. 
+ * The diagonal cells (i.e. the distance between a variable and itself) will be zero.
+ * Compares two column vectors at a time. Use dice views to compare two row vectors at a time.
+ * 
+ * @param matrix any matrix; a column holds the values of a given variable (vector).
+ * @param distanceFunction (EUCLID, CANBERRA, ..., or any user defined distance function operating on two vectors).
+ * @return the distance matrix (<tt>n x n, n=matrix.columns</tt>).
+ */
+public static DoubleMatrix2D distance(DoubleMatrix2D matrix, VectorVectorFunction distanceFunction) {
+	int columns = matrix.columns();
+	DoubleMatrix2D distance = new org.apache.mahout.colt.matrix.impl.DenseDoubleMatrix2D(columns,columns);
+
+	// cache views
+	DoubleMatrix1D[] cols = new DoubleMatrix1D[columns];
+	for (int i=columns; --i >= 0; ) {
+		cols[i] = matrix.viewColumn(i);
+	}
+
+	// work out all permutations
+	for (int i=columns; --i >= 0; ) {
+		for (int j=i; --j >= 0; ) {
+			double d = distanceFunction.apply(cols[i], cols[j]);
+			distance.setQuick(i,j,d);
+			distance.setQuick(j,i,d); // symmetric
+		}
+	}
+	return distance;
+}
+/**
+ * Fills all cells of the given vector into the given histogram.
+ * @return <tt>histo</tt> (for convenience only).
+ *
+public static hep.aida.IHistogram1D histogram(hep.aida.IHistogram1D histo, DoubleMatrix1D vector) {
+	for (int i=vector.size(); --i >= 0; ) {
+		histo.fill(vector.getQuick(i));
+	}
+	return histo;
+}
+**
+ * Fills all cells of the given vectors into the given histogram.
+ * @return <tt>histo</tt> (for convenience only).
+ * @throws IllegalArgumentException if <tt>x.size() != y.size()</tt>.
+ *
+public static hep.aida.IHistogram2D histogram(hep.aida.IHistogram2D histo, DoubleMatrix1D x, DoubleMatrix1D y) {
+	if (x.size() != y.size()) throw new IllegalArgumentException("vectors must have same size");
+	for (int i=x.size(); --i >= 0; ) {
+		histo.fill(x.getQuick(i), y.getQuick(i));
+	}
+	return histo;
+}
+**
+ * Fills all cells of the given vectors into the given histogram.
+ * @return <tt>histo</tt> (for convenience only).
+ * @throws IllegalArgumentException if <tt>x.size() != y.size() || y.size() != weights.size()</tt>.
+ *
+public static hep.aida.IHistogram2D histogram(hep.aida.IHistogram2D histo, DoubleMatrix1D x, DoubleMatrix1D y, DoubleMatrix1D weights) {
+	if (x.size() != y.size() || y.size() != weights.size()) throw new IllegalArgumentException("vectors must have same size");
+	for (int i=x.size(); --i >= 0; ) {
+		histo.fill(x.getQuick(i), y.getQuick(i), weights.getQuick(i));
+	}
+	return histo;
+}
+ *
+ * Fills all cells of the given vectors into the given histogram.
+ * @return <tt>histo</tt> (for convenience only).
+ * @throws IllegalArgumentException if <tt>x.size() != y.size() || x.size() != z.size() || x.size() != weights.size()</tt>.
+ *
+public static hep.aida.IHistogram3D histogram(hep.aida.IHistogram3D histo, DoubleMatrix1D x, DoubleMatrix1D y, DoubleMatrix1D z, DoubleMatrix1D weights) {
+	if (x.size() != y.size() || x.size() != z.size() || x.size() != weights.size()) throw new IllegalArgumentException("vectors must have same size");
+	for (int i=x.size(); --i >= 0; ) {
+		histo.fill(x.getQuick(i), y.getQuick(i), z.getQuick(i), weights.getQuick(i));
+	}
+	return histo;
+}
+**
+ * Benchmarks covariance computation.
+ */
+public static void main(String[] args) {
+	int rows = Integer.parseInt(args[0]);
+	int columns = Integer.parseInt(args[1]);
+	boolean print = args[2].equals("print");
+	demo2(rows,columns,print);
+}
+/**
+Constructs and returns a sampling view with a size of <tt>round(matrix.size() * fraction)</tt>.
+Samples "without replacement" from the uniform distribution.
+@param matrix any matrix.
+@param rowFraction the percentage of rows to be included in the view.
+@param columnFraction the percentage of columns to be included in the view.
+@param randomGenerator a uniform random number generator; set this parameter to <tt>null</tt> to use a default generator seeded with the current time.
+@return the sampling view.
+@throws IllegalArgumentException if <tt>! (0 <= rowFraction <= 1 && 0 <= columnFraction <= 1)</tt>.
+@see org.apache.mahout.jet.random.sampling.RandomSampler
+*/
+public static DoubleMatrix1D viewSample(DoubleMatrix1D matrix, double fraction, RandomEngine randomGenerator) {
+	// check preconditions and allow for a little tolerance
+	double epsilon = 1e-09;
+	if (fraction < 0 - epsilon || fraction > 1 + epsilon) throw new IllegalArgumentException();
+	if (fraction < 0) fraction = 0;
+	if (fraction > 1) fraction = 1;
+
+	// random generator seeded with current time
+	if (randomGenerator==null) randomGenerator = new org.apache.mahout.jet.random.engine.MersenneTwister((int) System.currentTimeMillis());
+
+	int ncols = (int) Math.round(matrix.size() * fraction);
+	int max = ncols;
+	long[] selected = new long[max]; // sampler works on long's, not int's
+
+	// sample 
+	int n = ncols;
+	int N = matrix.size();
+	org.apache.mahout.jet.random.sampling.RandomSampler.sample(n,N,n,0,selected,0,randomGenerator);
+	int[] selectedCols = new int[n];
+	for (int i=0; i<n; i++) selectedCols[i] = (int) selected[i];
+
+	return matrix.viewSelection(selectedCols);
+}
+/**
+Constructs and returns a sampling view with <tt>round(matrix.rows() * rowFraction)</tt> rows and <tt>round(matrix.columns() * columnFraction)</tt> columns.
+Samples "without replacement".
+Rows and columns are randomly chosen from the uniform distribution.
+Examples: 
+<table border="1" cellspacing="0">
+  <tr valign="top" align="center"> 
+	<td> 
+	  <div align="left"><tt>matrix</tt></div>
+	</td>
+	<td> 
+	  <div align="left"><tt>rowFraction=0.2<br>
+		columnFraction=0.2</tt></div>
+	</td>
+	<td> 
+	  <div align="left"><tt>rowFraction=0.2<br>
+		columnFraction=1.0 </tt></div>
+	</td>
+	<td> 
+	  <div align="left"><tt>rowFraction=1.0<br>
+		columnFraction=0.2 </tt></div>
+	</td>
+  </tr>
+  <tr valign="top"> 
+	<td><tt> 10&nbsp;x&nbsp;10&nbsp;matrix<br>
+	  &nbsp;1&nbsp;&nbsp;2&nbsp;&nbsp;3&nbsp;&nbsp;4&nbsp;&nbsp;5&nbsp;&nbsp;6&nbsp;&nbsp;7&nbsp;&nbsp;8&nbsp;&nbsp;9&nbsp;&nbsp;10<br>
+	  11&nbsp;12&nbsp;13&nbsp;14&nbsp;15&nbsp;16&nbsp;17&nbsp;18&nbsp;19&nbsp;&nbsp;20<br>
+	  21&nbsp;22&nbsp;23&nbsp;24&nbsp;25&nbsp;26&nbsp;27&nbsp;28&nbsp;29&nbsp;&nbsp;30<br>
+	  31&nbsp;32&nbsp;33&nbsp;34&nbsp;35&nbsp;36&nbsp;37&nbsp;38&nbsp;39&nbsp;&nbsp;40<br>
+	  41&nbsp;42&nbsp;43&nbsp;44&nbsp;45&nbsp;46&nbsp;47&nbsp;48&nbsp;49&nbsp;&nbsp;50<br>
+	  51&nbsp;52&nbsp;53&nbsp;54&nbsp;55&nbsp;56&nbsp;57&nbsp;58&nbsp;59&nbsp;&nbsp;60<br>
+	  61&nbsp;62&nbsp;63&nbsp;64&nbsp;65&nbsp;66&nbsp;67&nbsp;68&nbsp;69&nbsp;&nbsp;70<br>
+	  71&nbsp;72&nbsp;73&nbsp;74&nbsp;75&nbsp;76&nbsp;77&nbsp;78&nbsp;79&nbsp;&nbsp;80<br>
+	  81&nbsp;82&nbsp;83&nbsp;84&nbsp;85&nbsp;86&nbsp;87&nbsp;88&nbsp;89&nbsp;&nbsp;90<br>
+	  91&nbsp;92&nbsp;93&nbsp;94&nbsp;95&nbsp;96&nbsp;97&nbsp;98&nbsp;99&nbsp;100 
+	  </tt> </td>
+	<td><tt> 2&nbsp;x&nbsp;2&nbsp;matrix<br>
+	  43&nbsp;50<br>
+	  53&nbsp;60 </tt></td>
+	<td><tt> 2&nbsp;x&nbsp;10&nbsp;matrix<br>
+	  41&nbsp;42&nbsp;43&nbsp;44&nbsp;45&nbsp;46&nbsp;47&nbsp;48&nbsp;49&nbsp;&nbsp;50<br>
+	  91&nbsp;92&nbsp;93&nbsp;94&nbsp;95&nbsp;96&nbsp;97&nbsp;98&nbsp;99&nbsp;100 
+	  </tt> </td>
+	<td><tt> 10&nbsp;x&nbsp;2&nbsp;matrix<br>
+	  &nbsp;4&nbsp;&nbsp;8<br>
+	  14&nbsp;18<br>
+	  24&nbsp;28<br>
+	  34&nbsp;38<br>
+	  44&nbsp;48<br>
+	  54&nbsp;58<br>
+	  64&nbsp;68<br>
+	  74&nbsp;78<br>
+	  84&nbsp;88<br>
+	  94&nbsp;98 </tt> </td>
+  </tr>
+</table> 
+@param matrix any matrix.
+@param rowFraction the percentage of rows to be included in the view.
+@param columnFraction the percentage of columns to be included in the view.
+@param randomGenerator a uniform random number generator; set this parameter to <tt>null</tt> to use a default generator seeded with the current time.
+@return the sampling view.
+@throws IllegalArgumentException if <tt>! (0 <= rowFraction <= 1 && 0 <= columnFraction <= 1)</tt>.
+@see org.apache.mahout.jet.random.sampling.RandomSampler
+*/
+public static DoubleMatrix2D viewSample(DoubleMatrix2D matrix, double rowFraction, double columnFraction, RandomEngine randomGenerator) {
+	// check preconditions and allow for a little tolerance
+	double epsilon = 1e-09;
+	if (rowFraction < 0 - epsilon || rowFraction > 1 + epsilon) throw new IllegalArgumentException();
+	if (rowFraction < 0) rowFraction = 0;
+	if (rowFraction > 1) rowFraction = 1;
+
+	if (columnFraction < 0 - epsilon || columnFraction > 1 + epsilon) throw new IllegalArgumentException();
+	if (columnFraction < 0) columnFraction = 0;
+	if (columnFraction > 1) columnFraction = 1;
+
+	// random generator seeded with current time
+	if (randomGenerator==null) randomGenerator = new org.apache.mahout.jet.random.engine.MersenneTwister((int) System.currentTimeMillis());
+
+	int nrows = (int) Math.round(matrix.rows() * rowFraction);
+	int ncols = (int) Math.round(matrix.columns() * columnFraction);
+	int max = Math.max(nrows,ncols);
+	long[] selected = new long[max]; // sampler works on long's, not int's
+
+	// sample rows
+	int n = nrows;
+	int N = matrix.rows();
+	org.apache.mahout.jet.random.sampling.RandomSampler.sample(n,N,n,0,selected,0,randomGenerator);
+	int[] selectedRows = new int[n];
+	for (int i=0; i<n; i++) selectedRows[i] = (int) selected[i];
+
+	// sample columns
+	n = ncols;
+	N = matrix.columns();
+	org.apache.mahout.jet.random.sampling.RandomSampler.sample(n,N,n,0,selected,0,randomGenerator);
+	int[] selectedCols = new int[n];
+	for (int i=0; i<n; i++) selectedCols[i] = (int) selected[i];
+
+	return matrix.viewSelection(selectedRows, selectedCols);
+}
+/**
+Constructs and returns a sampling view with <tt>round(matrix.slices() * sliceFraction)</tt> slices and <tt>round(matrix.rows() * rowFraction)</tt> rows and <tt>round(matrix.columns() * columnFraction)</tt> columns.
+Samples "without replacement".
+Slices, rows and columns are randomly chosen from the uniform distribution.
+@param matrix any matrix.
+@param sliceFraction the percentage of slices to be included in the view.
+@param rowFraction the percentage of rows to be included in the view.
+@param columnFraction the percentage of columns to be included in the view.
+@param randomGenerator a uniform random number generator; set this parameter to <tt>null</tt> to use a default generator seeded with the current time.
+@return the sampling view.
+@throws IllegalArgumentException if <tt>! (0 <= sliceFraction <= 1 && 0 <= rowFraction <= 1 && 0 <= columnFraction <= 1)</tt>.
+@see org.apache.mahout.jet.random.sampling.RandomSampler
+*/
+public static DoubleMatrix3D viewSample(DoubleMatrix3D matrix, double sliceFraction, double rowFraction, double columnFraction, RandomEngine randomGenerator) {
+	// check preconditions and allow for a little tolerance
+	double epsilon = 1e-09;
+	if (sliceFraction < 0 - epsilon || sliceFraction > 1 + epsilon) throw new IllegalArgumentException();
+	if (sliceFraction < 0) sliceFraction = 0;
+	if (sliceFraction > 1) sliceFraction = 1;
+
+	if (rowFraction < 0 - epsilon || rowFraction > 1 + epsilon) throw new IllegalArgumentException();
+	if (rowFraction < 0) rowFraction = 0;
+	if (rowFraction > 1) rowFraction = 1;
+
+	if (columnFraction < 0 - epsilon || columnFraction > 1 + epsilon) throw new IllegalArgumentException();
+	if (columnFraction < 0) columnFraction = 0;
+	if (columnFraction > 1) columnFraction = 1;
+
+	// random generator seeded with current time
+	if (randomGenerator==null) randomGenerator = new org.apache.mahout.jet.random.engine.MersenneTwister((int) System.currentTimeMillis());
+
+	int nslices = (int) Math.round(matrix.slices() * sliceFraction);
+	int nrows = (int) Math.round(matrix.rows() * rowFraction);
+	int ncols = (int) Math.round(matrix.columns() * columnFraction);
+	int max = Math.max(nslices,Math.max(nrows,ncols));
+	long[] selected = new long[max]; // sampler works on long's, not int's
+
+	// sample slices
+	int n = nslices;
+	int N = matrix.slices();
+	org.apache.mahout.jet.random.sampling.RandomSampler.sample(n,N,n,0,selected,0,randomGenerator);
+	int[] selectedSlices = new int[n];
+	for (int i=0; i<n; i++) selectedSlices[i] = (int) selected[i];
+
+	// sample rows
+	n = nrows;
+	N = matrix.rows();
+	org.apache.mahout.jet.random.sampling.RandomSampler.sample(n,N,n,0,selected,0,randomGenerator);
+	int[] selectedRows = new int[n];
+	for (int i=0; i<n; i++) selectedRows[i] = (int) selected[i];
+
+	// sample columns
+	n = ncols;
+	N = matrix.columns();
+	org.apache.mahout.jet.random.sampling.RandomSampler.sample(n,N,n,0,selected,0,randomGenerator);
+	int[] selectedCols = new int[n];
+	for (int i=0; i<n; i++) selectedCols[i] = (int) selected[i];
+
+	return matrix.viewSelection(selectedSlices,selectedRows, selectedCols);
+}
+/**
+ * Constructs and returns the distance matrix of the given matrix.
+ * The distance matrix is a square, symmetric matrix consisting of nothing but distance coefficients. 
+ * The rows and the columns represent the variables, the cells represent distance coefficients. 
+ * The diagonal cells (i.e. the distance between a variable and itself) will be zero.
+ * Compares two column vectors at a time. Use dice views to compare two row vectors at a time.
+ * 
+ * @param matrix any matrix; a column holds the values of a given variable (vector).
+ * @param norm the kind of norm to be used (EUCLID, CANBERRA, ...).
+ * @return the distance matrix (<tt>n x n, n=matrix.columns</tt>).
+ */
+private static DoubleMatrix2D xdistanceOld(DoubleMatrix2D matrix, int norm) {
+	/*
+	int rows = matrix.rows();
+	int columns = matrix.columns();
+	DoubleMatrix2D distance = new org.apache.mahout.colt.matrix.impl.DenseDoubleMatrix2D(columns,columns);
+
+	// cache views
+	DoubleMatrix1D[] cols = new DoubleMatrix1D[columns];
+	for (int i=columns; --i >= 0; ) {
+		cols[i] = matrix.viewColumn(i);
+	}
+
+	// setup distance function
+	org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+	DoubleDoubleFunction function = null;
+	//DoubleDoubleFunction function2 = null;
+	if (norm==EUCLID) function = F.chain(F.square,F.minus);
+	else if (norm==BRAY_CURTIS) function = F.chain(F.abs,F.minus);
+	else if (norm==CANBERRA) function = new DoubleDoubleFunction() {
+		public final double apply(double a, double b) {	return Math.abs(a-b) / Math.abs(a+b);}
+	};
+	else if (norm==MAXIMUM) function = F.chain(F.abs,F.minus);
+	else if (norm==MANHATTAN) function = F.chain(F.abs,F.minus);
+	else throw new IllegalArgumentException("Unknown norm");
+
+	// work out all permutations
+	for (int i=columns; --i >= 0; ) {
+		for (int j=i; --j >= 0; ) {
+			double d = 0;
+			if (norm==EUCLID) d = Math.sqrt(cols[i].aggregate(cols[j], F.plus, function));
+			else if (norm==BRAY_CURTIS) d = cols[i].aggregate(cols[j], F.plus, function) / cols[i].aggregate(cols[j], F.plus, F.plus);
+			else if (norm==CANBERRA) d = cols[i].aggregate(cols[j], F.plus, function);
+			else if (norm==MAXIMUM) d = cols[i].aggregate(cols[j], F.max, function);
+			else if (norm==MANHATTAN) d = cols[i].aggregate(cols[j], F.plus, function);
+			distance.setQuick(i,j,d);
+			distance.setQuick(j,i,d); // symmetric
+		}
+	}
+	return distance;
+	*/
+	return null;
+}
+/**
+ * Constructs and returns the distance matrix of the given matrix.
+ * The distance matrix is a square, symmetric matrix consisting of nothing but distance coefficients. 
+ * The rows and the columns represent the variables, the cells represent distance coefficients. 
+ * The diagonal cells (i.e. the distance between a variable and itself) will be zero.
+ * Compares two column vectors at a time. Use dice views to compare two row vectors at a time.
+ * 
+ * @param matrix any matrix; a column holds the values of a given variable (vector).
+ * @param norm the kind of norm to be used (EUCLID, CANBERRA, ...).
+ * @return the distance matrix (<tt>n x n, n=matrix.columns</tt>).
+ */
+private static DoubleMatrix2D xdistanceOld2(DoubleMatrix2D matrix, int norm) {
+	/*
+	// setup distance function
+	final org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+	VectorVectorFunction function;
+	if (norm==EUCLID) function = new VectorVectorFunction() {
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {
+			return Math.sqrt(a.aggregate(b, F.plus, F.chain(F.square,F.minus)));
+		}
+	};
+	else if (norm==BRAY_CURTIS) function = new VectorVectorFunction() {
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {	
+			return a.aggregate(b, F.plus, F.chain(F.abs,F.minus)) / a.aggregate(b, F.plus, F.plus);
+		}
+	};
+	else if (norm==CANBERRA) function = new VectorVectorFunction() {
+		DoubleDoubleFunction fun = new DoubleDoubleFunction() {
+			public final double apply(double a, double b) {
+				return Math.abs(a-b) / Math.abs(a+b);
+			}
+		};
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {	
+			return a.aggregate(b, F.plus, fun);
+		}
+	};
+	else if (norm==MAXIMUM) function = new VectorVectorFunction() {
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {	
+			return a.aggregate(b, F.max, F.chain(F.abs,F.minus));
+		}
+	};
+	else if (norm==MANHATTAN) function = new VectorVectorFunction() {
+		public final double apply(DoubleMatrix1D a, DoubleMatrix1D b) {	
+			return a.aggregate(b, F.plus, F.chain(F.abs,F.minus));
+		}
+	};
+	else throw new IllegalArgumentException("Unknown norm");
+
+	return distance(matrix,function);
+	*/
+	return null;
+}
+}

Propchange: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Statistic.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Stencil.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Stencil.java?rev=883365&view=auto
==============================================================================
--- lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Stencil.java (added)
+++ lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Stencil.java Mon Nov 23 15:14:26 2009
@@ -0,0 +1,93 @@
+/*
+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.colt.matrix.doublealgo;
+
+import org.apache.mahout.colt.matrix.DoubleMatrix2D;
+import org.apache.mahout.colt.matrix.DoubleMatrix2DProcedure;
+import org.apache.mahout.colt.matrix.DoubleMatrix3D;
+import org.apache.mahout.colt.matrix.DoubleMatrix3DProcedure;
+/**
+Stencil operations. For efficient finite difference operations.
+Applies a function to a moving <tt>3 x 3</tt> or <tt>3 x 3 x 3</tt> window.
+Build on top of <tt>matrix.zAssignXXXNeighbors(...)</tt>.
+You can specify how many iterations shall at most be done, a convergence condition when iteration shall be terminated, and how many iterations shall pass between convergence checks.
+Always does two iterations at a time for efficiency.
+These class is for convencience and efficiency.
+
+@author wolfgang.hoschek@cern.ch
+@version 1.0, 01/02/2000
+*/
+/** 
+ * @deprecated until unit tests are in place.  Until this time, this class/interface is unsupported.
+ */
+@Deprecated
+public class Stencil extends Object {
+/**
+ * Makes this class non instantiable, but still let's others inherit from it.
+ */
+protected Stencil() {}
+/**
+27 point stencil operation.
+Applies a function to a moving <tt>3 x 3 x 3</tt> window.
+@param A the matrix to operate on.
+@param function the function to be applied to each window.
+@param maxIterations the maximum number of times the stencil shall be applied to the matrix. 
+	Should be a multiple of 2 because two iterations are always done in one atomic step.
+@param hasConverged Convergence condition; will return before maxIterations are done when <tt>hasConverged.apply(A)==true</tt>.
+	Set this parameter to <tt>null</tt> to indicate that no convergence checks shall be made.
+@param convergenceIterations the number of iterations to pass between each convergence check.
+	(Since a convergence may be expensive, you may want to do it only every 2,4 or 8 iterations.)
+@return the number of iterations actually executed. 
+*/
+public static int stencil27(DoubleMatrix3D A, org.apache.mahout.colt.function.Double27Function function, int maxIterations, DoubleMatrix3DProcedure hasConverged, int convergenceIterations) {
+	DoubleMatrix3D B = A.copy();
+	if (convergenceIterations <= 1) convergenceIterations=2;
+	if (convergenceIterations%2 != 0) convergenceIterations++; // odd -> make it even
+
+	int i=0;
+	while (i<maxIterations) { // do two steps at a time for efficiency
+		A.zAssign27Neighbors(B,function);
+		B.zAssign27Neighbors(A,function);
+		i=i+2;
+		if (i%convergenceIterations == 0 && hasConverged!=null) {
+			if (hasConverged.apply(A)) return i;
+		}
+	}
+	return i;
+}
+/**
+9 point stencil operation.
+Applies a function to a moving <tt>3 x 3</tt> window.
+@param A the matrix to operate on.
+@param function the function to be applied to each window.
+@param maxIterations the maximum number of times the stencil shall be applied to the matrix. 
+	Should be a multiple of 2 because two iterations are always done in one atomic step.
+@param hasConverged Convergence condition; will return before maxIterations are done when <tt>hasConverged.apply(A)==true</tt>.
+	Set this parameter to <tt>null</tt> to indicate that no convergence checks shall be made.
+@param convergenceIterations the number of iterations to pass between each convergence check.
+	(Since a convergence may be expensive, you may want to do it only every 2,4 or 8 iterations.)
+@return the number of iterations actually executed. 
+*/
+public static int stencil9(DoubleMatrix2D A, org.apache.mahout.colt.function.Double9Function function, int maxIterations, DoubleMatrix2DProcedure hasConverged, int convergenceIterations) {
+	DoubleMatrix2D B = A.copy();
+	if (convergenceIterations <= 1) convergenceIterations=2;
+	if (convergenceIterations%2 != 0) convergenceIterations++; // odd -> make it even
+
+	int i=0;
+	while (i<maxIterations) { // do two steps at a time for efficiency
+		A.zAssign8Neighbors(B,function);
+		B.zAssign8Neighbors(A,function);
+		i=i+2;
+		if (i%convergenceIterations == 0 && hasConverged!=null) {
+			if (hasConverged.apply(A)) return i;
+		}
+	}
+	return i;
+}
+}

Propchange: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Stencil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Transform.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Transform.java?rev=883365&view=auto
==============================================================================
--- lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Transform.java (added)
+++ lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Transform.java Mon Nov 23 15:14:26 2009
@@ -0,0 +1,376 @@
+/*
+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.colt.matrix.doublealgo;
+
+import org.apache.mahout.colt.matrix.DoubleMatrix1D;
+import org.apache.mahout.colt.matrix.DoubleMatrix2D;
+/**
+Deprecated; Basic element-by-element transformations on {@link org.apache.mahout.colt.matrix.DoubleMatrix1D} and {@link org.apache.mahout.colt.matrix.DoubleMatrix2D}.
+All transformations modify the first argument matrix to hold the result of the transformation.
+Use idioms like <tt>result = mult(matrix.copy(),5)</tt> to leave source matrices unaffected.
+<p>
+If your favourite transformation is not provided by this class, consider using method <tt>assign</tt> in combination with prefabricated function objects of {@link org.apache.mahout.jet.math.Functions},
+using idioms like 
+<table>
+<td class="PRE"> 
+<pre>
+org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions; // alias
+matrix.assign(F.square);
+matrix.assign(F.sqrt);
+matrix.assign(F.sin);
+matrix.assign(F.log);
+matrix.assign(F.log(b));
+matrix.assign(otherMatrix, F.min);
+matrix.assign(otherMatrix, F.max);
+</pre>
+</td>
+</table>
+Here are some <a href="../doc-files/functionObjects.html">other examples</a>.
+<p>
+Implementation: Performance optimized for medium to very large matrices.
+In fact, there is now nomore a performance advantage in using this class; The assign (transform) methods directly defined on matrices are now just as fast.
+Thus, this class will soon be removed altogether.
+
+@deprecated
+@author wolfgang.hoschek@cern.ch
+@version 1.0, 09/24/99
+*/
+/** 
+ * @deprecated until unit tests are in place.  Until this time, this class/interface is unsupported.
+ */
+@Deprecated
+public class Transform extends org.apache.mahout.colt.PersistentObject {
+	/**
+	 * Little trick to allow for "aliasing", that is, renaming this class.
+	 * Normally you would write
+	 * <pre>
+	 * Transform.mult(myMatrix,2);
+	 * Transform.plus(myMatrix,5);
+	 * </pre>
+	 * Since this class has only static methods, but no instance methods
+	 * you can also shorten the name "DoubleTransform" to a name that better suits you, for example "Trans".
+	 * <pre>
+	 * Transform T = Transform.transform; // kind of "alias"
+	 * T.mult(myMatrix,2);
+	 * T.plus(myMatrix,5);
+	 * </pre>
+	 */
+	public static final Transform transform = new Transform();
+
+	private static final org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions; // alias
+
+/**
+ * Makes this class non instantiable, but still let's others inherit from it.
+ */
+protected Transform() {}
+/**
+ * <tt>A[i] = Math.abs(A[i])</tt>.
+ * @param A the matrix to modify.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D abs(DoubleMatrix1D A) {
+	return A.assign(F.abs);
+}
+/**
+ * <tt>A[row,col] = Math.abs(A[row,col])</tt>.
+ * @param A the matrix to modify.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D abs(DoubleMatrix2D A) {
+	return A.assign(F.abs);
+}
+/**
+ * <tt>A = A / s <=> A[i] = A[i] / s</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D div(DoubleMatrix1D A, double s) {
+	return A.assign(F.div(s));
+}
+/**
+ * <tt>A = A / B <=> A[i] = A[i] / B[i]</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D div(DoubleMatrix1D A, DoubleMatrix1D B) {
+	return A.assign(B,F.div);
+}
+/**
+ * <tt>A = A / s <=> A[row,col] = A[row,col] / s</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D div(DoubleMatrix2D A, double s) {
+	return A.assign(F.div(s));
+}
+/**
+ * <tt>A = A / B <=> A[row,col] = A[row,col] / B[row,col]</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D div(DoubleMatrix2D A, DoubleMatrix2D B) {
+	return A.assign(B,F.div);
+}
+/**
+ * <tt>A[row,col] = A[row,col] == s ? 1 : 0</tt>; ignores tolerance.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D equals(DoubleMatrix2D A, double s) {
+	return A.assign(F.equals(s));
+}
+/**
+ * <tt>A[row,col] = A[row,col] == B[row,col] ? 1 : 0</tt>; ignores tolerance.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D equals(DoubleMatrix2D A, DoubleMatrix2D B) {
+	return A.assign(B,F.equals);
+}
+/**
+ * <tt>A[row,col] = A[row,col] > s ? 1 : 0</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D greater(DoubleMatrix2D A, double s) {
+	return A.assign(F.greater(s));
+}
+/**
+ * <tt>A[row,col] = A[row,col] > B[row,col] ? 1 : 0</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D greater(DoubleMatrix2D A, DoubleMatrix2D B) {
+	return A.assign(B,F.greater);
+}
+/**
+ * <tt>A[row,col] = A[row,col] < s ? 1 : 0</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D less(DoubleMatrix2D A, double s) {
+	return A.assign(F.less(s));
+}
+/**
+ * <tt>A[row,col] = A[row,col] < B[row,col] ? 1 : 0</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D less(DoubleMatrix2D A, DoubleMatrix2D B) {
+	return A.assign(B,F.less);
+}
+/**
+ * <tt>A = A - s <=> A[i] = A[i] - s</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D minus(DoubleMatrix1D A, double s) {
+	return A.assign(F.minus(s));
+}
+/**
+ * <tt>A = A - B <=> A[i] = A[i] - B[i]</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D minus(DoubleMatrix1D A, DoubleMatrix1D B) {
+	return A.assign(B,F.minus);
+}
+/**
+ * <tt>A = A - s <=> A[row,col] = A[row,col] - s</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D minus(DoubleMatrix2D A, double s) {
+	return A.assign(F.minus(s));
+}
+/**
+ * <tt>A = A - B <=> A[row,col] = A[row,col] - B[row,col]</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D minus(DoubleMatrix2D A, DoubleMatrix2D B) {
+	return A.assign(B,F.minus);
+}
+/**
+ * <tt>A = A - B*s <=> A[i] = A[i] - B[i]*s</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D minusMult(DoubleMatrix1D A, DoubleMatrix1D B, double s) {
+	return A.assign(B,F.minusMult(s));
+}
+/**
+ * <tt>A = A - B*s <=> A[row,col] = A[row,col] - B[row,col]*s</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D minusMult(DoubleMatrix2D A, DoubleMatrix2D B, double s) {
+	return A.assign(B,F.minusMult(s));
+}
+/**
+ * <tt>A = A * s <=> A[i] = A[i] * s</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D mult(DoubleMatrix1D A, double s) {
+	return A.assign(F.mult(s));
+}
+/**
+ * <tt>A = A * B <=> A[i] = A[i] * B[i]</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D mult(DoubleMatrix1D A, DoubleMatrix1D B) {
+	return A.assign(B,F.mult);
+}
+/**
+ * <tt>A = A * s <=> A[row,col] = A[row,col] * s</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D mult(DoubleMatrix2D A, double s) {
+	return A.assign(F.mult(s));
+}
+/**
+ * <tt>A = A * B <=> A[row,col] = A[row,col] * B[row,col]</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D mult(DoubleMatrix2D A, DoubleMatrix2D B) {
+	return A.assign(B,F.mult);
+}
+/**
+ * <tt>A = -A <=> A[i] = -A[i]</tt> for all cells.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D negate(DoubleMatrix1D A) {
+	return A.assign(F.mult(-1));
+}
+/**
+ * <tt>A = -A <=> A[row,col] = -A[row,col]</tt>.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D negate(DoubleMatrix2D A) {
+	return A.assign(F.mult(-1));
+}
+/**
+ * <tt>A = A + s <=> A[i] = A[i] + s</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D plus(DoubleMatrix1D A, double s) {
+	return A.assign(F.plus(s));
+}
+/**
+ * <tt>A = A + B <=> A[i] = A[i] + B[i]</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D plus(DoubleMatrix1D A, DoubleMatrix1D B) {
+	return A.assign(B,F.plus);
+}
+/**
+ * <tt>A = A + s <=> A[row,col] = A[row,col] + s</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D plus(DoubleMatrix2D A, double s) {
+	return A.assign(F.plus(s));
+}
+/**
+ * <tt>A = A + B <=> A[row,col] = A[row,col] + B[row,col]</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D plus(DoubleMatrix2D A, DoubleMatrix2D B) {
+	return A.assign(B,F.plus);
+}
+/**
+ * <tt>A = A + B*s<=> A[i] = A[i] + B[i]*s</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D plusMult(DoubleMatrix1D A, DoubleMatrix1D B, double s) {
+	return A.assign(B,F.plusMult(s));
+}
+/**
+ * <tt>A = A + B*s <=> A[row,col] = A[row,col] + B[row,col]*s</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D plusMult(DoubleMatrix2D A, DoubleMatrix2D B, double s) {
+	return A.assign(B,F.plusMult(s));
+}
+/**
+ * <tt>A = A<sup>s</sup> <=> A[i] = Math.pow(A[i], s)</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D pow(DoubleMatrix1D A, double s) {
+	return A.assign(F.pow(s));
+}
+/**
+ * <tt>A = A<sup>B</sup> <=> A[i] = Math.pow(A[i], B[i])</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix1D pow(DoubleMatrix1D A, DoubleMatrix1D B) {
+	return A.assign(B,F.pow);
+}
+/**
+ * <tt>A = A<sup>s</sup> <=> A[row,col] = Math.pow(A[row,col], s)</tt>.
+ * @param A the matrix to modify.
+ * @param s the scalar; can have any value.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D pow(DoubleMatrix2D A, double s) {
+	return A.assign(F.pow(s));
+}
+/**
+ * <tt>A = A<sup>B</sup> <=> A[row,col] = Math.pow(A[row,col], B[row,col])</tt>.
+ * @param A the matrix to modify.
+ * @param B the matrix to stay unaffected.
+ * @return <tt>A</tt> (for convenience only).
+ */
+public static DoubleMatrix2D pow(DoubleMatrix2D A, DoubleMatrix2D B) {
+	return A.assign(B,F.pow);
+}
+}

Propchange: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/doublealgo/Transform.java
------------------------------------------------------------------------------
    svn:eol-style = native