You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2009/04/30 14:05:22 UTC

svn commit: r770179 - in /commons/proper/math/trunk/src: java/org/apache/commons/math/ode/NordsieckTransformer.java test/org/apache/commons/math/ode/NordsieckTransformerTest.java

Author: luc
Date: Thu Apr 30 12:05:22 2009
New Revision: 770179

URL: http://svn.apache.org/viewvc?rev=770179&view=rev
Log:
simplified Nordsieck transformer
extended its domain to handle several layouts for multistep state

Modified:
    commons/proper/math/trunk/src/java/org/apache/commons/math/ode/NordsieckTransformer.java
    commons/proper/math/trunk/src/test/org/apache/commons/math/ode/NordsieckTransformerTest.java

Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/ode/NordsieckTransformer.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/ode/NordsieckTransformer.java?rev=770179&r1=770178&r2=770179&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/ode/NordsieckTransformer.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/ode/NordsieckTransformer.java Thu Apr 30 12:05:22 2009
@@ -19,59 +19,63 @@
 
 import java.io.Serializable;
 import java.math.BigInteger;
-import java.util.Arrays;
 
 import org.apache.commons.math.fraction.BigFraction;
+import org.apache.commons.math.linear.DefaultFieldMatrixPreservingVisitor;
+import org.apache.commons.math.linear.FieldMatrix;
+import org.apache.commons.math.linear.FieldMatrixImpl;
 import org.apache.commons.math.linear.RealMatrix;
 import org.apache.commons.math.linear.RealMatrixImpl;
+import org.apache.commons.math.linear.decomposition.FieldDecompositionSolver;
+import org.apache.commons.math.linear.decomposition.FieldLUDecompositionImpl;
 
 /**
  * This class transforms state history between multistep (with or without
  * derivatives) and Nordsieck forms.
  * <p>
- * {@link MultistepIntegrator multistep integrators} use state history
- * from several previous steps to compute the current state. They may also use
- * the first derivative of current state. All states are separated by a fixed
- * step size h from each other. Since these methods are based on polynomial
- * interpolation, the information from the previous state may be represented
- * in another equivalent way: using the state higher order derivatives at
- * current step rather. This class transforms state history between these three
- * equivalent forms.
- * <p>
+ * {@link MultistepIntegrator multistep integrators} use state and state
+ * derivative history from several previous steps to compute the current state.
+ * All states are separated by a fixed step size h from each other. Since these
+ * methods are based on polynomial interpolation, the information from the
+ * previous states may be represented in another equivalent way: using the state
+ * higher order derivatives at current step only. This class transforms state
+ * history between these equivalent forms.
+ * </p>
  * <p>
- * The supported forms for a dimension n history are:
- * <ul>
- *   <li>multistep without derivatives:<br/>
- *     <pre>
- *       y<sub>k</sub>, y<sub>k-1</sub> ... y<sub>k-(n-2), y<sub>k-(n-1)</sub>
- *     </pre>
- *   </li>
- *   <li>multistep with first derivative at current step:<br/>
- *     <pre>
- *       y<sub>k</sub>, y'<sub>k</sub>, y<sub>k-1</sub> ... y<sub>k-(n-2)</sub>
- *     </pre>
- *   </li>
- *   <li>Nordsieck:
- *     <pre>
- *       y<sub>k</sub>, h y'<sub>k</sub>, h<sup>2</sup>/2 y''<sub>k</sub> ... h<sup>n-1</sup>/(n-1)! yn-1<sub>k</sub>
- *     </pre>
- *   </li>
- * </ul> 
- * In these expressions, y<sub>k</sub> is the state at the current step. For each p,
- * y<sub>k-p</sub> is the state at the p<sup>th</sup> previous step. y'<sub>k</sub>,
- * y''<sub>k</sub> ... yn-1<sub>k</sub> are respectively the first, second, ...
- * (n-1)<sup>th</sup> derivatives of the state at current step and h is the fixed
- * step size.
+ * The general multistep form for a dimension n state history at step k is
+ * composed of q-p previous states followed by s-r previous scaled derivatives
+ * with n = (q-p) + (s-r):
+ * <pre>
+ *   y<sub>k-p</sub>, y<sub>k-(p+1)</sub> ... y<sub>k-(q-1)</sub>
+ *   h y'<sub>k-r</sub>, h y'<sub>k-(r+1)</sub> ... h y'<sub>k-(s-1)</sub>
+ * </pre>
+ * As an example, the {@link
+ * org.apache.commons.math.ode.nonstiff.AdamsBashforthIntegrator Adams-Bashforth}
+ * integrator uses p=1, q=2, r=1, s=n. The {@link
+ * org.apache.commons.math.ode.nonstiff.AdamsMoultonIntegrator Adams-Moulton}
+ * integrator uses p=1, q=2, r=0, s=n-1.
  * </p>
  * <p>
- * The transforms are exact for polynomials.
+ * The Nordsieck form for a dimension n state history at step k is composed of the
+ * current state followed by n-1 current scaled derivatives:
+ * <pre>
+ * y<sub>k</sub>
+ * h y'<sub>k</sub>, h<sup>2</sup>/2 y''<sub>k</sub> ... h<sup>n-1</sup>/(n-1)! yn-1<sub>k</sub>
+ * </pre>
+ * Where y'<sub>k</sub>, y''<sub>k</sub> ... yn-1<sub>k</sub> are respectively the
+ * first, second, ... (n-1)<sup>th</sup> derivatives of the state at current step
+ * and h is the fixed step size.
  * </p>
  * <p>
  * In Nordsieck form, the state history can be converted from step size h to step
- * size h' by rescaling each component by 1, h'/h, (h'/h)<sup>2</sup> ...
+ * size h' by scaling each component by 1, h'/h, (h'/h)<sup>2</sup> ...
  * (h'/h)<sup>n-1</sup>.
  * </p>
  * <p>
+ * The transform between general multistep and Nordsieck forms is exact for
+ * polynomials.
+ * </p>
+ * <p>
  * Instances of this class are guaranteed to be immutable.
  * </p>
  * @see org.apache.commons.math.ode.MultistepIntegrator
@@ -83,279 +87,129 @@
 public class NordsieckTransformer implements Serializable {
 
     /** Serializable version identifier. */
-    private static final long serialVersionUID = -2707468304560314664L;
-
-    /** Nordsieck to Multistep  without derivatives matrix. */
-    private final RealMatrix matNtoMWD;
-                                           
-    /** Multistep without derivatives to Nordsieck matrix. */
-    private final RealMatrix matMWDtoN;
+    private static final long serialVersionUID = 2216907099394084076L;
 
     /** Nordsieck to Multistep matrix. */
-    private final RealMatrix matNtoM;
+    private final RealMatrix nordsieckToMultistep;
                                            
     /** Multistep to Nordsieck matrix. */
-    private final RealMatrix matMtoN;
+    private final RealMatrix multistepToNordsieck;
 
     /**
      * Build a transformer for a specified order.
-     * @param n dimension of the history
+     * <p>states considered are y<sub>k-p</sub>, y<sub>k-(p+1)</sub> ...
+     * y<sub>k-(q-1)</sub> and scaled derivatives considered are
+     * h y'<sub>k-r</sub>, h y'<sub>k-(r+1)</sub> ... h y'<sub>k-(s-1)</sub>
+     * @param p start state index offset in multistep form
+     * @param q end state index offset in multistep form
+     * @param r start state derivative index offset in multistep form
+     * @param s end state derivative index offset in multistep form
      */
-    public NordsieckTransformer(final int n) {
-
-        // from Nordsieck to multistep without derivatives
-        final BigInteger[][] bigNtoMWD = buildNordsieckToMultistepWithoutDerivatives(n);
-        double[][] dataNtoMWD = new double[n][n];
-        for (int i = 0; i < n; ++i) {
-            double[]     dRow = dataNtoMWD[i];
-            BigInteger[] bRow = bigNtoMWD[i];
-            for (int j = 0; j < n; ++j) {
-                dRow[j] = bRow[j].doubleValue();
-            }
-        }
-        matNtoMWD = new RealMatrixImpl(dataNtoMWD, false);
-
-        // from multistep without derivatives to Nordsieck
-        final BigFraction[][] bigToN = buildMultistepWithoutDerivativesToNordsieck(n);
-        double[][] dataMWDtoN = new double[n][n];
-        for (int i = 0; i < n; ++i) {
-            double[]     dRow = dataMWDtoN[i];
-            BigFraction[] bRow = bigToN[i];
-            for (int j = 0; j < n; ++j) {
-                dRow[j] = bRow[j].doubleValue();
-            }
-        }
-        matMWDtoN = new RealMatrixImpl(dataMWDtoN, false);
+    public NordsieckTransformer(final int p, final int q, final int r, final int s) {
 
         // from Nordsieck to multistep
-        final BigInteger[][] bigNtoM = buildNordsieckToMultistep(n);
-        double[][] dataNtoM = new double[n][n];
-        for (int i = 0; i < n; ++i) {
-            double[]     dRow = dataNtoM[i];
-            BigInteger[] bRow = bigNtoM[i];
-            for (int j = 0; j < n; ++j) {
-                dRow[j] = bRow[j].doubleValue();
-            }
-        }
-        matNtoM = new RealMatrixImpl(dataNtoM, false);
+        final FieldMatrix<BigFraction> bigNtoM = buildNordsieckToMultistep(p, q, r, s);
+        Convertor convertor = new Convertor();
+        bigNtoM.walkInOptimizedOrder(convertor);
+        nordsieckToMultistep = convertor.getConvertedMatrix();
 
         // from multistep to Nordsieck
-        convertMWDtNtoMtN(bigToN);
-        double[][] dataMtoN = new double[n][n];
-        for (int i = 0; i < n; ++i) {
-            double[]     dRow = dataMtoN[i];
-            BigFraction[] bRow = bigToN[i];
-            for (int j = 0; j < n; ++j) {
-                dRow[j] = bRow[j].doubleValue();
-            }
-        }
-        matMtoN = new RealMatrixImpl(dataMtoN, false);
+        final FieldDecompositionSolver<BigFraction> solver =
+            new FieldLUDecompositionImpl<BigFraction>(bigNtoM).getSolver();
+        final FieldMatrix<BigFraction> bigMtoN = solver.getInverse();
+        convertor = new Convertor();
+        bigMtoN.walkInOptimizedOrder(convertor);
+        multistepToNordsieck = convertor.getConvertedMatrix();
 
     }
 
     /**
-     * Build the transform from Nordsieck to multistep without derivatives.
-     * @param n dimension of the history
-     * @return transform from Nordsieck to multistep without derivatives
+     * Build the transform from Nordsieck to multistep.
+     * <p>states considered are y<sub>k-p</sub>, y<sub>k-(p+1)</sub> ...
+     * y<sub>k-(q-1)</sub> and scaled derivatives considered are
+     * h y'<sub>k-r</sub>, h y'<sub>k-(r+1)</sub> ... h y'<sub>k-(s-1)</sub>
+     * @param p start state index offset in multistep form
+     * @param q end state index offset in multistep form
+     * @param r start state derivative index offset in multistep form
+     * @param s end state derivative index offset in multistep form
+     * @return transform from Nordsieck to multistep
      */
-    public static BigInteger[][] buildNordsieckToMultistepWithoutDerivatives(final int n) {
+    public static FieldMatrix<BigFraction> buildNordsieckToMultistep(final int p, final int q,
+                                                                     final int r, final int s) {
 
-        final BigInteger[][] array = new BigInteger[n][n];
+        final int n = (q - p) + (s - r);
+        final BigFraction[][] array = new BigFraction[n][n];
 
-        // row 0: [1 0 0 0 ... 0 ]
-        array[0][0] = BigInteger.ONE;
-        Arrays.fill(array[0], 1, n, BigInteger.ZERO);
-
-        // the following expressions are direct applications of Taylor series
-        // rows 1 to n-1: aij = (-i)^j
-        // [ 1  -1   1  -1   1 ...]
-        // [ 1  -2   4  -8  16 ...]
-        // [ 1  -3   9 -27  81 ...]
-        // [ 1  -4  16 -64 256 ...]
-        for (int i = 1; i < n; ++i) {
-            final BigInteger[] row  = array[i];
-            final BigInteger factor = BigInteger.valueOf(-i);
-            BigInteger aj = BigInteger.ONE;
+        int i = 0;
+        for (int l = p; l < q; ++l) {
+            // handle previous state y<sub>(k-l)</sub>
+            // the following expressions are direct applications of Taylor series
+            // y<sub>k-1</sub>: [ 1  -1   1  -1   1 ...]
+            // y<sub>k-2</sub>: [ 1  -2   4  -8  16 ...]
+            // y<sub>k-3</sub>: [ 1  -3   9 -27  81 ...]
+            // y<sub>k-4</sub>: [ 1  -4  16 -64 256 ...]
+            final BigFraction[] row = array[i++];
+            final BigInteger factor = BigInteger.valueOf(-l);
+            BigInteger al = BigInteger.ONE;
             for (int j = 0; j < n; ++j) {
-                row[j] = aj;
-                aj = aj.multiply(factor);
+                row[j] = new BigFraction(al, BigInteger.ONE);
+                al = al.multiply(factor);
             }
         }
 
-        return array;
-
-    }
-
-    /**
-     * Build the transform from multistep without derivatives to Nordsieck.
-     * @param n dimension of the history
-     * @return transform from multistep without derivatives to Nordsieck
-     */
-    public static BigFraction[][] buildMultistepWithoutDerivativesToNordsieck(final int n) {
-
-        final BigInteger[][] iArray = new BigInteger[n][n];
-
-        // row 0: [1 0 0 0 ... 0 ]
-        iArray[0][0] = BigInteger.ONE;
-        Arrays.fill(iArray[0], 1, n, BigInteger.ZERO);
-
-        // We use recursive definitions of triangular integer series for each column.
-        // For example column 0 of matrices of increasing dimensions are:
-        //  1/0! for dimension 1
-        //  1/1!,  1/1! for dimension 2
-        //  2/2!,  3/2!,  1/2! for dimension 3
-        //  6/3!, 11/3!,  6/3!,  1/3! for dimension 4
-        // 24/4!, 50/4!, 35/4!, 10/4!, 1/4! for dimension 5
-        // The numerators are the Stirling numbers of the first kind, (A008275 in
-        // Sloane's encyclopedia http://www.research.att.com/~njas/sequences/A008275)
-        // with a multiplicative factor of +/-1 (which we will write +/-binomial(n-1, 0)).
-        // In the same way, column 1 is A049444 with a multiplicative factor of
-        // +/-binomial(n-1, 1) and column 2 is A123319 with a multiplicative factor of
-        // +/-binomial(n-1, 2). The next columns are defined by similar definitions but
-        // are not identified in Sloane's encyclopedia.
-        // Another interesting observation is that for each dimension k, the last column
-        // (except the initial 0) is a copy of the first column of the dimension k-1 matrix,
-        // possibly with an opposite sign (i.e. these columns are also linked to Stirling
-        // numbers of the first kind).
-        for (int i = 1; i < n; ++i) {
-
-            final BigInteger bigI = BigInteger.valueOf(i);
-
-            // row i
-            BigInteger[] rowK   = iArray[i];
-            BigInteger[] rowKm1 = iArray[i - 1];
-            for (int j = 0; j < i; ++j) {
-                rowK[j] = BigInteger.ONE;
-            }
-            rowK[i] = rowKm1[0];
-
-            // rows i-1 to 1
-            for (int k = i - 1; k > 0; --k) {
-
-                // select rows
-                rowK   = rowKm1;
-                rowKm1 = iArray[k - 1];
-
-                // apply recursive defining formula
-                for (int j = 0; j < i; ++j) {
-                    rowK[j] = rowK[j].multiply(bigI).add(rowKm1[j]);
-                }
-
-                // initialize new last column
-                rowK[i] = rowKm1[0];
-
-            }
-            rowKm1[0] = rowKm1[0].multiply(bigI);
-
-        }
-
-        // apply column specific factors
-        final BigInteger factorial = iArray[0][0];
-        final BigFraction[][] fArray = new BigFraction[n][n];
-        for (int i = 0; i < n; ++i) {
-            final BigFraction[] fRow = fArray[i];
-            final BigInteger[]  iRow = iArray[i];
-            BigInteger binomial = BigInteger.ONE;
-            for (int j = 0; j < n; ++j) {
-                fRow[j] = new BigFraction(binomial.multiply(iRow[j]), factorial);
-                binomial = binomial.negate().multiply(BigInteger.valueOf(n - j - 1)).divide(BigInteger.valueOf(j + 1));
+        for (int l = r; l < s; ++l) {
+            // handle previous state scaled derivative h y'<sub>(k-l)</sub>
+            // the following expressions are direct applications of Taylor series
+            // h y'<sub>k-1</sub>: [ 0  1  -2   3  -4   5 ...]
+            // h y'<sub>k-2</sub>: [ 0  1  -4   6  -8  10 ...]
+            // h y'<sub>k-3</sub>: [ 0  1  -6   9 -12  15 ...]
+            // h y'<sub>k-4</sub>: [ 0  1  -8  12 -16  20 ...]
+            final BigFraction[] row = array[i++];
+            final BigInteger factor = BigInteger.valueOf(-l);
+            row[0] = BigFraction.ZERO;
+            BigInteger al = BigInteger.ONE;
+            for (int j = 1; j < n; ++j) {
+                row[j] = new BigFraction(al.multiply(BigInteger.valueOf(j)), BigInteger.ONE);
+                al = al.multiply(factor);
             }
         }
 
-        return fArray;
+        return new FieldMatrixImpl<BigFraction>(array, false);
 
     }
 
-    /**
-     * Build the transform from Nordsieck to multistep.
-     * @param n dimension of the history
-     * @return transform from Nordsieck to multistep
-     */
-    public static BigInteger[][] buildNordsieckToMultistep(final int n) {
-
-        final BigInteger[][] array = new BigInteger[n][n];
-
-        // row 0: [1 0 0 0 ... 0 ]
-        array[0][0] = BigInteger.ONE;
-        Arrays.fill(array[0], 1, n, BigInteger.ZERO);
+    /** Convertor for {@link FieldMatrix}/{@link BigFraction}. */
+    private static class Convertor extends DefaultFieldMatrixPreservingVisitor<BigFraction> {
 
-        if (n > 1) {
+        /** Serializable version identifier. */
+        private static final long serialVersionUID = -1799685632320460982L;
 
-            // row 1: [0 1 0 0 ... 0 ]
-            array[1][0] = BigInteger.ZERO;
-            array[1][1] = BigInteger.ONE;
-            Arrays.fill(array[1], 2, n, BigInteger.ZERO);
-
-            // the following expressions are direct applications of Taylor series
-            // rows 2 to n-1: aij = (1-i)^j
-            // [ 1  -1   1  -1   1 ...]
-            // [ 1  -2   4  -8  16 ...]
-            // [ 1  -3   9 -27  81 ...]
-            // [ 1  -4  16 -64 256 ...]
-            for (int i = 2; i < n; ++i) {
-                final BigInteger[] row  = array[i];
-                final BigInteger factor = BigInteger.valueOf(1 - i);
-                BigInteger aj = BigInteger.ONE;
-                for (int j = 0; j < n; ++j) {
-                    row[j] = aj;
-                    aj = aj.multiply(factor);
-                }
-            }
+        /** Converted array. */
+        private double[][] data;
 
+        /** Simple constructor. */
+        public Convertor() {
+            super(BigFraction.ZERO);
         }
 
-        return array;
-
-    }
-
-    /**
-     * Build the transform from multistep to Nordsieck.
-     * @param n dimension of the history
-     * @return transform from multistep to Nordsieck
-     */
-    public static BigFraction[][] buildMultistepToNordsieck(final int n) {
-        final BigFraction[][] array = buildMultistepWithoutDerivativesToNordsieck(n);
-        convertMWDtNtoMtN(array);
-        return array;
-    }
-
-    /**
-     * Convert a transform from multistep without derivatives to Nordsieck to
-     * multistep to Nordsieck.
-     * @param work array, contains tansform from multistep without derivatives
-     * to Nordsieck on input, will be overwritten with tansform from multistep
-     * to Nordsieck on output
-     */
-    private static void convertMWDtNtoMtN(BigFraction[][] array) {
-
-        final int n = array.length;
-        if (n == 1) {
-            return;
+        /** {@inheritDoc} */
+        @Override
+        public void start(int rows, int columns,
+                          int startRow, int endRow, int startColumn, int endColumn) {
+            data = new double[rows][columns];
         }
 
-        // the second row of the matrix without derivatives represents the linear equation:
-        // hy' = a0 yk + a1 yk-1 + ... + a(n-1) yk-(n-1)
-        // we solve it with respect to the oldest state yk-(n-1) and get
-        // yk-(n-1) = -a0/a(n-1) yk + 1/a(n-1) hy' - a1/a(n-1) yk-1 - ...
-        final BigFraction[] secondRow = array[1];
-        final BigFraction[] solved    = new BigFraction[n];
-        final BigFraction f = secondRow[n - 1].reciprocal().negate();
-        solved[0] = secondRow[0].multiply(f);
-        solved[1] = f.negate();
-        for (int j = 2; j < n; ++j) {
-            solved[j] = secondRow[j - 1].multiply(f);
+        /** {@inheritDoc} */
+        @Override
+        public void visit(int row, int column, BigFraction value) {
+            data[row][column] = value.doubleValue();
         }
 
-        // update the matrix so it expects hy' in second element
-        // rather than yk-(n-1) in last elements when post-multiplied
-        for (int i = 0; i < n; ++i) {
-            final BigFraction[] rowI = array[i];
-            final BigFraction last = rowI[n - 1];
-            for (int j = n - 1; j > 1; --j) {
-                rowI[j] = rowI[j - 1].add(last.multiply(solved[j]));
-            }
-            rowI[1] = last.multiply(solved[1]);
-            rowI[0] = rowI[0].add(last.multiply(solved[0]));
+        /** Get the converted matrix.
+         * @return converted matrix
+         */
+        RealMatrix getConvertedMatrix() {
+            return new RealMatrixImpl(data, false);
         }
 
     }
@@ -364,148 +218,76 @@
      * Transform a scalar state history from multistep form to Nordsieck form.
      * <p>
      * The input state history must be in multistep form with element 0 for
-     * current state, element 1 for current state scaled first derivative, element
-     * 2 for previous state ... element n-1 for (n-2)<sup>th</sup> previous state.
+     * y<sub>k-p</sub>, element 1 for y<sub>k-(p+1)</sub> ... element q-p-1 for
+     * y<sub>k-(q-1)</sub>, element q-p for h y'<sub>k-r</sub>, element q-p+1
+     * for h y'<sub>k-(r+1)</sub> ... element n-1 for h y'<sub>k-(s-1)</sub>.
      * The output state history will be in Nordsieck form with element 0 for
-     * current state, element 1 for current state scaled first derivative, element
-     * 2 for current state scaled second derivative ... element n-1 for current state
-     * scaled (n-1)<sup>th</sup> derivative.
+     * y<sub>k</sub>, element 1 for h y'<sub>k</sub>, element 2 for
+     * h<sup>2</sup>/2 y''<sub>k</sub> ... element n-1 for
+     * h<sup>n-1</sup>/(n-1)! yn-1<sub>k</sub>.
      * </p>
      * @param multistepHistory scalar state history in multistep form
      * @return scalar state history in Nordsieck form
      */
     public double[] multistepToNordsieck(final double[] multistepHistory) {
-        return matMtoN.operate(multistepHistory);
+        return multistepToNordsieck.operate(multistepHistory);
     }
 
     /**
      * Transform a vectorial state history from multistep form to Nordsieck form.
      * <p>
      * The input state history must be in multistep form with row 0 for
-     * current state, row 1 for current state scaled first derivative, row
-     * 2 for previous state ... row n-1 for (n-2)<sup>th</sup> previous state.
+     * y<sub>k-p</sub>, row 1 for y<sub>k-(p+1)</sub> ... row q-p-1 for
+     * y<sub>k-(q-1)</sub>, row q-p for h y'<sub>k-r</sub>, row q-p+1
+     * for h y'<sub>k-(r+1)</sub> ... row n-1 for h y'<sub>k-(s-1)</sub>.
      * The output state history will be in Nordsieck form with row 0 for
-     * current state, row 1 for current state scaled first derivative, row
-     * 2 for current state scaled second derivative ... row n-1 for current state
-     * scaled (n-1)<sup>th</sup> derivative.
+     * y<sub>k</sub>, row 1 for h y'<sub>k</sub>, row 2 for
+     * h<sup>2</sup>/2 y''<sub>k</sub> ... row n-1 for
+     * h<sup>n-1</sup>/(n-1)! yn-1<sub>k</sub>.
      * </p>
      * @param multistepHistory vectorial state history in multistep form
      * @return vectorial state history in Nordsieck form
      */
     public RealMatrix multistepToNordsieck(final RealMatrix multistepHistory) {
-        return matMtoN.multiply(multistepHistory);
+        return multistepToNordsieck.multiply(multistepHistory);
     }
 
     /**
      * Transform a scalar state history from Nordsieck form to multistep form.
      * <p>
      * The input state history must be in Nordsieck form with element 0 for
-     * current state, element 1 for current state scaled first derivative, element
-     * 2 for current state scaled second derivative ... element n-1 for current state
-     * scaled (n-1)<sup>th</sup> derivative.
+     * y<sub>k</sub>, element 1 for h y'<sub>k</sub>, element 2 for
+     * h<sup>2</sup>/2 y''<sub>k</sub> ... element n-1 for
+     * h<sup>n-1</sup>/(n-1)! yn-1<sub>k</sub>.
      * The output state history will be in multistep form with element 0 for
-     * current state, element 1 for current state scaled first derivative, element
-     * 2 for previous state ... element n-1 for (n-2)<sup>th</sup> previous state.
+     * y<sub>k-p</sub>, element 1 for y<sub>k-(p+1)</sub> ... element q-p-1 for
+     * y<sub>k-(q-1)</sub>, element q-p for h y'<sub>k-r</sub>, element q-p+1
+     * for h y'<sub>k-(r+1)</sub> ... element n-1 for h y'<sub>k-(s-1)</sub>.
      * </p>
      * @param nordsieckHistory scalar state history in Nordsieck form
      * @return scalar state history in multistep form
      */
     public double[] nordsieckToMultistep(final double[] nordsieckHistory) {
-        return matNtoM.operate(nordsieckHistory);
+        return nordsieckToMultistep.operate(nordsieckHistory);
     }
 
     /**
      * Transform a vectorial state history from Nordsieck form to multistep form.
      * <p>
      * The input state history must be in Nordsieck form with row 0 for
-     * current state, row 1 for current state scaled first derivative, row
-     * 2 for current state scaled second derivative ... row n-1 for current state
-     * scaled (n-1)<sup>th</sup> derivative.
+     * y<sub>k</sub>, row 1 for h y'<sub>k</sub>, row 2 for
+     * h<sup>2</sup>/2 y''<sub>k</sub> ... row n-1 for
+     * h<sup>n-1</sup>/(n-1)! yn-1<sub>k</sub>.
      * The output state history will be in multistep form with row 0 for
-     * current state, row 1 for current state scaled first derivative, row
-     * 2 for previous state ... row n-1 for (n-2)<sup>th</sup> previous state.
+     * y<sub>k-p</sub>, row 1 for y<sub>k-(p+1)</sub> ... row q-p-1 for
+     * y<sub>k-(q-1)</sub>, row q-p for h y'<sub>k-r</sub>, row q-p+1
+     * for h y'<sub>k-(r+1)</sub> ... row n-1 for h y'<sub>k-(s-1)</sub>.
      * </p>
      * @param nordsieckHistory vectorial state history in Nordsieck form
      * @return vectorial state history in multistep form
      */
     public RealMatrix nordsieckToMultistep(final RealMatrix nordsieckHistory) {
-        return matNtoM.multiply(nordsieckHistory);
-    }
-
-    /**
-     * Transform a scalar state history from multistep without derivatives form
-     * to Nordsieck form.
-     * <p>
-     * The input state history must be in multistep without derivatives form with
-     * element 0 for current state, element 1 for previous state ... element n-1
-     * for (n-1)<sup>th</sup> previous state.
-     * The output state history will be in Nordsieck form with element 0 for
-     * current state, element 1 for current state scaled first derivative, element
-     * 2 for current state scaled second derivative ... element n-1 for current state
-     * scaled (n-1)<sup>th</sup> derivative.
-     * </p>
-     * @param mwdHistory scalar state history in multistep without derivatives form
-     * @return scalar state history in Nordsieck form
-     */
-    public double[] multistepWithoutDerivativesToNordsieck(final double[] mwdHistory) {
-        return matMWDtoN.operate(mwdHistory);
-    }
-
-    /**
-     * Transform a vectorial state history from multistep without derivatives form
-     * to Nordsieck form.
-     * <p>
-     * The input state history must be in multistep without derivatives form with
-     * row 0 for current state, row 1 for previous state ... row n-1
-     * for (n-1)<sup>th</sup> previous state.
-     * The output state history will be in Nordsieck form with row 0 for
-     * current state, row 1 for current state scaled first derivative, row
-     * 2 for current state scaled second derivative ... row n-1 for current state
-     * scaled (n-1)<sup>th</sup> derivative.
-     * </p>
-     * @param mwdHistory vectorial state history in multistep without derivatives form
-     * @return vectorial state history in Nordsieck form
-     */
-    public RealMatrix multistepWithoutDerivativesToNordsieck(final RealMatrix mwdHistory) {
-        return matMWDtoN.multiply(mwdHistory);
-    }
-
-    /**
-     * Transform a scalar state history from Nordsieck form to multistep without
-     * derivatives form.
-     * <p>
-     * The input state history must be in Nordsieck form with element 0 for
-     * current state, element 1 for current state scaled first derivative, element
-     * 2 for current state scaled second derivative ... element n-1 for current state
-     * scaled (n-1)<sup>th</sup> derivative.
-     * The output state history will be in multistep without derivatives form with
-     * element 0 for current state, element 1 for previous state ... element n-1
-     * for (n-1)<sup>th</sup> previous state.
-     * </p>
-     * @param nordsieckHistory scalar state history in Nordsieck form
-     * @return scalar state history in multistep without derivatives form
-     */
-    public double[] nordsieckToMultistepWithoutDerivatives(final double[] nordsieckHistory) {
-        return matNtoMWD.operate(nordsieckHistory);
-    }
-
-    /**
-     * Transform a vectorial state history from Nordsieck form to multistep without
-     * derivatives form.
-     * <p>
-     * The input state history must be in Nordsieck form with row 0 for
-     * current state, row 1 for current state scaled first derivative, row
-     * 2 for current state scaled second derivative ... row n-1 for current state
-     * scaled (n-1)<sup>th</sup> derivative.
-     * The output state history will be in multistep without derivatives form with
-     * row 0 for current state, row 1 for previous state ... row n-1
-     * for (n-1)<sup>th</sup> previous state.
-     * </p>
-     * @param nordsieckHistory vectorial state history in Nordsieck form
-     * @return vectorial state history in multistep without derivatives form
-     */
-    public RealMatrix nordsieckToMultistepWithoutDerivatives(final RealMatrix nordsieckHistory) {
-        return matNtoMWD.multiply(nordsieckHistory);
+        return nordsieckToMultistep.multiply(nordsieckHistory);
     }
 
 }

Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/ode/NordsieckTransformerTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/ode/NordsieckTransformerTest.java?rev=770179&r1=770178&r2=770179&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/org/apache/commons/math/ode/NordsieckTransformerTest.java (original)
+++ commons/proper/math/trunk/src/test/org/apache/commons/math/ode/NordsieckTransformerTest.java Thu Apr 30 12:05:22 2009
@@ -17,7 +17,6 @@
 
 package org.apache.commons.math.ode;
 
-import java.math.BigInteger;
 import java.util.Random;
 
 import junit.framework.Test;
@@ -26,6 +25,7 @@
 
 import org.apache.commons.math.analysis.polynomials.PolynomialFunction;
 import org.apache.commons.math.fraction.BigFraction;
+import org.apache.commons.math.linear.FieldMatrix;
 import org.apache.commons.math.linear.RealMatrix;
 import org.apache.commons.math.linear.RealMatrixImpl;
 
@@ -37,29 +37,39 @@
     }
 
     public void testDimension2() {
-        NordsieckTransformer transformer = new NordsieckTransformer(2);
+        NordsieckTransformer transformer = new NordsieckTransformer(0, 2, 0, 0);
+        double[] nordsieckHistory = new double[] { 1.0,  2.0 };
+        double[] multistepHistory = new double[] { 1.0, -1.0 };
+        checkVector(nordsieckHistory, transformer.multistepToNordsieck(multistepHistory));
+        checkVector(multistepHistory, transformer.nordsieckToMultistep(nordsieckHistory));
+    }
+
+    public void testDimension2Der() {
+        NordsieckTransformer transformer = new NordsieckTransformer(0, 1, 0, 1);
         double[] nordsieckHistory = new double[] { 1.0,  2.0 };
-        double[] mwdHistory       = new double[] { 1.0, -1.0 };
         double[] multistepHistory = new double[] { 1.0,  2.0 };
-        checkVector(nordsieckHistory, transformer.multistepWithoutDerivativesToNordsieck(mwdHistory));
-        checkVector(mwdHistory, transformer.nordsieckToMultistepWithoutDerivatives(nordsieckHistory));
         checkVector(nordsieckHistory, transformer.multistepToNordsieck(multistepHistory));
         checkVector(multistepHistory, transformer.nordsieckToMultistep(nordsieckHistory));
     }
 
     public void testDimension3() {
-        NordsieckTransformer transformer = new NordsieckTransformer(3);
+        NordsieckTransformer transformer = new NordsieckTransformer(0, 3, 0, 0);
+        double[] nordsieckHistory = new double[] { 1.0,  4.0, 18.0 };
+        double[] multistepHistory = new double[] { 1.0, 15.0, 65.0 };
+        checkVector(nordsieckHistory, transformer.multistepToNordsieck(multistepHistory));
+        checkVector(multistepHistory, transformer.nordsieckToMultistep(nordsieckHistory));
+    }
+
+    public void testDimension3Der() {
+        NordsieckTransformer transformer = new NordsieckTransformer(0, 2, 0, 1);
         double[] nordsieckHistory = new double[] { 1.0,  4.0, 18.0 };
-        double[] mwdHistory       = new double[] { 1.0, 15.0, 65.0 };
-        double[] multistepHistory = new double[] { 1.0,  4.0, 15.0 };
-        checkVector(nordsieckHistory, transformer.multistepWithoutDerivativesToNordsieck(mwdHistory));
-        checkVector(mwdHistory, transformer.nordsieckToMultistepWithoutDerivatives(nordsieckHistory));
+        double[] multistepHistory = new double[] { 1.0, 15.0,  4.0 };
         checkVector(nordsieckHistory, transformer.multistepToNordsieck(multistepHistory));
         checkVector(multistepHistory, transformer.nordsieckToMultistep(nordsieckHistory));
     }
 
     public void testDimension7() {
-        NordsieckTransformer transformer = new NordsieckTransformer(7);
+        NordsieckTransformer transformer = new NordsieckTransformer(0, 7, 0, 0);
         RealMatrix nordsieckHistory =
             new RealMatrixImpl(new double[][] {
                                    {  1,  2,  3 },
@@ -70,7 +80,7 @@
                                    {  2,  0,  1 },
                                    {  1,  1,  2 }
                                 }, false);
-        RealMatrix mwdHistory       =
+        RealMatrix multistepHistory =
             new RealMatrixImpl(new double[][] {
                                    {     1,     2,     3 },
                                    {     4,     3,     6 },
@@ -80,183 +90,130 @@
                                    { 10036, 15147, 29278 },
                                    { 32449, 45608, 87951 }
                                }, false);
+
+        RealMatrix m = transformer.multistepToNordsieck(multistepHistory);
+        assertEquals(0.0, m.subtract(nordsieckHistory).getNorm(), 1.0e-11);
+        m = transformer.nordsieckToMultistep(nordsieckHistory);
+        assertEquals(0.0, m.subtract(multistepHistory).getNorm(), 1.0e-11);
+
+    }
+
+    public void testDimension7Der() {
+        NordsieckTransformer transformer = new NordsieckTransformer(0, 6, 0, 1);
+        RealMatrix nordsieckHistory =
+            new RealMatrixImpl(new double[][] {
+                                   {  1,  2,  3 },
+                                   { -2,  1,  0 },
+                                   {  1,  1,  1 },
+                                   {  0, -1,  1 },
+                                   {  1, -1,  2 },
+                                   {  2,  0,  1 },
+                                   {  1,  1,  2 }
+                                }, false);
         RealMatrix multistepHistory =
             new RealMatrixImpl(new double[][] {
                                    {     1,     2,     3 },
-                                   {    -2,     1,     0 },
                                    {     4,     3,     6 },
                                    {    25,    60,   127 },
                                    {   340,   683,  1362 },
                                    {  2329,  3918,  7635 },
-                                   { 10036, 15147, 29278 }
+                                   { 10036, 15147, 29278 },
+                                   {    -2,     1,     0 }
                                }, false);
 
-        RealMatrix m = transformer.multistepWithoutDerivativesToNordsieck(mwdHistory);
-        assertEquals(0.0, m.subtract(nordsieckHistory).getNorm(), 1.0e-11);
-        m = transformer.nordsieckToMultistepWithoutDerivatives(nordsieckHistory);
-        assertEquals(0.0, m.subtract(mwdHistory).getNorm(), 1.0e-11);
-        m = transformer.multistepToNordsieck(multistepHistory);
+        RealMatrix m = transformer.multistepToNordsieck(multistepHistory);
         assertEquals(0.0, m.subtract(nordsieckHistory).getNorm(), 1.0e-11);
         m = transformer.nordsieckToMultistep(nordsieckHistory);
         assertEquals(0.0, m.subtract(multistepHistory).getNorm(), 1.0e-11);
 
     }
 
-    public void testInverseWithoutDerivatives() {
-        for (int n = 1; n < 20; ++n) {
-            BigInteger[][] nTom =
-                NordsieckTransformer.buildNordsieckToMultistepWithoutDerivatives(n);
-            BigFraction[][] mTon =
-                NordsieckTransformer.buildMultistepWithoutDerivativesToNordsieck(n);
-            for (int i = 0; i < n; ++i) {
-                for (int j = 0; j < n; ++j) {
-                    BigFraction s = BigFraction.ZERO;
-                    for (int k = 0; k < n; ++k) {
-                        s = s.add(mTon[i][k].multiply(nTom[k][j]));
-                    }
-                    assertEquals((i == j) ? BigFraction.ONE : BigFraction.ZERO, s);
-                }
-            }
-        }
-    }
-
-    public void testInverse() {
-        for (int n = 1; n < 20; ++n) {
-            BigInteger[][] nTom =
-                NordsieckTransformer.buildNordsieckToMultistep(n);
-            BigFraction[][] mTon =
-                NordsieckTransformer.buildMultistepToNordsieck(n);
-            for (int i = 0; i < n; ++i) {
-                for (int j = 0; j < n; ++j) {
-                    BigFraction s = BigFraction.ZERO;
-                    for (int k = 0; k < n; ++k) {
-                        s = s.add(mTon[i][k].multiply(nTom[k][j]));
-                    }
-                    assertEquals((i == j) ? BigFraction.ONE : BigFraction.ZERO, s);
-                }
-            }
-        }
-    }
-
     public void testMatrices1() {
         checkMatrix(1, new int[][] { { 1 } },
-                    NordsieckTransformer.buildMultistepWithoutDerivativesToNordsieck(1));
-        checkMatrix(new int[][] { { 1 } },
-                    NordsieckTransformer.buildNordsieckToMultistepWithoutDerivatives(1));
-        checkMatrix(1, new int[][] { { 1 } },
-                    NordsieckTransformer.buildMultistepToNordsieck(1));
-        checkMatrix(new int[][] { { 1 } },
-                    NordsieckTransformer.buildNordsieckToMultistep(1));
+                    NordsieckTransformer.buildNordsieckToMultistep(0, 1, 0, 0));
     }
 
     public void testMatrices2() {
         checkMatrix(1, new int[][] { { 1, 0 }, { 1, -1 } },
-                    NordsieckTransformer.buildMultistepWithoutDerivativesToNordsieck(2));
-        checkMatrix(new int[][] { { 1, 0 }, { 1, -1 } },
-                    NordsieckTransformer.buildNordsieckToMultistepWithoutDerivatives(2));
-        checkMatrix(1, new int[][] { { 1, 0 }, { 0, 1 } },
-                    NordsieckTransformer.buildMultistepToNordsieck(2));
-        checkMatrix(new int[][] { { 1, 0 }, { 0, 1 } },
-                    NordsieckTransformer.buildNordsieckToMultistep(2));
+                    NordsieckTransformer.buildNordsieckToMultistep(0, 2, 0, 0));
     }
 
     public void testMatrices3() {
-        checkMatrix(2, new int[][] { { 2, 0, 0 }, { 3, -4, 1 }, { 1, -2, 1 } },
-                    NordsieckTransformer.buildMultistepWithoutDerivativesToNordsieck(3));
-        checkMatrix(new int[][] { { 1, 0, 0 }, { 1, -1, 1 }, { 1, -2, 4 } },
-                    NordsieckTransformer.buildNordsieckToMultistepWithoutDerivatives(3));
-        checkMatrix(1, new int[][] { { 1, 0, 0 }, { 0, 1, 0 }, { -1, 1, 1} },
-                    NordsieckTransformer.buildMultistepToNordsieck(3));
-        checkMatrix(new int[][] { { 1, 0, 0 }, { 0, 1, 0 }, { 1, -1, 1 } },
-                    NordsieckTransformer.buildNordsieckToMultistep(3));
+        checkMatrix(1, new int[][] { { 1, 0, 0 }, { 1, -1, 1 }, { 1, -2, 4 } },
+                    NordsieckTransformer.buildNordsieckToMultistep(0, 3, 0, 0));
     }
 
     public void testMatrices4() {
-        checkMatrix(6, new int[][] { { 6, 0, 0, 0 }, { 11, -18, 9, -2 }, { 6, -15, 12, -3 }, { 1, -3, 3, -1 } },
-                    NordsieckTransformer.buildMultistepWithoutDerivativesToNordsieck(4));
-        checkMatrix(new int[][] { { 1, 0, 0, 0 }, { 1, -1, 1, -1 }, { 1, -2, 4, -8 }, { 1, -3, 9, -27 } },
-                    NordsieckTransformer.buildNordsieckToMultistepWithoutDerivatives(4));
-        checkMatrix(4, new int[][] { { 4, 0, 0, 0 }, { 0, 4, 0, 0 }, { -7, 6, 8, -1 }, { -3, 2, 4, -1 } },
-                    NordsieckTransformer.buildMultistepToNordsieck(4));
-        checkMatrix(new int[][] { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 1, -1, 1, -1 }, { 1, -2, 4, -8 } },
-                    NordsieckTransformer.buildNordsieckToMultistep(4));
+        checkMatrix(1, new int[][] { { 1, 0, 0, 0 }, { 1, -1, 1, -1 }, { 1, -2, 4, -8 }, { 1, -3, 9, -27 } },
+                    NordsieckTransformer.buildNordsieckToMultistep(0, 4, 0, 0));
     }
 
     public void testPolynomial() {
-        Random r = new Random(1847222905841997856l);
-        for (int n = 2; n < 9; ++n) {
-
-            // build a polynomial and its derivatives
-            double[] coeffs = new double[n + 1];
-            for (int i = 0; i < n; ++i) {
-                coeffs[i] = 2 * r.nextDouble() - 1.0;
-            }
-            PolynomialFunction[] polynomials = new PolynomialFunction[n];
-            polynomials[0] = new PolynomialFunction(coeffs);
-            for (int k = 1; k < polynomials.length; ++k) {
-                polynomials[k] = (PolynomialFunction) polynomials[k - 1].derivative();
-            }
-            double h = 0.01;
+        Random random = new Random(1847222905841997856l);
+        for (int n = 2; n < 10; ++n) {
+            for (int m = 0; m < 10; ++m) {
+
+                // choose p, q, r, s
+                int qMinusP = 1 + random.nextInt(n);
+                int sMinusR = n - qMinusP;
+                int p       = random.nextInt(5) - 2; // possible values: -2, -1, 0, 1, 2
+                int q       = p + qMinusP;
+                int r       = random.nextInt(5) - 2; // possible values: -2, -1, 0, 1, 2
+                int s       = r + sMinusR;
+
+                // build a polynomial and its derivatives
+                double[] coeffs = new double[n + 1];
+                for (int i = 0; i < n; ++i) {
+                    coeffs[i] = 2.0 * random.nextDouble() - 1.0;
+                }
+                PolynomialFunction[] polynomials = new PolynomialFunction[n];
+                polynomials[0] = new PolynomialFunction(coeffs);
+                for (int i = 1; i < polynomials.length; ++i) {
+                    polynomials[i] = (PolynomialFunction) polynomials[i - 1].derivative();
+                }
 
-            // build a state history in multistep form
-            double[] multistepHistory = new double[n];
-            multistepHistory[0] = polynomials[0].value(1.0);
-            multistepHistory[1] = h * polynomials[1].value(1.0);
-            for (int i = 2; i < multistepHistory.length; ++i) {
-                multistepHistory[i] = polynomials[0].value(1.0 - (i - 1) * h);
-            }
+                double x = 0.75;
+                double h = 0.01;
 
-            // build the same state history in multistep without derivatives form
-            double[] mwdHistory = new double[n];
-            for (int i = 0; i < multistepHistory.length; ++i) {
-                mwdHistory[i] = polynomials[0].value(1.0 - i * h);
-            }
+                // build a state history in multistep form
+                double[] multistepHistory = new double[n];
+                for (int k = p; k < q; ++k) {
+                    multistepHistory[k-p] = polynomials[0].value(x - k * h);
+                }
+                for (int k = r; k < s; ++k) {
+                    multistepHistory[k + qMinusP - r] = h * polynomials[1].value(x - k * h);
+                }
 
-            // build the same state history in Nordsieck form
-            double[] nordsieckHistory = new double[n];
-            double scale = 1.0;
-            for (int i = 0; i < nordsieckHistory.length; ++i) {
-                nordsieckHistory[i] = scale * polynomials[i].value(1.0);
-                scale *= h / (i + 1);
-            }
+                // build the same state history in Nordsieck form
+                double[] nordsieckHistory = new double[n];
+                double scale = 1.0;
+                for (int i = 0; i < nordsieckHistory.length; ++i) {
+                    nordsieckHistory[i] = scale * polynomials[i].value(x);
+                    scale *= h / (i + 1);
+                }
 
-            // check the transform is exact for these polynomials states
-            NordsieckTransformer transformer = new NordsieckTransformer(n);
-            checkVector(nordsieckHistory, transformer.multistepWithoutDerivativesToNordsieck(mwdHistory));
-            checkVector(mwdHistory,       transformer.nordsieckToMultistepWithoutDerivatives(nordsieckHistory));
-            checkVector(nordsieckHistory, transformer.multistepToNordsieck(multistepHistory));
-            checkVector(multistepHistory, transformer.nordsieckToMultistep(nordsieckHistory));
+                // check the transform is exact for these polynomials states
+                NordsieckTransformer transformer = new NordsieckTransformer(p, q, r, s);
+                checkVector(nordsieckHistory, transformer.multistepToNordsieck(multistepHistory));
+                checkVector(multistepHistory, transformer.nordsieckToMultistep(nordsieckHistory));
 
+            }
         }
     }
 
     private void checkVector(double[] reference, double[] candidate) {
         assertEquals(reference.length, candidate.length);
         for (int i = 0; i < reference.length; ++i) {
-            assertEquals(reference[i], candidate[i], 1.0e-14);
+            assertEquals(reference[i], candidate[i], 2.0e-12);
         }
     }
 
-    private void checkMatrix(int[][] reference, BigInteger[][] candidate) {
-        assertEquals(reference.length, candidate.length);
-        for (int i = 0; i < reference.length; ++i) {
-            int[] rRow = reference[i];
-            BigInteger[] cRow = candidate[i];
-            assertEquals(rRow.length, cRow.length);
-            for (int j = 0; j < rRow.length; ++j) {
-                assertEquals(rRow[j], cRow[j].intValue());
-            }
-        }
-    }
-
-    private void checkMatrix(int denominator, int[][] reference, BigFraction[][] candidate) {
-        assertEquals(reference.length, candidate.length);
+    private void checkMatrix(int denominator, int[][] reference, FieldMatrix<BigFraction> candidate) {
+        assertEquals(reference.length, candidate.getRowDimension());
         for (int i = 0; i < reference.length; ++i) {
             int[] rRow = reference[i];
-            BigFraction[] cRow = candidate[i];
-            assertEquals(rRow.length, cRow.length);
             for (int j = 0; j < rRow.length; ++j) {
-                assertEquals(new BigFraction(rRow[j], denominator), cRow[j]);
+                assertEquals(new BigFraction(rRow[j], denominator), candidate.getEntry(i, j));
             }
         }
     }