/// <summary>
        /// Determines whether the matrix is diagonal.
        /// </summary>
        /// <param name="matrix">The matrix.</param>
        /// <returns><c>true</c> if the matrix is both lower and upper triangular; otherwise, <c>false</c>.</returns>
        /// <exception cref="System.ArgumentNullException">The matrix is null.</exception>
        public static Boolean IsDiagonal(this Matrix matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException(nameof(matrix));
            }

            return(MatrixComputations.IsUpperTriangular(matrix) && MatrixComputations.IsLowerTriangular(matrix));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="CholeskyDecomposition" /> class.
        /// </summary>
        /// <param name="matrix">The matrix of which the decomposition is computed.</param>
        /// <exception cref="System.ArgumentNullException">The matrix is null.</exception>
        /// <exception cref="System.ArgumentException">The matrix is not symmetric.</exception>
        public CholeskyDecomposition(Matrix matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException(nameof(matrix));
            }
            if (!MatrixComputations.IsSymmetric(matrix))
            {
                throw new ArgumentException(NumericsMessages.MatrixIsNotSymmetric, nameof(matrix));
            }

            this.matrix = matrix;
        }
        /// <summary>
        /// Tridiagonalizes the specified matrix.
        /// </summary>
        /// <param name="matrix">The matrix.</param>
        /// <returns>The tridiagonalization of the <paramref name="matrix" />.</returns>
        /// <exception cref="System.ArgumentNullException">The matrix is null.</exception>
        /// <exception cref="System.ArgumentException">
        /// The matrix is not square.
        /// or
        /// The matrix is not symmetric.
        /// </exception>
        public static Matrix Tridiagonalize(Matrix matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException(nameof(matrix));
            }
            if (!matrix.IsSquare)
            {
                throw new ArgumentException(NumericsMessages.MatrixIsNotSquare, nameof(matrix));
            }
            if (!MatrixComputations.IsSymmetric(matrix))
            {
                throw new ArgumentException(NumericsMessages.MatrixIsNotSymmetric, nameof(matrix));
            }

            Matrix tridiagonalMatrix = new Matrix(matrix);

            for (Int32 columnIndex = 0; columnIndex < matrix.NumberOfColumns - 2; columnIndex++)
            {
                Double[] column = tridiagonalMatrix.GetColumn(columnIndex);

                Double sum = 0;
                for (Int32 index = columnIndex + 1; index < column.Length; index++)
                {
                    sum += column[index] * column[index];
                }

                Double alpha = -Math.Sign(column[columnIndex + 1]) * Math.Sqrt(sum);
                Double r     = Math.Sqrt(0.5 * (alpha * alpha - column[columnIndex + 1] * alpha));

                Vector v = new Vector(column.Length);
                v[columnIndex + 1] = (column[columnIndex + 1] - alpha) / 2 / r;
                for (Int32 j = columnIndex + 2; j < column.Length; j++)
                {
                    v[j] = column[j] / 2 / r;
                }

                Matrix p = MatrixFactory.CreateIdentity(column.Length) - 2 * v * v.Transpose();

                tridiagonalMatrix = p * tridiagonalMatrix * p;
            }

            return(tridiagonalMatrix);
        }