JAL-2380 fix Matrix.postMultiply()
[jalview.git] / src / jalview / math / Matrix.java
index bb7ed37..28b9d67 100755 (executable)
@@ -57,24 +57,33 @@ public class Matrix
   int maxIter = 45; // fudge - add 15 iterations, just in case
 
   /**
-   * Creates a new Matrix object.
+   * Creates a new Matrix object. For example
    * 
-   * @param value
-   *          DOCUMENT ME!
+   * <pre>
+   *   new Matrix(new double[][] {{2, 3}, {4, 5}, 2, 2)
+   * constructs
+   *   (2 3)
+   *   (4 5)
+   * </pre>
+   * 
+   * Note that ragged arrays (with not all rows, or columns, of the same
+   * length), are not supported by this class. They can be constructed, but
+   * results of operations on them are undefined and may throw exceptions.
+   * 
+   * @param values
+   *          the matrix values in row-major order
    * @param rows
-   *          DOCUMENT ME!
    * @param cols
-   *          DOCUMENT ME!
    */
-  public Matrix(double[][] value, int rows, int cols)
+  public Matrix(double[][] values, int rows, int cols)
   {
     this.rows = rows;
     this.cols = cols;
-    this.value = value;
+    this.value = values;
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns a new matrix which is the transposes of this one
    * 
    * @return DOCUMENT ME!
    */
@@ -113,15 +122,24 @@ public class Matrix
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns a new matrix which is the result of premultiplying this matrix by
+   * the supplied argument. If this of size AxB (A rows and B columns), and the
+   * argument is CxA (C rows and A columns), the result is of size CxB.
    * 
    * @param in
-   *          DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
+   * @return
+   * @throws IllegalArgumentException
+   *           if the number of columns in the pre-multiplier is not equal to
+   *           the number of rows in the multiplicand (this)
    */
   public Matrix preMultiply(Matrix in)
   {
+    if (in.cols != this.rows)
+    {
+      throw new IllegalArgumentException("Can't pre-multiply " + this.rows
+              + " rows by " + in.cols + " columns");
+    }
     double[][] tmp = new double[in.rows][this.cols];
 
     for (int i = 0; i < in.rows; i++)
@@ -141,12 +159,10 @@ public class Matrix
   }
 
   /**
-   * DOCUMENT ME!
    * 
    * @param in
-   *          DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
   public double[] vectorPostMultiply(double[] in)
   {
@@ -166,37 +182,34 @@ public class Matrix
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns a new matrix which is the result of postmultiplying this matrix by
+   * the supplied argument. If this of size AxB (A rows and B columns), and the
+   * argument is BxC (B rows and C columns), the result is of size AxC.
+   * <p>
+   * This method simply returns the result of in.preMultiply(this)
    * 
    * @param in
-   *          DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
+   * @return
+   * @throws IllegalArgumentException
+   *           if the number of rows in the post-multiplier is not equal to the
+   *           number of columns in the multiplicand (this)
+   * @see #preMultiply(Matrix)
    */
   public Matrix postMultiply(Matrix in)
   {
-    double[][] out = new double[this.rows][in.cols];
-
-    for (int i = 0; i < this.rows; i++)
+    if (in.rows != this.cols)
     {
-      for (int j = 0; j < in.cols; j++)
-      {
-        out[i][j] = 0.0;
-
-        for (int k = 0; k < rows; k++)
-        {
-          out[i][j] = out[i][j] + (value[i][k] * in.value[k][j]);
-        }
-      }
+      throw new IllegalArgumentException("Can't post-multiply " + this.cols
+              + " columns by " + in.rows + " rows");
     }
-
-    return new Matrix(out, this.cols, in.rows);
+    return in.preMultiply(this);
   }
 
   /**
-   * DOCUMENT ME!
+   * Answers a new matrix with a copy of the values in this one
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
   public Matrix copy()
   {
@@ -204,10 +217,11 @@ public class Matrix
 
     for (int i = 0; i < rows; i++)
     {
-      for (int j = 0; j < cols; j++)
-      {
-        newmat[i][j] = value[i][j];
-      }
+      System.arraycopy(value[i], 0, newmat[i], 0, value[i].length);
+      // for (int j = 0; j < cols; j++)
+      // {
+      // newmat[i][j] = value[i][j];
+      // }
     }
 
     return new Matrix(newmat, rows, cols);
@@ -738,20 +752,19 @@ public class Matrix
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns an array containing the values in the specified column
    * 
-   * @param n
-   *          DOCUMENT ME!
+   * @param col
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
-  public double[] getColumn(int n)
+  public double[] getColumn(int col)
   {
     double[] out = new double[rows];
 
     for (int i = 0; i < rows; i++)
     {
-      out[i] = value[i][n];
+      out[i] = value[i][col];
     }
 
     return out;
@@ -784,85 +797,4 @@ public class Matrix
       Format.print(ps, "%15.4e", e[j]);
     }
   }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param args
-   *          DOCUMENT ME!
-   */
-  public static void main(String[] args) throws Exception
-  {
-    int n = Integer.parseInt(args[0]);
-    double[][] in = new double[n][n];
-
-    for (int i = 0; i < n; i++)
-    {
-      for (int j = 0; j < n; j++)
-      {
-        in[i][j] = (double) Math.random();
-      }
-    }
-
-    Matrix origmat = new Matrix(in, n, n);
-
-    // System.out.println(" --- Original matrix ---- ");
-    // / origmat.print(System.out);
-    // System.out.println();
-    // System.out.println(" --- transpose matrix ---- ");
-    Matrix trans = origmat.transpose();
-
-    // trans.print(System.out);
-    // System.out.println();
-    // System.out.println(" --- OrigT * Orig ---- ");
-    Matrix symm = trans.postMultiply(origmat);
-
-    // symm.print(System.out);
-    // System.out.println();
-    // Copy the symmetric matrix for later
-    // Matrix origsymm = symm.copy();
-
-    // This produces the tridiagonal transformation matrix
-    // long tstart = System.currentTimeMillis();
-    symm.tred();
-
-    // long tend = System.currentTimeMillis();
-
-    // System.out.println("Time take for tred = " + (tend-tstart) + "ms");
-    // System.out.println(" ---Tridiag transform matrix ---");
-    // symm.print(System.out);
-    // System.out.println();
-    // System.out.println(" --- D vector ---");
-    // symm.printD(System.out);
-    // System.out.println();
-    // System.out.println(" --- E vector ---");
-    // symm.printE(System.out);
-    // System.out.println();
-    // Now produce the diagonalization matrix
-    // tstart = System.currentTimeMillis();
-    symm.tqli();
-    // tend = System.currentTimeMillis();
-
-    // System.out.println("Time take for tqli = " + (tend-tstart) + " ms");
-    // System.out.println(" --- New diagonalization matrix ---");
-    // symm.print(System.out);
-    // System.out.println();
-    // System.out.println(" --- D vector ---");
-    // symm.printD(System.out);
-    // System.out.println();
-    // System.out.println(" --- E vector ---");
-    // symm.printE(System.out);
-    // System.out.println();
-    // System.out.println(" --- First eigenvector --- ");
-    // double[] eigenv = symm.getColumn(0);
-    // for (int i=0; i < eigenv.length;i++) {
-    // Format.print(System.out,"%15.4f",eigenv[i]);
-    // }
-    // System.out.println();
-    // double[] neigenv = origsymm.vectorPostMultiply(eigenv);
-    // for (int i=0; i < neigenv.length;i++) {
-    // Format.print(System.out,"%15.4f",neigenv[i]/symm.d[0]);
-    // }
-    // System.out.println();
-  }
 }