/**
  * Only eigenvalues of a symmetric real matrix are computed.
  *
  * @param A a symmetric real matrix
  * @return a 1D {@code double} array containing the eigenvalues in decreasing order (absolute
  *     value)
  */
 public static double[] computeEigenvalues(Matrix A) {
   SparseMatrix S = (SparseMatrix) decompose(A, false)[1];
   int m = S.getRowDimension();
   int n = S.getColumnDimension();
   int len = m >= n ? n : m;
   double[] s = ArrayOperator.allocateVector(len, 0);
   for (int i = 0; i < len; i++) {
     s[i] = S.getEntry(i, i);
   }
   return s;
 }
 /**
  * Build the diagonal matrix containing all eigenvalues.
  *
  * @param s eigenvalues
  * @param m number of rows
  * @param n number of columns
  * @return a diagonal matrix containing all eigenvalues
  */
 private static Matrix buildD(double[] s, int m, int n) {
   TreeMap<Pair<Integer, Integer>, Double> map = new TreeMap<Pair<Integer, Integer>, Double>();
   for (int i = 0; i < m; i++) {
     if (i < n) map.put(Pair.of(i, i), s[i]);
   }
   return SparseMatrix.createSparseMatrix(map, m, n);
 }
  /**
   * Unpack Q and T from the result of tridiagonalization.
   *
   * @param A tridiagonalization result
   * @param a diagonal
   * @param b superdiagonal
   * @param computeV if V is to be computed
   * @return a {@code Matrix} array [Q, T]
   */
  private static Matrix[] unpack(Matrix A, double[] a, double[] b, boolean computeV) {
    Matrix[] QT = new Matrix[3];
    int m = A.getRowDimension();
    int n = A.getColumnDimension();
    DenseMatrix Q = null;
    if (computeV) {
      Q = new DenseMatrix(m, m, 0);
      double[][] QData = Q.getData();
      double s = 0;
      double[] y = null;
      for (int i = 0; i < m; i++) {
        // Compute U^T * e_i
        y = QData[i];
        y[i] = 1;
        for (int j = 0; j < n - 2; j++) {
          s = 0;
          for (int k = j + 1; k < m; k++) {
            s += A.getEntry(k, j) * y[k];
          }
          for (int k = j + 1; k < m; k++) {
            y[k] -= A.getEntry(k, j) * s;
          }
        }
      }
      /*fprintf("Q:\n");
      disp(Q);*/
    }
    TreeMap<Pair<Integer, Integer>, Double> map = new TreeMap<Pair<Integer, Integer>, Double>();
    for (int i = 0; i < m; i++) {
      if (i < n) map.put(Pair.of(i, i), a[i]);
      if (i < n - 1) {
        map.put(Pair.of(i, i + 1), b[i]);
        map.put(Pair.of(i + 1, i), b[i]);
      }
    }
    Matrix T = SparseMatrix.createSparseMatrix(map, m, n);
    /*fprintf("T:\n");
    printMatrix(T);
    T = new SparseMatrix(m, n);
    for (int i = 0; i < m; i++) {
    	if (i < n)
    		T.setEntry(i, i, a[i]);
    	if (i < n - 1) {
    		T.setEntry(i, i + 1, b[i]);
    		T.setEntry(i + 1, i, b[i]);
    	}
    }*/
    if (computeV) {
      /*fprintf("T:\n");
      printMatrix(T);*/

      /*fprintf("A:\n");
      printMatrix(A);

      fprintf("Q'Q:\n");
      disp(Q.transpose().mtimes(Q));*/

      /*fprintf("QTQ':\n");
      disp(Q.mtimes(T).mtimes(Q.transpose()));*/
    }

    QT[0] = Q;
    QT[1] = T;
    return QT;
  }