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 [26/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/map/package.html
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/map/package.html?rev=883365&view=auto
==============================================================================
--- lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/map/package.html (added)
+++ lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/map/package.html Mon Nov 23 15:14:26 2009
@@ -0,0 +1,290 @@
+<HTML>
+<BODY>
+Automatically growing and shrinking maps holding objects or primitive
+data types such as <tt>int</tt>, <tt>double</tt>, etc. Currently all maps are
+based upon hashing.
+<h2><a name="Overview"></a>1. Overview</h2>
+
+<p>The map package offers flexible object oriented abstractions modelling automatically
+ resizing maps. It is designed to be scalable in terms of performance and memory
+ requirements.</p>
+
+<p>Features include: </p>
+
+<p></p>
+<ul>
+ <li>Maps operating on objects as well as all primitive data types such as <code>int</code>,
+ <code>double</code>, etc.
+ </li>
+ <li>Compact representations</li>
+ <li>Support for quick access to associations</li>
+ <li>A number of general purpose map operations</li>
+</ul>
+<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. It provides data
+ structures and algorithms only.
+
+<p> This toolkit borrows some terminology from the Javasoft <a
+ href="http://www.javasoft.com/products/jdk/1.2/docs/guide/collections/index.html">
+ Collections framework</a> written by Josh Bloch and introduced in JDK 1.2.
+
+<h2>2. Introduction</h2>
+
+<p>A map is an associative container that manages a set of (key,value) pairs.
+ It is useful for implementing a collection of one-to-one mappings. A (key,value)
+ pair is called an <i>association</i>. A value can be looked up up via its key.
+ Associations can quickly be set, removed and retrieved. They are stored in a
+ hashing structure based on the hash code of their keys, which is obtained by
+ using a hash function. </p>
+
+<p> A map can, for example, contain <tt>Name-->Location</tt> associations like
+ <tt>{("Pete", "Geneva"), ("Steve", "Paris"), ("Robert", "New York")}</tt> used
+ in address books or <tt>Index-->Value</tt> mappings like <tt>{(0, 100), (3,
+ 1000), (100000, 70)}</tt> representing sparse lists or matrices. For example
+ this could mean at index 0 we have a value of 100, at index 3 we have a value
+ of 1000, at index 1000000 we have a value of 70, and at all other indexes we
+ have a value of, say, zero. Another example is a map of IP addresses to domain
+ names (DNS). Maps can also be useful to represent<i> multi sets</i>, that is,
+ sets where elements can occur more than once. For multi sets one would have
+ <tt>Value-->Frequency</tt> mappings like <tt>{(100, 1), (50, 1000), (101, 3))}</tt>
+ meaning element 100 occurs 1 time, element 50 occurs 1000 times, element 101
+ occurs 3 times. Further, maps can also manage <tt>ObjectIdentifier-->Object</tt>
+ mappings like <tt>{(12, obj1), (7, obj2), (10000, obj3), (9, obj4)}</tt> used
+ in Object Databases.
+
+<p> A map cannot contain two or more <i>equal</i> keys; a key can map to at most
+ one value. However, more than one key can map to identical values. For primitive
+ data types "equality" of keys is defined as identity (operator <tt>==</tt>).
+ For maps using <tt>Object</tt> keys, the meaning of "equality" can be specified
+ by the user upon instance construction. It can either be defined to be identity
+ (operator <tt>==</tt>) or to be given by the method {@link java.lang.Object#equals(Object)}.
+ Associations of kind <tt>(AnyType,Object)</tt> can be of the form <tt>(AnyKey,null)
+ </tt>, i.e. values can be <tt>null</tt>.
+
+<p> The classes of this package make no guarantees as to the order of the elements
+ returned by iterators; in particular, they do not guarantee that the order will
+ remain constant over time.
+
+<h2></h2>
+<h4>Copying</h4>
+
+<p>
+
+<p>Any map can be copied. A copy is <i>equal</i> to the original but entirely
+ independent of the original. So changes in the copy are not reflected in the
+ original, and vice-versa.
+
+<h2>3. Package organization</h2>
+
+<p>For most primitive data types and for objects there exists a separate map version.
+ All versions are just the same, except that they operate on different data types.
+ Colt includes two kinds of implementations for maps: The two different implementations
+ are tagged <b>Chained</b> and <b>Open</b>.
+ Note: Chained is no more included. Wherever it is mentioned it is of historic interest only.</p>
+<ul>
+ <li><b>Chained</b> uses extendible separate chaining with chains holding unsorted
+ dynamically linked collision lists.
+ <li><b>Open</b> uses extendible open addressing with double hashing.
+</ul>
+<p>Class naming follows the schema <tt><Implementation><KeyType><ValueType>HashMap</tt>.
+ For example, a {@link cern.colt.map.OpenIntDoubleHashMap} holds <tt>(int-->double)</tt>
+ associations and is implemented with open addressing. A {@link cern.colt.map.OpenIntObjectHashMap}
+ holds <tt>(int-->Object)</tt> associations and is implemented with open addressing.
+</p>
+
+<p>The classes for maps of a given (key,value) type are derived from a common
+ abstract base class tagged <tt>Abstract<KeyType><ValueType></tt><tt>Map</tt>.
+ For example, all maps operating on <tt>(int-->double)</tt> associations are
+ derived from {@link cern.colt.map.AbstractIntDoubleMap}, which in turn is derived
+ from an abstract base class tying together all maps regardless of assocation
+ type, {@link cern.colt.map.AbstractMap}. The abstract base classes provide skeleton
+ implementations for all but few methods. Experimental layouts (such as chaining,
+ open addressing, extensible hashing, red-black-trees, etc.) can easily be implemented
+ and inherit a rich set of functionality. Have a look at the javadoc <a href="package-tree.html">tree
+ view</a> to get the broad picture.</p>
+
+<h2>4. Example usage</h2>
+<TABLE>
+ <TD CLASS="PRE">
+ <PRE>
+int[] keys = {0 , 3 , 100000, 9 };
+double[] values = {100.0, 1000.0, 70.0 , 71.0};
+
+AbstractIntDoubleMap map = new OpenIntDoubleHashMap();
+
+// add several associations
+for (int i=0; i < keys.length; i++) map.put(keys[i], values[i]);
+
+System.out.println("map="+map);
+System.out.println("size="+map.size());
+System.out.println(map.containsKey(3));
+System.out.println("get(3)="+map.get(3));
+System.out.println(map.containsKey(4));
+System.out.println("get(4)="+map.get(4));
+System.out.println(map.containsValue(71.0));
+System.out.println("keyOf(71.0)="+map.keyOf(71.0));
+
+// remove one association
+map.removeKey(3);
+System.out.println("\nmap="+map);
+System.out.println(map.containsKey(3));
+System.out.println("get(3)="+map.get(3));
+System.out.println(map.containsValue(1000.0));
+System.out.println("keyOf(1000.0)="+map.keyOf(1000.0));
+
+// clear
+map.clear();
+System.out.println("\nmap="+map);
+System.out.println("size="+map.size());
+</PRE>
+ </TD>
+</TABLE>
+
+yields the following output
+
+<TABLE>
+ <TD CLASS="PRE">
+<PRE>
+map=[0->100.0, 3->1000.0, 9->71.0, 100000->70.0]
+size=4
+true
+get(3)=1000.0
+false
+get(4)=0.0
+true
+keyOf(71.0)=9
+
+map=[0->100.0, 9->71.0, 100000->70.0]
+false
+get(3)=0.0
+false
+keyOf(1000.0)=-2147483648
+
+map=[]
+size=0
+</PRE>
+ </TD>
+</TABLE>
+<h2> 5. Notes </h2>
+
+<p>
+ Note that implementations are not synchronized.
+
+<p>
+ Choosing efficient parameters for hash maps is not always easy.
+ However, since parameters determine efficiency and memory requirements, here is a quick guide how to choose them.
+ If your use case does not heavily operate on hash maps but uses them just because they provide
+ convenient functionality, you can safely skip this section.
+ For those of you who care, read on.
+
+<p>
+
+ There are three parameters that can be customized upon map construction: <tt>initialCapacity</tt>,
+ <tt>minLoadFactor</tt> and <tt>maxLoadFactor</tt>.
+ The more memory one can afford, the faster a hash map.
+ The hash map's capacity is the maximum number of associations that can be added without needing to allocate new
+ internal memory.
+ A larger capacity means faster adding, searching and removing.
+ The <tt>initialCapacity</tt> corresponds to the capacity used upon instance construction.
+
+<p>
+ The <tt>loadFactor</tt> of a hash map measures the degree of "fullness".
+ It is given by the number of assocations (<tt>size()</tt>)
+ divided by the hash map capacity <tt>(0.0 <= loadFactor <= 1.0)</tt>.
+ The more associations are added, the larger the loadFactor and the more hash map performance degrades.
+ Therefore, when the loadFactor exceeds a customizable threshold (<tt>maxLoadFactor</tt>), the hash map is
+ automatically grown.
+ In such a way performance degradation can be avoided.
+ Similarly, when the loadFactor falls below a customizable threshold (<tt>minLoadFactor</tt>), the hash map is
+ automatically shrinked.
+ In such a way excessive memory consumption can be avoided.
+ Automatic resizing (both growing and shrinking) obeys the following invariant:
+
+<p>
+ <tt>capacity * minLoadFactor <= size() <= capacity * maxLoadFactor</tt>
+
+<p> The term <tt>capacity * minLoadFactor</tt> is called the <i>low water mark</i>,
+ <tt>capacity * maxLoadFactor</tt> is called the <i>high water mark</i>. In other
+ words, the number of associations may vary within the water mark constraints.
+ When it goes out of range, the map is automatically resized and memory consumption
+ changes proportionally.
+<ul>
+ <li>To tune for memory at the expense of performance, both increase <tt>minLoadFactor</tt> and <tt>maxLoadFactor</tt>.
+ <li>To tune for performance at the expense of memory, both decrease <tt>minLoadFactor</tt> and <tt>maxLoadFactor</tt>.
+ As as special case set <tt>minLoadFactor=0</tt> to avoid any automatic shrinking.
+</ul>
+Resizing large hash maps can be time consuming, <tt>O(size())</tt>, and should be avoided if possible (maintaining
+primes is not the reason).
+Unnecessary growing operations can be avoided if the number of associations is known before they are added, or can be
+estimated.<p>
+ In such a case good parameters are as follows:
+
+<p>
+ <i>For chaining:</i>
+ <br>Set the <tt>initialCapacity = 1.4*expectedSize</tt> or greater.
+ <br>Set the <tt>maxLoadFactor = 0.8</tt> or greater.
+
+<p>
+ <i>For open addressing:</i>
+ <br>Set the <tt>initialCapacity = 2*expectedSize</tt> or greater. Alternatively call <tt>ensureCapacity(...)</tt>.
+ <br>Set the <tt>maxLoadFactor = 0.5</tt>.
+ <br>Never set <tt>maxLoadFactor > 0.55</tt>; open addressing exponentially slows down beyond that point.
+
+<p>
+ In this way the hash map will never need to grow and still stay fast.
+ It is never a good idea to set <tt>maxLoadFactor < 0.1</tt>,
+ because the hash map would grow too often.
+ If it is entirelly unknown how many associations the application will use,
+ the default constructor should be used. The map will grow and shrink as needed.
+
+<p>
+
+ <b>Comparision of chaining and open addressing</b>
+
+<p> Chaining is faster than open addressing, when assuming unconstrained memory
+ consumption. Open addressing is more space efficient than chaining, because
+ it does not create entry objects but uses primitive arrays which are considerably
+ smaller. Entry objects consume significant amounts of memory compared to the
+ information they actually hold. Open addressing also poses no problems to the
+ garbage collector. In contrast, chaining can create millions of entry objects
+ which are linked; a nightmare for any garbage collector. In addition, entry
+ object creation is a bit slow. <br>
+ Therefore, with the same amount of memory, or even less memory, hash maps with
+ larger capacity can be maintained under open addressing, which yields smaller
+ loadFactors, which in turn keeps performance competitive with chaining. In our
+ benchmarks, using significantly less memory, open addressing usually is not
+ more than 1.2-1.5 times slower than chaining.
+
+<p><b>Further readings</b>:
+ <br>Knuth D., The Art of Computer Programming: Searching and Sorting, 3rd ed.
+ <br>Griswold W., Townsend G., The Design and Implementation of Dynamic Hashing for Sets and Tables in Icon, Software -
+ Practice and Experience, Vol. 23(4), 351-367 (April 1993).
+ <br>Larson P., Dynamic hash tables, Comm. of the ACM, 31, (4), 1988.
+
+<p>
+ <b>Performance:</b>
+
+<p>
+ Time complexity:
+ <br>The classes offer <i>expected</i> time complexity <tt>O(1)</tt> (i.e. constant time) for the basic operations
+ <tt>put</tt>, <tt>get</tt>, <tt>removeKey</tt>, <tt>containsKey</tt> and <tt>size</tt>,
+ assuming the hash function disperses the elements properly among the buckets.
+ Otherwise, pathological cases, although highly improbable, can occur, degrading performance to <tt>O(N)</tt> in the
+ worst case.
+ Operations <tt>containsValue</tt> and <tt>keyOf</tt> are <tt>O(N)</tt>.
+
+<p>
+ Memory requirements for <i>open addressing</i>:
+ <br>worst case: <tt>memory [bytes] = (1/minLoadFactor) * size() * (1 + sizeOf(key) + sizeOf(value))</tt>.
+ <br>best case: <tt>memory [bytes] = (1/maxLoadFactor) * size() * (1 + sizeOf(key) + sizeOf(value))</tt>.
+ Where <tt>sizeOf(int) = 4</tt>, <tt>sizeOf(double) = 8</tt>, <tt>sizeOf(Object) = 4</tt>, etc.
+ Thus, an <tt>OpenIntIntHashMap</tt> with minLoadFactor=0.25 and maxLoadFactor=0.5 and 1000000 associations uses
+ between 17 MB and 34 MB.
+ The same map with 1000 associations uses between 17 and 34 KB.
+
+<p>
+
+</BODY>
+</HTML>
+
Propchange: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/map/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory1D.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory1D.java?rev=883365&view=auto
==============================================================================
--- lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory1D.java (added)
+++ lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory1D.java Mon Nov 23 15:14:26 2009
@@ -0,0 +1,205 @@
+/*
+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;
+
+import org.apache.mahout.colt.matrix.impl.DenseDoubleMatrix1D;
+import org.apache.mahout.colt.matrix.impl.SparseDoubleMatrix1D;
+/**
+Factory for convenient construction of 1-d matrices holding <tt>double</tt> cells.
+Use idioms like <tt>DoubleFactory1D.dense.make(1000)</tt> to construct dense matrices,
+<tt>DoubleFactory1D.sparse.make(1000)</tt> to construct sparse matrices.
+
+If the factory is used frequently it might be useful to streamline the notation.
+For example by aliasing:
+<table>
+<td class="PRE">
+<pre>
+DoubleFactory1D F = DoubleFactory1D.dense;
+F.make(1000);
+F.descending(10);
+F.random(3);
+...
+</pre>
+</td>
+</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 DoubleFactory1D extends org.apache.mahout.colt.PersistentObject {
+ /**
+ * A factory producing dense matrices.
+ */
+ public static final DoubleFactory1D dense = new DoubleFactory1D();
+
+ /**
+ * A factory producing sparse matrices.
+ */
+ public static final DoubleFactory1D sparse = new DoubleFactory1D();
+/**
+ * Makes this class non instantiable, but still let's others inherit from it.
+ */
+protected DoubleFactory1D() {}
+/**
+C = A||B; Constructs a new matrix which is the concatenation of two other matrices.
+Example: <tt>0 1</tt> append <tt>3 4</tt> --> <tt>0 1 3 4</tt>.
+*/
+public DoubleMatrix1D append(DoubleMatrix1D A, DoubleMatrix1D B) {
+ // concatenate
+ DoubleMatrix1D matrix = make(A.size()+B.size());
+ matrix.viewPart(0,A.size()).assign(A);
+ matrix.viewPart(A.size(),B.size()).assign(B);
+ return matrix;
+}
+/**
+Constructs a matrix with cells having ascending values.
+For debugging purposes.
+Example: <tt>0 1 2</tt>
+*/
+public DoubleMatrix1D ascending(int size) {
+ org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+ return descending(size).assign(F.chain(F.neg,F.minus(size)));
+}
+/**
+Constructs a matrix with cells having descending values.
+For debugging purposes.
+Example: <tt>2 1 0</tt>
+*/
+public DoubleMatrix1D descending(int size) {
+ DoubleMatrix1D matrix = make(size);
+ int v = 0;
+ for (int i=size; --i >= 0;) {
+ matrix.setQuick(i, v++);
+ }
+ return matrix;
+}
+/**
+ * Constructs a matrix with the given cell values.
+ * The values are copied. So subsequent changes in <tt>values</tt> are not reflected in the matrix, and vice-versa.
+ *
+ * @param values The values to be filled into the new matrix.
+ */
+public DoubleMatrix1D make(double[] values) {
+ if (this==sparse) return new SparseDoubleMatrix1D(values);
+ else return new DenseDoubleMatrix1D(values);
+}
+/**
+Constructs a matrix which is the concatenation of all given parts.
+Cells are copied.
+*/
+public DoubleMatrix1D make(DoubleMatrix1D[] parts) {
+ if (parts.length==0) return make(0);
+
+ int size = 0;
+ for (int i=0; i < parts.length; i++) size += parts[i].size();
+
+ DoubleMatrix1D vector = make(size);
+ size = 0;
+ for (int i=0; i < parts.length; i++) {
+ vector.viewPart(size,parts[i].size()).assign(parts[i]);
+ size += parts[i].size();
+ }
+
+ return vector;
+}
+/**
+ * Constructs a matrix with the given shape, each cell initialized with zero.
+ */
+public DoubleMatrix1D make(int size) {
+ if (this==sparse) return new SparseDoubleMatrix1D(size);
+ return new DenseDoubleMatrix1D(size);
+}
+/**
+ * Constructs a matrix with the given shape, each cell initialized with the given value.
+ */
+public DoubleMatrix1D make(int size, double initialValue) {
+ return make(size).assign(initialValue);
+}
+/**
+ * Constructs a matrix from the values of the given list.
+ * The values are copied. So subsequent changes in <tt>values</tt> are not reflected in the matrix, and vice-versa.
+ *
+ * @param values The values to be filled into the new matrix.
+ * @return a new matrix.
+ */
+public DoubleMatrix1D make(org.apache.mahout.colt.list.AbstractDoubleList values) {
+ int size = values.size();
+ DoubleMatrix1D vector = make(size);
+ for (int i=size; --i >= 0; ) vector.set(i, values.get(i));
+ return vector;
+}
+/**
+ * Constructs a matrix with uniformly distributed values in <tt>(0,1)</tt> (exclusive).
+ */
+public DoubleMatrix1D random(int size) {
+ return make(size).assign(org.apache.mahout.jet.math.Functions.random());
+}
+/**
+C = A||A||..||A; Constructs a new matrix which is concatenated <tt>repeat</tt> times.
+Example:
+<pre>
+0 1
+repeat(3) -->
+0 1 0 1 0 1
+</pre>
+*/
+public DoubleMatrix1D repeat(DoubleMatrix1D A, int repeat) {
+ int size = A.size();
+ DoubleMatrix1D matrix = make(repeat * size);
+ for (int i=repeat; --i >= 0; ) {
+ matrix.viewPart(size*i,size).assign(A);
+ }
+ return matrix;
+}
+/**
+ * Constructs a randomly sampled matrix with the given shape.
+ * Randomly picks exactly <tt>Math.round(size*nonZeroFraction)</tt> cells and initializes them to <tt>value</tt>, all the rest will be initialized to zero.
+ * Note that this is not the same as setting each cell with probability <tt>nonZeroFraction</tt> to <tt>value</tt>.
+ * @throws IllegalArgumentException if <tt>nonZeroFraction < 0 || nonZeroFraction > 1</tt>.
+ * @see org.apache.mahout.jet.random.sampling.RandomSampler
+ */
+public DoubleMatrix1D sample(int size, double value, double nonZeroFraction) {
+ double epsilon = 1e-09;
+ if (nonZeroFraction < 0 - epsilon || nonZeroFraction > 1 + epsilon) throw new IllegalArgumentException();
+ if (nonZeroFraction < 0) nonZeroFraction = 0;
+ if (nonZeroFraction > 1) nonZeroFraction = 1;
+
+ DoubleMatrix1D matrix = make(size);
+
+ int n = (int) Math.round(size*nonZeroFraction);
+ if (n==0) return matrix;
+
+ org.apache.mahout.jet.random.sampling.RandomSamplingAssistant sampler = new org.apache.mahout.jet.random.sampling.RandomSamplingAssistant(n,size,new org.apache.mahout.jet.random.engine.MersenneTwister());
+ for (int i=size; --i >=0; ) {
+ if (sampler.sampleNextElement()) {
+ matrix.set(i, value);
+ }
+ }
+
+ return matrix;
+}
+/**
+ * Constructs a list from the given matrix.
+ * The values are copied. So subsequent changes in <tt>values</tt> are not reflected in the list, and vice-versa.
+ *
+ * @param values The values to be filled into the new list.
+ * @return a new list.
+ */
+public org.apache.mahout.colt.list.DoubleArrayList toList(DoubleMatrix1D values) {
+ int size = values.size();
+ org.apache.mahout.colt.list.DoubleArrayList list = new org.apache.mahout.colt.list.DoubleArrayList(size);
+ list.setSize(size);
+ for (int i=size; --i >= 0; ) list.set(i, values.get(i));
+ return list;
+}
+}
Propchange: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory1D.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory2D.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory2D.java?rev=883365&view=auto
==============================================================================
--- lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory2D.java (added)
+++ lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory2D.java Mon Nov 23 15:14:26 2009
@@ -0,0 +1,845 @@
+/*
+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;
+
+import org.apache.mahout.colt.matrix.impl.DenseDoubleMatrix2D;
+import org.apache.mahout.colt.matrix.impl.RCDoubleMatrix2D;
+import org.apache.mahout.colt.matrix.impl.SparseDoubleMatrix2D;
+/**
+Factory for convenient construction of 2-d matrices holding <tt>double</tt>
+ cells. Also provides convenient methods to compose (concatenate) and decompose
+ (split) matrices from/to constituent blocks. </p>
+<p> </p>
+<table border="0" cellspacing="0">
+ <tr align="left" valign="top">
+ <td><i>Construction</i></td>
+ <td>Use idioms like <tt>DoubleFactory2D.dense.make(4,4)</tt> to construct
+ dense matrices, <tt>DoubleFactory2D.sparse.make(4,4)</tt> to construct sparse
+ matrices.</td>
+ </tr>
+ <tr align="left" valign="top">
+ <td><i> Construction with initial values </i></td>
+ <td>Use other <tt>make</tt> methods to construct matrices with given initial
+ values. </td>
+ </tr>
+ <tr align="left" valign="top">
+ <td><i> Appending rows and columns </i></td>
+ <td>Use methods {@link #appendColumns(DoubleMatrix2D,DoubleMatrix2D) appendColumns},
+ {@link #appendColumns(DoubleMatrix2D,DoubleMatrix2D) appendRows} and {@link
+ #repeat(DoubleMatrix2D,int,int) repeat} to append rows and columns. </td>
+ </tr>
+ <tr align="left" valign="top">
+ <td><i> General block matrices </i></td>
+ <td>Use methods {@link #compose(DoubleMatrix2D[][]) compose} and {@link #decompose(DoubleMatrix2D[][],DoubleMatrix2D)
+ decompose} to work with general block matrices. </td>
+ </tr>
+ <tr align="left" valign="top">
+ <td><i> Diagonal matrices </i></td>
+ <td>Use methods {@link #diagonal(DoubleMatrix1D) diagonal(vector)}, {@link
+ #diagonal(DoubleMatrix2D) diagonal(matrix)} and {@link #identity(int) identity}
+ to work with diagonal matrices. </td>
+ </tr>
+ <tr align="left" valign="top">
+ <td><i> Diagonal block matrices </i></td>
+ <td>Use method {@link #composeDiagonal(DoubleMatrix2D,DoubleMatrix2D,DoubleMatrix2D)
+ composeDiagonal} to work with diagonal block matrices. </td>
+ </tr>
+ <tr align="left" valign="top">
+ <td><i>Random</i></td>
+ <td>Use methods {@link #random(int,int) random} and {@link #sample(int,int,double,double)
+ sample} to construct random matrices. </td>
+ </tr>
+</table>
+<p> </p>
+<p>If the factory is used frequently it might be useful to streamline the notation.
+ For example by aliasing: </p>
+<table>
+ <td class="PRE">
+ <pre>
+DoubleFactory2D F = DoubleFactory2D.dense;
+F.make(4,4);
+F.descending(10,20);
+F.random(4,4);
+...
+</pre>
+ </td>
+</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 DoubleFactory2D extends org.apache.mahout.colt.PersistentObject {
+ /**
+ * A factory producing dense matrices.
+ */
+ public static final DoubleFactory2D dense = new DoubleFactory2D();
+
+ /**
+ * A factory producing sparse hash matrices.
+ */
+ public static final DoubleFactory2D sparse = new DoubleFactory2D();
+
+ /**
+ * A factory producing sparse row compressed matrices.
+ */
+ public static final DoubleFactory2D rowCompressed = new DoubleFactory2D();
+
+ /*
+ * A factory producing sparse row compressed modified matrices.
+ */
+ //public static final DoubleFactory2D rowCompressedModified = new DoubleFactory2D();
+/**
+ * Makes this class non instantiable, but still let's others inherit from it.
+ */
+protected DoubleFactory2D() {}
+/**
+C = A||B; Constructs a new matrix which is the column-wise concatenation of two other matrices.
+<pre>
+0 1 2
+3 4 5
+appendColumns
+6 7
+8 9
+-->
+0 1 2 6 7
+3 4 5 8 9
+</pre>
+*/
+public DoubleMatrix2D appendColumns(DoubleMatrix2D A, DoubleMatrix2D B) {
+ // force both to have maximal shared number of rows.
+ if (B.rows() > A.rows()) B = B.viewPart(0,0,A.rows(),B.columns());
+ else if (B.rows() < A.rows()) A = A.viewPart(0,0,B.rows(),A.columns());
+
+ // concatenate
+ int ac = A.columns();
+ int bc = B.columns();
+ int r = A.rows();
+ DoubleMatrix2D matrix = make(r,ac+bc);
+ matrix.viewPart(0,0,r,ac).assign(A);
+ matrix.viewPart(0,ac,r,bc).assign(B);
+ return matrix;
+}
+/**
+C = A||B; Constructs a new matrix which is the row-wise concatenation of two other matrices.
+<pre>
+0 1
+2 3
+4 5
+appendRows
+6 7
+8 9
+-->
+0 1
+2 3
+4 5
+6 7
+8 9
+</pre>
+*/
+public DoubleMatrix2D appendRows(DoubleMatrix2D A, DoubleMatrix2D B) {
+ // force both to have maximal shared number of columns.
+ if (B.columns() > A.columns()) B = B.viewPart(0,0,B.rows(),A.columns());
+ else if (B.columns() < A.columns()) A = A.viewPart(0,0,A.rows(),B.columns());
+
+ // concatenate
+ int ar = A.rows();
+ int br = B.rows();
+ int c = A.columns();
+ DoubleMatrix2D matrix = make(ar+br, c);
+ matrix.viewPart(0,0,ar,c).assign(A);
+ matrix.viewPart(ar,0,br,c).assign(B);
+ return matrix;
+}
+/**
+Constructs a matrix with cells having ascending values.
+For debugging purposes.
+Example:
+<pre>
+0 1 2
+3 4 5
+</pre>
+*/
+public DoubleMatrix2D ascending(int rows, int columns) {
+ org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+ return descending(rows,columns).assign(F.chain(F.neg,F.minus(columns*rows)));
+}
+/**
+Checks whether the given array is rectangular, that is, whether all rows have the same number of columns.
+@throws IllegalArgumentException if the array is not rectangular.
+*/
+protected static void checkRectangularShape(double[][] array) {
+ int columns = -1;
+ for (int row=array.length; --row >= 0; ) {
+ if (array[row] != null) {
+ if (columns == -1) columns = array[row].length;
+ if (array[row].length != columns) throw new IllegalArgumentException("All rows of array must have same number of columns.");
+ }
+ }
+}
+/**
+Checks whether the given array is rectangular, that is, whether all rows have the same number of columns.
+@throws IllegalArgumentException if the array is not rectangular.
+*/
+protected static void checkRectangularShape(DoubleMatrix2D[][] array) {
+ int columns = -1;
+ for (int row=array.length; --row >= 0; ) {
+ if (array[row] != null) {
+ if (columns == -1) columns = array[row].length;
+ if (array[row].length != columns) throw new IllegalArgumentException("All rows of array must have same number of columns.");
+ }
+ }
+}
+/**
+Constructs a block matrix made from the given parts.
+The inverse to method {@link #decompose(DoubleMatrix2D[][], DoubleMatrix2D)}.
+<p>
+All matrices of a given column within <tt>parts</tt> must have the same number of columns.
+All matrices of a given row within <tt>parts</tt> must have the same number of rows.
+Otherwise an <tt>IllegalArgumentException</tt> is thrown.
+Note that <tt>null</tt>s within <tt>parts[row,col]</tt> are an exception to this rule: they are ignored.
+Cells are copied.
+Example:
+<table border="1" cellspacing="0">
+ <tr align="left" valign="top">
+ <td><tt>Code</tt></td>
+ <td><tt>Result</tt></td>
+ </tr>
+ <tr align="left" valign="top">
+ <td>
+ <pre>
+DoubleMatrix2D[][] parts1 =
+{
+ { null, make(2,2,1), null },
+ { make(4,4,2), null, make(4,3,3) },
+ { null, make(2,2,4), null }
+};
+System.out.println(compose(parts1));
+</pre>
+ </td>
+ <td><tt>8 x 9 matrix<br>
+ 0 0 0 0 1 1 0 0 0<br>
+ 0 0 0 0 1 1 0 0 0<br>
+ 2 2 2 2 0 0 3 3 3<br>
+ 2 2 2 2 0 0 3 3 3<br>
+ 2 2 2 2 0 0 3 3 3<br>
+ 2 2 2 2 0 0 3 3 3<br>
+ 0 0 0 0 4 4 0 0 0<br>
+ 0 0 0 0 4 4 0 0 0</tt></td>
+ </tr>
+ <tr align="left" valign="top">
+ <td>
+ <pre>
+DoubleMatrix2D[][] parts3 =
+{
+ { identity(3), null, },
+ { null, identity(3).viewColumnFlip() },
+ { identity(3).viewRowFlip(), null }
+};
+System.out.println("\n"+make(parts3));
+</pre>
+ </td>
+ <td><tt>9 x 6 matrix<br>
+ 1 0 0 0 0 0<br>
+ 0 1 0 0 0 0<br>
+ 0 0 1 0 0 0<br>
+ 0 0 0 0 0 1<br>
+ 0 0 0 0 1 0<br>
+ 0 0 0 1 0 0<br>
+ 0 0 1 0 0 0<br>
+ 0 1 0 0 0 0<br>
+ 1 0 0 0 0 0 </tt></td>
+ </tr>
+ <tr align="left" valign="top">
+ <td>
+ <pre>
+DoubleMatrix2D A = ascending(2,2);
+DoubleMatrix2D B = descending(2,2);
+DoubleMatrix2D _ = null;
+
+DoubleMatrix2D[][] parts4 =
+{
+ { A, _, A, _ },
+ { _, A, _, B }
+};
+System.out.println("\n"+make(parts4));
+</pre>
+ </td>
+ <td><tt>4 x 8 matrix<br>
+ 1 2 0 0 1 2 0 0<br>
+ 3 4 0 0 3 4 0 0<br>
+ 0 0 1 2 0 0 3 2<br>
+ 0 0 3 4 0 0 1 0 </tt></td>
+ </tr>
+ <tr align="left" valign="top">
+ <td>
+ <pre>
+DoubleMatrix2D[][] parts2 =
+{
+ { null, make(2,2,1), null },
+ { make(4,4,2), null, make(4,3,3) },
+ { null, make(2,3,4), null }
+};
+System.out.println("\n"+Factory2D.make(parts2));
+</pre>
+ </td>
+ <td><tt>IllegalArgumentException<br>
+ A[0,1].cols != A[2,1].cols<br>
+ (2 != 3)</tt></td>
+ </tr>
+</table>
+@throws IllegalArgumentException subject to the conditions outlined above.
+*/
+public DoubleMatrix2D compose(DoubleMatrix2D[][] parts) {
+ checkRectangularShape(parts);
+ int rows = parts.length;
+ int columns = 0;
+ if (parts.length > 0) columns = parts[0].length;
+ DoubleMatrix2D empty = make(0,0);
+
+ if (rows==0 || columns==0) return empty;
+
+ // determine maximum column width of each column
+ int[] maxWidths = new int[columns];
+ for (int column=columns; --column >= 0; ) {
+ int maxWidth = 0;
+ for (int row=rows; --row >= 0; ) {
+ DoubleMatrix2D part = parts[row][column];
+ if (part != null) {
+ int width = part.columns();
+ if (maxWidth>0 && width>0 && width!=maxWidth) throw new IllegalArgumentException("Different number of columns.");
+ maxWidth = Math.max(maxWidth,width);
+ }
+ }
+ maxWidths[column] = maxWidth;
+ }
+
+ // determine row height of each row
+ int[] maxHeights = new int[rows];
+ for (int row=rows; --row >= 0; ) {
+ int maxHeight = 0;
+ for (int column=columns; --column >= 0; ) {
+ DoubleMatrix2D part = parts[row][column];
+ if (part != null) {
+ int height = part.rows();
+ if (maxHeight>0 && height>0 && height!=maxHeight) throw new IllegalArgumentException("Different number of rows.");
+ maxHeight = Math.max(maxHeight,height);
+ }
+ }
+ maxHeights[row] = maxHeight;
+ }
+
+
+ // shape of result
+ int resultRows = 0;
+ for (int row=rows; --row >= 0; ) resultRows += maxHeights[row];
+ int resultCols = 0;
+ for (int column=columns; --column >= 0; ) resultCols += maxWidths[column];
+
+ DoubleMatrix2D matrix = make(resultRows,resultCols);
+
+ // copy
+ int r=0;
+ for (int row=0; row < rows; row++) {
+ int c=0;
+ for (int column=0; column < columns; column++) {
+ DoubleMatrix2D part = parts[row][column];
+ if (part != null) {
+ matrix.viewPart(r,c,part.rows(),part.columns()).assign(part);
+ }
+ c += maxWidths[column];
+ }
+ r += maxHeights[row];
+ }
+
+ return matrix;
+}
+/**
+Constructs a diagonal block matrix from the given parts (the <i>direct sum</i> of two matrices).
+That is the concatenation
+<pre>
+A 0
+0 B
+</pre>
+(The direct sum has <tt>A.rows()+B.rows()</tt> rows and <tt>A.columns()+B.columns()</tt> columns).
+Cells are copied.
+@return a new matrix which is the direct sum.
+*/
+public DoubleMatrix2D composeDiagonal(DoubleMatrix2D A, DoubleMatrix2D B) {
+ int ar = A.rows(); int ac = A.columns();
+ int br = B.rows(); int bc = B.columns();
+ DoubleMatrix2D sum = make(ar+br, ac+bc);
+ sum.viewPart(0,0,ar,ac).assign(A);
+ sum.viewPart(ar,ac,br,bc).assign(B);
+ return sum;
+}
+/**
+Constructs a diagonal block matrix from the given parts.
+The concatenation has the form
+<pre>
+A 0 0
+0 B 0
+0 0 C
+</pre>
+from the given parts.
+Cells are copied.
+*/
+public DoubleMatrix2D composeDiagonal(DoubleMatrix2D A, DoubleMatrix2D B, DoubleMatrix2D C) {
+ DoubleMatrix2D diag = make(A.rows()+B.rows()+C.rows(), A.columns()+B.columns()+C.columns());
+ diag.viewPart(0,0,A.rows(),A.columns()).assign(A);
+ diag.viewPart(A.rows(),A.columns(),B.rows(),B.columns()).assign(B);
+ diag.viewPart(A.rows()+B.rows(),A.columns()+B.columns(),C.rows(),C.columns()).assign(C);
+ return diag;
+}
+/**
+Splits a block matrix into its constituent blocks; Copies blocks of a matrix into the given parts.
+The inverse to method {@link #compose(DoubleMatrix2D[][])}.
+<p>
+All matrices of a given column within <tt>parts</tt> must have the same number of columns.
+All matrices of a given row within <tt>parts</tt> must have the same number of rows.
+Otherwise an <tt>IllegalArgumentException</tt> is thrown.
+Note that <tt>null</tt>s within <tt>parts[row,col]</tt> are an exception to this rule: they are ignored.
+Cells are copied.
+Example:
+<table border="1" cellspacing="0">
+ <tr align="left" valign="top">
+ <td><tt>Code</tt></td>
+ <td><tt>matrix</tt></td>
+ <td><tt>--> parts </tt></td>
+ </tr>
+ <tr align="left" valign="top">
+ <td>
+ <pre>
+DoubleMatrix2D matrix = ... ;
+DoubleMatrix2D _ = null;
+DoubleMatrix2D A,B,C,D;
+A = make(2,2); B = make (4,4);
+C = make(4,3); D = make (2,2);
+DoubleMatrix2D[][] parts =
+{
+ { _, A, _ },
+ { B, _, C },
+ { _, D, _ }
+};
+decompose(parts,matrix);
+System.out.println("\nA = "+A);
+System.out.println("\nB = "+B);
+System.out.println("\nC = "+C);
+System.out.println("\nD = "+D);
+</pre>
+ </td>
+ <td><tt>8 x 9 matrix<br>
+ 9 9 9 9 1 1 9 9 9<br>
+ 9 9 9 9 1 1 9 9 9<br>
+ 2 2 2 2 9 9 3 3 3<br>
+ 2 2 2 2 9 9 3 3 3<br>
+ 2 2 2 2 9 9 3 3 3<br>
+ 2 2 2 2 9 9 3 3 3<br>
+ 9 9 9 9 4 4 9 9 9<br>
+ 9 9 9 9 4 4 9 9 9</tt></td>
+ <td>
+ <p><tt>A = 2 x 2 matrix<br>
+ 1 1<br>
+ 1 1</tt></p>
+ <p><tt>B = 4 x 4 matrix<br>
+ 2 2 2 2<br>
+ 2 2 2 2<br>
+ 2 2 2 2<br>
+ 2 2 2 2</tt></p>
+ <p><tt>C = 4 x 3 matrix<br>
+ 3 3 3<br>
+ 3 3 3<br>
+ </tt><tt>3 3 3<br>
+ </tt><tt>3 3 3</tt></p>
+ <p><tt>D = 2 x 2 matrix<br>
+ 4 4<br>
+ 4 4</tt></p>
+ </td>
+ </tr>
+</table>
+@throws IllegalArgumentException subject to the conditions outlined above.
+*/
+public void decompose(DoubleMatrix2D[][] parts, DoubleMatrix2D matrix) {
+ checkRectangularShape(parts);
+ int rows = parts.length;
+ int columns = 0;
+ if (parts.length > 0) columns = parts[0].length;
+ if (rows==0 || columns==0) return;
+
+ // determine maximum column width of each column
+ int[] maxWidths = new int[columns];
+ for (int column=columns; --column >= 0; ) {
+ int maxWidth = 0;
+ for (int row=rows; --row >= 0; ) {
+ DoubleMatrix2D part = parts[row][column];
+ if (part != null) {
+ int width = part.columns();
+ if (maxWidth>0 && width>0 && width!=maxWidth) throw new IllegalArgumentException("Different number of columns.");
+ maxWidth = Math.max(maxWidth,width);
+ }
+ }
+ maxWidths[column] = maxWidth;
+ }
+
+ // determine row height of each row
+ int[] maxHeights = new int[rows];
+ for (int row=rows; --row >= 0; ) {
+ int maxHeight = 0;
+ for (int column=columns; --column >= 0; ) {
+ DoubleMatrix2D part = parts[row][column];
+ if (part != null) {
+ int height = part.rows();
+ if (maxHeight>0 && height>0 && height!=maxHeight) throw new IllegalArgumentException("Different number of rows.");
+ maxHeight = Math.max(maxHeight,height);
+ }
+ }
+ maxHeights[row] = maxHeight;
+ }
+
+
+ // shape of result parts
+ int resultRows = 0;
+ for (int row=rows; --row >= 0; ) resultRows += maxHeights[row];
+ int resultCols = 0;
+ for (int column=columns; --column >= 0; ) resultCols += maxWidths[column];
+
+ if (matrix.rows() < resultRows || matrix.columns() < resultCols) throw new IllegalArgumentException("Parts larger than matrix.");
+
+ // copy
+ int r=0;
+ for (int row=0; row < rows; row++) {
+ int c=0;
+ for (int column=0; column < columns; column++) {
+ DoubleMatrix2D part = parts[row][column];
+ if (part != null) {
+ part.assign(matrix.viewPart(r,c,part.rows(),part.columns()));
+ }
+ c += maxWidths[column];
+ }
+ r += maxHeights[row];
+ }
+
+}
+/**
+ * Demonstrates usage of this class.
+ */
+public void demo1() {
+System.out.println("\n\n");
+DoubleMatrix2D[][] parts1 =
+{
+ { null, make(2,2,1), null },
+ { make(4,4,2), null, make(4,3,3) },
+ { null, make(2,2,4), null }
+};
+System.out.println("\n"+compose(parts1));
+//System.out.println("\n"+org.apache.mahout.colt.matrixpattern.Converting.toHTML(make(parts1).toString()));
+
+/*
+//
+illegal 2 != 3
+DoubleMatrix2D[][] parts2 =
+{
+ { null, make(2,2,1), null },
+ { make(4,4,2), null, make(4,3,3) },
+ { null, make(2,3,4), null }
+};
+System.out.println("\n"+make(parts2));
+*/
+
+DoubleMatrix2D[][] parts3 =
+{
+ { identity(3), null, },
+ { null, identity(3).viewColumnFlip() },
+ { identity(3).viewRowFlip(), null }
+};
+System.out.println("\n"+compose(parts3));
+//System.out.println("\n"+org.apache.mahout.colt.matrixpattern.Converting.toHTML(make(parts3).toString()));
+
+DoubleMatrix2D A = ascending(2,2);
+DoubleMatrix2D B = descending(2,2);
+DoubleMatrix2D _ = null;
+
+DoubleMatrix2D[][] parts4 =
+{
+ { A, _, A, _ },
+ { _, A, _, B }
+};
+System.out.println("\n"+compose(parts4));
+//System.out.println("\n"+org.apache.mahout.colt.matrixpattern.Converting.toHTML(make(parts4).toString()));
+
+}
+/**
+ * Demonstrates usage of this class.
+ */
+public void demo2() {
+System.out.println("\n\n");
+DoubleMatrix2D matrix;
+DoubleMatrix2D A,B,C,D,E,F,G;
+DoubleMatrix2D _ = null;
+A = make(2,2,1); B = make (4,4,2); C = make(4,3,3); D = make (2,2,4);
+DoubleMatrix2D[][] parts1 =
+{
+ { _, A, _ },
+ { B, _, C },
+ { _, D, _ }
+};
+matrix = compose(parts1);
+System.out.println("\n"+matrix);
+
+A.assign(9); B.assign(9); C.assign(9); D.assign(9);
+decompose(parts1,matrix);
+System.out.println(A);
+System.out.println(B);
+System.out.println(C);
+System.out.println(D);
+//System.out.println("\n"+org.apache.mahout.colt.matrixpattern.Converting.toHTML(make(parts1).toString()));
+
+/*
+//
+illegal 2 != 3
+DoubleMatrix2D[][] parts2 =
+{
+ { null, make(2,2,1), null },
+ { make(4,4,2), null, make(4,3,3) },
+ { null, make(2,3,4), null }
+};
+System.out.println("\n"+Factory2D.make(parts2));
+*/
+
+/*
+DoubleMatrix2D[][] parts3 =
+{
+ { identity(3), null, },
+ { null, identity(3).viewColumnFlip() },
+ { identity(3).viewRowFlip(), null }
+};
+System.out.println("\n"+make(parts3));
+//System.out.println("\n"+org.apache.mahout.colt.matrixpattern.Converting.toHTML(make(parts3).toString()));
+
+DoubleMatrix2D A = ascending(2,2);
+DoubleMatrix2D B = descending(2,2);
+DoubleMatrix2D _ = null;
+
+DoubleMatrix2D[][] parts4 =
+{
+ { A, _, A, _ },
+ { _, A, _, B }
+};
+System.out.println("\n"+make(parts4));
+//System.out.println("\n"+org.apache.mahout.colt.matrixpattern.Converting.toHTML(make(parts4).toString()));
+*/
+}
+/**
+Constructs a matrix with cells having descending values.
+For debugging purposes.
+Example:
+<pre>
+5 4 3
+2 1 0
+</pre>
+*/
+public DoubleMatrix2D descending(int rows, int columns) {
+ DoubleMatrix2D matrix = make(rows,columns);
+ int v = 0;
+ for (int row=rows; --row >= 0;) {
+ for (int column=columns; --column >= 0;) {
+ matrix.setQuick(row, column, v++);
+ }
+ }
+ return matrix;
+}
+/**
+Constructs a new diagonal matrix whose diagonal elements are the elements of <tt>vector</tt>.
+Cells values are copied. The new matrix is not a view.
+Example:
+<pre>
+5 4 3 -->
+5 0 0
+0 4 0
+0 0 3
+</pre>
+@return a new matrix.
+*/
+public DoubleMatrix2D diagonal(DoubleMatrix1D vector) {
+ int size = vector.size();
+ DoubleMatrix2D diag = make(size,size);
+ for (int i=size; --i >= 0; ) {
+ diag.setQuick(i,i, vector.getQuick(i));
+ }
+ return diag;
+}
+/**
+Constructs a new vector consisting of the diagonal elements of <tt>A</tt>.
+Cells values are copied. The new vector is not a view.
+Example:
+<pre>
+5 0 0 9
+0 4 0 9
+0 0 3 9
+--> 5 4 3
+</pre>
+@param A the matrix, need not be square.
+@return a new vector.
+*/
+public DoubleMatrix1D diagonal(DoubleMatrix2D A) {
+ int min = Math.min(A.rows(),A.columns());
+ DoubleMatrix1D diag = make1D(min);
+ for (int i=min; --i >= 0; ) {
+ diag.setQuick(i, A.getQuick(i,i));
+ }
+ return diag;
+}
+/**
+ * Constructs an identity matrix (having ones on the diagonal and zeros elsewhere).
+ */
+public DoubleMatrix2D identity(int rowsAndColumns) {
+ DoubleMatrix2D matrix = make(rowsAndColumns,rowsAndColumns);
+ for (int i=rowsAndColumns; --i >= 0; ) {
+ matrix.setQuick(i,i, 1);
+ }
+ return matrix;
+}
+/**
+ * Constructs a matrix with the given cell values.
+ * <tt>values</tt> is required to have the form <tt>values[row][column]</tt>
+ * and have exactly the same number of columns in every row.
+ * <p>
+ * The values are copied. So subsequent changes in <tt>values</tt> are not reflected in the matrix, and vice-versa.
+ *
+ * @param values The values to be filled into the new matrix.
+ * @throws IllegalArgumentException if <tt>for any 1 <= row < values.length: values[row].length != values[row-1].length</tt>.
+ */
+public DoubleMatrix2D make(double[][] values) {
+ if (this==sparse) return new SparseDoubleMatrix2D(values);
+ else return new DenseDoubleMatrix2D(values);
+}
+/**
+Construct a matrix from a one-dimensional column-major packed array, ala Fortran.
+Has the form <tt>matrix.get(row,column) == values[row + column*rows]</tt>.
+The values are copied.
+
+@param values One-dimensional array of doubles, packed by columns (ala Fortran).
+@param rows the number of rows.
+@exception IllegalArgumentException <tt>values.length</tt> must be a multiple of <tt>rows</tt>.
+*/
+public DoubleMatrix2D make(double values[], int rows) {
+ int columns = (rows != 0 ? values.length/rows : 0);
+ if (rows*columns != values.length)
+ throw new IllegalArgumentException("Array length must be a multiple of m.");
+
+ DoubleMatrix2D matrix = make(rows,columns);
+ for (int row=0; row < rows; row++) {
+ for (int column=0; column < columns; column++) {
+ matrix.setQuick(row,column, values[row + column*rows]);
+ }
+ }
+ return matrix;
+}
+/**
+ * Constructs a matrix with the given shape, each cell initialized with zero.
+ */
+public DoubleMatrix2D make(int rows, int columns) {
+ if (this==sparse) return new SparseDoubleMatrix2D(rows,columns);
+ if (this==rowCompressed) return new RCDoubleMatrix2D(rows,columns);
+ //if (this==rowCompressedModified) return new RCMDoubleMatrix2D(rows,columns);
+ else return new DenseDoubleMatrix2D(rows,columns);
+}
+/**
+ * Constructs a matrix with the given shape, each cell initialized with the given value.
+ */
+public DoubleMatrix2D make(int rows, int columns, double initialValue) {
+ if (initialValue == 0) return make(rows,columns);
+ return make(rows,columns).assign(initialValue);
+}
+/**
+ * Constructs a 1d matrix of the right dynamic type.
+ */
+protected DoubleMatrix1D make1D(int size) {
+ return make(0,0).like1D(size);
+}
+/**
+ * Constructs a matrix with uniformly distributed values in <tt>(0,1)</tt> (exclusive).
+ */
+public DoubleMatrix2D random(int rows, int columns) {
+ return make(rows,columns).assign(org.apache.mahout.jet.math.Functions.random());
+}
+/**
+C = A||A||..||A; Constructs a new matrix which is duplicated both along the row and column dimension.
+Example:
+<pre>
+0 1
+2 3
+repeat(2,3) -->
+0 1 0 1 0 1
+2 3 2 3 2 3
+0 1 0 1 0 1
+2 3 2 3 2 3
+</pre>
+*/
+public DoubleMatrix2D repeat(DoubleMatrix2D A, int rowRepeat, int columnRepeat) {
+ int r = A.rows();
+ int c = A.columns();
+ DoubleMatrix2D matrix = make(r*rowRepeat, c*columnRepeat);
+ for (int i=rowRepeat; --i >= 0; ) {
+ for (int j=columnRepeat; --j >= 0; ) {
+ matrix.viewPart(r*i,c*j,r,c).assign(A);
+ }
+ }
+ return matrix;
+}
+/**
+ * Constructs a randomly sampled matrix with the given shape.
+ * Randomly picks exactly <tt>Math.round(rows*columns*nonZeroFraction)</tt> cells and initializes them to <tt>value</tt>, all the rest will be initialized to zero.
+ * Note that this is not the same as setting each cell with probability <tt>nonZeroFraction</tt> to <tt>value</tt>.
+ * Note: The random seed is a constant.
+ * @throws IllegalArgumentException if <tt>nonZeroFraction < 0 || nonZeroFraction > 1</tt>.
+ * @see org.apache.mahout.jet.random.sampling.RandomSampler
+ */
+public DoubleMatrix2D sample(int rows, int columns, double value, double nonZeroFraction) {
+ DoubleMatrix2D matrix = make(rows,columns);
+ sample(matrix,value,nonZeroFraction);
+ return matrix;
+}
+/**
+ * Modifies the given matrix to be a randomly sampled matrix.
+ * Randomly picks exactly <tt>Math.round(rows*columns*nonZeroFraction)</tt> cells and initializes them to <tt>value</tt>, all the rest will be initialized to zero.
+ * Note that this is not the same as setting each cell with probability <tt>nonZeroFraction</tt> to <tt>value</tt>.
+ * Note: The random seed is a constant.
+ * @throws IllegalArgumentException if <tt>nonZeroFraction < 0 || nonZeroFraction > 1</tt>.
+ * @see org.apache.mahout.jet.random.sampling.RandomSampler
+ */
+public DoubleMatrix2D sample(DoubleMatrix2D matrix, double value, double nonZeroFraction) {
+ int rows = matrix.rows();
+ int columns = matrix.columns();
+ double epsilon = 1e-09;
+ if (nonZeroFraction < 0 - epsilon || nonZeroFraction > 1 + epsilon) throw new IllegalArgumentException();
+ if (nonZeroFraction < 0) nonZeroFraction = 0;
+ if (nonZeroFraction > 1) nonZeroFraction = 1;
+
+ matrix.assign(0);
+
+ int size = rows*columns;
+ int n = (int) Math.round(size*nonZeroFraction);
+ if (n==0) return matrix;
+
+ org.apache.mahout.jet.random.sampling.RandomSamplingAssistant sampler = new org.apache.mahout.jet.random.sampling.RandomSamplingAssistant(n,size,new org.apache.mahout.jet.random.engine.MersenneTwister());
+ for (int i=0; i < size; i++) {
+ if (sampler.sampleNextElement()) {
+ int row = (int) (i/columns);
+ int column = (int) (i%columns);
+ matrix.set(row,column, value);
+ }
+ }
+
+ return matrix;
+}
+}
Propchange: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory2D.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory3D.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory3D.java?rev=883365&view=auto
==============================================================================
--- lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory3D.java (added)
+++ lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory3D.java Mon Nov 23 15:14:26 2009
@@ -0,0 +1,112 @@
+/*
+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;
+
+import org.apache.mahout.colt.matrix.impl.DenseDoubleMatrix3D;
+import org.apache.mahout.colt.matrix.impl.SparseDoubleMatrix3D;
+/**
+Factory for convenient construction of 3-d matrices holding <tt>double</tt> cells.
+Use idioms like <tt>DoubleFactory3D.dense.make(4,4,4)</tt> to construct dense matrices,
+<tt>DoubleFactory3D.sparse.make(4,4,4)</tt> to construct sparse matrices.
+
+If the factory is used frequently it might be useful to streamline the notation.
+For example by aliasing:
+<table>
+<td class="PRE">
+<pre>
+DoubleFactory3D F = DoubleFactory3D.dense;
+F.make(4,4,4);
+F.descending(10,20,5);
+F.random(4,4,5);
+...
+</pre>
+</td>
+</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 DoubleFactory3D extends org.apache.mahout.colt.PersistentObject {
+ /**
+ * A factory producing dense matrices.
+ */
+ public static final DoubleFactory3D dense = new DoubleFactory3D();
+
+ /**
+ * A factory producing sparse matrices.
+ */
+ public static final DoubleFactory3D sparse = new DoubleFactory3D();
+/**
+ * Makes this class non instantiable, but still let's others inherit from it.
+ */
+protected DoubleFactory3D() {}
+/**
+ * Constructs a matrix with cells having ascending values.
+ * For debugging purposes.
+ */
+public DoubleMatrix3D ascending(int slices, int rows, int columns) {
+ org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+ return descending(slices,rows,columns).assign(F.chain(F.neg,F.minus(slices*rows*columns)));
+}
+/**
+ * Constructs a matrix with cells having descending values.
+ * For debugging purposes.
+ */
+public DoubleMatrix3D descending(int slices, int rows, int columns) {
+ DoubleMatrix3D matrix = make(slices,rows,columns);
+ int v = 0;
+ for (int slice=slices; --slice >= 0;) {
+ for (int row=rows; --row >= 0;) {
+ for (int column=columns; --column >= 0;) {
+ matrix.setQuick(slice, row, column, v++);
+ }
+ }
+ }
+ return matrix;
+}
+/**
+ * Constructs a matrix with the given cell values.
+ * <tt>values</tt> is required to have the form <tt>values[slice][row][column]</tt>
+ * and have exactly the same number of slices, rows and columns as the receiver.
+ * <p>
+ * The values are copied. So subsequent changes in <tt>values</tt> are not reflected in the matrix, and vice-versa.
+ *
+ * @param values the values to be filled into the cells.
+ * @return <tt>this</tt> (for convenience only).
+ * @throws IllegalArgumentException if <tt>values.length != slices() || for any 0 <= slice < slices(): values[slice].length != rows()</tt>.
+ * @throws IllegalArgumentException if <tt>for any 0 <= column < columns(): values[slice][row].length != columns()</tt>.
+ */
+public DoubleMatrix3D make(double[][][] values) {
+ if (this==sparse) return new SparseDoubleMatrix3D(values);
+ return new DenseDoubleMatrix3D(values);
+}
+/**
+ * Constructs a matrix with the given shape, each cell initialized with zero.
+ */
+public DoubleMatrix3D make(int slices, int rows, int columns) {
+ if (this==sparse) return new SparseDoubleMatrix3D(slices,rows,columns);
+ return new DenseDoubleMatrix3D(slices,rows,columns);
+}
+/**
+ * Constructs a matrix with the given shape, each cell initialized with the given value.
+ */
+public DoubleMatrix3D make(int slices, int rows, int columns, double initialValue) {
+ return make(slices,rows,columns).assign(initialValue);
+}
+/**
+ * Constructs a matrix with uniformly distributed values in <tt>(0,1)</tt> (exclusive).
+ */
+public DoubleMatrix3D random(int slices, int rows, int columns) {
+ return make(slices,rows,columns).assign(org.apache.mahout.jet.math.Functions.random());
+}
+}
Propchange: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleFactory3D.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleMatrix1D.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleMatrix1D.java?rev=883365&view=auto
==============================================================================
--- lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleMatrix1D.java (added)
+++ lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleMatrix1D.java Mon Nov 23 15:14:26 2009
@@ -0,0 +1,812 @@
+/*
+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;
+
+import org.apache.mahout.colt.list.DoubleArrayList;
+import org.apache.mahout.colt.list.IntArrayList;
+import org.apache.mahout.colt.matrix.impl.AbstractMatrix1D;
+/**
+Abstract base class for 1-d matrices (aka <i>vectors</i>) holding <tt>double</tt> elements.
+First see the <a href="package-summary.html">package summary</a> and javadoc <a href="package-tree.html">tree view</a> to get the broad picture.
+<p>
+A matrix has a number of cells (its <i>size</i>), which are assigned upon instance construction.
+Elements are accessed via zero based indexes.
+Legal indexes are of the form <tt>[0..size()-1]</tt>.
+Any attempt to access an element at a coordinate <tt>index<0 || index>=size()</tt> will throw an <tt>IndexOutOfBoundsException</tt>.
+
+@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 abstract class DoubleMatrix1D extends AbstractMatrix1D {
+/**
+ * Makes this class non instantiable, but still let's others inherit from it.
+ */
+protected DoubleMatrix1D() {}
+/**
+Applies a function to each cell and aggregates the results.
+Returns a value <tt>v</tt> such that <tt>v==a(size())</tt> where <tt>a(i) == aggr( a(i-1), f(get(i)) )</tt> and terminators are <tt>a(1) == f(get(0)), a(0)==Double.NaN</tt>.
+<p>
+<b>Example:</b>
+<pre>
+org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+matrix = 0 1 2 3
+
+// Sum( x[i]*x[i] )
+matrix.aggregate(F.plus,F.square);
+--> 14
+</pre>
+For further examples, see the <a href="package-summary.html#FunctionObjects">package doc</a>.
+
+@param aggr an aggregation function taking as first argument the current aggregation and as second argument the transformed current cell value.
+@param f a function transforming the current cell value.
+@return the aggregated measure.
+@see org.apache.mahout.jet.math.Functions
+*/
+public double aggregate(org.apache.mahout.colt.function.DoubleDoubleFunction aggr, org.apache.mahout.colt.function.DoubleFunction f) {
+ if (size==0) return Double.NaN;
+ double a = f.apply(getQuick(size-1));
+ for (int i=size-1; --i >= 0; ) {
+ a = aggr.apply(a, f.apply(getQuick(i)));
+ }
+ return a;
+}
+/**
+Applies a function to each corresponding cell of two matrices and aggregates the results.
+Returns a value <tt>v</tt> such that <tt>v==a(size())</tt> where <tt>a(i) == aggr( a(i-1), f(get(i),other.get(i)) )</tt> and terminators are <tt>a(1) == f(get(0),other.get(0)), a(0)==Double.NaN</tt>.
+<p>
+<b>Example:</b>
+<pre>
+org.apache.mahout.jet.math.Functions F = org.apache.mahout.jet.math.Functions.functions;
+x = 0 1 2 3
+y = 0 1 2 3
+
+// Sum( x[i]*y[i] )
+x.aggregate(y, F.plus, F.mult);
+--> 14
+
+// Sum( (x[i]+y[i])^2 )
+x.aggregate(y, F.plus, F.chain(F.square,F.plus));
+--> 56
+</pre>
+For further examples, see the <a href="package-summary.html#FunctionObjects">package doc</a>.
+
+@param aggr an aggregation function taking as first argument the current aggregation and as second argument the transformed current cell values.
+@param f a function transforming the current cell values.
+@return the aggregated measure.
+@throws IllegalArgumentException if <tt>size() != other.size()</tt>.
+@see org.apache.mahout.jet.math.Functions
+*/
+public double aggregate(DoubleMatrix1D other, org.apache.mahout.colt.function.DoubleDoubleFunction aggr, org.apache.mahout.colt.function.DoubleDoubleFunction f) {
+ checkSize(other);
+ if (size==0) return Double.NaN;
+ double a = f.apply(getQuick(size-1),other.getQuick(size-1));
+ for (int i=size-1; --i >= 0; ) {
+ a = aggr.apply(a, f.apply(getQuick(i),other.getQuick(i)));
+ }
+ return a;
+}
+/**
+ * Sets all cells to the state specified by <tt>values</tt>.
+ * <tt>values</tt> is required to have the same number of cells as the receiver.
+ * <p>
+ * The values are copied. So subsequent changes in <tt>values</tt> are not reflected in the matrix, and vice-versa.
+ *
+ * @param values the values to be filled into the cells.
+ * @return <tt>this</tt> (for convenience only).
+ * @throws IllegalArgumentException if <tt>values.length != size()</tt>.
+ */
+public DoubleMatrix1D assign(double[] values) {
+ if (values.length != size) throw new IllegalArgumentException("Must have same number of cells: length="+values.length+"size()="+size());
+ for (int i=size; --i >= 0;) {
+ setQuick(i,values[i]);
+ }
+ return this;
+}
+/**
+ * Sets all cells to the state specified by <tt>value</tt>.
+ * @param value the value to be filled into the cells.
+ * @return <tt>this</tt> (for convenience only).
+ */
+public DoubleMatrix1D assign(double value) {
+ for (int i=size; --i >= 0;) {
+ setQuick(i,value);
+ }
+ return this;
+}
+/**
+Assigns the result of a function to each cell; <tt>x[i] = function(x[i])</tt>.
+(Iterates downwards from <tt>[size()-1]</tt> to <tt>[0]</tt>).
+<p>
+<b>Example:</b>
+<pre>
+// change each cell to its sine
+matrix = 0.5 1.5 2.5 3.5
+matrix.assign(org.apache.mahout.jet.math.Functions.sin);
+-->
+matrix == 0.479426 0.997495 0.598472 -0.350783
+</pre>
+For further examples, see the <a href="package-summary.html#FunctionObjects">package doc</a>.
+
+@param function a function object taking as argument the current cell's value.
+@return <tt>this</tt> (for convenience only).
+@see org.apache.mahout.jet.math.Functions
+*/
+public DoubleMatrix1D assign(org.apache.mahout.colt.function.DoubleFunction function) {
+ for (int i=size; --i >= 0; ) {
+ setQuick(i, function.apply(getQuick(i)));
+ }
+ return this;
+}
+/**
+ * Replaces all cell values of the receiver with the values of another matrix.
+ * Both matrices must have the same size.
+ * If both matrices share the same cells (as is the case if they are views derived from the same matrix) and intersect in an ambiguous way, then replaces <i>as if</i> using an intermediate auxiliary deep copy of <tt>other</tt>.
+ *
+ * @param other the source matrix to copy from (may be identical to the receiver).
+ * @return <tt>this</tt> (for convenience only).
+ * @throws IllegalArgumentException if <tt>size() != other.size()</tt>.
+ */
+public DoubleMatrix1D assign(DoubleMatrix1D other) {
+ if (other==this) return this;
+ checkSize(other);
+ if (haveSharedCells(other)) other = other.copy();
+
+ for (int i=size; --i >= 0;) {
+ setQuick(i,other.getQuick(i));
+ }
+ return this;
+}
+/**
+Assigns the result of a function to each cell; <tt>x[i] = function(x[i],y[i])</tt>.
+<p>
+<b>Example:</b>
+<pre>
+// assign x[i] = x[i]<sup>y[i]</sup>
+m1 = 0 1 2 3;
+m2 = 0 2 4 6;
+m1.assign(m2, org.apache.mahout.jet.math.Functions.pow);
+-->
+m1 == 1 1 16 729
+</pre>
+For further examples, see the <a href="package-summary.html#FunctionObjects">package doc</a>.
+
+@param y the secondary matrix to operate on.
+@param function a function object taking as first argument the current cell's value of <tt>this</tt>,
+and as second argument the current cell's value of <tt>y</tt>,
+@return <tt>this</tt> (for convenience only).
+@throws IllegalArgumentException if <tt>size() != y.size()</tt>.
+@see org.apache.mahout.jet.math.Functions
+*/
+public DoubleMatrix1D assign(DoubleMatrix1D y, org.apache.mahout.colt.function.DoubleDoubleFunction function) {
+ checkSize(y);
+ for (int i=size; --i >= 0; ) {
+ setQuick(i, function.apply(getQuick(i), y.getQuick(i)));
+ }
+ return this;
+}
+/**
+Assigns the result of a function to each cell; <tt>x[i] = function(x[i],y[i])</tt>.
+(Iterates downwards from <tt>[size()-1]</tt> to <tt>[0]</tt>).
+<p>
+<b>Example:</b>
+<pre>
+// assign x[i] = x[i]<sup>y[i]</sup>
+m1 = 0 1 2 3;
+m2 = 0 2 4 6;
+m1.assign(m2, org.apache.mahout.jet.math.Functions.pow);
+-->
+m1 == 1 1 16 729
+
+// for non-standard functions there is no shortcut:
+m1.assign(m2,
+ new DoubleDoubleFunction() {
+ public double apply(double x, double y) { return Math.pow(x,y); }
+ }
+);
+</pre>
+For further examples, see the <a href="package-summary.html#FunctionObjects">package doc</a>.
+
+@param y the secondary matrix to operate on.
+@param function a function object taking as first argument the current cell's value of <tt>this</tt>,
+and as second argument the current cell's value of <tt>y</tt>,
+@return <tt>this</tt> (for convenience only).
+@throws IllegalArgumentException if <tt>size() != y.size()</tt>.
+@see org.apache.mahout.jet.math.Functions
+*/
+public DoubleMatrix1D assign(DoubleMatrix1D y, org.apache.mahout.colt.function.DoubleDoubleFunction function, org.apache.mahout.colt.list.IntArrayList nonZeroIndexes) {
+ checkSize(y);
+ int[] nonZeroElements = nonZeroIndexes.elements();
+
+ // specialized for speed
+ if (function== org.apache.mahout.jet.math.Functions.mult) { // x[i] = x[i] * y[i]
+ int j = 0;
+ for (int index=nonZeroIndexes.size(); --index >= 0; ) {
+ int i = nonZeroElements[index];
+ for (; j<i; j++) setQuick(j,0); // x[i] = 0 for all zeros
+ setQuick(i, getQuick(i) * y.getQuick(i)); // x[i] * y[i] for all nonZeros
+ j++;
+ }
+ }
+ else if (function instanceof org.apache.mahout.jet.math.PlusMult) {
+ double multiplicator = ((org.apache.mahout.jet.math.PlusMult) function).multiplicator;
+ if (multiplicator == 0) { // x[i] = x[i] + 0*y[i]
+ return this;
+ }
+ else if (multiplicator == 1) { // x[i] = x[i] + y[i]
+ for (int index=nonZeroIndexes.size(); --index >= 0; ) {
+ int i = nonZeroElements[index];
+ setQuick(i, getQuick(i) + y.getQuick(i));
+ }
+ }
+ else if (multiplicator == -1) { // x[i] = x[i] - y[i]
+ for (int index=nonZeroIndexes.size(); --index >= 0; ) {
+ int i = nonZeroElements[index];
+ setQuick(i, getQuick(i) - y.getQuick(i));
+ }
+ }
+ else { // the general case x[i] = x[i] + mult*y[i]
+ for (int index=nonZeroIndexes.size(); --index >= 0; ) {
+ int i = nonZeroElements[index];
+ setQuick(i, getQuick(i) + multiplicator*y.getQuick(i));
+ }
+ }
+ }
+ else { // the general case x[i] = f(x[i],y[i])
+ return assign(y,function);
+ }
+ return this;
+}
+/**
+ * Returns the number of cells having non-zero values; ignores tolerance.
+ */
+public int cardinality() {
+ int cardinality = 0;
+ for (int i=size; --i >= 0;) {
+ if (getQuick(i) != 0) cardinality++;
+ }
+ return cardinality;
+}
+/**
+ * Returns the number of cells having non-zero values, but at most maxCardinality; ignores tolerance.
+ */
+protected int cardinality(int maxCardinality) {
+ int cardinality = 0;
+ int i=size;
+ while (--i >= 0 && cardinality < maxCardinality) {
+ if (getQuick(i) != 0) cardinality++;
+ }
+ return cardinality;
+}
+/**
+ * Constructs and returns a deep copy of the receiver.
+ * <p>
+ * <b>Note that the returned matrix is an independent deep copy.</b>
+ * The returned matrix is not backed by this matrix, so changes in the returned matrix are not reflected in this matrix, and vice-versa.
+ *
+ * @return a deep copy of the receiver.
+ */
+public DoubleMatrix1D copy() {
+ DoubleMatrix1D copy = like();
+ copy.assign(this);
+ return copy;
+}
+/**
+ * Returns whether all cells are equal to the given value.
+ *
+ * @param value the value to test against.
+ * @return <tt>true</tt> if all cells are equal to the given value, <tt>false</tt> otherwise.
+ */
+public boolean equals(double value) {
+ return org.apache.mahout.colt.matrix.linalg.Property.DEFAULT.equals(this,value);
+}
+/**
+ * Compares this object against the specified object.
+ * The result is <code>true</code> if and only if the argument is
+ * not <code>null</code> and is at least a <code>DoubleMatrix1D</code> object
+ * that has the same sizes as the receiver and
+ * has exactly the same values at the same indexes.
+ * @param obj the object to compare with.
+ * @return <code>true</code> if the objects are the same;
+ * <code>false</code> otherwise.
+ */
+public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (!(obj instanceof DoubleMatrix1D)) return false;
+
+ return org.apache.mahout.colt.matrix.linalg.Property.DEFAULT.equals(this,(DoubleMatrix1D) obj);
+}
+/**
+ * Returns the matrix cell value at coordinate <tt>index</tt>.
+ *
+ * @param index the index of the cell.
+ * @return the value of the specified cell.
+ * @throws IndexOutOfBoundsException if <tt>index<0 || index>=size()</tt>.
+ */
+public double get(int index) {
+ if (index<0 || index>=size) checkIndex(index);
+ return getQuick(index);
+}
+/**
+ * Returns the content of this matrix if it is a wrapper; or <tt>this</tt> otherwise.
+ * Override this method in wrappers.
+ */
+protected DoubleMatrix1D getContent() {
+ return this;
+}
+/**
+Fills the coordinates and values of cells having non-zero values into the specified lists.
+Fills into the lists, starting at index 0.
+After this call returns the specified lists all have a new size, the number of non-zero values.
+<p>
+In general, fill order is <i>unspecified</i>.
+This implementation fills like: <tt>for (index = 0..size()-1) do ... </tt>.
+However, subclasses are free to us any other order, even an order that may change over time as cell values are changed.
+(Of course, result lists indexes are guaranteed to correspond to the same cell).
+<p>
+<b>Example:</b>
+<br>
+<pre>
+0, 0, 8, 0, 7
+-->
+indexList = (2,4)
+valueList = (8,7)
+</pre>
+In other words, <tt>get(2)==8, get(4)==7</tt>.
+
+@param indexList the list to be filled with indexes, can have any size.
+@param valueList the list to be filled with values, can have any size.
+*/
+public void getNonZeros(IntArrayList indexList, DoubleArrayList valueList) {
+ boolean fillIndexList = indexList != null;
+ boolean fillValueList = valueList != null;
+ if (fillIndexList) indexList.clear();
+ if (fillValueList) valueList.clear();
+ int s = size;
+ for (int i=0; i < s; i++) {
+ double value = getQuick(i);
+ if (value != 0) {
+ if (fillIndexList) indexList.add(i);
+ if (fillValueList) valueList.add(value);
+ }
+ }
+}
+/**
+Fills the coordinates and values of cells having non-zero values into the specified lists.
+Fills into the lists, starting at index 0.
+After this call returns the specified lists all have a new size, the number of non-zero values.
+<p>
+In general, fill order is <i>unspecified</i>.
+This implementation fills like: <tt>for (index = 0..size()-1) do ... </tt>.
+However, subclasses are free to us any other order, even an order that may change over time as cell values are changed.
+(Of course, result lists indexes are guaranteed to correspond to the same cell).
+<p>
+<b>Example:</b>
+<br>
+<pre>
+0, 0, 8, 0, 7
+-->
+indexList = (2,4)
+valueList = (8,7)
+</pre>
+In other words, <tt>get(2)==8, get(4)==7</tt>.
+
+@param indexList the list to be filled with indexes, can have any size.
+@param valueList the list to be filled with values, can have any size.
+*/
+public void getNonZeros(IntArrayList indexList, DoubleArrayList valueList, int maxCardinality) {
+ boolean fillIndexList = indexList != null;
+ boolean fillValueList = valueList != null;
+ int card = cardinality(maxCardinality);
+ if (fillIndexList) indexList.setSize(card);
+ if (fillValueList) valueList.setSize(card);
+ if (!(card<maxCardinality)) return;
+
+ if (fillIndexList) indexList.setSize(0);
+ if (fillValueList) valueList.setSize(0);
+ int s = size;
+ for (int i=0; i < s; i++) {
+ double value = getQuick(i);
+ if (value != 0) {
+ if (fillIndexList) indexList.add(i);
+ if (fillValueList) valueList.add(value);
+ }
+ }
+}
+/**
+ * Returns the matrix cell value at coordinate <tt>index</tt>.
+ *
+ * <p>Provided with invalid parameters this method may return invalid objects without throwing any exception.
+ * <b>You should only use this method when you are absolutely sure that the coordinate is within bounds.</b>
+ * Precondition (unchecked): <tt>index<0 || index>=size()</tt>.
+ *
+ * @param index the index of the cell.
+ * @return the value of the specified cell.
+ */
+public abstract double getQuick(int index);
+/**
+ * Returns <tt>true</tt> if both matrices share at least one identical cell.
+ */
+protected boolean haveSharedCells(DoubleMatrix1D other) {
+ if (other==null) return false;
+ if (this==other) return true;
+ return getContent().haveSharedCellsRaw(other.getContent());
+}
+/**
+ * Returns <tt>true</tt> if both matrices share at least one identical cell.
+ */
+protected boolean haveSharedCellsRaw(DoubleMatrix1D other) {
+ return false;
+}
+/**
+ * Construct and returns a new empty matrix <i>of the same dynamic type</i> as the receiver, having the same size.
+ * For example, if the receiver is an instance of type <tt>DenseDoubleMatrix1D</tt> the new matrix must also be of type <tt>DenseDoubleMatrix1D</tt>,
+ * if the receiver is an instance of type <tt>SparseDoubleMatrix1D</tt> the new matrix must also be of type <tt>SparseDoubleMatrix1D</tt>, etc.
+ * In general, the new matrix should have internal parametrization as similar as possible.
+ *
+ * @return a new empty matrix of the same dynamic type.
+ */
+public DoubleMatrix1D like() {
+ return like(size);
+}
+/**
+ * Construct and returns a new empty matrix <i>of the same dynamic type</i> as the receiver, having the specified size.
+ * For example, if the receiver is an instance of type <tt>DenseDoubleMatrix1D</tt> the new matrix must also be of type <tt>DenseDoubleMatrix1D</tt>,
+ * if the receiver is an instance of type <tt>SparseDoubleMatrix1D</tt> the new matrix must also be of type <tt>SparseDoubleMatrix1D</tt>, etc.
+ * In general, the new matrix should have internal parametrization as similar as possible.
+ *
+ * @param size the number of cell the matrix shall have.
+ * @return a new empty matrix of the same dynamic type.
+ */
+public abstract DoubleMatrix1D like(int size);
+/**
+ * Construct and returns a new 2-d matrix <i>of the corresponding dynamic type</i>, entirelly independent of the receiver.
+ * For example, if the receiver is an instance of type <tt>DenseDoubleMatrix1D</tt> the new matrix must be of type <tt>DenseDoubleMatrix2D</tt>,
+ * if the receiver is an instance of type <tt>SparseDoubleMatrix1D</tt> the new matrix must be of type <tt>SparseDoubleMatrix2D</tt>, etc.
+ *
+ * @param rows the number of rows the matrix shall have.
+ * @param columns the number of columns the matrix shall have.
+ * @return a new matrix of the corresponding dynamic type.
+ */
+public abstract DoubleMatrix2D like2D(int rows, int columns);
+/**
+ * Sets the matrix cell at coordinate <tt>index</tt> to the specified value.
+ *
+ * @param index the index of the cell.
+ * @param value the value to be filled into the specified cell.
+ * @throws IndexOutOfBoundsException if <tt>index<0 || index>=size()</tt>.
+ */
+public void set(int index, double value) {
+ if (index<0 || index>=size) checkIndex(index);
+ setQuick(index,value);
+}
+/**
+ * Sets the matrix cell at coordinate <tt>index</tt> to the specified value.
+ *
+ * <p>Provided with invalid parameters this method may access illegal indexes without throwing any exception.
+ * <b>You should only use this method when you are absolutely sure that the coordinate is within bounds.</b>
+ * Precondition (unchecked): <tt>index<0 || index>=size()</tt>.
+ *
+ * @param index the index of the cell.
+ * @param value the value to be filled into the specified cell.
+ */
+public abstract void setQuick(int index, double value);
+/**
+Swaps each element <tt>this[i]</tt> with <tt>other[i]</tt>.
+@throws IllegalArgumentException if <tt>size() != other.size()</tt>.
+*/
+public void swap(DoubleMatrix1D other) {
+ checkSize(other);
+ for (int i=size; --i >= 0; ) {
+ double tmp = getQuick(i);
+ setQuick(i, other.getQuick(i));
+ other.setQuick(i, tmp);
+ }
+ return;
+}
+/**
+Constructs and returns a 1-dimensional array containing the cell values.
+The values are copied. So subsequent changes in <tt>values</tt> are not reflected in the matrix, and vice-versa.
+The returned array <tt>values</tt> has the form
+<br>
+<tt>for (int i=0; i < size(); i++) values[i] = get(i);</tt>
+
+@return an array filled with the values of the cells.
+*/
+public double[] toArray() {
+ double[] values = new double[size];
+ toArray(values);
+ return values;
+}
+/**
+Fills the cell values into the specified 1-dimensional array.
+The values are copied. So subsequent changes in <tt>values</tt> are not reflected in the matrix, and vice-versa.
+After this call returns the array <tt>values</tt> has the form
+<br>
+<tt>for (int i=0; i < size(); i++) values[i] = get(i);</tt>
+
+@throws IllegalArgumentException if <tt>values.length < size()</tt>.
+*/
+public void toArray(double[] values) {
+ if (values.length < size) throw new IllegalArgumentException("values too small");
+ for (int i=size; --i >= 0; ) {
+ values[i] = getQuick(i);
+ }
+}
+/**
+ * Returns a string representation using default formatting.
+ * @see org.apache.mahout.colt.matrix.doublealgo.Formatter
+ */
+public String toString() {
+ return new org.apache.mahout.colt.matrix.doublealgo.Formatter().toString(this);
+}
+/**
+ * Constructs and returns a new view equal to the receiver.
+ * The view is a shallow clone. Calls <code>clone()</code> and casts the result.
+ * <p>
+ * <b>Note that the view is not a deep copy.</b>
+ * The returned matrix is backed by this matrix, so changes in the returned matrix are reflected in this matrix, and vice-versa.
+ * <p>
+ * Use {@link #copy()} to construct an independent deep copy rather than a new view.
+ *
+ * @return a new view of the receiver.
+ */
+protected DoubleMatrix1D view() {
+ return (DoubleMatrix1D) clone();
+}
+/**
+Constructs and returns a new <i>flip view</i>.
+What used to be index <tt>0</tt> is now index <tt>size()-1</tt>, ..., what used to be index <tt>size()-1</tt> is now index <tt>0</tt>.
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+
+@return a new flip view.
+*/
+public DoubleMatrix1D viewFlip() {
+ return (DoubleMatrix1D) (view().vFlip());
+}
+/**
+Constructs and returns a new <i>sub-range view</i> that is a <tt>width</tt> sub matrix starting at <tt>index</tt>.
+
+Operations on the returned view can only be applied to the restricted range.
+Any attempt to access coordinates not contained in the view will throw an <tt>IndexOutOfBoundsException</tt>.
+<p>
+<b>Note that the view is really just a range restriction:</b>
+The returned matrix is backed by this matrix, so changes in the returned matrix are reflected in this matrix, and vice-versa.
+<p>
+The view contains the cells from <tt>index..index+width-1</tt>.
+and has <tt>view.size() == width</tt>.
+A view's legal coordinates are again zero based, as usual.
+In other words, legal coordinates of the view are <tt>0 .. view.size()-1==width-1</tt>.
+As usual, any attempt to access a cell at other coordinates will throw an <tt>IndexOutOfBoundsException</tt>.
+
+@param index The index of the first cell.
+@param width The width of the range.
+@throws IndexOutOfBoundsException if <tt>index<0 || width<0 || index+width>size()</tt>.
+@return the new view.
+
+*/
+public DoubleMatrix1D viewPart(int index, int width) {
+ return (DoubleMatrix1D) (view().vPart(index,width));
+}
+/**
+Constructs and returns a new <i>selection view</i> that is a matrix holding the indicated cells.
+There holds <tt>view.size() == indexes.length</tt> and <tt>view.get(i) == this.get(indexes[i])</tt>.
+Indexes can occur multiple times and can be in arbitrary order.
+<p>
+<b>Example:</b>
+<br>
+<pre>
+this = (0,0,8,0,7)
+indexes = (0,2,4,2)
+-->
+view = (0,8,7,8)
+</pre>
+Note that modifying <tt>indexes</tt> after this call has returned has no effect on the view.
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+
+@param indexes The indexes of the cells that shall be visible in the new view. To indicate that <i>all</i> cells shall be visible, simply set this parameter to <tt>null</tt>.
+@return the new view.
+@throws IndexOutOfBoundsException if <tt>!(0 <= indexes[i] < size())</tt> for any <tt>i=0..indexes.length()-1</tt>.
+*/
+public DoubleMatrix1D viewSelection(int[] indexes) {
+ // check for "all"
+ if (indexes==null) {
+ indexes = new int[size];
+ for (int i=size; --i >= 0; ) indexes[i] = i;
+ }
+
+ checkIndexes(indexes);
+ int[] offsets = new int[indexes.length];
+ for (int i=indexes.length; --i >= 0; ) {
+ offsets[i] = index(indexes[i]);
+ }
+ return viewSelectionLike(offsets);
+}
+/**
+Constructs and returns a new <i>selection view</i> that is a matrix holding the cells matching the given condition.
+Applies the condition to each cell and takes only those cells where <tt>condition.apply(get(i))</tt> yields <tt>true</tt>.
+<p>
+<b>Example:</b>
+<br>
+<pre>
+// extract and view all cells with even value
+matrix = 0 1 2 3
+matrix.viewSelection(
+ new DoubleProcedure() {
+ public final boolean apply(double a) { return a % 2 == 0; }
+ }
+);
+-->
+matrix == 0 2
+</pre>
+For further examples, see the <a href="package-summary.html#FunctionObjects">package doc</a>.
+The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa.
+
+@param condition The condition to be matched.
+@return the new view.
+*/
+public DoubleMatrix1D viewSelection(org.apache.mahout.colt.function.DoubleProcedure condition) {
+ IntArrayList matches = new IntArrayList();
+ for (int i=0; i < size; i++) {
+ if (condition.apply(getQuick(i))) matches.add(i);
+ }
+ matches.trimToSize();
+ return viewSelection(matches.elements());
+}
+/**
+ * Construct and returns a new selection view.
+ *
+ * @param offsets the offsets of the visible elements.
+ * @return a new view.
+ */
+protected abstract DoubleMatrix1D viewSelectionLike(int[] offsets);
+/**
+Sorts the vector into ascending order, according to the <i>natural ordering</i>.
+This sort is guaranteed to be <i>stable</i>.
+For further information, see {@link org.apache.mahout.colt.matrix.doublealgo.Sorting#sort(DoubleMatrix1D)}.
+For more advanced sorting functionality, see {@link org.apache.mahout.colt.matrix.doublealgo.Sorting}.
+@return a new sorted vector (matrix) view.
+*/
+public DoubleMatrix1D viewSorted() {
+ return org.apache.mahout.colt.matrix.doublealgo.Sorting.mergeSort.sort(this);
+}
+/**
+Constructs and returns a new <i>stride view</i> which is a sub matrix consisting of every i-th cell.
+More specifically, the view has size <tt>this.size()/stride</tt> holding cells <tt>this.get(i*stride)</tt> for all <tt>i = 0..size()/stride - 1</tt>.
+
+@param stride the step factor.
+@throws IndexOutOfBoundsException if <tt>stride <= 0</tt>.
+@return the new view.
+
+*/
+public DoubleMatrix1D viewStrides(int stride) {
+ return (DoubleMatrix1D) (view().vStrides(stride));
+}
+/**
+ * Applies a procedure to each cell's value.
+ * Iterates downwards from <tt>[size()-1]</tt> to <tt>[0]</tt>,
+ * as demonstrated by this snippet:
+ * <pre>
+ * for (int i=size(); --i >=0;) {
+ * if (!procedure.apply(getQuick(i))) return false;
+ * }
+ * return true;
+ * </pre>
+ * Note that an implementation may use more efficient techniques, but must not use any other order.
+ *
+ * @param procedure a procedure object taking as argument the current cell's value. Stops iteration if the procedure returns <tt>false</tt>, otherwise continues.
+ * @return <tt>false</tt> if the procedure stopped before all elements where iterated over, <tt>true</tt> otherwise.
+ */
+private boolean xforEach(final org.apache.mahout.colt.function.DoubleProcedure procedure) {
+ for (int i=size; --i >= 0;) {
+ if (!procedure.apply(getQuick(i))) return false;
+ }
+ return true;
+}
+/**
+ * Returns the dot product of two vectors x and y, which is <tt>Sum(x[i]*y[i])</tt>.
+ * Where <tt>x == this</tt>.
+ * Operates on cells at indexes <tt>0 .. Math.min(size(),y.size())</tt>.
+ * @param y the second vector.
+ * @return the sum of products.
+ */
+public double zDotProduct(DoubleMatrix1D y) {
+ return zDotProduct(y,0,size);
+}
+/**
+ * Returns the dot product of two vectors x and y, which is <tt>Sum(x[i]*y[i])</tt>.
+ * Where <tt>x == this</tt>.
+ * Operates on cells at indexes <tt>from .. Min(size(),y.size(),from+length)-1</tt>.
+ * @param y the second vector.
+ * @param from the first index to be considered.
+ * @param length the number of cells to be considered.
+ * @return the sum of products; zero if <tt>from<0 || length<0</tt>.
+ */
+public double zDotProduct(DoubleMatrix1D y, int from, int length) {
+ if (from<0 || length<=0) return 0;
+
+ int tail = from+length;
+ if (size < tail) tail = size;
+ if (y.size < tail) tail = y.size;
+ length = tail-from;
+
+ double sum = 0;
+ int i = tail-1;
+ for (int k=length; --k >= 0; i--) {
+ sum += getQuick(i) * y.getQuick(i);
+ }
+ return sum;
+}
+/**
+ * Returns the dot product of two vectors x and y, which is <tt>Sum(x[i]*y[i])</tt>.
+ * Where <tt>x == this</tt>.
+ * @param y the second vector.
+ * @param nonZeroIndexes the indexes of cells in <tt>y</tt>having a non-zero value.
+ * @return the sum of products.
+ */
+public double zDotProduct(DoubleMatrix1D y, int from, int length, IntArrayList nonZeroIndexes) {
+ // determine minimum length
+ if (from<0 || length<=0) return 0;
+
+ int tail = from+length;
+ if (size < tail) tail = size;
+ if (y.size < tail) tail = y.size;
+ length = tail-from;
+ if (length<=0) return 0;
+
+ // setup
+ int[] nonZeroIndexElements = nonZeroIndexes.elements();
+ int index = 0;
+ int s = nonZeroIndexes.size();
+
+ // skip to start
+ while ((index < s) && nonZeroIndexElements[index]<from) index++;
+
+ // now the sparse dot product
+ int i;
+ double sum = 0;
+ while ((--length >= 0) && (index < s) && ((i=nonZeroIndexElements[index]) < tail)) {
+ sum += getQuick(i) * y.getQuick(i);
+ index++;
+ }
+
+ return sum;
+}
+/**
+ * Returns the dot product of two vectors x and y, which is <tt>Sum(x[i]*y[i])</tt>.
+ * Where <tt>x == this</tt>.
+ * @param y the second vector.
+ * @param nonZeroIndexes the indexes of cells in <tt>y</tt>having a non-zero value.
+ * @return the sum of products.
+ */
+protected double zDotProduct(DoubleMatrix1D y, IntArrayList nonZeroIndexes) {
+ return zDotProduct(y,0,size,nonZeroIndexes);
+ /*
+ double sum = 0;
+ int[] nonZeroIndexElements = nonZeroIndexes.elements();
+ for (int index=nonZeroIndexes.size(); --index >= 0; ) {
+ int i = nonZeroIndexElements[index];
+ sum += getQuick(i) * y.getQuick(i);
+ }
+ return sum;
+ */
+}
+/**
+ * Returns the sum of all cells; <tt>Sum( x[i] )</tt>.
+ * @return the sum.
+ */
+public double zSum() {
+ if (size()==0) return 0;
+ return aggregate(org.apache.mahout.jet.math.Functions.plus, org.apache.mahout.jet.math.Functions.identity);
+}
+}
Propchange: lucene/mahout/trunk/matrix/src/main/java/org/apache/mahout/matrix/matrix/DoubleMatrix1D.java
------------------------------------------------------------------------------
svn:eol-style = native