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/12/18 00:22:41 UTC

svn commit: r891983 [45/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...

Added: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/package.html
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/package.html?rev=891983&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/package.html (added)
+++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/package.html Thu Dec 17 23:22:16 2009
@@ -0,0 +1,789 @@
+<HTML>
+<BODY>
+Matrix <i>interfaces and factories</i>; efficient and flexible dense and sparse
+1, 2, 3 and d-dimensional matrices holding objects or primitive data types such
+as <tt>int</tt>, <tt>double</tt>, etc; Templated, fixed sized (not dynamically
+resizable); Also known as <i>multi-dimensional arrays</i> or<i> Data Cubes</i>.
+Note that d-dimensional and <tt>int</tt> based matrices are not yet provided.
+<p></p>
+
+<h1><a name="Overview"></a>Getting Started</h1>
+<ol>
+  <li><a href="#Overview">Overview</a></li>
+  <li><a href="#Introduction">Introduction</a></li>
+  <li><a href="#SemanticsOfViews">Semantics of Views</a></li>
+  <li><a href="#FunctionObjects">Functional Programming with Objects</a></li>
+  <li><a href="#Algorithms">Algorithms</a></li>
+  <li><a href="#LinearAlgebra">Linear Algebra</a></li>
+  <li><a href="#Orthogonality">Orthogonality and Polymorphism</a></li>
+  <li><a href="#PackageOrganization">Package Organization, Naming Conventions,
+    Policies</a></li>
+  <li><a href="#Performance">Performance</a></li>
+  <li><a href="#Notes">Notes</a></li>
+</ol>
+<h2></h2>
+
+<h2>1. Overview</h2>
+
+<p>The matrix package offers flexible object oriented abstractions modelling multi-dimensional
+  arrays, resembling the way they can be manipulated in Fortran. It is designed
+  to be scalable, not only in terms of performance and memory requirements, but
+  also in terms of the number of operations that make sense on such data structures.
+  Features include</p>
+<table width="75%" border="0" bgcolor="#EEEEEE">
+<tr valign="top" align="left">
+  <td>
+    <table border="0" cellpadding="0" cellspacing="0" width="358">
+      <tr>
+        <td colspan="2" bgcolor="#770000">
+          <p align="CENTER"><font color="#FFFFFF"><b>Multi-dimensional Array
+            Types</b></font>
+        </td>
+      </tr>
+      <tr valign="top">
+        <td align="LEFT" width="180">
+          <ul>
+            <li>dense
+            <li>sparse hashed
+            <li>sparse row compressed
+          </ul>
+        </td>
+        <td align="LEFT" width="180">
+          <ul>
+            <li>1-d, 2-d, 3-d
+          </ul>
+        </td>
+      </tr>
+    </table>
+  </td>
+  <td>
+    <table border="0" cellpadding="0" cellspacing="0" width="358">
+      <tr>
+        <td colspan="2" bgcolor="#770000">
+          <p align="CENTER"><font color="#FFFFFF"><b>Matrix Operations</b></font>
+        </td>
+      </tr>
+      <tr valign="top">
+        <td align="LEFT" width="180">
+          <ul>
+            <li>matrix-matrix multiply
+            <li>matrix-vector multiply
+            <li>inner, outer products
+            <li>tranposition
+          </ul>
+        </td>
+        <td align="LEFT" width="180">
+          <ul>
+            <li>equation solving
+            <li>permutation (pivoting)
+            <li>integer powers
+            <li>norms
+            <li>trace
+          </ul>
+        </td>
+      </tr>
+    </table>
+  </td>
+</tr>
+<tr valign="top" align="left">
+  <td>
+    <table border="0" cellpadding="0" cellspacing="0" width="358">
+      <tr>
+        <td colspan="2" bgcolor="#770000">
+          <p align="CENTER"><font color="#FFFFFF"><b>Array Views (by Reference)</b></font>
+        </td>
+      </tr>
+      <tr valign="top">
+        <td align="LEFT" width="180">
+          <ul>
+            <li>sub-range
+            <li>slice
+            <li>dice
+            <li>flip
+            <li>stride
+          </ul>
+        </td>
+        <td align="LEFT" width="180">
+          <ul>
+            <li>selection
+            <li>sort
+          </ul>
+          <ul>
+            <li>assigment
+            <li>copying
+          </ul>
+        </td>
+      </tr>
+    </table>
+  </td>
+  <td>
+    <table border="0" cellpadding="0" cellspacing="0" width="358">
+      <tr>
+        <td valign="MIDDLE" colspan="2" bgcolor="#770000">
+          <p align="CENTER"><font color="#FFFFFF"><b>Matrix Factorizations and
+            Decompositions</b></font>
+        </td>
+      </tr>
+      <tr valign="top">
+        <td width="180" align="LEFT">
+          <ul>
+            <li>LU
+            <li>QR
+            <li>Cholesky
+            <li>eigenvectors and eigenvalues
+            <li>singular value (SVD)
+          </ul>
+        </td>
+        <td align="LEFT" width="180">
+          <ul>
+            <li> inverse
+            <li>pseudoinverse
+            <li>condition
+            <li>determinant
+            <li>rank
+          </ul>
+        </td>
+      </tr>
+    </table>
+  </td>
+</tr>
+<tr valign="top" align="left">
+  <td>
+    <table border="0" cellpadding="0" cellspacing="0" width="358">
+      <tr>
+        <td colspan="2" bgcolor="#770000">
+          <p align="CENTER"><font color="#FFFFFF"><b>Elementwise Array Operations</b></font>
+        </td>
+      </tr>
+      <tr valign="top">
+        <td align="LEFT" width="180">
+          <ul>
+            <li>addition
+            <li>subtraction
+            <li>multiplication
+            <li>division
+            <li>power
+            <li>square root
+            <li>logarithm
+            <li>exponential
+            <li>absolute value
+            <li>trigonometric functions
+          </ul>
+        </td>
+        <td align="LEFT" width="180">
+          <ul>
+            <li> assignment
+            <li>functional programming via user-defined functions (for transformations,
+              aggregations, selections, sorting)
+            <li>comparison
+          </ul>
+        </td>
+      </tr>
+    </table>
+    <p>&nbsp;</p>
+  </td>
+  <td>
+    <table border="0" cellpadding="0" cellspacing="0" width="358" height="55">
+      <tr>
+        <td valign="MIDDLE" colspan="2" bgcolor="#770000">
+          <p align="CENTER"><font color="#FFFFFF"><b>Columnwise Data Analysis</b></font>
+        </td>
+      </tr>
+      <tr valign="top">
+        <td width="180" align="LEFT">
+          <ul>
+            <li>covariance, correlation matrix
+            <li>maximum
+            <li>minimum
+            <li>mean
+            <li>variance, standard deviation
+            <li>median
+            <li>exact and approximate quantiles
+          </ul>
+        </td>
+        <td align="LEFT" width="180">
+          <ul>
+            <li>(cumulative) sum
+            <li>(cumulative) product
+            <li>harmonic, geometric mean
+            <li>skew, kurtosis
+            <li>moments
+            <li>frequencies
+            <li>sorting
+          </ul>
+        </td>
+      </tr>
+    </table>
+  </td>
+</tr>
+<tr valign="top" align="left">
+  <td>
+    <table border="0" cellpadding="0" cellspacing="0" width="358">
+      <tr>
+        <td colspan="2" bgcolor="#770000">
+          <p align="CENTER"><font color="#FFFFFF"><b>Array and Matrix Utilities</b></font>
+        </td>
+      </tr>
+      <tr valign="top">
+        <td align="LEFT" width="180">
+          <ul>
+            <li> dense and sparse creation
+            <li>string formatting
+            <li>up-down or left-right concatenation
+            <li>create, extract block matrix
+          </ul>
+        </td>
+        <td align="LEFT" width="180">
+          <ul>
+            <li>create, extract diagonals
+            <li>extract upper, lower triangular parts
+            <li>random matrix, array
+          </ul>
+        </td>
+      </tr>
+    </table>
+  </td>
+  <td>
+    <p>&nbsp;</p>
+  </td>
+</tr>
+</table>
+<p>File-based I/O can be achieved through the standard Java-built-in serialization
+  mechanism. All classes implement the {@link java.io.Serializable} interface.
+  However, the toolkit is entirely decoupled from advanced I/O and visualisation
+  techniques. It provides data structures and algorithms only. </p>
+
+<p> This toolkit borrows many fundamental concepts and terminology from the IBM
+  <a href="http://math.nist.gov/javanumerics/array/"> Array</a> package written
+  by Jose Moreira, Marc Snir and Sam Midkiff. They introduced well designed multi-dimensional
+  arrays to the Java world.
+
+<p><a href="#Overview">Back</a> to Overview
+
+<h2><a name="Introduction"></a>2. Introduction</h2>
+
+<p>Multi-dimensional arrays are arguably <i>the</i> most frequently used abstraction
+  in scientific and technical codes. They support a broad variety of applications
+  in the domain of Physics, Linear Algebra, Computational Fluid Dynamics, Relational
+  Algebra, Statistics, Graphics Rendering and others. For example many physics
+  problems can be mapped to matrix problems: Linear and nonlinear systems of equations,
+  linear differential equations, quantum mechanical eigenvalue problems, Tensors,
+  etc. Physics<i> NTuples</i> are essentially 2-d arrays. In the area of Online
+  Analytic Processing <i>(OLAP</i>) multi-dimensional arrays are called <i>Data
+    Cubes</i>. In this toolkit they are called <i>Matrices</i>, simply because the
+  term <i>Array</i> is already heavily overloaded and <i>Data Cube</i> is somewhat
+  fuzzy to many people.</p>
+
+<h2></h2>
+
+<p>Matrices are basically rectangular grids with each cell in the grid containing
+  a single value. Cells are accessed via zero-based integer indexes. Matrices
+  can be characterized by</p>
+<ul>
+  <li><i>Rank</i>: The number of dimensions (axes). Most frequently used are one and
+    two dimensions.
+  </li>
+  <li><i>Shape:</i> Each dimension has a certain number of slots. All slots together
+    make up the shape. For example, a 2-dimensional 10 x 50 matrix has 10 slots
+    along its first dimension, and 50 slots along its second dimension, yielding
+    500 cells.
+  </li>
+  <li><i>Value type</i>: The type of value to be stored in each cell. Can be integer,
+    floating point or an arbitrary object.
+  </li>
+</ul>
+<p>Here is an example of a <tt>8x8x8</tt> matrix and other matrices.
+
+<p><img src="doc-files/slice.gif" width="644" height="401">
+
+<p>As broad as the spectrum of applications using multi-dimensional matrices is
+  the number of operations meaningful on them. Only a smallish subset of those
+  operations are provided in this library. We hope that this will change over
+  time. However, core multi-purpose functionality such as <i>subrange</i>, <i>slice</i>,
+  <i>dice</i>, <i>flip</i>, <i>stride</i>, <i>selection</i> and<i> sort</i> views
+  as well as <i>copying</i> and <i>numerical transformations</i> (*,/,+,-,...)
+  are efficiently provided. The primary motivation for views is ease-of-use. Views
+  allow to express otherwise complex aggregate operations in simple terms. They
+  seek to present a matrix in different ways to a user and/or functions operating
+  on a matrix. Subranging, slicing, dicing, flipping, striding, selecting and
+  sorting are virtual transformations: they merely alter the way we see the <i>same
+    data</i>. They produce <i>views</i>, which are objects that know only about
+  certain regions of the entire matrix. Views all point to the same data, so changes
+  in the view are reflected in the original matrix, all other possibly nested
+  views of the original matrix, and vice-versa. Pete and Jane can look at a flower
+  in many different ways although it remains one single flower. If Pete steps
+  on top of the flower, Jane will certainly note. Which is not the case when copying
+  is applied, since it is a materializing transformation. It means, the connection
+  between the original and the copy is lost. If Pete is stepping on top of a rose
+  and Jane is admiring another one, it won't have any impact on her. Views can
+  arbitrarily be nested. They eliminate the need for explicit region operations.
+  Any operation on a matrix can be used as a region restricted operation by operating
+  on a matrix view instead of the whole matrix. Here are some examples:
+
+<p>&nbsp;
+<table border="0">
+<tr>
+  <td>Lets construct a dense 3 x 4 matrix</td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td>
+    <p><tt>DoubleMatrix2D matrix;<br>
+      matrix </tt><tt>= new DenseDoubleMatrix2D(3,4);<br>
+    </tt><tt>//matrix </tt><tt>= new SparseDoubleMatrix2D(3,4);</tt><tt> </tt><tt>//
+      has same interface<br>
+    </tt><tt>//matrix </tt><tt>= new RCDoubleMatrix2D(3,4);</tt><tt> </tt><tt>
+      // has same interface<br>
+    </tt><tt></tt><tt>log.info(matrix); </tt></p>
+  </td>
+  <td nowrap><tt>3 x 4 matrix: <br>
+    0 0 0 0 <br>
+    0 0 0 0 <br>
+    0 0 0 0 </tt></td>
+</tr>
+<tr>
+  <td> We can get rid of the typed distinction between sparse and dense matrices.
+    Use a factory, as follows
+  </td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td>
+    <p><tt>DoubleFactory2D factory;<br>
+      if (wantDense) factory = DoubleFactory2D.dense;<br>
+      else if (wantSparseHashed)&nbsp;factory = DoubleFactory2D.sparse;<br>
+      else factory = DoubleFactory2D.rowCompressed;<br>
+      <br>
+      // From now on all instantiations will go via the factory -<br>
+      // No explicit constructor calls anymore</tt><tt><br>
+      DoubleMatrix2D matrix = factory.make(3,4);<br>
+      log.info(matrix);</tt></p>
+  </td>
+  <td nowrap><tt>3 x 4 matrix: <br>
+    0 0 0 0 <br>
+    0 0 0 0 <br>
+    0 0 0 0 </tt></td>
+</tr>
+<tr>
+  <td>The shape can be retrieved with <br>
+    <tt>int rows = matrix.rows(); <br>
+      int columns = matrix.columns();</tt></td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td>We set and get a cell value:</td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td>
+    <p><tt>int row = 2, column = 0;<br>
+    </tt><tt>matrix.set(row,column, 7);<br>
+      log.info(matrix.get(row,column));<br>
+      // --&gt; 7</tt></p>
+  </td>
+  <td nowrap><tt>3 x 4 matrix <br>
+    0 0 0 0 <br>
+    0 0 0 0 <br>
+    7 0 0 0 </tt></td>
+</tr>
+<tr>
+  <td>Looping is done as expected:</td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td><tt>
+      <pre>
+double sum = 0;
+for (int row=rows; --row &gt;= 0; ) {
+   for (int column=columns; --column &gt;= 0; ) {
+      sum += matrix.get(row,column); // bounds check
+      //sum += matrix.getQuick(row,column); // no bounds check
+   }
+}
+log.info(sum);
+</pre>
+  </tt></td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td>The following idiom uses a subranging view to set all cells of the box
+    <br>
+    starting at <tt>[1,0]</tt> with width and height of 2 to the value <tt>1</tt>:
+  </td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td><tt>matrix.viewPart(1,0,2,2).assign(1);<br>
+    log.info(matrix); <br>
+  </tt></td>
+  <td nowrap><tt>3 x 4 matrix <br>
+    0 0 0 0 <br>
+    1 1 0 0 <br>
+    1 1 0 0 </tt></td>
+</tr>
+<tr>
+  <td>
+    <p>A dicing view can be used to print the matrix in a different format (4
+      x 3). This is equivalent to a zero-copy transposition:</p>
+  </td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td><tt>log.info(matrix.viewDice())</tt></td>
+  <td nowrap><tt>4 x 3 matrix <br>
+    0 1 1 <br>
+    0 1 1 <br>
+    0 0 0 <br>
+    0 0 0 </tt></td>
+</tr>
+<tr>
+  <td>
+    <p>Next, a flipping view mirrors the matrix. </p>
+  </td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td><tt>log.info(matrix.viewColumnFlip());</tt></td>
+  <td nowrap><tt>3 x 4 matrix <br>
+    0 0 0 0 <br>
+    0 0 1 1 <br>
+    0 0 1 1 </tt></td>
+</tr>
+<tr>
+  <td>
+    <p>A slicing view shows the second row, a 1-dimensional matrix:</p>
+  </td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td><tt>log.info(matrix.viewRow(1)); </tt></td>
+  <td nowrap><tt>4 matrix <br>
+    1 1 0 0 </tt></td>
+</tr>
+<tr>
+  <td>
+    <p>Note that the result of a slicing operation is not a 2-d matrix with
+      one row, but a true 1-d <b>type</b> with all capabilities of the type,
+      namely {@link org.apache.mahout.math.matrix.DoubleMatrix1D}, generated in constant
+      time.</p>
+
+    <p>The slicing view is now fed into some external algorithm expecting a
+      1-dimensional matrix:<br>
+      <tt>someAlgorithm(matrix.viewRow(1));</tt></p>
+  </td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td>If the algorithm is designed such that it modifies data of the row, <br>
+    but we want to avoid any side-effects, we can feed it a copy of the row:
+    <tt><br>
+      someAlgorithm(matrix.viewRow(1).copy());</tt></td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td>A stride view shows every row and every second column. It is useful for
+    scatter/gather operations.
+  </td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td><tt>log.info(matrix.viewStrides(1,2)); </tt></td>
+  <td nowrap><tt>3 x 2 matrix <br>
+    0 0<br>
+    1 0<br>
+    1 0</tt></td>
+</tr>
+<tr>
+  <td>A selection view shows explicitly specified rows and columns. Imagine
+    a 2-d matrix. Columns are attributes <i>energy</i>, <i>tracks</i>, <i>momentum</i>,
+    the rows hold <tt>N</tt> such measurements, as recorded by some device.
+    We want to operate on some subset of the columns and exclude some measurements
+    not of interest for our analysis.
+  </td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td><tt>int[] rowIndexes = {0,2};<br>
+    int[] columnIndexes = {2,3,1,1};<br>
+    log.info(matrix.viewSelection(rowIndexes,columnIndexes)); </tt></td>
+  <td nowrap><tt>2 x 4 matrix <br>
+    0 0 0 0 <br>
+    0 0 1 1 </tt></td>
+</tr>
+<tr>
+  <td>A sort view with row flipping shows rows sorted descending by column 1:</td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td><tt>log.info(matrix.viewSorted(1).viewRowFlip()); </tt></td>
+  <td nowrap><tt>3 x 4 matrix <br>
+    1 1 0 0 <br>
+    1 1 0 0 <br>
+    0 0 0 0 </tt></td>
+</tr>
+<tr>
+  <td>Last, lets combine some of the methods to stimulate imagination:</td>
+  <td nowrap>&nbsp;</td>
+</tr>
+<tr>
+  <td><tt>matrix.viewPart(0,1,2,2).viewRowFlip().viewColumn(0).assign(2);<br>
+    log.info(matrix); <br>
+  </tt></td>
+  <td nowrap><tt>3 x 4 matrix <br>
+    0 2 0 0 <br>
+    1 2 0 0 <br>
+    1 1 0 0 </tt></td>
+</tr>
+</table>
+<p><a href="#Overview">Back</a> to Overview
+
+<h2></h2>
+
+<h2><a name="SemanticsOfViews"></a>3. Semantics of Views </h2>
+
+<p>Find out more about the <a href="doc-files/semanticsOfViews.html">precise semantics</a>
+  of views and basic operations.</p>
+
+<p><a href="#Overview">Back</a> to Overview
+
+<h2></h2>
+
+<h2><a name="Orthogonality"></a>4. Orthogonality and Polymorphism</h2>
+
+<p>If this section sounds trivial and obvious, you can safely skip it.<br>
+  The desire for orthogonality is a desire for &quot;plug and play&quot;. Orthogonality
+  demands that everything can be plugged together with everything, or, in other
+  words, that different things can be handled in the same way. Of course only
+  things that syntactically and semantically share a common set of interfaces
+  can be handled in the same way, or work together in the same way. Polymorphism
+  is an implementation mechanism supporting orthogonality. It is about being able
+  to exchange things without noticing any difference. Again, as long as the things
+  adhere to some common interface.</p>
+
+<p>The common interface for matrices is defined in abstract base classes (e.g.
+  {@link org.apache.mahout.math.matrix.DoubleMatrix2D}). Note that looking at the documentation
+  of some concrete instantiable class (e.g. {@link org.apache.mahout.math.matrix.impl.DenseDoubleMatrix2D},
+  {@link org.apache.mahout.math.matrix.impl.SparseDoubleMatrix2D}, {@link
+  impl.RCDoubleMatrix2D}<img
+      src="../doc-files/new.gif" width="32" height="22" align="top">)
+  will not reveal more information than can be obtained by looking at the abstract
+  base classes. The convention is that concrete classes <i>do no subsetting or
+    supersetting</i>. They override methods to implement behaviour dictated by abstract
+  classes, or to improve performance, but they do not introduce any new functionality.
+</p>
+
+<p>Although each matrix of a given rank and value type comes with dense and sparse
+  implementations and a multitude of views, there is from the user interface perspective
+  no difference between them. All implementations have exactly the same interface
+  with exactly the same semantics attached. In particular, everything that &quot;can
+  be done&quot; with a dense matrix can also be done with a sparse specie, and
+  vice-versa. The same principle applies to views. </p>
+
+<p><i>This implies that any internal or external function expecting as argument
+  an abstract matrix (and any operation defined on an abstract matrix) can be
+  used with any kind of matrix of the given rank and value type, whether it be
+  dense, sparse, sub-ranged, selected, strided, sorted, flipped, transposed, or
+  any arbitrary combination thereof. For example, dense matrices can be multiplied/assigned/transformed/compared
+  with sparse matrices, dense stride views with dense flip views, dense sorted
+  flipped sub-range views with sparse selection views, in all conceivable permutations.
+  The result is a powerful and flexible tool.</i></p>
+
+<h2></h2>
+
+<p><a href="#Overview">Back</a> to Overview
+
+<h2><a name="FunctionObjects"></a>5. Function Objects</h2>
+
+<p>Function objects conveniently allow to express arbitrary functions in a generic
+  manner. Essentially, a function object is an object that can perform a function
+  on some arguments. It has a minimal interface: a method <tt>apply</tt> that
+  takes the arguments, computes something and returns some result value. Function
+  objects are comparable to function pointers in C used for call-backs. Here are
+  some examples demonstrating how function objects can be used to </p>
+<ol>
+  <li><a href="doc-files/function1.html">transform</a> a matrix A into another
+    matrix B which is a function of the original matrix A (and optionally yet
+    another matrix C)
+  </li>
+  <li><a href="doc-files/function2.html">aggregate</a> cell values or a function
+    of them
+  </li>
+  <li><a href="doc-files/function3.html">generate selection views</a> for cells
+    satisfying a given condition
+  </li>
+  <li><a href="doc-files/function4.html">sort</a> matrix rows or columns into
+    a user specified order
+  </li>
+  <li>You will most likely use them to do many more powerful things</li>
+</ol>
+<p>Usually, assign operations are heavily optimized for frequently used function
+  objects like plus, minus, mult, div, plusMult, minusMult, etc. Concerning the
+  performance of unoptimized function objects, see {@link org.apache.mahout.math.jet.math.Functions}.</p>
+
+<p></p>
+
+<p><a href="#Overview">Back</a> to Overview
+
+<h2></h2>
+
+<h2><a name="Algorithms"></a>6. Algorithms </h2>
+
+<p>As already stated, the spectrum of applications using multi-dimensional matrices
+  is large and so is the number of operations meaningful on them. One single flat
+  interface cannot satisfy all needs and would soon get unmanageably fat. To avoid
+  interface bloat, it can be a good idea to separate algorithms from data structures.
+  Special purpose algorithms, wrappers, mediators etc. should therefore go into
+  external packages and classes. By using the common interfaces defined in abstract
+  classes, algorithms can be implemented such that they generically work both
+  on sparse and dense matrices and all their views. This will ensure scalability
+  over time, as more and more features are added. </p>
+
+<p>Some algorithms for formatting, sorting, statistics and partitioning, are,
+  for example, provided in the package {@link org.apache.mahout.math.matrix.doublealgo}. </p>
+
+<p><a href="#Overview">Back</a> to Overview</p>
+
+<h2></h2>
+
+<h2><a name="LinearAlgebra"></a>7. Linear Algebra</h2>
+
+<p>See the documentation of the linear algebra package {@link org.apache.mahout.math.matrix.linalg}.</p>
+
+<p><a href="#Overview">Back</a> to Overview </p>
+
+<h2><a name="PackageOrganization"></a>8. Package Organization, Naming Conventions,
+  Policies</h2>
+<h4>Class Naming / Inheritance</h4>
+
+<p>Have a look at the javadoc <a href="package-tree.html">tree view</a> to get
+  the broad picture. The classes for matrices of a given rank are derived from
+  a common abstract base class named <tt>&lt;ValueType&gt;Matrix&lt;Rank&gt;D</tt>,
+  which is in many ways equivalent to an &quot;interface&quot;. <b>99% of the
+    time you will operate on these abstract classes only</b>. For example, all 2-dimensional
+  matrices operating on <tt>double</tt> values are derived from {@link org.apache.mahout.math.matrix.DoubleMatrix2D}.
+  This is the interface to operate on.</p>
+
+<p>Class naming for concrete instantiable classes follows the schema <tt>&lt;Property&gt;&lt;ValueType&gt;Matrix&lt;Rank&gt;D</tt>.
+  For example, we have a {@link org.apache.mahout.math.matrix.impl.DenseDoubleMatrix2D}, a
+  {@link org.apache.mahout.math.matrix.impl.SparseDoubleMatrix2D}, a {@link
+  impl.DenseIntMatrix3D},
+  and so on. All concrete instantiable classes are separated into an extra package,
+  {@link org.apache.mahout.math.matrix.impl}, to clearly distinguish between interfaces and
+  implementations.</p>
+
+<p>{@link org.apache.mahout.math.matrix.DoubleMatrix2D} in turn is derived from an abstract
+  base class tying together all 2-dimensional matrices regardless of value type,
+  {@link org.apache.mahout.math.matrix.impl.AbstractMatrix2D}, which finally is rooted in grandmother
+  {@link org.apache.mahout.math.matrix.impl.AbstractMatrix}.</p>
+
+<p>The abstract base classes provide skeleton implementations for all but few
+  methods. Experimental data layouts can easily be implemented and inherit a rich
+  set of functionality. For example, to implement a fully functional 2-d or 3-d
+  matrix, only 6 abstract methods need to be overridden: <tt>getQuick, setQuick,
+    like, like1D, viewSelectionLike</tt>.</p>
+<h4>Method Naming</h4>
+
+<p>In order to improve browsing and better keep an overview, the namespace of
+  logically related operations is localized: Methods getting and setting individual
+  cell values are named <tt>get</tt> and <tt>set</tt>. Methods constructing views
+  are named <tt>viewXXX</tt> (e.g. <tt>viewPart</tt>). Copying/assignment methods
+  are named <tt>copy</tt> and <tt>assignXXX</tt>. Mathematical operations are
+  named <tt>zXXX</tt> (e.g. <tt>zMult</tt>). Generic aggregation operations are
+  named <tt>aggregateXXX</tt>.</p>
+<h4>Convenience Methods</h4>
+
+<p>To keep interfaces lean and manageable, we tried to avoid littering them with
+  convenience methods obfuscating more fundamental concepts. Convenience operations
+  expressible in one to three lines of code are omitted. For example, all operations
+  modifying cell values modify the receiver (<tt>this</tt>) itself. There are
+  no methods to fill results into empty result matrices. Use idioms like <tt>result
+    = matrix.copy().mult(5)</tt> to achieve the same functionality. Some convenience
+  methods are provided in the factory classes as well as in external packages
+  like {@link org.apache.mahout.math.matrix.doublealgo}.</p>
+
+<p><a href="#Overview">Back</a> to Overview
+
+<h2><a name="Performance"></a>9. Performance</h2>
+
+<p>The following statements apply to all currently implemented features (i.e.
+  dense and sparse matrices including all view kinds), except where indicated.</p>
+
+<p> Constant factors are kept as small as possible.Views are constructed in guaranteed
+  <tt>O(1)</tt>, i.e. constant time, except for selection views and sort views:
+  Selection views take time linear in the number of indexes, sort views take <tt>O(N*logN)</tt>
+  on average. Getting/setting a cell value takes <i>guaranteed </i>constant time
+  for <font color="#CC0000">dense</font> matrices (and all their views), while
+  it takes <i>expected</i> constant time for sparse hash matrices (and all their
+  views). More specifically, on <font color="#CC0000">sparse hash</font> matrices,
+  these operations can, although highly improbable, degenerate to time linear
+  in the number of non-zero cells. This is because of the nature of hashing: Average
+  case behaviour is extremely good, worst case behaviour is bad. </p>
+
+<p><font color="#CE0000">Sparse row compressed</font> matrices have the following
+  characteristics: Getting a cell value takes time<tt> O(log nzr)</tt> where <tt>nzr</tt>
+  is the number of non-zeros of the touched row. This is usually quick, because
+  typically there are only few nonzeros per row. So, in practice, get has <i>expected</i>
+  constant time. Setting a cell value takes <i> </i>worst-case time <tt>O(nz)</tt>
+  where <tt>nzr</tt> is the total number of non-zeros in the matrix. This can
+  be extremely slow, but if you traverse coordinates properly, each write is done
+  much quicker. For how to do this and other tips, see the <a href="doc-files/performanceNotes.html">performance
+    notes</a>. <img src="../doc-files/new.gif" width="32" height="22" align="middle">
+</p>
+
+<p></p>
+
+<p>Some preliminary benchmarks can be found in the <a href="doc-files/PerformanceLogFrame.html">performance
+  log</a>.</p>
+
+<p>All matrices use strided 32-bit integer arithmetic for linear cell addressing,
+  similar to Fortran. The chosen cell addressing implementation is the key feature
+  enabling the easy implementation and good performance of advanced views.</p>
+
+<p>All methods are bounds checking, except for trusting variants of <tt>get</tt>
+  and <tt>set</tt> called <tt>getQuick</tt> and <tt>setQuick</tt> which should
+  and are used in expensive (often cubic) loops where it is dramatically cheaper
+  to check bounds before entering the loop, not in the loop. Fundamentally time
+  critical methods of dense matrices override default implementations such that
+  iteration eliminates function calls, minimizes cell addressing overhead and
+  gets pipelined. Some operations use processor cache oriented optimization techniques
+  such as memory layout aware iteration, blocking of slow changing operands followed
+  by logical optimizations such as sparsity detection.</p>
+
+<p>In order to eliminate expensive call chains, views directly point to the data
+  without indirection, no matter how deeply nested they are. In particular they
+  are not implemented with delegation. In fact they are not nested at all, even
+  if they logically appear like that. There is largely no distinction between
+  views and non-views. Note that this is not true for row-compressed matrices;
+  their views are wrappers and do use delegation (aka call chains). <img src="../doc-files/new.gif" width="32"
+                                                                         height="22" align="top"></p>
+
+<p>Although view objects occupy only a couple of bytes, generating temporary views
+  at very high frequency can lead to heavy garbage collection. </p>
+
+<p>To keep the overhead minimal, copying operations are highly optimized. They
+  sometimes boil down to <tt>System.arraycopy</tt> (which is nothing else than
+  a byte-aligned C <tt>memmove</tt>). Also note that memory access patterns (cache
+  locality) of self-modifying matrix operations are better than for result matrix
+  modifying operations.</p>
+
+<p><a href="#Overview">Back</a> to Overview
+
+<h2></h2>
+
+<h2><a name="Notes"></a>10. Notes </h2>
+
+<h2></h2>
+
+<p>Matrices are not dynamically resizable; it is impossible to physically insert
+  or remove cells. Some logical cell removal and insertion can be achieved by
+  means of views. To achieve physical cell removal or insertion, a new matrix
+  with the needed shape must be constructed and cells copied. Note, however, that
+  there are convenience methods to do many kind of resizing operations.</p>
+
+<p>Another current limitation is the inability to address more than 2<sup>31</sup>
+  cells. This can be a problem for very large sparse matrices. 64-bit addressing
+  is possible, but unlikely to be implemented unless there is serious demand.</p>
+
+<p><a href="#Overview">Back</a> to Overview</p>
+</BODY>
+</HTML>

Propchange: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/matrix/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/package.html
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/package.html?rev=891983&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/package.html (added)
+++ lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/package.html Thu Dec 17 23:22:16 2009
@@ -0,0 +1,5 @@
+<HTML>
+<BODY>
+Core base classes; Operations on primitive arrays such as sorting, partitioning and permuting.
+</BODY>
+</HTML>

Propchange: lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/GenericSortingTest.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/GenericSortingTest.java?rev=891983&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/GenericSortingTest.java (added)
+++ lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/GenericSortingTest.java Thu Dec 17 23:22:16 2009
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.math;
+
+import org.apache.mahout.math.GenericSorting;
+import org.apache.mahout.math.Swapper;
+import org.apache.mahout.math.function.IntComparator;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GenericSortingTest extends Assert {
+
+	private static class SomethingToSort implements Swapper, IntComparator {
+		private final int[] data;
+
+		private SomethingToSort(int[] data) {
+			this.data = data;
+		}
+
+		@Override
+		public void swap(int a, int b) {
+			int temp = data[a];
+			data[a] = data[b];
+			data[b] = temp;
+		}
+
+		@Override
+		public int compare(int o1, int o2) {
+			if (data[o1] < data[o2]) {
+				return -1;
+			} else if (data[o1] > data[o2]) {
+				return 1;
+			} else {
+				return 0;
+			}
+		}
+	}
+
+	@Test
+	public void testQuickSort() {
+		int[] td = new int[20];
+		for (int x = 0; x < 20; x ++) {
+			td[x] = 20 - x;
+		}
+		SomethingToSort sts = new SomethingToSort(td);
+		GenericSorting.quickSort(0, 20, sts, sts);
+		for (int x = 0; x < 20; x ++) {
+			assertEquals(x+1, td[x]);
+		}
+	}
+
+	private static class SomethingToSortStable implements Swapper, IntComparator {
+		private final String[] data;
+
+		private SomethingToSortStable(String[] data) {
+			this.data = data;
+		}
+
+		@Override
+		public void swap(int a, int b) {
+			String temp = data[a];
+			data[a] = data[b];
+			data[b] = temp;
+		}
+
+		@Override
+		public int compare(int o1, int o2) {
+			return data[o1].compareTo(data[o2]);
+		}
+	}
+
+	@Test
+	public void testMergeSort() {
+		String[] sd = {new String("z"), new String("a"), new String("a"), new String("q"), new String("1")};
+		String[] correct = {sd[4], sd[1], sd[2], sd[3], sd[0]};
+
+		SomethingToSortStable sts = new SomethingToSortStable(sd);
+		GenericSorting.mergeSort(0, 5, sts, sts);
+
+		for (int x = 0; x < 5; x ++) {
+      assertSame(correct[x], sd[x]);
+		}
+	}
+}

Propchange: lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/GenericSortingTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/MatrixTest.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/MatrixTest.java?rev=891983&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/MatrixTest.java (added)
+++ lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/MatrixTest.java Thu Dec 17 23:22:16 2009
@@ -0,0 +1,664 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.math;
+
+import junit.framework.TestCase;
+import org.apache.hadoop.io.DataOutputBuffer;
+import org.apache.mahout.math.AbstractMatrix;
+import org.apache.mahout.math.CardinalityException;
+import org.apache.mahout.math.DenseMatrix;
+import org.apache.mahout.math.DenseVector;
+import org.apache.mahout.math.IndexException;
+import org.apache.mahout.math.Matrix;
+import org.apache.mahout.math.NegateFunction;
+import org.apache.mahout.math.PlusFunction;
+import org.apache.mahout.math.UnboundLabelException;
+import org.apache.mahout.math.Vector;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class MatrixTest extends TestCase {
+
+  protected static final int ROW = AbstractMatrix.ROW;
+
+  protected static final int COL = AbstractMatrix.COL;
+
+  protected final double[][] values = {{1.1, 2.2}, {3.3, 4.4},
+      {5.5, 6.6}};
+
+  protected final double[] vectorAValues = {1.0 / 1.1, 2.0 / 1.1};
+
+  protected final double[] vectorBValues = {5.0, 10.0, 100.0};
+
+  protected Matrix test;
+
+  protected MatrixTest(String name) {
+    super(name);
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    test = matrixFactory(values);
+  }
+
+  public abstract Matrix matrixFactory(double[][] values);
+
+  public void testCardinality() {
+    int[] c = test.size();
+    assertEquals("row cardinality", values.length, c[ROW]);
+    assertEquals("col cardinality", values[0].length, c[COL]);
+  }
+
+  public void testCopy() {
+    int[] c = test.size();
+    Matrix copy = test.clone();
+    assertEquals("wrong class", copy.getClass(), test.getClass());
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']',
+            test.getQuick(row, col), copy.getQuick(row, col));
+      }
+    }
+  }
+
+  public void testGetQuick() {
+    int[] c = test.size();
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']', values[row][col], test
+            .getQuick(row, col));
+      }
+    }
+  }
+
+  public void testHaveSharedCells() {
+    assertTrue("same", test.haveSharedCells(test));
+    assertFalse("different", test.haveSharedCells(test.clone()));
+  }
+
+  public void testLike() {
+    Matrix like = test.like();
+    assertEquals("type", like.getClass(), test.getClass());
+    assertEquals("rows", test.size()[ROW], like.size()[ROW]);
+    assertEquals("columns", test.size()[COL], like.size()[COL]);
+  }
+
+  public void testLikeIntInt() {
+    Matrix like = test.like(4, 4);
+    assertEquals("type", like.getClass(), test.getClass());
+    assertEquals("rows", 4, like.size()[ROW]);
+    assertEquals("columns", 4, like.size()[COL]);
+  }
+
+  public void testSetQuick() {
+    int[] c = test.size();
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        test.setQuick(row, col, 1.23);
+        assertEquals("value[" + row + "][" + col + ']', 1.23, test.getQuick(
+            row, col));
+      }
+    }
+  }
+
+  public void testSize() {
+    int[] c = test.getNumNondefaultElements();
+    assertEquals("row size", values.length, c[ROW]);
+    assertEquals("col size", values[0].length, c[COL]);
+  }
+
+  public void testViewPart() {
+    int[] offset = {1, 1};
+    int[] size = {2, 1};
+    Matrix view = test.viewPart(offset, size);
+    int[] c = view.size();
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']',
+            values[row + 1][col + 1], view.getQuick(row, col));
+      }
+    }
+  }
+
+  public void testViewPartCardinality() {
+    int[] offset = {1, 1};
+    int[] size = {3, 3};
+    try {
+      test.viewPart(offset, size);
+      fail("exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    } catch (IndexException e) {
+      fail("cardinality exception expected");
+    }
+  }
+
+  public void testViewPartIndexOver() {
+    int[] offset = {1, 1};
+    int[] size = {2, 2};
+    try {
+      test.viewPart(offset, size);
+      fail("exception expected");
+    } catch (CardinalityException e) {
+      fail("index exception expected");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testViewPartIndexUnder() {
+    int[] offset = {-1, -1};
+    int[] size = {2, 2};
+    try {
+      test.viewPart(offset, size);
+      fail("exception expected");
+    } catch (CardinalityException e) {
+      fail("index exception expected");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testAssignDouble() {
+    int[] c = test.size();
+    test.assign(4.53);
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']', 4.53, test.getQuick(
+            row, col));
+      }
+    }
+  }
+
+  public void testAssignDoubleArrayArray() {
+    int[] c = test.size();
+    test.assign(new double[3][2]);
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']', 0.0, test.getQuick(row,
+            col));
+      }
+    }
+  }
+
+  public void testAssignDoubleArrayArrayCardinality() {
+    int[] c = test.size();
+    try {
+      test.assign(new double[c[ROW] + 1][c[COL]]);
+      fail("exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testAssignMatrixBinaryFunction() {
+    int[] c = test.size();
+    test.assign(test, new PlusFunction());
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']', 2 * values[row][col],
+            test.getQuick(row, col));
+      }
+    }
+  }
+
+  public void testAssignMatrixBinaryFunctionCardinality() {
+    try {
+      test.assign(test.transpose(), new PlusFunction());
+      fail("exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testAssignMatrix() {
+    int[] c = test.size();
+    Matrix value = test.like();
+    value.assign(test);
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']',
+            test.getQuick(row, col), value.getQuick(row, col));
+      }
+    }
+  }
+
+  public void testAssignMatrixCardinality() {
+    try {
+      test.assign(test.transpose());
+      fail("exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testAssignUnaryFunction() {
+    int[] c = test.size();
+    test.assign(new NegateFunction());
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']', -values[row][col], test
+            .getQuick(row, col));
+      }
+    }
+  }
+
+  public void testDivide() {
+    int[] c = test.size();
+    Matrix value = test.divide(4.53);
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']',
+            values[row][col] / 4.53, value.getQuick(row, col));
+      }
+    }
+  }
+
+  public void testGet() {
+    int[] c = test.size();
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']', values[row][col], test
+            .get(row, col));
+      }
+    }
+  }
+
+  public void testGetIndexUnder() {
+    int[] c = test.size();
+    try {
+      for (int row = -1; row < c[ROW]; row++) {
+        for (int col = 0; col < c[COL]; col++) {
+          test.get(row, col);
+        }
+      }
+      fail("index exception expected");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testGetIndexOver() {
+    int[] c = test.size();
+    try {
+      for (int row = 0; row < c[ROW] + 1; row++) {
+        for (int col = 0; col < c[COL]; col++) {
+          test.get(row, col);
+        }
+      }
+      fail("index exception expected");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testMinus() {
+    int[] c = test.size();
+    Matrix value = test.minus(test);
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']', 0.0, value.getQuick(
+            row, col));
+      }
+    }
+  }
+
+  public void testMinusCardinality() {
+    try {
+      test.minus(test.transpose());
+      fail("cardinality exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testPlusDouble() {
+    int[] c = test.size();
+    Matrix value = test.plus(4.53);
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']',
+            values[row][col] + 4.53, value.getQuick(row, col));
+      }
+    }
+  }
+
+  public void testPlusMatrix() {
+    int[] c = test.size();
+    Matrix value = test.plus(test);
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']', values[row][col] * 2,
+            value.getQuick(row, col));
+      }
+    }
+  }
+
+  public void testPlusMatrixCardinality() {
+    try {
+      test.plus(test.transpose());
+      fail("cardinality exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testSetUnder() {
+    int[] c = test.size();
+    try {
+      for (int row = -1; row < c[ROW]; row++) {
+        for (int col = 0; col < c[COL]; col++) {
+          test.set(row, col, 1.23);
+        }
+      }
+      fail("index exception expected");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testSetOver() {
+    int[] c = test.size();
+    try {
+      for (int row = 0; row < c[ROW] + 1; row++) {
+        for (int col = 0; col < c[COL]; col++) {
+          test.set(row, col, 1.23);
+        }
+      }
+      fail("index exception expected");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testTimesDouble() {
+    int[] c = test.size();
+    Matrix value = test.times(4.53);
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']',
+            values[row][col] * 4.53, value.getQuick(row, col));
+      }
+    }
+  }
+
+  public void testTimesMatrix() {
+    int[] c = test.size();
+    Matrix transpose = test.transpose();
+    Matrix value = test.times(transpose);
+    int[] v = value.size();
+    assertEquals("rows", c[ROW], v[ROW]);
+    assertEquals("cols", c[ROW], v[COL]);
+
+    Matrix expected = new DenseMatrix(new double[][]{{5.0, 11.0, 17.0},
+        {11.0, 25.0, 39.0}, {17.0, 39.0, 61.0}}).times(1.21);
+
+    for (int i = 0; i < expected.numCols(); i++) {
+      for (int j = 0; j < expected.numRows(); j++) {
+        assertTrue("Matrix times transpose not correct: " + i + ", " + j
+            + "\nexpected:\n\t" + expected.asFormatString() + "\nactual:\n\t"
+            + value.asFormatString(),
+            Math.abs(expected.get(i, j) - value.get(i, j)) < 1e-12);
+      }
+    }
+
+    Matrix timestest = new DenseMatrix(10, 1);
+    /* will throw ArrayIndexOutOfBoundsException exception without MAHOUT-26 */
+    timestest.transpose().times(timestest);
+  }
+
+  public void testTimesVector() {
+    Vector vectorA = new DenseVector(vectorAValues);
+    Vector testTimesVectorA = test.times(vectorA);
+    Vector expected = new DenseVector(new double[]{5.0, 11.0, 17.0});
+    assertTrue("Matrix times vector not equals: " + vectorA.asFormatString()
+        + " != " + testTimesVectorA.asFormatString(),
+        expected.minus(testTimesVectorA).norm(2) < 1e-12);
+    try {
+      test.times(testTimesVectorA);
+      fail("Cardinalities do not match, should throw exception");
+    } catch (CardinalityException ce) {
+      assertTrue(true);
+    }
+  }
+
+  public void testTimesSquaredTimesVector() {
+    Vector vectorA = new DenseVector(vectorAValues);
+    Vector ttA = test.timesSquared(vectorA);
+    Vector ttASlow = test.transpose().times(test.times(vectorA));
+    assertTrue("M'Mv != M.timesSquared(v): " + ttA.asFormatString()
+        + " != " + ttASlow.asFormatString(),
+        ttASlow.minus(ttA).norm(2) < 1e-12);
+
+  }
+
+  public void testTimesMatrixCardinality() {
+    Matrix other = test.like(5, 8);
+    try {
+      test.times(other);
+      fail("cardinality exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testTranspose() {
+    int[] c = test.size();
+    Matrix transpose = test.transpose();
+    int[] t = transpose.size();
+    assertEquals("rows", c[COL], t[ROW]);
+    assertEquals("cols", c[ROW], t[COL]);
+    for (int row = 0; row < c[ROW]; row++) {
+      for (int col = 0; col < c[COL]; col++) {
+        assertEquals("value[" + row + "][" + col + ']',
+            test.getQuick(row, col), transpose.getQuick(col, row));
+      }
+    }
+  }
+
+  public void testZSum() {
+    double sum = test.zSum();
+    assertEquals("zsum", 23.1, sum);
+  }
+
+  public void testAssignRow() {
+    double[] data = {2.1, 3.2};
+    test.assignRow(1, new DenseVector(data));
+    assertEquals("test[1][0]", 2.1, test.getQuick(1, 0));
+    assertEquals("test[1][1]", 3.2, test.getQuick(1, 1));
+  }
+
+  public void testAssignRowCardinality() {
+    double[] data = {2.1, 3.2, 4.3};
+    try {
+      test.assignRow(1, new DenseVector(data));
+      fail("expecting cardinality exception");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testAssignColumn() {
+    double[] data = {2.1, 3.2, 4.3};
+    test.assignColumn(1, new DenseVector(data));
+    assertEquals("test[0][1]", 2.1, test.getQuick(0, 1));
+    assertEquals("test[1][1]", 3.2, test.getQuick(1, 1));
+    assertEquals("test[2][1]", 4.3, test.getQuick(2, 1));
+  }
+
+  public void testAssignColumnCardinality() {
+    double[] data = {2.1, 3.2};
+    try {
+      test.assignColumn(1, new DenseVector(data));
+      fail("expecting cardinality exception");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testGetRow() {
+    Vector row = test.getRow(1);
+    assertEquals("row size", 2, row.getNumNondefaultElements());
+  }
+
+  public void testGetRowIndexUnder() {
+    try {
+      test.getRow(-1);
+      fail("expecting index exception");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testGetRowIndexOver() {
+    try {
+      test.getRow(5);
+      fail("expecting index exception");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testGetColumn() {
+    Vector column = test.getColumn(1);
+    assertEquals("row size", 3, column.getNumNondefaultElements());
+  }
+
+  public void testGetColumnIndexUnder() {
+    try {
+      test.getColumn(-1);
+      fail("expecting index exception");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testGetColumnIndexOver() {
+    try {
+      test.getColumn(5);
+      fail("expecting index exception");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testDetermitant() {
+    Matrix m = matrixFactory(new double[][]{{1, 3, 4}, {5, 2, 3},
+        {1, 4, 2}});
+    assertEquals("determinant", 43.0, m.determinant());
+  }
+
+  public void testAsFormatString() {
+    String string = test.asFormatString();
+    int[] cardinality = {values.length, values[0].length};
+    Matrix m = AbstractMatrix.decodeMatrix(string);
+    for (int row = 0; row < cardinality[ROW]; row++) {
+      for (int col = 0; col < cardinality[COL]; col++) {
+        assertEquals("m[" + row + ',' + col + ']', test.get(row, col), m.get(
+            row, col));
+      }
+    }
+  }
+
+  public void testLabelBindings() {
+    Matrix m = matrixFactory(new double[][]{{1, 3, 4}, {5, 2, 3},
+        {1, 4, 2}});
+    assertNull("row bindings", m.getRowLabelBindings());
+    assertNull("col bindings", m.getColumnLabelBindings());
+    Map<String, Integer> rowBindings = new HashMap<String, Integer>();
+    rowBindings.put("Fee", 0);
+    rowBindings.put("Fie", 1);
+    rowBindings.put("Foe", 2);
+    m.setRowLabelBindings(rowBindings);
+    assertEquals("row", rowBindings, m.getRowLabelBindings());
+    Map<String, Integer> colBindings = new HashMap<String, Integer>();
+    colBindings.put("Foo", 0);
+    colBindings.put("Bar", 1);
+    colBindings.put("Baz", 2);
+    m.setColumnLabelBindings(colBindings);
+    assertEquals("row", rowBindings, m.getRowLabelBindings());
+    assertEquals("Fee", m.get(0, 1), m.get("Fee", "Bar"));
+
+    double[] newrow = {9, 8, 7};
+    m.set("Foe", newrow);
+    assertEquals("FeeBaz", m.get(0, 2), m.get("Fee", "Baz"));
+  }
+
+  public void testSettingLabelBindings() {
+    Matrix m = matrixFactory(new double[][]{{1, 3, 4}, {5, 2, 3},
+        {1, 4, 2}});
+    assertNull("row bindings", m.getRowLabelBindings());
+    assertNull("col bindings", m.getColumnLabelBindings());
+    m.set("Fee", "Foo", 1, 2, 9);
+    assertNotNull("row", m.getRowLabelBindings());
+    assertNotNull("row", m.getRowLabelBindings());
+    assertEquals("Fee", 1, m.getRowLabelBindings().get("Fee").intValue());
+    assertEquals("Fee", 2, m.getColumnLabelBindings().get("Foo").intValue());
+    assertEquals("FeeFoo", m.get(1, 2), m.get("Fee", "Foo"));
+    try {
+      m.get("Fie", "Foe");
+      fail("Expected UnboundLabelException");
+    } catch (IndexException e) {
+      fail("Expected UnboundLabelException");
+    } catch (UnboundLabelException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testLabelBindingSerialization() {
+    Matrix m = matrixFactory(new double[][]{{1, 3, 4}, {5, 2, 3},
+        {1, 4, 2}});
+    assertNull("row bindings", m.getRowLabelBindings());
+    assertNull("col bindings", m.getColumnLabelBindings());
+    Map<String, Integer> rowBindings = new HashMap<String, Integer>();
+    rowBindings.put("Fee", 0);
+    rowBindings.put("Fie", 1);
+    rowBindings.put("Foe", 2);
+    m.setRowLabelBindings(rowBindings);
+    assertEquals("row", rowBindings, m.getRowLabelBindings());
+    Map<String, Integer> colBindings = new HashMap<String, Integer>();
+    colBindings.put("Foo", 0);
+    colBindings.put("Bar", 1);
+    colBindings.put("Baz", 2);
+    m.setColumnLabelBindings(colBindings);
+    String json = m.asFormatString();
+    Matrix mm = AbstractMatrix.decodeMatrix(json);
+    assertEquals("Fee", m.get(0, 1), mm.get("Fee", "Bar"));
+  }
+
+  public void testMatrixWritable() throws IOException {
+    Matrix m = matrixFactory(new double[][]{{1, 3, 4}, {5, 2, 3},
+        {1, 4, 2}});
+    DataOutputBuffer out = new DataOutputBuffer();
+    m.write(out);
+    out.close();
+
+    DataInputStream in = new DataInputStream(new ByteArrayInputStream(out
+        .getData()));
+    Matrix m2 = m.like();
+    m2.readFields(in);
+    in.close();
+    assertEquals("row size", m.size()[ROW], m2.size()[ROW]);
+    assertEquals("col size", m.size()[COL], m2.size()[COL]);
+  }
+}

Propchange: lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/MatrixTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseMatrix.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseMatrix.java?rev=891983&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseMatrix.java (added)
+++ lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseMatrix.java Thu Dec 17 23:22:16 2009
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.math;
+
+import org.apache.mahout.math.DenseMatrix;
+import org.apache.mahout.math.Matrix;
+
+public class TestDenseMatrix extends MatrixTest {
+
+  public TestDenseMatrix(String name) {
+    super(name);
+  }
+
+  @Override
+  public Matrix matrixFactory(double[][] values) {
+    return new DenseMatrix(values);
+  }
+
+}

Propchange: lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseMatrix.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseVector.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseVector.java?rev=891983&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseVector.java (added)
+++ lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseVector.java Thu Dec 17 23:22:16 2009
@@ -0,0 +1,426 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.math;
+
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.mahout.math.AbstractVector;
+import org.apache.mahout.math.CardinalityException;
+import org.apache.mahout.math.DenseVector;
+import org.apache.mahout.math.IndexException;
+import org.apache.mahout.math.Matrix;
+import org.apache.mahout.math.NegateFunction;
+import org.apache.mahout.math.PlusFunction;
+import org.apache.mahout.math.TimesFunction;
+import org.apache.mahout.math.Vector;
+
+public class TestDenseVector extends TestCase {
+
+  final double[] values = {1.1, 2.2, 3.3};
+
+  final Vector test = new DenseVector(values);
+
+  public TestDenseVector(String name) {
+    super(name);
+  }
+
+  public void testAsFormatString() {
+    String formatString = test.asFormatString();
+    Vector vec = AbstractVector.decodeVector(formatString);
+    assertEquals(vec, test);
+  }
+
+  public void testCardinality() {
+    assertEquals("cardinality", 3, test.size());
+  }
+
+  public void testCopy() throws Exception {
+    Vector copy = test.clone();
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("copy [" + i + ']', test.get(i), copy.get(i));
+    }
+  }
+
+  public void testGet() throws Exception {
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("get [" + i + ']', values[i], test.get(i));
+    }
+  }
+
+  public void testGetOver() {
+    try {
+      test.get(test.size());
+      fail("expected exception");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testGetUnder() {
+    try {
+      test.get(-1);
+      fail("expected exception");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testSet() throws Exception {
+    test.set(2, 4.5);
+    for (int i = 0; i < test.size(); i++) {
+      if (i == 2) {
+        assertEquals("set [" + i + ']', 4.5, test.get(i));
+      } else {
+        assertEquals("set [" + i + ']', values[i], test.get(i));
+      }
+    }
+  }
+
+
+  public void testIterator() throws Exception {
+    Iterator<Vector.Element> iterator = test.iterateNonZero();
+    checkIterator(iterator, values, 3);
+
+    iterator = test.iterateAll();
+    checkIterator(iterator, values, 3);
+
+    double[] doubles = {0.0, 5.0, 0, 3.0};
+    DenseVector zeros = new DenseVector(doubles);
+    iterator = zeros.iterateNonZero();
+    checkIterator(iterator, doubles, 2);
+    iterator = zeros.iterateAll();
+    checkIterator(iterator, doubles, doubles.length);
+
+    doubles = new double[]{0.0, 0.0, 0, 0.0};
+    zeros = new DenseVector(doubles);
+    iterator = zeros.iterateNonZero();
+    checkIterator(iterator, doubles, 0);
+    iterator = zeros.iterateAll();
+    checkIterator(iterator, doubles, doubles.length);
+
+  }
+
+  private static void checkIterator(Iterator<Vector.Element> nzIter, double[] values, int expectedNum) {
+    int i = 0;
+    while (nzIter.hasNext()) {
+      Vector.Element elt = nzIter.next();
+      assertEquals((elt.index()) + " Value: " + values[elt.index()] + " does not equal: " + elt.get(),
+          values[elt.index()], elt.get(), 0.0);
+      i++;
+    }
+    assertEquals(i + " does not equal: " + expectedNum, i, expectedNum);
+  }
+
+  public void testSize() throws Exception {
+    assertEquals("size", 3, test.getNumNondefaultElements());
+  }
+
+  public void testViewPart() throws Exception {
+    Vector part = test.viewPart(1, 2);
+    assertEquals("part size", 2, part.getNumNondefaultElements());
+    for (int i = 0; i < part.size(); i++) {
+      assertEquals("part[" + i + ']', values[i + 1], part.get(i));
+    }
+  }
+
+  public void testViewPartUnder() {
+    try {
+      test.viewPart(-1, values.length);
+      fail("no exception");
+    } catch (CardinalityException e) {
+      fail("wrong exception");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testViewPartOver() {
+    try {
+      test.viewPart(2, values.length);
+      fail("no exception");
+    } catch (CardinalityException e) {
+      fail("wrong exception");
+    } catch (IndexException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testViewPartCardinality() {
+    try {
+      test.viewPart(1, values.length + 1);
+      fail("no exception");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    } catch (IndexException e) {
+      fail("wrong exception");
+    }
+  }
+
+  public void testDecodeVector() throws Exception {
+    Vector val = AbstractVector.decodeVector(test.asFormatString());
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("get [" + i + ']', test.get(i), val.get(i));
+    }
+  }
+
+  public void testDenseVectorDoubleArray() throws Exception {
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("test[" + i + ']', values[i], test.get(i));
+    }
+  }
+
+  public void testDenseVectorInt() throws Exception {
+    Vector val = new DenseVector(4);
+    assertEquals("cardinality", 4, val.size());
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("get [" + i + ']', 0.0, val.get(i));
+    }
+  }
+
+  public void testDot() throws Exception {
+    double res = test.dot(test);
+    assertEquals("dot", 1.1 * 1.1 + 2.2 * 2.2 + 3.3 * 3.3, res);
+  }
+
+  public void testDotCardinality() {
+    try {
+      test.dot(new DenseVector(test.size() + 1));
+      fail("expected exception");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testNormalize() throws Exception {
+    Vector res = test.normalize();
+    double mag = Math.sqrt(1.1 * 1.1 + 2.2 * 2.2 + 3.3 * 3.3);
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("dot", values[i] / mag, res.get(i));
+    }
+  }
+
+  public void testMinus() throws Exception {
+    Vector val = test.minus(test);
+    assertEquals("cardinality", 3, val.size());
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("get [" + i + ']', 0.0, val.get(i));
+    }
+  }
+
+  public void testPlusDouble() throws Exception {
+    Vector val = test.plus(1);
+    assertEquals("cardinality", 3, val.size());
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("get [" + i + ']', values[i] + 1, val.get(i));
+    }
+  }
+
+  public void testPlusVector() throws Exception {
+    Vector val = test.plus(test);
+    assertEquals("cardinality", 3, val.size());
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("get [" + i + ']', values[i] * 2, val.get(i));
+    }
+  }
+
+  public void testPlusVectorCardinality() {
+    try {
+      test.plus(new DenseVector(test.size() + 1));
+      fail("expected exception");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testTimesDouble() throws Exception {
+    Vector val = test.times(3);
+    assertEquals("cardinality", 3, val.size());
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("get [" + i + ']', values[i] * 3, val.get(i));
+    }
+  }
+
+  public void testDivideDouble() throws Exception {
+    Vector val = test.divide(3);
+    assertEquals("cardinality", 3, val.size());
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("get [" + i + ']', values[i] / 3, val.get(i));
+    }
+  }
+
+  public void testTimesVector() throws Exception {
+    Vector val = test.times(test);
+    assertEquals("cardinality", 3, val.size());
+    for (int i = 0; i < test.size(); i++) {
+      assertEquals("get [" + i + ']', values[i] * values[i], val.get(i));
+    }
+  }
+
+  public void testTimesVectorCardinality() {
+    try {
+      test.times(new DenseVector(test.size() + 1));
+      fail("expected exception");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testZSum() {
+    double expected = 0;
+    for (double value : values) {
+      expected += value;
+    }
+    assertEquals("wrong zSum", expected, test.zSum());
+  }
+
+  public void testAssignDouble() {
+    test.assign(0);
+    for (int i = 0; i < values.length; i++) {
+      assertEquals("value[" + i + ']', 0.0, test.getQuick(i));
+    }
+  }
+
+  public void testAssignDoubleArray() throws Exception {
+    double[] array = new double[test.size()];
+    test.assign(array);
+    for (int i = 0; i < values.length; i++) {
+      assertEquals("value[" + i + ']', 0.0, test.getQuick(i));
+    }
+  }
+
+  public void testAssignDoubleArrayCardinality() {
+    double[] array = new double[test.size() + 1];
+    try {
+      test.assign(array);
+      fail("cardinality exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testAssignVector() throws Exception {
+    Vector other = new DenseVector(test.size());
+    test.assign(other);
+    for (int i = 0; i < values.length; i++) {
+      assertEquals("value[" + i + ']', 0.0, test.getQuick(i));
+    }
+  }
+
+  public void testAssignVectorCardinality() {
+    Vector other = new DenseVector(test.size() - 1);
+    try {
+      test.assign(other);
+      fail("cardinality exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testAssignUnaryFunction() {
+    test.assign(new NegateFunction());
+    for (int i = 0; i < values.length; i++) {
+      assertEquals("value[" + i + ']', -values[i], test.getQuick(i));
+    }
+  }
+
+  public void testAssignBinaryFunction() throws Exception {
+    test.assign(test, new PlusFunction());
+    for (int i = 0; i < values.length; i++) {
+      assertEquals("value[" + i + ']', 2 * values[i], test.getQuick(i));
+    }
+  }
+
+  public void testAssignBinaryFunction2() throws Exception {
+    test.assign(new PlusFunction(), 4);
+    for (int i = 0; i < values.length; i++) {
+      assertEquals("value[" + i + ']', values[i] + 4, test.getQuick(i));
+    }
+  }
+
+  public void testAssignBinaryFunction3() throws Exception {
+    test.assign(new TimesFunction(), 4);
+    for (int i = 0; i < values.length; i++) {
+      assertEquals("value[" + i + ']', values[i] * 4, test.getQuick(i));
+    }
+  }
+
+  public void testAssignBinaryFunctionCardinality() {
+    try {
+      test.assign(test.like(2), new PlusFunction());
+      fail("Cardinality exception expected");
+    } catch (CardinalityException e) {
+      assertTrue(true);
+    }
+  }
+
+  public void testThisHaveSharedCells() throws Exception {
+    assertTrue("test not shared?", test.haveSharedCells(test));
+  }
+
+  public void testViewHaveSharedCells() throws Exception {
+    Vector view = test.viewPart(1, 2);
+    assertTrue("view not shared?", view.haveSharedCells(test));
+    assertTrue("test not shared?", test.haveSharedCells(view));
+  }
+
+  public void testViewsHaveSharedCells() throws Exception {
+    Vector view1 = test.viewPart(0, 2);
+    Vector view2 = test.viewPart(1, 2);
+    assertTrue("view1 not shared?", view1.haveSharedCells(view2));
+    assertTrue("view2 not shared?", view2.haveSharedCells(view1));
+  }
+
+  public void testLike() {
+    assertTrue("not like", test.like() instanceof DenseVector);
+  }
+
+  public void testLikeN() {
+    Vector other = test.like(5);
+    assertTrue("not like", other instanceof DenseVector);
+    assertEquals("size", 5, other.size());
+  }
+
+  public void testCrossProduct() {
+    Matrix result = test.cross(test);
+    assertEquals("row size", test.size(), result.size()[0]);
+    assertEquals("col size", test.size(), result.size()[1]);
+    for (int row = 0; row < result.size()[0]; row++) {
+      for (int col = 0; col < result.size()[1]; col++) {
+        assertEquals("cross[" + row + "][" + col + ']', test.getQuick(row)
+            * test.getQuick(col), result.getQuick(row, col));
+      }
+    }
+  }
+
+  public void testLabelIndexing() {
+    Map<String, Integer> bindings = new HashMap<String, Integer>();
+    bindings.put("Fee", 0);
+    bindings.put("Fie", 1);
+    bindings.put("Foe", 2);
+    test.setLabelBindings(bindings);
+    assertEquals("Fee", test.get(0), test.get("Fee"));
+    assertEquals("Fie", test.get(1), test.get("Fie"));
+    assertEquals("Foe", test.get(2), test.get("Foe"));
+    test.set("Fie", 15.3);
+    assertEquals("Fie", test.get(1), test.get("Fie"));
+  }
+}

Propchange: lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/TestDenseVector.java
------------------------------------------------------------------------------
    svn:eol-style = native