Added rigging for checking eigenvalues and eigenvectors and some easy test cases.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/branches/MATH_2_0@721943 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/test/org/apache/commons/math/linear/EigenDecompositionImplTest.java b/src/test/org/apache/commons/math/linear/EigenDecompositionImplTest.java
index 2cae9f9..fed8121 100644
--- a/src/test/org/apache/commons/math/linear/EigenDecompositionImplTest.java
+++ b/src/test/org/apache/commons/math/linear/EigenDecompositionImplTest.java
@@ -255,6 +255,107 @@
         }
 
     }
+    
+    /**
+     * Matrix with eigenvalues {8, -1, -1}
+     */
+    public void testRepeatedEigenvalue() {
+        RealMatrix repeated = new RealMatrixImpl(new double[][] {
+                {3,  2,  4},
+                {2,  0,  2},
+                {4,  2,  3}
+        }); 
+        EigenDecomposition ed = new EigenDecompositionImpl(repeated);
+        checkEigenValues((new double[] {8, -1, -1}), ed, 1E-12);
+        checkEigenVector((new double[] {2, 1, 2}), ed, 1E-12);
+    }
+    
+    /**
+     * Matrix with eigenvalues {2, 0, 12}
+     */
+    public void testDistinctEigenvalues() {
+        RealMatrix distinct = new RealMatrixImpl(new double[][] {
+                {3, 1, -4},  
+                {1, 3, -4}, 
+                {-4, -4, 8}
+        });
+        EigenDecomposition ed = new EigenDecompositionImpl(distinct);
+        checkEigenValues((new double[] {2, 0, 12}), ed, 1E-12);
+        checkEigenVector((new double[] {1, -1, 0}), ed, 1E-12);
+        checkEigenVector((new double[] {1, 1, 1}), ed, 1E-12);
+        checkEigenVector((new double[] {-1, -1, 2}), ed, 1E-12);
+    }
+    
+    /**
+     * Verifies that the given EigenDecomposition has eigenvalues equivalent to
+     * the targetValues, ignoring the order of the values and allowing
+     * values to differ by tolerance.
+     */
+    protected void checkEigenValues(double[] targetValues,
+            EigenDecomposition ed, double tolerance) {
+        double[] observed = ed.getEigenvalues();
+        for (int i = 0; i < observed.length; i++) {
+            assertTrue(isIncludedValue(observed[i], targetValues, tolerance));
+            assertTrue(isIncludedValue(targetValues[i], observed, tolerance));
+        }
+    }
+    
+    /**
+     * Returns true iff there is an entry within tolerance of value in
+     * searchArray.
+     */
+    private boolean isIncludedValue(double value, double[] searchArray,
+            double tolerance) {
+       boolean found = false;
+       int i = 0;
+       while (!found && i < searchArray.length) {
+           if (Math.abs(value - searchArray[i]) < tolerance) {
+               found = true;
+           }
+           i++;
+       }
+       return found;
+    }
+    
+    /**
+     * Returns true iff eigenVector is a scalar multiple of one of the columns
+     * of ed.getV().  Does not try linear combinations - i.e., should only be
+     * used to find vectors in one-dimensional eigenspaces.
+     */
+    protected void checkEigenVector(double[] eigenVector,
+            EigenDecomposition ed, double tolerance) {
+        assertTrue(isIncludedColumn(eigenVector, ed.getV(), tolerance));
+    }
+    
+    /**
+     * Returns true iff there is a column that is a scalar multiple of column
+     * in searchMatrix (modulo tolerance)
+     */
+    private boolean isIncludedColumn(double[] column, RealMatrix searchMatrix,
+            double tolerance) {
+        boolean found = false;
+        int i = 0;
+        while (!found && i < searchMatrix.getColumnDimension()) {
+            double multiplier = 1d;
+            boolean matching = true;
+            int j = 0;
+            while (matching && j < searchMatrix.getRowDimension()) {
+                double colEntry = searchMatrix.getEntry(j, i);
+                // Use the first entry where both are non-zero as scalar
+                if (multiplier == 1d && Math.abs(colEntry) > 1E-14
+                        && Math.abs(column[j]) > 1e-14) {
+                    multiplier = colEntry / column[j];
+                } 
+                if (Math.abs(column[j] * multiplier - colEntry) > tolerance) {
+                    matching = false;
+                }
+                j++;
+            }
+            found = matching;
+            i++;
+        }
+        return found;
+    }
 
     public void setUp() {
         refValues = new double[] {