Author: mikl
Date: Mon Mar 21 09:28:34 2011
New Revision: 1083713

URL: http://svn.apache.org/viewvc?rev=1083713&view=rev
Log:
Fixes MATH-435 for FieldMatrix<T>, too.

Modified:
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractFieldMatrix.java
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/FieldMatrix.java
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/FieldMatrixImplTest.java

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractFieldMatrix.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractFieldMatrix.java?rev=1083713&r1=1083712&r2=1083713&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractFieldMatrix.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractFieldMatrix.java
 Mon Mar 21 09:28:34 2011
@@ -18,6 +18,7 @@
 package org.apache.commons.math.linear;
 
 import java.lang.reflect.Array;
+import java.util.ArrayList;
 import java.util.Arrays;
 
 import org.apache.commons.math.Field;
@@ -264,6 +265,65 @@ public abstract class AbstractFieldMatri
     public FieldMatrix<T> preMultiply(final FieldMatrix<T> m) {
         return m.multiply(this);
     }
+    
+    /** {@inheritDoc} */
+    @Override
+    public FieldMatrix<T> power(final int p) {
+        if (p < 0) {
+            throw new IllegalArgumentException("p must be >= 0");
+        }
+        
+        if (!isSquare()) {
+            throw new NonSquareMatrixException(getRowDimension(), 
getColumnDimension());
+        }
+        
+        if (p == 0) {
+            return MatrixUtils.createFieldIdentityMatrix(this.getField(), 
this.getRowDimension());
+        }
+        
+        if (p == 1) {
+            return this.copy();
+        }
+
+        final int power = p - 1;
+
+        /*
+         * Only log_2(p) operations is used by doing as follows:
+         * 5^214 = 5^128 * 5^64 * 5^16 * 5^4 * 5^2
+         * 
+         * In general, the same approach is used for A^p.
+         */
+
+        final char[] binaryRepresentation = Integer.toBinaryString(power)
+                .toCharArray();
+        final ArrayList<Integer> nonZeroPositions = new ArrayList<Integer>();
+
+        for (int i = 0; i < binaryRepresentation.length; ++i) {
+            if (binaryRepresentation[i] == '1') {
+                final int pos = binaryRepresentation.length - i - 1;
+                nonZeroPositions.add(pos);
+            }
+        }
+
+        ArrayList<FieldMatrix<T>> results = new ArrayList<FieldMatrix<T>>(
+                binaryRepresentation.length);
+
+        results.add(0, this.copy());
+
+        for (int i = 1; i < binaryRepresentation.length; ++i) {
+            final FieldMatrix<T> s = results.get(i - 1);
+            final FieldMatrix<T> r = s.multiply(s);
+            results.add(i, r);
+        }
+
+        FieldMatrix<T> result = this.copy();
+
+        for (Integer i : nonZeroPositions) {
+            result = result.multiply(results.get(i));
+        }
+
+        return result;
+    }
 
     /** {@inheritDoc} */
     public T[][] getData() {

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/FieldMatrix.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/FieldMatrix.java?rev=1083713&r1=1083712&r2=1083713&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/FieldMatrix.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/FieldMatrix.java
 Mon Mar 21 09:28:34 2011
@@ -116,6 +116,17 @@ public interface FieldMatrix<T extends F
     FieldMatrix<T> preMultiply(FieldMatrix<T> m);
 
     /**
+     * Returns the result multiplying this with itself <code>p</code> times. 
+     * Depending on the type of the field elements, T, 
+     * instability for high powers might occur. 
+     * @param      p raise this to power p
+     * @return     this^p
+     * @throws     IllegalArgumentException if p < 0
+     *             NonSquareMatrixException if the matrix is not square
+     */
+    FieldMatrix<T> power(final int p);
+    
+    /**
      * Returns matrix entries as a two-dimensional array.
      *
      * @return a 2-dimensional array of entries.

Modified: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/FieldMatrixImplTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/FieldMatrixImplTest.java?rev=1083713&r1=1083712&r2=1083713&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/FieldMatrixImplTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/FieldMatrixImplTest.java
 Mon Mar 21 09:28:34 2011
@@ -199,6 +199,52 @@ public final class FieldMatrixImplTest {
        TestUtils.assertEquals(m3.multiply(m4), m5);
    }
 
+    @Test
+    public void testPower() {
+        FieldMatrix<Fraction> m = new 
Array2DRowFieldMatrix<Fraction>(testData);
+        FieldMatrix<Fraction> mInv = new 
Array2DRowFieldMatrix<Fraction>(testDataInv);
+        FieldMatrix<Fraction> mPlusInv = new 
Array2DRowFieldMatrix<Fraction>(testDataPlusInv);
+        FieldMatrix<Fraction> identity = new 
Array2DRowFieldMatrix<Fraction>(id);
+        
+        TestUtils.assertEquals(m.power(0), identity);        
+        TestUtils.assertEquals(mInv.power(0), identity);        
+        TestUtils.assertEquals(mPlusInv.power(0), identity);
+        
+        TestUtils.assertEquals(m.power(1), m);        
+        TestUtils.assertEquals(mInv.power(1), mInv);        
+        TestUtils.assertEquals(mPlusInv.power(1), mPlusInv); 
+        
+        FieldMatrix<Fraction> C1 = m.copy();
+        FieldMatrix<Fraction> C2 = mInv.copy();
+        FieldMatrix<Fraction> C3 = mPlusInv.copy();
+        
+        // stop at 5 to avoid overflow
+        for (int i = 2; i <= 5; ++i) {
+            C1 = C1.multiply(m);
+            C2 = C2.multiply(mInv);
+            C3 = C3.multiply(mPlusInv);
+            
+            TestUtils.assertEquals(m.power(i), C1);        
+            TestUtils.assertEquals(mInv.power(i), C2);        
+            TestUtils.assertEquals(mPlusInv.power(i), C3);            
+        }
+        
+        try {
+            FieldMatrix<Fraction> mNotSquare = new 
Array2DRowFieldMatrix<Fraction>(testData2T);
+            mNotSquare.power(2);
+            Assert.fail("Expecting NonSquareMatrixException");
+        } catch (NonSquareMatrixException ex) {
+            // ignored
+        }
+        
+        try {
+            m.power(-1);
+            Assert.fail("Expecting IllegalArgumentException");
+        } catch (IllegalArgumentException ex) {
+            // ignored
+        }
+    }
+
     /** test trace */
     @Test
     public void testTrace() {


Reply via email to