/// <summary>
 /// Returns the diagonal matrix &Sigma; of the decomposition.
 /// <para>&Sigma; is a diagonal matrix. The singular values are provided in
 /// non-increasing order, for compatibility with Jama.</para>
 /// </summary>
 /// <returns>the &Sigma; matrix</returns>
 public RealMatrix getS()
 {
     if (cachedS == null)
     {
         // cache the matrix for subsequent calls
         cachedS = MatrixUtils.createRealDiagonalMatrix(singularValues);
     }
     return(cachedS);
 }
        /// <summary>
        /// Gets the block diagonal matrix D of the decomposition.
        /// D is a block diagonal matrix.
        /// Real eigenvalues are on the diagonal while complex values are on
        /// 2x2 blocks { {real +imaginary}, {-imaginary, real} }.
        /// </summary>
        /// <returns>the D matrix.</returns>
        /// <remarks>
        /// See <see cref="getRealEigenvalues()"/><para/>
        /// See <see cref="getImagEigenvalues()"/>
        /// </remarks>
        public RealMatrix getD()
        {
            if (cachedD == null)
            {
                // cache the matrix for subsequent calls
                cachedD = MatrixUtils.createRealDiagonalMatrix(realEigenvalues);

                for (int i = 0; i < imagEigenvalues.Length; i++)
                {
                    if (Precision.compareTo(imagEigenvalues[i], 0.0, EPSILON) > 0)
                    {
                        cachedD.setEntry(i, i + 1, imagEigenvalues[i]);
                    }
                    else if (Precision.compareTo(imagEigenvalues[i], 0.0, EPSILON) < 0)
                    {
                        cachedD.setEntry(i, i - 1, imagEigenvalues[i]);
                    }
                }
            }
            return(cachedD);
        }
        /// <summary>
        /// Computes the square-root of the matrix.
        /// This implementation assumes that the matrix is symmetric and positive
        /// definite.
        /// </summary>
        /// <returns>the square-root of the matrix.</returns>
        /// <exception cref="MathUnsupportedOperationException"> if the matrix is not
        /// symmetric or not positive definite.</exception>
        public RealMatrix getSquareRoot()
        {
            if (!isSymmetric)
            {
                throw new MathUnsupportedOperationException();
            }

            double[] sqrtEigenValues = new double[realEigenvalues.Length];
            for (int i = 0; i < realEigenvalues.Length; i++)
            {
                double eigen = realEigenvalues[i];
                if (eigen <= 0)
                {
                    throw new MathUnsupportedOperationException();
                }
                sqrtEigenValues[i] = FastMath.sqrt(eigen);
            }
            RealMatrix sqrtEigen = MatrixUtils.createRealDiagonalMatrix(sqrtEigenValues);
            RealMatrix v         = getV();
            RealMatrix vT        = getVT();

            return(v.multiply(sqrtEigen).multiply(vT));
        }