/**
   * Preforms standard tests that can be performed on any decomposition without prior knowledge of
   * what the results should be.
   */
  public void performStandardTests(SymmetricQRAlgorithmDecomposition alg, Matrix A, int numReal) {

    // basic sanity tests
    assertEquals(A.rowCount(), alg.getNumberOfEigenvalues());

    if (numReal >= 0) {
      for (int i = 0; i < A.rowCount(); i++) {
        Vector2 v = alg.getEigenvalue(i);

        assertFalse(Double.isNaN(v.x));
        if (v.y == 0) numReal--;
        else if (Math.abs(v.y) < 10 * EPS) numReal--;
      }

      // if there are more than the expected number of real eigenvalues this will
      // be negative
      assertEquals(0, numReal);
    }

    //        checkCharacteristicEquation(alg,A);
    if (computeVectors) {
      testPairsConsistent(alg, A);
      testVectorsLinearlyIndependent(alg);
    }
  }
  /** If the eigenvalues are all known, real, and the same this can be used to check them. */
  public void testEigenvalues(SymmetricQRAlgorithmDecomposition alg, double expected) {

    for (int i = 0; i < alg.getNumberOfEigenvalues(); i++) {
      Vector2 c = alg.getEigenvalue(i);

      assertTrue(c.y == 0);

      assertEquals(expected, c.x, 1e-8);
    }
  }
  public void testForEigenvalue(
      SymmetricQRAlgorithmDecomposition alg,
      Matrix A,
      double valueReal,
      double valueImg,
      int numMatched) {
    int N = alg.getNumberOfEigenvalues();

    int numFound = 0;
    for (int i = 0; i < N; i++) {
      Vector2 c = alg.getEigenvalue(i);

      if (Math.abs(c.x - valueReal) < 1e-4 && Math.abs(c.y - valueImg) < 1e-4) {
        numFound++;
      }
    }

    assertEquals(numMatched, numFound);
  }
  /** See if eigenvalues cause the characteristic equation to have a value of zero */
  public void checkCharacteristicEquation(SymmetricQRAlgorithmDecomposition alg, Matrix A) {
    int N = alg.getNumberOfEigenvalues();

    Matrix a = Matrix.create(A);

    for (int i = 0; i < N; i++) {
      Vector2 c = alg.getEigenvalue(i);

      if (Math.abs(c.y - 0) < 1e-8) {
        // test using the characteristic equation
        Matrix temp = Matrix.createIdentity(A.columnCount());
        temp.scale(c.x);
        temp.sub(a);
        double det = temp.determinant();

        // extremely crude test.  given perfect data this is probably considered a failure...
        // However,
        // its hard to tell what a good test value actually is.
        assertEquals(0, det, 0.1);
      }
    }
  }
  /** Sees if the pair of eigenvalue and eigenvector was found in the decomposition. */
  public void testForEigenpair(
      SymmetricQRAlgorithmDecomposition alg, double valueReal, double valueImg, double... vector) {
    int N = alg.getNumberOfEigenvalues();

    int numMatched = 0;
    for (int i = 0; i < N; i++) {
      Vector2 c = alg.getEigenvalue(i);

      if (Math.abs(c.x - valueReal) < 1e-4 && Math.abs(c.y - valueImg) < 1e-4) {

        //                if( c.isReal() ) {
        if (Math.abs(c.y - 0) < 1e-8)
          if (vector.length > 0) {
            AVector v = alg.getEigenVector(i);
            AMatrix e = Matrix.createFromRows(vector);
            e = e.getTranspose();

            Matrix t = Matrix.create(v.length(), 1);
            t.setColumn(0, v);
            double error = diffNormF(e, t);
            //                        CommonOps.changeSign(e);
            e.multiply(-1);
            double error2 = diffNormF(e, t);

            if (error < 1e-3 || error2 < 1e-3) numMatched++;
          } else {
            numMatched++;
          }
        else if (Math.abs(c.y - 0) > 1e-8) {
          numMatched++;
        }
      }
    }

    assertEquals(1, numMatched);
  }
  /**
   * Checks to see if an eigenvalue is complex then the eigenvector is null. If it is real it then
   * checks to see if the equation A*v = lambda*v holds true.
   */
  public void testPairsConsistent(SymmetricQRAlgorithmDecomposition alg, Matrix A) {
    //
    // System.out.println("-------------------------------------------------------------------------");
    int N = alg.getNumberOfEigenvalues();

    for (int i = 0; i < N; i++) {
      Vector2 c = alg.getEigenvalue(i);
      AVector v = alg.getEigenVector(i);

      if (Double.isInfinite(c.x)
          || Double.isNaN(c.x)
          || Double.isInfinite(c.y)
          || Double.isNaN(c.y)) fail("Uncountable eigenvalue");

      if (Math.abs(c.y) > 1e-20) {
        assertTrue(v == null);
      } else {
        assertTrue(v != null);
        //                if( MatrixFeatures.hasUncountable(v)) {
        //                    throw new RuntimeException("Egads");
        //                }
        assertFalse(v.hasUncountable());

        //                CommonOps.mult(A,v,tempA);
        Matrix ta = Matrix.create(A.rowCount(), 1);
        ta.setColumn(0, (v));
        AMatrix tempA = Multiplications.multiply(A, ta);
        //                CommonOps.scale(c.real,v,tempB);
        Matrix tb = Matrix.create(v.length(), 1);
        tb.setColumn(0, v);
        AMatrix tempB = tb.multiplyCopy(c.x);
        //                double max = NormOps.normPInf(A);
        double max = normPInf(A);
        if (max == 0) max = 1;

        double error = diffNormF(tempA, tempB) / max;

        if (error > 1e-12) {
          //                    System.out.println("Original matrix:");
          //                    System.out.println(A);
          //                    A.print();
          //                    System.out.println("Eigenvalue = "+c.x);
          //                    Eigenpair p = EigenOps.computeEigenVector(A,c.real);
          //                    p.vector.print();
          //                    v.print();
          //
          //
          //                    CommonOps.mult(A,p.vector,tempA);
          //                    CommonOps.scale(c.real,p.vector,tempB);
          //
          //                    max = NormOps.normPInf(A);
          //
          //                    System.out.println("error before = "+error);
          //                    error = SpecializedOps.diffNormF(tempA,tempB)/max;
          //                    System.out.println("error after = "+error);
          //                    A.print("%f");
          //                    System.out.println();
          fail("Error was too large");
        }

        assertTrue(error <= 1e-12);
      }
    }
  }