/// <summary> /// Solve a square Toeplitz system with a right-side matrix. /// </summary> /// <param name="Y">The right-side matrix</param> /// <returns>The solution matrix.</returns> /// <exception cref="ArgumentNullException"> /// Parameter <B>Y</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The number of rows in <B>Y</B> is not equal to the number of rows in the Toeplitz matrix. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This member solves the linear system <B>TX</B> = <B>Y</B>, where <B>T</B> is /// a square Toeplitz matrix, <B>X</B> is the unknown solution matrix /// and <B>Y</B> is a known matrix. /// <para> /// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation /// using the Levinson algorithm, before calculating the solution vector. /// </para> /// </remarks> public ComplexDoubleMatrix Solve(IROComplexDoubleMatrix Y) { ComplexDoubleMatrix X; Complex Inner; Complex[] a, b, x, y; int i, j, l; // check parameters if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (m_Order != Y.Columns) { throw new RankException("The numer of rows in Y is not equal to the number of rows in the Toeplitz matrix."); } Compute(); if (m_IsSingular == true) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // allocate memory for solution X = new ComplexDoubleMatrix(m_Order, Y.Rows); x = new Complex[m_Order]; for (l = 0; l < Y.Rows; l++) { // get right-side column y = ComplexDoubleVector.GetColumnAsArray(Y, l); // solve left-side column for (i = 0; i < m_Order; i++) { a = m_LowerTriangle[i]; b = m_UpperTriangle[i]; Inner = y[i]; for (j = 0; j < i; j++) { Inner += a[j] * y[j]; } Inner *= m_Diagonal[i]; x[i] = Inner; for (j = 0; j < i; j++) { x[j] += Inner * b[j]; } } // insert left-side column into the matrix X.SetColumn(l, x); } return(X); }
///<summary>Constructor for QR decomposition class. The constructor performs the factorization and the upper and ///lower matrices are accessible by the <c>Q</c> and <c>R</c> properties.</summary> ///<param name="matrix">The matrix to factor.</param> ///<exception cref="ArgumentNullException">matrix is null.</exception> public ComplexDoubleQRDecomp(IROComplexDoubleMatrix matrix) { if (matrix == null) { throw new System.ArgumentNullException("matrix cannot be null."); } this.matrix = matrix; }
///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary> ///<param name="B">RHS side of the system.</param> ///<returns>the solution matrix, X.</returns> ///<exception cref="ArgumentNullException">B is null.</exception> ///<exception cref="SingularMatrixException">Ais singular.</exception> ///<exception cref="ArgumentException">The number of rows of A and B must be the same.</exception> public ComplexDoubleMatrix Solve(IROComplexDoubleMatrix B) { if (B == null) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if (singular) { throw new SingularMatrixException(); } else { if (B.Rows != order) { throw new System.ArgumentException("Matrix row dimensions must agree."); } #if MANAGED // Copy right hand side with pivoting int nx = B.Columns; ComplexDoubleMatrix X = Pivot(B); // Solve L*Y = B(piv,:) for (int k = 0; k < order; k++) { for (int i = k + 1; i < order; i++) { for (int j = 0; j < nx; j++) { X.data[i][j] -= X.data[k][j] * factor[i][k]; } } } // Solve U*X = Y; for (int k = order - 1; k >= 0; k--) { for (int j = 0; j < nx; j++) { X.data[k][j] /= factor[k][k]; } for (int i = 0; i < k; i++) { for (int j = 0; j < nx; j++) { X.data[i][j] -= X.data[k][j] * factor[i][k]; } } } return(X); #else Complex[] rhs = ComplexDoubleMatrix.ToLinearComplexArray(B); Lapack.Getrs.Compute(Lapack.Transpose.NoTrans, order, B.Columns, factor, order, pivots, rhs, B.Rows); ComplexDoubleMatrix ret = new ComplexDoubleMatrix(order, B.Columns); ret.data = rhs; return(ret); #endif } }
///<summary>Constructor for SVD decomposition class.</summary> ///<param name="matrix">The matrix to decompose.</param> ///<param name="computeVectors">Whether to compute the singular vectors or not.</param> ///<exception cref="ArgumentNullException">matrix is null.</exception> public ComplexDoubleSVDDecomp(IROComplexDoubleMatrix matrix, bool computeVectors) { if (matrix == null) { throw new System.ArgumentNullException("matrix cannot be null."); } this.matrix = new ComplexDoubleMatrix(matrix); this.computeVectors = computeVectors; }
///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary> ///<param name="B">RHS side of the system.</param> ///<returns>the solution matrix, X.</returns> ///<exception cref="ArgumentNullException">B is null.</exception> ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception> ///<exception cref="ArgumentException">The number of rows of A and B must be the same.</exception> public ComplexDoubleMatrix Solve(IROComplexDoubleMatrix B) { if (B == null) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if (!ispd) { throw new NotPositiveDefiniteException(); } else { if (B.Rows != order) { throw new System.ArgumentException("Matrix row dimensions must agree."); } #if MANAGED // Copy right hand side. int cols = B.Columns; var X = new ComplexDoubleMatrix(B); for (int c = 0; c < cols; c++) { // Solve L*Y = B; for (int i = 0; i < order; i++) { Complex sum = B[i, c]; for (int k = i - 1; k >= 0; k--) { sum -= l.data[i][k] * X.data[k][c]; } X.data[i][c] = sum / l.data[i][i]; } // Solve L'*X = Y; for (int i = order - 1; i >= 0; i--) { Complex sum = X.data[i][c]; for (int k = i + 1; k < order; k++) { sum -= ComplexMath.Conjugate(l.data[k][i]) * X.data[k][c]; } X.data[i][c] = sum / ComplexMath.Conjugate(l.data[i][i]); } } return(X); #else Complex[] rhs = ComplexDoubleMatrix.ToLinearComplexArray(B); Lapack.Potrs.Compute(Lapack.UpLo.Lower, order, B.Columns, l.data, order, rhs, B.Rows); ComplexDoubleMatrix ret = new ComplexDoubleMatrix(order, B.Columns); ret.data = rhs; return(ret); #endif } }
/// <summary> /// Returns the column of a <see cref="IROComplexDoubleMatrix" /> as a new <c>Complex[]</c> array. /// </summary> /// <param name="mat">The matrix to copy the column from.</param> /// <param name="col">Number of column to copy from the matrix.</param> /// <returns>A new array of <c>Complex</c> with the same elements as the column of the given matrix.</returns> public static Complex[] GetColumnAsArray(IROComplexDoubleMatrix mat, int col) { Complex[] result = new Complex[mat.Rows]; for (int i = 0; i < result.Length; ++i) { result[i] = mat[i, col]; } return(result); }
/// <summary> /// Returns the row of a <see cref="IROComplexDoubleMatrix" /> as a new <c>ComplexDoubleVector.</c> /// </summary> /// <param name="mat">The matrix to copy the column from.</param> /// <param name="row">Number of row to copy from the matrix.</param> /// <returns>A new <c>ComplexDoubleVector</c> with the same elements as the row of the given matrix.</returns> public static ComplexDoubleVector GetRow(IROComplexDoubleMatrix mat, int row) { ComplexDoubleVector result = new ComplexDoubleVector(mat.Columns); for (int i = 0; i < result.data.Length; ++i) { result.data[i] = mat[row, i]; } return(result); }
/// <summary> /// Returns the column of a <see cref="IROComplexDoubleMatrix" /> as a new <c>ComplexDoubleVector.</c> /// </summary> /// <param name="mat">The matrix to copy the column from.</param> /// <param name="col">Number of column to copy from the matrix.</param> /// <returns>A new <c>ComplexDoubleVector</c> with the same elements as the column of the given matrix.</returns> public static ComplexDoubleVector GetColumn(IROComplexDoubleMatrix mat, int col) { ComplexDoubleVector result = new ComplexDoubleVector(mat.Rows); for (int i = 0; i < result.data.Length; ++i) { result.data[i] = mat[i, col]; } return(result); }
///<summary>Constructor for Cholesky decomposition class. The constructor performs the factorization of a Hermitian positive ///definite matrax and the Cholesky factored matrix is accessible by the <c>Factor</c> property. The factor is the lower ///triangular factor.</summary> ///<param name="matrix">The matrix to factor.</param> ///<exception cref="ArgumentNullException">matrix is null.</exception> ///<exception cref="NotSquareMatrixException">matrix is not square.</exception> ///<remarks>This class only uses the lower triangle of the input matrix. It ignores the ///upper triangle.</remarks> public ComplexDoubleCholeskyDecomp(IROComplexDoubleMatrix matrix) { if (matrix == null) { throw new System.ArgumentNullException("matrix cannot be null."); } if (matrix.Rows != matrix.Columns) { throw new NotSquareMatrixException("Matrix must be square."); } order = matrix.Columns; this.matrix = new ComplexDoubleMatrix(matrix); }
///<summary>Constructor for Cholesky decomposition class. The constructor performs the factorization of a Hermitian positive ///definite matrax and the Cholesky factored matrix is accessible by the <c>Factor</c> property. The factor is the lower ///triangular factor.</summary> ///<param name="matrix">The matrix to factor.</param> ///<exception cref="ArgumentNullException">matrix is null.</exception> ///<exception cref="NotSquareMatrixException">matrix is not square.</exception> ///<remarks>This class only uses the lower triangle of the input matrix. It ignores the ///upper triangle.</remarks> public ComplexDoubleCholeskyDecomp(IROComplexDoubleMatrix matrix) { if ( matrix == null ) { throw new System.ArgumentNullException("matrix cannot be null."); } if ( matrix.Rows != matrix.Columns ) { throw new NotSquareMatrixException("Matrix must be square."); } order = matrix.Columns; this.matrix = new ComplexDoubleMatrix(matrix); }
private ComplexDoubleMatrix Pivot(IROComplexDoubleMatrix B) { int m = B.Rows; int n = B.Columns; ComplexDoubleMatrix ret = new ComplexDoubleMatrix(m, n); for (int i = 0; i < pivots.Length; i++) { for (int j = 0; j < n; j++) { ret.data[i][j] = B[pivots[i], j]; } } return(ret); }
///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary> ///<param name="B">RHS side of the system.</param> ///<returns>the solution matrix, X.</returns> ///<exception cref="ArgumentNullException">B is null.</exception> ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception> ///<exception cref="ArgumentException">The number of rows of A and B must be the same.</exception> public ComplexDoubleMatrix Solve (IROComplexDoubleMatrix B) { if ( B == null ) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if ( !ispd ) { throw new NotPositiveDefiniteException(); } else { if ( B.Rows != order ) { throw new System.ArgumentException("Matrix row dimensions must agree." ); } #if MANAGED // Copy right hand side. int cols = B.Columns; ComplexDoubleMatrix X = new ComplexDoubleMatrix(B); for (int c = 0; c < cols; c++ ) { // Solve L*Y = B; for (int i = 0; i < order; i++) { Complex sum = B[i,c]; for (int k = i-1; k >= 0; k--) { sum -= l.data[i][k] * X.data[k][c]; } X.data[i][c] = sum / l.data[i][i]; } // Solve L'*X = Y; for (int i =order-1; i >= 0; i--) { Complex sum = X.data[i][c]; for (int k = i+1; k < order; k++) { sum -= ComplexMath.Conjugate(l.data[k][i]) * X.data[k][c]; } X.data[i][c] = sum / ComplexMath.Conjugate(l.data[i][i]); } } return X; #else Complex[] rhs = ComplexDoubleMatrix.ToLinearComplexArray(B); Lapack.Potrs.Compute(Lapack.UpLo.Lower,order,B.Columns,l.data,order,rhs,B.Rows); ComplexDoubleMatrix ret = new ComplexDoubleMatrix(order,B.Columns); ret.data = rhs; return ret; #endif } }
public static string MatrixToString(string name, IROComplexDoubleMatrix a) { if (null == name) name = ""; if (a.Rows == 0 || a.Columns == 0) return string.Format("EmptyMatrix {0}({1},{2})", name, a.Rows, a.Columns); System.Text.StringBuilder s = new System.Text.StringBuilder(); s.Append("Matrix " + name + ":"); for (int i = 0; i < a.Rows; i++) { s.Append("\n("); for (int j = 0; j < a.Columns; j++) { s.Append(a[i, j].ToString()); if (j + 1 < a.Columns) s.Append(";"); else s.Append(")"); } } return s.ToString(); }
/// <summary> /// Returns the column of a <see cref="IROComplexDoubleMatrix" /> as a new <c>Complex[]</c> array. /// </summary> /// <param name="mat">The matrix to copy the column from.</param> /// <param name="col">Number of column to copy from the matrix.</param> /// <returns>A new array of <c>Complex</c> with the same elements as the column of the given matrix.</returns> public static Complex[] GetColumnAsArray(IROComplexDoubleMatrix mat, int col) { Complex[] result = new Complex[mat.Rows]; for(int i=0;i<result.Length;++i) result[i] = mat[i,col]; return result; }
///<summary>Constructor for SVD decomposition class.</summary> ///<param name="matrix">The matrix to decompose.</param> ///<exception cref="ArgumentNullException">matrix is null.</exception> public ComplexDoubleSVDDecomp(IROComplexDoubleMatrix matrix) { if ( matrix == null ) { throw new System.ArgumentNullException("matrix cannot be null."); } this.matrix = new ComplexDoubleMatrix(matrix); }
/// <summary> /// Returns the row of a <see cref="IROComplexDoubleMatrix" /> as a new <c>ComplexDoubleVector.</c> /// </summary> /// <param name="mat">The matrix to copy the column from.</param> /// <param name="row">Number of row to copy from the matrix.</param> /// <returns>A new <c>ComplexDoubleVector</c> with the same elements as the row of the given matrix.</returns> public static ComplexDoubleVector GetRow(IROComplexDoubleMatrix mat, int row) { ComplexDoubleVector result = new ComplexDoubleVector(mat.Columns); for(int i=0;i<result.data.Length;++i) result.data[i] = mat[row,i]; return result; }
/// <summary> /// Solve a square Toeplitz system with a right-side matrix. /// </summary> /// <param name="Y">The right-side matrix</param> /// <returns>The solution matrix.</returns> /// <exception cref="ArgumentNullException"> /// Parameter <B>Y</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The number of rows in <B>Y</B> is not equal to the number of rows in the Toeplitz matrix. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This member solves the linear system <B>TX</B> = <B>Y</B>, where <B>T</B> is /// a square Toeplitz matrix, <B>X</B> is the unknown solution matrix /// and <B>Y</B> is a known matrix. /// <para> /// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation /// using the Levinson algorithm, before calculating the solution vector. /// </para> /// </remarks> public ComplexDoubleMatrix Solve(IROComplexDoubleMatrix Y) { ComplexDoubleMatrix X; Complex Inner; Complex[] a, b, x, y; int i, j, l; // check parameters if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (m_Order != Y.Columns) { throw new RankException("The numer of rows in Y is not equal to the number of rows in the Toeplitz matrix."); } Compute(); if (m_IsSingular == true) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // allocate memory for solution X = new ComplexDoubleMatrix(m_Order, Y.Rows); x = new Complex[m_Order]; for (l = 0; l < Y.Rows; l++) { // get right-side column y = ComplexDoubleVector.GetColumnAsArray(Y, l); // solve left-side column for (i = 0; i < m_Order; i++) { a = m_LowerTriangle[i]; b = m_UpperTriangle[i]; Inner = y[i]; for (j = 0; j < i; j++) { Inner += a[j] * y[j]; } Inner *= m_Diagonal[i]; x[i] = Inner; for (j = 0; j < i; j++) { x[j] += Inner * b[j]; } } // insert left-side column into the matrix X.SetColumn(l, x); } return X; }
/// <summary> /// Solve a square Toeplitz system with a right-side matrix. /// </summary> /// <param name="col">The left-most column of the Toeplitz matrix.</param> /// <param name="row">The top-most row of the Toeplitz matrix.</param> /// <param name="Y">The right-side matrix of the system.</param> /// <returns>The solution matrix.</returns> /// <exception cref="ArgumentNullException"> /// <EM>col</EM> is a null reference, /// <para>or</para> /// <para><EM>row</EM> is a null reference,</para> /// <para>or</para> /// <para><EM>Y</EM> is a null reference.</para> /// </exception> /// <exception cref="RankException"> /// The length of <EM>col</EM> is 0, /// <para>or</para> /// <para>the lengths of <EM>col</EM> and <EM>row</EM> are not equal,</para> /// <para>or</para> /// <para>the number of rows in <EM>Y</EM> does not the length of <EM>col</EM> and <EM>row</EM>.</para> /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <exception cref="ArithmeticException"> /// The values of the first element of <EM>col</EM> and <EM>row</EM> are not equal. /// </exception> /// <remarks> /// This method solves the linear system <B>AX</B> = <B>Y</B>. Where /// <B>T</B> is a square Toeplitz matrix, <B>X</B> is an unknown /// matrix and <B>Y</B> is a known matrix. /// <para> /// The classic Levinson algorithm is used to solve the system. The algorithm /// assumes that all the leading sub-matrices of the Toeplitz matrix are /// non-singular. When a sub-matrix is near singular, accuracy will /// be degraded. This member requires approximately <B>N</B> squared /// FLOPS to calculate a solution, where <B>N</B> is the matrix order. /// </para> /// <para> /// This static method has minimal storage requirements as it combines /// the <b>UDL</b> decomposition with the calculation of the solution vector /// in a single algorithm. /// </para> /// </remarks> public static ComplexDoubleMatrix Solve(IROComplexDoubleVector col, IROComplexDoubleVector row, IROComplexDoubleMatrix Y) { // check parameters if (col == null) { throw new System.ArgumentNullException("col"); } else if (col.Length == 0) { throw new RankException("The length of col is zero."); } else if (row == null) { throw new System.ArgumentNullException("row"); } else if (col.Length != row.Length) { throw new RankException("The lengths of col and row are not equal."); } else if (col[0] != row[0]) { throw new ArithmeticException("The values of the first element of col and row are not equal."); } else if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (col.Length != Y.Columns) { throw new RankException("The numer of rows in Y does not match the length of col and row."); } // check if leading diagonal is zero if (col[0] == Complex.Zero) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // decompose matrix int order = col.Length; Complex[] A = new Complex[order]; Complex[] B = new Complex[order]; Complex[] Z = new Complex[order]; ComplexDoubleMatrix X = new ComplexDoubleMatrix(order); Complex Q, S, Ke, Kr, e; Complex Inner; int i, j, l; // setup the zero order solution A[0] = Complex.One; B[0] = Complex.One; e = Complex.One / col[0]; X.SetRow(0, e * ComplexDoubleVector.GetRow(Y, 0)); for (i = 1; i < order; i++) { // calculate inner products Q = Complex.Zero; for (j = 0, l = 1; j < i; j++, l++) { Q += col[l] * A[j]; } S = Complex.Zero; for (j = 0, l = 1; j < i; j++, l++) { S += row[l] * B[j]; } // reflection coefficients Kr = -S * e; Ke = -Q * e; // update lower triangle (in temporary storage) Z[0] = Complex.Zero; Array.Copy(A, 0, Z, 1, i); for (j = 0, l = i - 1; j < i; j++, l--) { Z[j] += Ke * B[l]; } // update upper triangle for (j = i; j > 0; j--) { B[j] = B[j - 1]; } B[0] = Complex.Zero; for (j = 0, l = i - 1; j < i; j++, l--) { B[j] += Kr * A[l]; } // copy from temporary storage to lower triangle Array.Copy(Z, 0, A, 0, i + 1); // check for singular sub-matrix) if (Ke * Kr == Complex.One) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // update diagonal e = e / (Complex.One - Ke * Kr); for (l = 0; l < Y.Rows; l++) { ComplexDoubleVector W = X.GetColumn(l); ComplexDoubleVector M = ComplexDoubleVector.GetColumn(Y, l); Inner = M[i]; for (j = 0; j < i; j++) { Inner += A[j] * M[j]; } Inner *= e; W[i] = Inner; for (j = 0; j < i; j++) { W[j] += Inner * B[j]; } X.SetColumn(l, W); } } return X; }
/// <summary> /// Solve a symmetric square Toeplitz system with a right-side matrix. /// </summary> /// <param name="T">The left-most column of the Toeplitz matrix.</param> /// <param name="Y">The right-side matrix of the system.</param> /// <returns>The solution matrix.</returns> /// <exception cref="ArgumentNullException"> /// <B>T</B> and/or <B>Y</B> are null references /// </exception> /// <exception cref="RankException"> /// The length of <B>T</B> does not match the number of rows in <B>Y</B>. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This method solves the linear system <B>AX</B> = <B>Y</B>. Where /// <B>T</B> is a symmetric square Toeplitz matrix, <B>X</B> is an unknown /// matrix and <B>Y</B> is a known matrix. /// <para> /// This static member combines the <b>UDL</b> decomposition and the calculation of the solution into a /// single algorithm. When compared to the non-static member it requires minimal data storage /// and suffers from no speed penalty. /// </para> /// </remarks> public static ComplexDoubleMatrix Solve(IROComplexDoubleVector T, IROComplexDoubleMatrix Y) { ComplexDoubleMatrix X; // check parameters if (T == null) { throw new System.ArgumentNullException("T"); } else if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (T.Length != Y.Columns) { throw new RankException("The length of T and Y are not equal."); } else { // allocate memory int N = T.Length; int M = Y.Rows; X = new ComplexDoubleMatrix(N, M); // solution matrix ComplexDoubleVector Z = new ComplexDoubleVector(N); // temporary storage vector Complex e; // prediction error int i, j, l, m; // setup zero order solution e = T[0]; if (e == Complex.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } for (m = 0; m < M; m++) { X[0, m] = Y[0, m] / T[0]; } if (N > 1) { ComplexDoubleVector a = new ComplexDoubleVector(N - 1); // prediction coefficients Complex p; // reflection coefficient Complex inner; // inner product Complex k; // calculate solution for successive orders for (i = 1; i < N; i++) { // calculate first inner product inner = T[i]; for (j = 0, l = i - 1; j < i - 1; j++, l--) { inner += a[j] * T[l]; } // update predictor coefficients p = -(inner / e); for (j = 0, l = i - 2; j < i - 1; j++, l--) { Z[j] = a[j] + p * a[l]; } // copy vector for (j = 0; j < i - 1; j++) { a[j] = Z[j]; } a[i - 1] = p; e *= (Complex.One - p * p); if (e == Complex.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } // update the solution matrix for (m = 0; m < M; m++) { // retrieve a copy of solution column for (j = 0; j < i; j++) { Z[j] = X[j, m]; } // calculate second inner product inner = Y[i, m]; for (j = 0, l = i; j < i; j++, l--) { inner -= Z[j] * T[l]; } // update solution vector k = inner / e; for (j = 0, l = i - 1; j < i; j++, l--) { Z[j] = Z[j] + k * a[l]; } Z[j] = k; // store solution column in matrix for (j = 0; j <= i; j++) { X[j, m] = Z[j]; } } } } } return(X); }
/// <summary> /// Returns the column of a <see cref="IROComplexDoubleMatrix" /> as a new <c>ComplexDoubleVector.</c> /// </summary> /// <param name="mat">The matrix to copy the column from.</param> /// <param name="col">Number of column to copy from the matrix.</param> /// <returns>A new <c>ComplexDoubleVector</c> with the same elements as the column of the given matrix.</returns> public static ComplexDoubleVector GetColumn(IROComplexDoubleMatrix mat, int col) { ComplexDoubleVector result = new ComplexDoubleVector(mat.Rows); for(int i=0;i<result.data.Length;++i) result.data[i] = mat[i,col]; return result; }
/// <summary> /// Solve a symmetric square Toeplitz system with a right-side matrix. /// </summary> /// <param name="T">The left-most column of the Toeplitz matrix.</param> /// <param name="Y">The right-side matrix of the system.</param> /// <returns>The solution matrix.</returns> /// <exception cref="ArgumentNullException"> /// <B>T</B> and/or <B>Y</B> are null references /// </exception> /// <exception cref="RankException"> /// The length of <B>T</B> does not match the number of rows in <B>Y</B>. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This method solves the linear system <B>AX</B> = <B>Y</B>. Where /// <B>T</B> is a symmetric square Toeplitz matrix, <B>X</B> is an unknown /// matrix and <B>Y</B> is a known matrix. /// <para> /// This static member combines the <b>UDL</b> decomposition and the calculation of the solution into a /// single algorithm. When compared to the non-static member it requires minimal data storage /// and suffers from no speed penalty. /// </para> /// </remarks> public static ComplexDoubleMatrix Solve(IROComplexDoubleVector T, IROComplexDoubleMatrix Y) { ComplexDoubleMatrix X; // check parameters if (T == null) { throw new System.ArgumentNullException("T"); } else if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (T.Length != Y.Columns) { throw new RankException("The length of T and Y are not equal."); } else { // allocate memory int N = T.Length; int M = Y.Rows; X = new ComplexDoubleMatrix(N, M); // solution matrix ComplexDoubleVector Z = new ComplexDoubleVector(N); // temporary storage vector Complex e; // prediction error int i, j, l, m; // setup zero order solution e = T[0]; if (e == Complex.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } for (m = 0; m < M; m++) { X[0, m] = Y[0,m] / T[0]; } if (N > 1) { ComplexDoubleVector a = new ComplexDoubleVector(N - 1); // prediction coefficients Complex p; // reflection coefficient Complex inner; // inner product Complex k; // calculate solution for successive orders for (i = 1; i < N; i++) { // calculate first inner product inner = T[i]; for (j = 0, l = i - 1; j < i - 1; j++, l--) { inner += a[j] * T[l]; } // update predictor coefficients p = -(inner / e); for (j = 0, l = i - 2; j < i - 1; j++, l--) { Z[j] = a[j] + p * a[l]; } // copy vector for (j = 0; j < i - 1; j++) { a[j] = Z[j]; } a[i - 1] = p; e *= (Complex.One - p * p); if (e == Complex.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } // update the solution matrix for (m = 0; m < M; m++) { // retrieve a copy of solution column for (j = 0; j < i; j++) { Z[j] = X[j, m]; } // calculate second inner product inner = Y[i, m]; for (j = 0, l = i; j < i; j++, l--) { inner -= Z[j] * T[l]; } // update solution vector k = inner / e; for (j = 0, l = i - 1; j < i; j++, l--) { Z[j] = Z[j] + k * a[l]; } Z[j] = k; // store solution column in matrix for (j = 0; j <= i; j++) { X[j, m] = Z[j]; } } } } } return X; }
/// <summary> /// Solve a square Toeplitz system with a right-side matrix. /// </summary> /// <param name="col">The left-most column of the Toeplitz matrix.</param> /// <param name="row">The top-most row of the Toeplitz matrix.</param> /// <param name="Y">The right-side matrix of the system.</param> /// <returns>The solution matrix.</returns> /// <exception cref="ArgumentNullException"> /// <EM>col</EM> is a null reference, /// <para>or</para> /// <para><EM>row</EM> is a null reference,</para> /// <para>or</para> /// <para><EM>Y</EM> is a null reference.</para> /// </exception> /// <exception cref="RankException"> /// The length of <EM>col</EM> is 0, /// <para>or</para> /// <para>the lengths of <EM>col</EM> and <EM>row</EM> are not equal,</para> /// <para>or</para> /// <para>the number of rows in <EM>Y</EM> does not the length of <EM>col</EM> and <EM>row</EM>.</para> /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <exception cref="ArithmeticException"> /// The values of the first element of <EM>col</EM> and <EM>row</EM> are not equal. /// </exception> /// <remarks> /// This method solves the linear system <B>AX</B> = <B>Y</B>. Where /// <B>T</B> is a square Toeplitz matrix, <B>X</B> is an unknown /// matrix and <B>Y</B> is a known matrix. /// <para> /// The classic Levinson algorithm is used to solve the system. The algorithm /// assumes that all the leading sub-matrices of the Toeplitz matrix are /// non-singular. When a sub-matrix is near singular, accuracy will /// be degraded. This member requires approximately <B>N</B> squared /// FLOPS to calculate a solution, where <B>N</B> is the matrix order. /// </para> /// <para> /// This static method has minimal storage requirements as it combines /// the <b>UDL</b> decomposition with the calculation of the solution vector /// in a single algorithm. /// </para> /// </remarks> public static ComplexDoubleMatrix Solve(IROComplexDoubleVector col, IROComplexDoubleVector row, IROComplexDoubleMatrix Y) { // check parameters if (col == null) { throw new System.ArgumentNullException("col"); } else if (col.Length == 0) { throw new RankException("The length of col is zero."); } else if (row == null) { throw new System.ArgumentNullException("row"); } else if (col.Length != row.Length) { throw new RankException("The lengths of col and row are not equal."); } else if (col[0] != row[0]) { throw new ArithmeticException("The values of the first element of col and row are not equal."); } else if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (col.Length != Y.Columns) { throw new RankException("The numer of rows in Y does not match the length of col and row."); } // check if leading diagonal is zero if (col[0] == Complex.Zero) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // decompose matrix int order = col.Length; Complex[] A = new Complex[order]; Complex[] B = new Complex[order]; Complex[] Z = new Complex[order]; ComplexDoubleMatrix X = new ComplexDoubleMatrix(order); Complex Q, S, Ke, Kr, e; Complex Inner; int i, j, l; // setup the zero order solution A[0] = Complex.One; B[0] = Complex.One; e = Complex.One / col[0]; X.SetRow(0, e * ComplexDoubleVector.GetRow(Y, 0)); for (i = 1; i < order; i++) { // calculate inner products Q = Complex.Zero; for (j = 0, l = 1; j < i; j++, l++) { Q += col[l] * A[j]; } S = Complex.Zero; for (j = 0, l = 1; j < i; j++, l++) { S += row[l] * B[j]; } // reflection coefficients Kr = -S * e; Ke = -Q * e; // update lower triangle (in temporary storage) Z[0] = Complex.Zero; Array.Copy(A, 0, Z, 1, i); for (j = 0, l = i - 1; j < i; j++, l--) { Z[j] += Ke * B[l]; } // update upper triangle for (j = i; j > 0; j--) { B[j] = B[j - 1]; } B[0] = Complex.Zero; for (j = 0, l = i - 1; j < i; j++, l--) { B[j] += Kr * A[l]; } // copy from temporary storage to lower triangle Array.Copy(Z, 0, A, 0, i + 1); // check for singular sub-matrix) if (Ke * Kr == Complex.One) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // update diagonal e = e / (Complex.One - Ke * Kr); for (l = 0; l < Y.Rows; l++) { ComplexDoubleVector W = X.GetColumn(l); ComplexDoubleVector M = ComplexDoubleVector.GetColumn(Y, l); Inner = M[i]; for (j = 0; j < i; j++) { Inner += A[j] * M[j]; } Inner *= e; W[i] = Inner; for (j = 0; j < i; j++) { W[j] += Inner * B[j]; } X.SetColumn(l, W); } } return(X); }
/// <summary> /// Solve a symmetric square Toeplitz system with a right-side matrix. /// </summary> /// <param name="Y">The right-hand side of the system.</param> /// <returns>The solution matrix.</returns> /// <exception cref="ArgumentNullException"> /// Parameter <B>Y</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The number of rows in <B>Y</B> is not equal to the number of rows in the Toeplitz matrix. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This member solves the linear system <B>TX</B> = <B>Y</B>, where <B>T</B> is /// a symmetric square Toeplitz matrix, <B>X</B> is the unknown solution matrix /// and <B>Y</B> is a known matrix. /// <para> /// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation /// using the Levinson algorithm, and then calculates the solution matrix. /// </para> /// </remarks> public ComplexDoubleMatrix Solve(IROComplexDoubleMatrix Y) { ComplexDoubleMatrix X; // check parameters if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (m_Order != Y.Columns) { throw new RankException("The numer of rows in Y is not equal to the number of rows in the Toeplitz matrix."); } Compute(); if (m_IsSingular == true) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } int M = Y.Rows; int i, j, l, m; // index/loop variables Complex[] Inner; // inner product Complex[] G; // scaling constant Complex[] A; // reference to current order coefficients Complex scalar; // allocate memory for solution X = new ComplexDoubleMatrix(m_Order, M); Inner = new Complex[M]; G = new Complex[M]; // setup zero order solution scalar = Complex.One / m_LeftColumn[0]; for (m = 0; m < M; m++) { #if MANAGED X.data[0][m] = scalar * Y[0, m]; #else X.data[m * m_Order] = scalar * Y[0, m]; #endif } // solve systems of increasing order for (i = 1; i < m_Order; i++) { // calculate inner product for (m = 0; m < M; m++) { #if MANAGED Inner[m] = Y[i, m]; #else Inner[m] = Y[i, m]; #endif } for (j = 0, l = i; j < i; j++, l--) { scalar = m_LeftColumn[l]; for (m = 0; m < M; m++) { #if MANAGED Inner[m] -= scalar * X.data[j][m]; #else Inner[m] -= scalar * X.data[m * m_Order + j]; #endif } } // get the current predictor coefficients row A = m_LowerTriangle[i]; // update the solution matrix for (m = 0; m < M; m++) { G[m] = m_Diagonal[i] * Inner[m]; } for (j = 0; j <= i; j++) { scalar = A[j]; for (m = 0; m < M; m++) { #if MANAGED X.data[j][m] += scalar * G[m]; #else X.data[m * m_Order + j] += scalar * G[m]; #endif } } } return(X); }
/// <summary> /// Solve a symmetric square Toeplitz system with a right-side matrix. /// </summary> /// <param name="Y">The right-hand side of the system.</param> /// <returns>The solution matrix.</returns> /// <exception cref="ArgumentNullException"> /// Parameter <B>Y</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The number of rows in <B>Y</B> is not equal to the number of rows in the Toeplitz matrix. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This member solves the linear system <B>TX</B> = <B>Y</B>, where <B>T</B> is /// a symmetric square Toeplitz matrix, <B>X</B> is the unknown solution matrix /// and <B>Y</B> is a known matrix. /// <para> /// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation /// using the Levinson algorithm, and then calculates the solution matrix. /// </para> /// </remarks> public ComplexDoubleMatrix Solve(IROComplexDoubleMatrix Y) { ComplexDoubleMatrix X; // check parameters if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (m_Order != Y.Columns) { throw new RankException("The numer of rows in Y is not equal to the number of rows in the Toeplitz matrix."); } Compute(); if (m_IsSingular == true) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } int M = Y.Rows; int i, j, l, m; // index/loop variables Complex[] Inner; // inner product Complex[] G; // scaling constant Complex[] A; // reference to current order coefficients Complex scalar; // allocate memory for solution X = new ComplexDoubleMatrix(m_Order, M); Inner = new Complex[M]; G = new Complex[M]; // setup zero order solution scalar = Complex.One / m_LeftColumn[0]; for (m = 0; m < M; m++) { #if MANAGED X.data[0][m] = scalar * Y[0,m]; #else X.data[m*m_Order] = scalar * Y[0,m]; #endif } // solve systems of increasing order for (i = 1; i < m_Order; i++) { // calculate inner product for (m = 0; m < M; m++) { #if MANAGED Inner[m] = Y[i,m]; #else Inner[m] = Y[i,m]; #endif } for (j = 0, l = i; j < i; j++, l--) { scalar = m_LeftColumn[l]; for (m = 0; m < M; m++) { #if MANAGED Inner[m] -= scalar * X.data[j][m]; #else Inner[m] -= scalar * X.data[m*m_Order+j]; #endif } } // get the current predictor coefficients row A = m_LowerTriangle[i]; // update the solution matrix for (m = 0; m < M; m++) { G[m] = m_Diagonal[i] * Inner[m]; } for (j = 0; j <= i; j++) { scalar = A[j]; for (m = 0; m < M; m++) { #if MANAGED X.data[j][m] += scalar * G[m]; #else X.data[m*m_Order+j] += scalar * G[m]; #endif } } } return X; }
///<summary>Constructor for QR decomposition class. The constructor performs the factorization and the upper and ///lower matrices are accessible by the <c>Q</c> and <c>R</c> properties.</summary> ///<param name="matrix">The matrix to factor.</param> ///<exception cref="ArgumentNullException">matrix is null.</exception> public ComplexDoubleQRDecomp(IROComplexDoubleMatrix matrix) { if (matrix == null) throw new System.ArgumentNullException("matrix cannot be null."); this.matrix = matrix; }