/// <summary> ///Computes the singular value decomposition (SVD) of a real /// M-by-N matrix A. /// The SVD is written /// A = U * S * transpose(V) /// </summary> /// <param name="A">The A matrix.</param> /// <param name="S">A vector of singular values.</param> public void ComputeSVD(Matrix A, out Vector S) { if (this._dgesvd == null) { this._dgesvd = new DGESVD(); } Matrix ACopy = A.Clone(); double[] ACopyData = ACopy.Data; S = new Vector(Math.Min(A.RowCount, A.ColumnCount)); // (output) DOUBLE PRECISION array, dimension (min(M,N)) double[] SingularValuesData = S.Data; Matrix U = new Matrix(1, 1); // A is MxN, U is MxM, como aqui no se requiere no importa double[] UData = U.Data; Matrix VT = new Matrix(1, 1);// A is MxN, V is NxN, como aqui no se requiere no importa double[] VTData = VT.Data; double[] Work = new double[1]; int LWork = -1; int Info = 0; //Calculamos LWORK this._dgesvd.Run("N", "N", A.RowCount, A.ColumnCount, ref ACopyData, 0, A.RowCount, ref SingularValuesData, 0, ref UData, 0, U.RowCount, ref VTData, 0, VT.RowCount, ref Work, 0, LWork, ref Info); LWork = Convert.ToInt32(Work[0]); if (LWork > 0) { Work = new double[LWork]; _dgesvd.Run("N", "N", A.RowCount, A.ColumnCount, ref ACopyData, 0, A.RowCount, ref SingularValuesData, 0, ref UData, 0, U.RowCount, ref VTData, 0, VT.RowCount, ref Work, 0, LWork, ref Info); } else { //Error } #region Error // <param name="INFO"> // (output) INTEGER // = 0: successful exit. // .LT. 0: if INFO = -i, the i-th argument had an illegal value. // .GT. 0: if DBDSQR did not converge, INFO specifies how many // superdiagonals of an intermediate bidiagonal form B // did not converge to zero. See the description of WORK // above for details. if (Info < 0) { string infoSTg = Math.Abs(Info).ToString(); throw new ArgumentException("the " + infoSTg + " -th argument had an illegal value"); } else if (Info > 0) { string infoSTg = Math.Abs(Info).ToString(); throw new Exception("DBDSQR did not converge."); } #endregion }
/// <summary> ///Computes the singular value decomposition (SVD) of a real /// M-by-N matrix A. /// The SVD is written /// A = U * S * transpose(V) /// </summary> /// <param name="A">The A matrix.</param> /// <param name="S">The diagonal elements of S are the singular values of A.</param> /// <param name="U">The U matrix, U is an M-by-M orthogonal matrix</param> /// <param name="VT">the transpose(V), V is an N-by-N orthogonal matrix.</param> public void ComputeSVD(Matrix A, out Matrix S, out Matrix U, out Matrix VT) { if (this._dgesvd == null) { this._dgesvd = new DGESVD(); } Matrix ACopy = A.Clone(); double[] ACopyData = ACopy.Data; S = new Matrix(A.RowCount, A.ColumnCount); // A is MxN, S is MxN double[] SingularValuesData = new double[Math.Min(A.RowCount, A.ColumnCount)]; U = new Matrix(A.RowCount, A.RowCount); // A is MxN, U is MxM double[] UData = U.Data; VT = new Matrix(A.ColumnCount, A.ColumnCount); // A is MxN, V is NxN double[] VTData = VT.Data; double[] Work = new double[1]; int LWork = -1; int Info = 0; //Calculamos LWORK this._dgesvd.Run("A", "A", A.RowCount, A.ColumnCount, ref ACopyData, 0, A.RowCount, ref SingularValuesData, 0, ref UData, 0, U.RowCount, ref VTData, 0, VT.RowCount, ref Work, 0, LWork, ref Info); LWork = Convert.ToInt32(Work[0]); if (LWork > 0) { Work = new double[LWork]; _dgesvd.Run("A", "A", A.RowCount, A.ColumnCount, ref ACopyData, 0, A.RowCount, ref SingularValuesData, 0, ref UData, 0, U.RowCount, ref VTData, 0, VT.RowCount, ref Work, 0, LWork, ref Info); } else { //Error } #region Error // <param name="INFO"> // (output) INTEGER // = 0: successful exit. // .LT. 0: if INFO = -i, the i-th argument had an illegal value. // .GT. 0: if DBDSQR did not converge, INFO specifies how many // superdiagonals of an intermediate bidiagonal form B // did not converge to zero. See the description of WORK // above for details. if (Info < 0) { string infoSTg = Math.Abs(Info).ToString(); throw new ArgumentException("the " + infoSTg + " -th argument had an illegal value"); } else if (Info > 0) { string infoSTg = Math.Abs(Info).ToString(); throw new Exception("DBDSQR did not converge."); } #endregion for (int i = 0; i < SingularValuesData.Length; i++) { S[i, i] = SingularValuesData[i]; } }