/// <overloads> /// There are two permuations of the constructor, both require a parameter corresponding /// to the left-most column of a Toeplitz matrix. /// </overloads> /// <summary> /// Constructor with <c>ComplexFloatVector</c> parameter. /// </summary> /// <param name="T">The left-most column of the Toeplitz matrix.</param> /// <exception cref="ArgumentNullException"> /// <B>T</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The length of <B>T</B> is zero. /// </exception> public ComplexFloatSymmetricLevinson(IROComplexFloatVector T) { // check parameter if (T == null) { throw new System.ArgumentNullException("T"); } else if (T.Length == 0) { throw new RankException("The length of T is zero."); } // save the vector m_LeftColumn = new ComplexFloatVector(T); m_Order = m_LeftColumn.Length; // allocate memory for lower triangular matrix m_LowerTriangle = new ComplexFloat[m_Order][]; for (int i = 0; i < m_Order; i++) { m_LowerTriangle[i] = new ComplexFloat[i + 1]; } // allocate memory for diagonal m_Diagonal = new ComplexFloat[m_Order]; }
public static IComplexFloatMatrix UA(IROComplexFloatVector u, IComplexFloatMatrix A, int r1, int r2, int c1, int c2) { if (c1 > c2) { return(A); } return(UA(u, A, r1, r2, c1, c2, new ComplexFloatVector(c2 - c1 + 1))); }
public static IComplexFloatMatrix AU(IComplexFloatMatrix A, IROComplexFloatVector u, int r1, int r2, int c1, int c2) { if (r2 < r1) { return(A); } return(AU(A, u, r1, r2, c1, c2, new ComplexFloatVector(r2 - r1 + 1))); }
/// <overloads> /// Solve a symmetric square Toeplitz system. /// </overloads> /// <summary> /// Solve a symmetric square Toeplitz system with a right-side vector. /// </summary> /// <param name="Y">The right-hand side of the system.</param> /// <returns>The solution vector.</returns> /// <exception cref="ArgumentNullException"> /// Parameter <B>Y</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The length of <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 /// the symmetric square Toeplitz matrix, <B>X</B> is the unknown solution vector /// and <B>Y</B> is a known vector. /// <para> /// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation /// using the Levinson algorithm, and then calculates the solution vector. /// </para> /// </remarks> public ComplexFloatVector Solve(IROComplexFloatVector Y) { ComplexFloatVector X; // check parameters if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (m_Order != Y.Length) { throw new RankException("The length of 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 i, j, l; // index/loop variables ComplexFloat Inner; // inner product ComplexFloat G; // scaling constant ComplexFloat[] A; // reference to current order coefficients // allocate memory for solution X = new ComplexFloatVector(m_Order) { // setup zero order solution [0] = Y[0] / m_LeftColumn[0] }; // solve systems of increasing order for (i = 1; i < m_Order; i++) { // calculate inner product Inner = Y[i]; for (j = 0, l = i; j < i; j++, l--) { Inner -= X[j] * m_LeftColumn[l]; } // get the current predictor coefficients row A = m_LowerTriangle[i]; // update the solution vector G = Inner * m_Diagonal[i]; for (j = 0; j <= i; j++) { X[j] += G * A[j]; } } return(X); }
private ComplexFloatVector Pivot(IROComplexFloatVector B) { ComplexFloatVector ret = new ComplexFloatVector(B.Length); for (int i = 0; i < pivots.Length; i++) { ret.data[i] = B[pivots[i]]; } 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 vector, 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 the length of B must be the same.</exception> public ComplexFloatVector Solve(IROComplexFloatVector B) { if (B == null) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if (!ispd) { throw new NotPositiveDefiniteException(); } else { if (B.Length != order) { throw new System.ArgumentException("The length of B must be the same as the order of the matrix."); } #if MANAGED // Copy right hand side. var X = new ComplexFloatVector(B); // Solve L*Y = B; for (int i = 0; i < order; i++) { ComplexFloat sum = B[i]; for (int k = i - 1; k >= 0; k--) { sum -= l.data[i][k] * X.data[k]; } X.data[i] = sum / l.data[i][i]; } // Solve L'*X = Y; for (int i = order - 1; i >= 0; i--) { ComplexFloat sum = X.data[i]; for (int k = i + 1; k < order; k++) { sum -= ComplexMath.Conjugate(l.data[k][i]) * X.data[k]; } X.data[i] = sum / ComplexMath.Conjugate(l.data[i][i]); } return(X); #else ComplexFloat[] rhs = ComplexFloatMatrix.ToLinearComplexArray(B); Lapack.Potrs.Compute(Lapack.UpLo.Lower, order, 1, l.data, order, rhs, B.Length); ComplexFloatVector ret = new ComplexFloatVector(order, B.Length); ret.data = rhs; return(ret); #endif } }
/// <summary> /// Invert a symmetric square Toeplitz matrix. /// </summary> /// <param name="T">The left-most column of the symmetric Toeplitz matrix.</param> /// <returns>The inverse matrix.</returns> /// <exception cref="ArgumentNullException"> /// <B>T</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The length of <B>T</B> must be greater than zero. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This static member combines the <b>UDL</b> decomposition and Trench's algorithm into a /// single algorithm. When compared to the non-static member it requires minimal data storage /// and suffers from no speed penalty. /// <para> /// Trench's algorithm requires <b>N</b> squared FLOPS, compared to <b>N</b> cubed FLOPS /// if we simply solved a linear Toeplitz system with a right-side identity matrix (<b>N</b> is the matrix order). /// </para> /// </remarks> public static ComplexFloatMatrix Inverse(IROComplexFloatVector T) { ComplexFloatMatrix X; // check parameters if (T == null) { throw new System.ArgumentNullException("T"); } else if (T.Length < 1) { throw new System.RankException("The length of T must be greater than zero."); } else if (T.Length == 1) { X = new ComplexFloatMatrix(1) {
///<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 vector, X.</returns> ///<exception cref="ArgumentNullException">B is null.</exception> ///<exception cref="SingularMatrixException">A is singular.</exception> ///<exception cref="ArgumentException">The number of rows of A and the length of B must be the same.</exception> public ComplexFloatVector Solve(IROComplexFloatVector B) { if (B == null) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if (singular) { throw new SingularMatrixException(); } else { if (B.Length != order) { throw new System.ArgumentException("The length of B must be the same as the order of the matrix."); } #if MANAGED // Copy right hand side with pivoting ComplexFloatVector X = Pivot(B); // Solve L*Y = B(piv,:) for (int k = 0; k < order; k++) { for (int i = k + 1; i < order; i++) { X[i] -= X[k] * factor[i][k]; } } // Solve U*X = Y; for (int k = order - 1; k >= 0; k--) { X[k] /= factor[k][k]; for (int i = 0; i < k; i++) { X[i] -= X[k] * factor[i][k]; } } return(X); #else ComplexFloat[] rhs = ComplexFloatMatrix.ToLinearComplexArray(B); Lapack.Getrs.Compute(Lapack.Transpose.NoTrans, order, 1, factor, order, pivots, rhs, rhs.Length); return(new ComplexFloatVector(rhs)); #endif } }
///<summary>Constructor for <c>ComplexDoubleVector</c> to deep copy from a <see cref="IROComplexDoubleVector" /></summary> ///<param name="src"><c>ComplexDoubleVector</c> to deep copy into <c>ComplexDoubleVector</c>.</param> ///<exception cref="ArgumentNullException">Exception thrown if null passed as 'src' parameter.</exception> public ComplexFloatVector(IROComplexFloatVector src) { if (src == null) { throw new ArgumentNullException("IROComplexFloatVector cannot be null"); } if (src is ComplexFloatVector) { data = (ComplexFloat[])(((ComplexFloatVector)src).data.Clone()); } else { data = new ComplexFloat[src.Length]; for (int i = 0; i < src.Length; ++i) { data[i] = src[i]; } } }
public static IComplexFloatMatrix UA(IROComplexFloatVector u, IComplexFloatMatrix A, int r1, int r2, int c1, int c2, IComplexFloatVector v) { if (r2 < r1 || c2 < c1) { return(A); } if (r2 - r1 + 1 > u.Length) { throw new ArgumentException("Householder vector too short.", "u"); } if (c2 - c1 + 1 > v.Length) { throw new ArgumentException("Work vector too short.", "v"); } for (int j = c1; j <= c2; j++) { v[j - c1] = ComplexFloat.Zero; } for (int i = r1; i <= r2; i++) { for (int j = c1; j <= c2; j++) { v[j - c1] = new ComplexFloat(v[j - c1].Real + u[i - r1].Real * A[i, j].Real + u[i - r1].Imag * A[i, j].Imag, v[j - c1].Imag + u[i - r1].Real * A[i, j].Imag - u[i - r1].Imag * A[i, j].Real); } } for (int i = r1; i <= r2; i++) { for (int j = c1; j <= c2; j++) { A[i, j] = new ComplexFloat(A[i, j].Real - u[i - r1].Real * v[j - c1].Real + u[i - r1].Imag * v[j - c1].Imag, A[i, j].Imag - u[i - r1].Real * v[j - c1].Imag - u[i - r1].Imag * v[j - c1].Real); } } return(A); }
/// <summary> /// Invert a square Toeplitz 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> /// <returns>The inverse matrix.</returns> /// <exception cref="ArgumentNullException"> /// <B>col</B> is a null reference. /// <para>or</para> /// <para><B>row</B> is a null reference.</para> /// </exception> /// <exception cref="RankException"> /// The length of <B>col</B> is 0, /// <para>or</para> /// <para>the lengths of <B>col</B> and <B>row</B> are not equal.</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 <B>col</B> and <B>row</B> are not equal. /// </exception> /// <remarks> /// This static member combines the <b>UDL</b> decomposition and Trench's algorithm into a /// single algorithm. It requires minimal data storage, compared to the non-static member /// and suffers from no speed penalty in comparision. /// <para> /// Trench's algorithm requires <b>N</b> squared FLOPS, compared to <b>N</b> cubed FLOPS /// if we simply solved a linear Toeplitz system with a right-side identity matrix (<b>N</b> is the matrix order). /// </para> /// </remarks> public static ComplexFloatMatrix Inverse(IROComplexFloatVector col, IROComplexFloatVector row) { // 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."); } // check if leading diagonal is zero if (col[0] == ComplexFloat.Zero) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // decompose matrix int order = col.Length; ComplexFloat[] A = new ComplexFloat[order]; ComplexFloat[] B = new ComplexFloat[order]; ComplexFloat[] Z = new ComplexFloat[order]; ComplexFloat Q, S, Ke, Kr, e; int i, j, k, l; // setup the zero order solution A[0] = ComplexFloat.One; B[0] = ComplexFloat.One; e = ComplexFloat.One / col[0]; for (i = 1; i < order; i++) { // calculate inner products Q = ComplexFloat.Zero; for (j = 0, l = 1; j < i; j++, l++) { Q += col[l] * A[j]; } S = ComplexFloat.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] = ComplexFloat.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] = ComplexFloat.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 == ComplexFloat.One) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // update diagonal e = e / (ComplexFloat.One - Ke * Kr); } // calculate the inverse ComplexFloatMatrix I = new ComplexFloatMatrix(order); // the solution matrix ComplexFloat A1, B1; #if MANAGED ComplexFloat[] current, previous; // references to rows in the solution // setup the first row in wedge current = I.data[0]; for (i = 0, j = order - 1; i < order; i++, j--) { current[i] = e * B[j]; } // calculate values in the rest of the wedge for (i = 1; i < order; i++) { previous = current; current = I.data[i]; A1 = e * A[order - i - 1]; B1 = e * B[i - 1]; current[0] = A1; for (j = 1, k = 0, l = order - 2; j < order - i; j++, k++, l--) { current[j] = previous[k] + A1 * B[l] - B1 * A[k]; } } #else // setup the first row in wedge for (i = 0, j = order - 1; i < order; i++, j--) { I[0, i] = e * B[j]; } // calculate values in the rest of the wedge for (i = 1; i < order; i++) { A1 = e * A[order - i - 1]; B1 = e * B[i - 1]; I[i, 0] = A1; for (j = 1, k = 0, l = order - 2; j < order - i; j++, k++, l--) { I[i, j] = I[i - 1, k] + A1 * B[l] - B1 * A[k]; } } #endif // inverse is a persymmetric matrix. for (i = 0, j = order - 1; i < order; i++, j--) { for (k = 0, l = order - 1; k < j; k++, l--) { I[l, j] = I[i, k]; } } return I; }
/// <overloads> /// Solve a square Toeplitz system. /// </overloads> /// <summary> /// Solve a square Toeplitz system with a right-side vector. /// </summary> /// <param name="Y">The right-hand side of the system.</param> /// <returns>The solution vector.</returns> /// <exception cref="ArgumentNullException"> /// Parameter <B>Y</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The length of Y 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 /// the square Toeplitz matrix, <B>X</B> is the unknown solution vector /// and <B>Y</B> is a known vector. /// <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 ComplexFloatVector Solve(IROComplexFloatVector Y) { ComplexFloatVector X; ComplexFloat Inner; int i, j; // check parameters if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (m_Order != Y.Length) { throw new RankException("The length of 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 ComplexFloat[] A, B; X = new ComplexFloatVector(m_Order); 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]; } } return X; }
/// <summary> /// Constructor with <c>ComplexFloatVector</c> parameters. /// </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> /// <exception cref="ArgumentNullException"> /// <B>col</B> is a null reference, /// <para>or</para> /// <para><B>row</B> is a null reference.</para> /// </exception> /// <exception cref="RankException"> /// The length col <B>col</B> is zero, /// <para>or</para> /// <para>the length of <B>col</B> does not match that of <B>row</B>.</para> /// </exception> /// <exception cref="ArithmeticException"> /// The values of the first element of <B>col</B> and <B>row</B> are not equal. /// </exception> public ComplexFloatLevinson(IROComplexFloatVector col, IROComplexFloatVector row) { // 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."); } // save the vectors m_LeftColumn = new ComplexFloatVector(col); m_TopRow = new ComplexFloatVector(row); m_Order = m_LeftColumn.Length; // allocate memory for lower triangular matrix m_LowerTriangle = new ComplexFloat[m_Order][]; for (int i = 0; i < m_Order; i++) { m_LowerTriangle[i] = new ComplexFloat[i + 1]; } // allocate memory for diagonal m_Diagonal = new ComplexFloat[m_Order]; // allocate memory for upper triangular matrix m_UpperTriangle = new ComplexFloat[m_Order][]; for (int i = 0; i < m_Order; i++) { m_UpperTriangle[i] = new ComplexFloat[i + 1]; } }
/// <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 ComplexFloatMatrix Solve(IROComplexFloatVector col, IROComplexFloatVector row, IROComplexFloatMatrix 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] == ComplexFloat.Zero) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // decompose matrix int order = col.Length; ComplexFloat[] A = new ComplexFloat[order]; ComplexFloat[] B = new ComplexFloat[order]; ComplexFloat[] Z = new ComplexFloat[order]; ComplexFloatMatrix X = new ComplexFloatMatrix(order); ComplexFloat Q, S, Ke, Kr, e; ComplexFloat Inner; int i, j, l; // setup the zero order solution A[0] = ComplexFloat.One; B[0] = ComplexFloat.One; e = ComplexFloat.One / col[0]; X.SetRow(0, e * ComplexFloatVector.GetRow(Y, 0)); for (i = 1; i < order; i++) { // calculate inner products Q = ComplexFloat.Zero; for (j = 0, l = 1; j < i; j++, l++) { Q += col[l] * A[j]; } S = ComplexFloat.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] = ComplexFloat.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] = ComplexFloat.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 == ComplexFloat.One) { throw new SingularMatrixException("One of the leading sub-matrices is singular."); } // update diagonal e = e / (ComplexFloat.One - Ke * Kr); for (l = 0; l < Y.Rows; l++) { ComplexFloatVector W = X.GetColumn(l); ComplexFloatVector M = ComplexFloatVector.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> /// Invert a symmetric square Toeplitz matrix. /// </summary> /// <param name="T">The left-most column of the symmetric Toeplitz matrix.</param> /// <returns>The inverse matrix.</returns> /// <exception cref="ArgumentNullException"> /// <B>T</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The length of <B>T</B> must be greater than zero. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This static member combines the <b>UDL</b> decomposition and Trench's algorithm into a /// single algorithm. When compared to the non-static member it requires minimal data storage /// and suffers from no speed penalty. /// <para> /// Trench's algorithm requires <b>N</b> squared FLOPS, compared to <b>N</b> cubed FLOPS /// if we simply solved a linear Toeplitz system with a right-side identity matrix (<b>N</b> is the matrix order). /// </para> /// </remarks> public static ComplexFloatMatrix Inverse(IROComplexFloatVector T) { ComplexFloatMatrix X; // check parameters if (T == null) { throw new System.ArgumentNullException("T"); } else if (T.Length < 1) { throw new System.RankException("The length of T must be greater than zero."); } else if (T.Length == 1) { X = new ComplexFloatMatrix(1); X[0, 0] = ComplexFloat.One / T[0]; } else { int N = T.Length; ComplexFloat f, g; int i, j, l, k, m, n; X = new ComplexFloatMatrix(N); // calculate the predictor coefficients ComplexFloatVector Y = ComplexFloatSymmetricLevinson.YuleWalker(T); // calculate gamma f = T[0]; for (i = 1, j = 0; i < N; i++, j++) { f += T[i] * Y[j]; } g = ComplexFloat.One / f; // calculate first row of inverse X[0, 0] = g; for (i = 1, j = 0; i < N; i++, j++) { X[0, i] = g * Y[j]; } // calculate successive rows of upper wedge for (i = 0, j = 1, k = N - 2; i < N / 2; i++, j++, k--) { for (l = j, m = i, n = N - 1 - j; l < N - j; l++, m++, n--) { X[j, l] = X[i, m] + g * (Y[i] * Y[m] - Y[k] * Y[n]); } } // this is symmetric matrix ... for (i = 0; i <= N / 2; i++) { for (j = i + 1; j < N - i; j++) { X[j, i] = X[i, j]; } } // and a persymmetric matrix. for (i = 0, j = N - 1; i < N; i++, j--) { for (k = 0, l = N - 1; k < j; k++, l--) { X[l, j] = X[i, k]; } } } return(X); }
/// <overloads> /// Solve a symmetric square Toeplitz system. /// </overloads> /// <summary> /// Solve a symmetric square Toeplitz system with a right-side vector. /// </summary> /// <param name="Y">The right-hand side of the system.</param> /// <returns>The solution vector.</returns> /// <exception cref="ArgumentNullException"> /// Parameter <B>Y</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The length of <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 /// the symmetric square Toeplitz matrix, <B>X</B> is the unknown solution vector /// and <B>Y</B> is a known vector. /// <para> /// The class implicitly decomposes the inverse Toeplitz matrix into a <b>UDL</b> factorisation /// using the Levinson algorithm, and then calculates the solution vector. /// </para> /// </remarks> public ComplexFloatVector Solve(IROComplexFloatVector Y) { ComplexFloatVector X; // check parameters if (Y == null) { throw new System.ArgumentNullException("Y"); } else if (m_Order != Y.Length) { throw new RankException("The length of 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 i, j, l; // index/loop variables ComplexFloat Inner; // inner product ComplexFloat G; // scaling constant ComplexFloat[] A; // reference to current order coefficients // allocate memory for solution X = new ComplexFloatVector(m_Order); // setup zero order solution X[0] = Y[0] / m_LeftColumn[0]; // solve systems of increasing order for (i = 1; i < m_Order; i++) { // calculate inner product Inner = Y[i]; for (j = 0, l = i; j < i; j++, l--) { Inner -= X[j] * m_LeftColumn[l]; } // get the current predictor coefficients row A = m_LowerTriangle[i]; // update the solution vector G = Inner * m_Diagonal[i]; for (j = 0; j <= i; j++) { X[j] += G * A[j]; } } return X; }
/// <summary> /// Invert a symmetric square Toeplitz matrix. /// </summary> /// <param name="T">The left-most column of the symmetric Toeplitz matrix.</param> /// <returns>The inverse matrix.</returns> /// <exception cref="ArgumentNullException"> /// <B>T</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The length of <B>T</B> must be greater than zero. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This static member combines the <b>UDL</b> decomposition and Trench's algorithm into a /// single algorithm. When compared to the non-static member it requires minimal data storage /// and suffers from no speed penalty. /// <para> /// Trench's algorithm requires <b>N</b> squared FLOPS, compared to <b>N</b> cubed FLOPS /// if we simply solved a linear Toeplitz system with a right-side identity matrix (<b>N</b> is the matrix order). /// </para> /// </remarks> public static ComplexFloatMatrix Inverse(IROComplexFloatVector T) { ComplexFloatMatrix X; // check parameters if (T == null) { throw new System.ArgumentNullException("T"); } else if (T.Length < 1) { throw new System.RankException("The length of T must be greater than zero."); } else if (T.Length == 1) { X = new ComplexFloatMatrix(1); X[0, 0] = ComplexFloat.One / T[0]; } else { int N = T.Length; ComplexFloat f, g; int i, j, l, k, m, n; X = new ComplexFloatMatrix(N); // calculate the predictor coefficients ComplexFloatVector Y = ComplexFloatSymmetricLevinson.YuleWalker(T); // calculate gamma f = T[0]; for (i = 1, j = 0; i < N; i++, j++) { f += T[i] * Y[j]; } g = ComplexFloat.One / f; // calculate first row of inverse X[0, 0] = g; for (i = 1, j = 0; i < N; i++, j++) { X[0, i] = g * Y[j]; } // calculate successive rows of upper wedge for (i = 0, j = 1, k = N - 2; i < N / 2; i++, j++, k--) { for (l = j, m = i, n = N-1-j; l < N - j; l++, m++, n--) { X[j, l] = X[i, m] + g * (Y[i] * Y[m] - Y[k] * Y[n]); } } // this is symmetric matrix ... for (i = 0; i <= N / 2; i++) { for (j = i + 1; j < N - i; j++) { X[j, i] = X[i, j]; } } // and a persymmetric matrix. for (i = 0, j = N - 1; i < N; i++, j--) { for (k = 0, l = N - 1; k < j; k++, l--) { X[l, j] = X[i, k]; } } } return X; }
public static IComplexFloatMatrix UA(IROComplexFloatVector u, IComplexFloatMatrix A, int r1, int r2, int c1, int c2) { if (c1 > c2) { return A; } return UA(u, A, r1, r2, c1, c2, new ComplexFloatVector(c2 - c1 + 1)); }
public static IComplexFloatMatrix AU(IComplexFloatMatrix A, IROComplexFloatVector u, int r1, int r2, int c1, int c2, IComplexFloatVector v) { if (r2 < r1 || c2 < c1) { return A; } if (c2 - c1 + 1 > u.Length) { throw new ArgumentException("Householder vector too short.", "u"); } if (r2 - r1 + 1 > v.Length) { throw new ArgumentException("Work vector too short.", "v"); } for (int i = r1; i <= r2; i++) { v[i - r1] = ComplexFloat.Zero; for (int j = c1; j <= c2; j++) { v[i - r1] = new ComplexFloat(v[i - r1].Real + A[i, j].Real * u[j - c1].Real - A[i, j].Imag * u[j - c1].Imag, v[i - r1].Imag + A[i, j].Real * u[j - c1].Imag + A[i, j].Imag * u[j - c1].Real); } } for (int i = r1; i <= r2; i++) { for (int j = c1; j <= c2; j++) { A[i, j] = new ComplexFloat(A[i, j].Real - v[i - r1].Real * u[j - c1].Real - v[i - r1].Imag * u[j - c1].Imag, A[i, j].Imag + v[i - r1].Real * u[j - c1].Imag - v[i - r1].Imag * u[j - c1].Real); } } return A; }
public static IComplexFloatMatrix AU(IComplexFloatMatrix A, IROComplexFloatVector u, int r1, int r2, int c1, int c2) { if (r2 < r1) { return A; } return AU(A, u, r1, r2, c1, c2, new ComplexFloatVector(r2 - r1 + 1)); }
/// <overloads> /// Solve a symmetric square Toeplitz system. /// </overloads> /// <summary> /// Solve a symmetric square Toeplitz system with a right-side vector. /// </summary> /// <param name="T">The left-most column of the Toeplitz matrix.</param> /// <param name="Y">The right-side vector of the system.</param> /// <returns>The solution vector.</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 length of <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 /// vector and <B>Y</B> is a known vector. /// <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 ComplexFloatVector Solve(IROComplexFloatVector T, IROComplexFloatVector Y) { ComplexFloatVector 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.Length) { throw new RankException("The length of T and Y are not equal."); } else { // allocate memory int N = T.Length; X = new ComplexFloatVector(N); // solution vector ComplexFloat e; // prediction error // setup zero order solution e = T[0]; if (e == ComplexFloat.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } X[0] = Y[0] / T[0]; if (N > 1) { ComplexFloatVector a = new ComplexFloatVector(N - 1); // prediction coefficients ComplexFloatVector Z = new ComplexFloatVector(N - 1); // temporary storage vector ComplexFloat g; // reflection coefficient ComplexFloat inner; // inner product ComplexFloat k; int i, j, l; // 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 g = -(inner / e); for (j = 0, l = i - 2; j < i - 1; j++, l--) { Z[j] = a[j] + g * a[l]; } // copy vector for (j = 0; j < i - 1; j++) { a[j] = Z[j]; } a[i - 1] = g; e *= (ComplexFloat.One - g * g); if (e == ComplexFloat.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } // calculate second inner product inner = Y[i]; for (j = 0, l = i; j < i; j++, l--) { inner -= X[j] * T[l]; } // update solution vector k = inner / e; for (j = 0, l = i - 1; j < i; j++, l--) { X[j] = X[j] + k * a[l]; } X[j] = k; } } } 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 ComplexFloatMatrix Solve(IROComplexFloatVector T, IROComplexFloatMatrix Y) { ComplexFloatMatrix 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 ComplexFloatMatrix(N, M); // solution matrix ComplexFloatVector Z = new ComplexFloatVector(N); // temporary storage vector ComplexFloat e; // prediction error int i, j, l, m; // setup zero order solution e = T[0]; if (e == ComplexFloat.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) { ComplexFloatVector a = new ComplexFloatVector(N - 1); // prediction coefficients ComplexFloat p; // reflection coefficient ComplexFloat inner; // inner product ComplexFloat 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 *= (ComplexFloat.One - p * p); if (e == ComplexFloat.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 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 ComplexFloatMatrix Solve(IROComplexFloatVector T, IROComplexFloatMatrix Y) { ComplexFloatMatrix 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 ComplexFloatMatrix(N, M); // solution matrix ComplexFloatVector Z = new ComplexFloatVector(N); // temporary storage vector ComplexFloat e; // prediction error int i, j, l, m; // setup zero order solution e = T[0]; if (e == ComplexFloat.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) { ComplexFloatVector a = new ComplexFloatVector(N - 1); // prediction coefficients ComplexFloat p; // reflection coefficient ComplexFloat inner; // inner product ComplexFloat 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 *= (ComplexFloat.One - p * p); if (e == ComplexFloat.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 the Yule-Walker equations for a symmetric square Toeplitz system /// </summary> /// <param name="R">The left-most column of the Toeplitz matrix.</param> /// <returns>The solution vector.</returns> /// <exception cref="ArgumentNullException"> /// <B>R</B> is a null reference. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// The length of <B>R</B> must be greater than one. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This member is used to solve the Yule-Walker system <B>AX</B> = -<B>a</B>, /// where <B>A</B> is a symmetric square Toeplitz matrix, constructed /// from the elements <B>R[0]</B>, ..., <B>R[N-2]</B> and /// the vector <B>a</B> is constructed from the elements /// <B>R[1]</B>, ..., <B>R[N-1]</B>. /// <para> /// Durbin's algorithm is used to solve the linear system. It requires /// approximately the <b>N</b> squared FLOPS to calculate the /// solution (<b>N</b> is the matrix order). /// </para> /// </remarks> public static ComplexFloatVector YuleWalker(IROComplexFloatVector R) { ComplexFloatVector a; // check parameters if (R == null) { throw new System.ArgumentNullException("R"); } else if (R.Length < 2) { throw new System.ArgumentOutOfRangeException("R", "The length of R must be greater than 1."); } else { int N = R.Length - 1; a = new ComplexFloatVector(N); // prediction coefficients ComplexFloatVector Z = new ComplexFloatVector(N); // temporary storage vector ComplexFloat e; // predictor error ComplexFloat inner; // inner product ComplexFloat g; // reflection coefficient int i, j, l; // setup first order solution e = R[0]; if (e == ComplexFloat.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } g = -R[1] / R[0]; a[0] = g; // calculate solution for successive orders for (i = 1; i < N; i++) { e *= (ComplexFloat.One - g * g); if (e == ComplexFloat.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } // calculate inner product inner = R[i + 1]; for (j = 0, l = i; j < i; j++, l--) { inner += a[j] * R[l]; } // update prediction coefficients g = -(inner / e); for (j = 0, l = i - 1; j < i; j++, l--) { Z[j] = a[j] + g * a[l]; } // copy vector for (j = 0; j < i; j++) { a[j] = Z[j]; } a[i] = g; } } return a; }
///<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 vector, 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 the length of B must be the same.</exception> public ComplexFloatVector Solve (IROComplexFloatVector B) { if ( B == null ) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if ( !ispd ) { throw new NotPositiveDefiniteException(); } else { if ( B.Length != order ) { throw new System.ArgumentException("The length of B must be the same as the order of the matrix." ); } #if MANAGED // Copy right hand side. ComplexFloatVector X = new ComplexFloatVector(B); // Solve L*Y = B; for (int i = 0; i < order; i++) { ComplexFloat sum = B[i]; for (int k = i-1; k >= 0; k--) { sum -= l.data[i][k] * X.data[k]; } X.data[i] = sum / l.data[i][i]; } // Solve L'*X = Y; for (int i =order-1; i >= 0; i--) { ComplexFloat sum = X.data[i]; for (int k = i+1; k < order; k++) { sum -= ComplexMath.Conjugate(l.data[k][i]) * X.data[k]; } X.data[i] = sum / ComplexMath.Conjugate(l.data[i][i]); } return X; #else ComplexFloat[] rhs = ComplexFloatMatrix.ToLinearComplexArray(B); Lapack.Potrs.Compute(Lapack.UpLo.Lower,order,1,l.data,order,rhs,B.Length); ComplexFloatVector ret = new ComplexFloatVector(order,B.Length); ret.data = rhs; return ret; #endif } }
/// <overloads> /// There are two permuations of the constructor, both require a parameter corresponding /// to the left-most column of a Toeplitz matrix. /// </overloads> /// <summary> /// Constructor with <c>ComplexFloatVector</c> parameter. /// </summary> /// <param name="T">The left-most column of the Toeplitz matrix.</param> /// <exception cref="ArgumentNullException"> /// <B>T</B> is a null reference. /// </exception> /// <exception cref="RankException"> /// The length of <B>T</B> is zero. /// </exception> public ComplexFloatSymmetricLevinson(IROComplexFloatVector T) { // check parameter if (T == null) { throw new System.ArgumentNullException("T"); } else if (T.Length == 0) { throw new RankException("The length of T is zero."); } // save the vector m_LeftColumn = new ComplexFloatVector(T); m_Order = m_LeftColumn.Length; // allocate memory for lower triangular matrix m_LowerTriangle = new ComplexFloat[m_Order][]; for (int i = 0; i < m_Order; i++) { m_LowerTriangle[i] = new ComplexFloat[i+1]; } // allocate memory for diagonal m_Diagonal = new ComplexFloat[m_Order]; }
///<summary>Constructor for <c>ComplexDoubleVector</c> to deep copy from a <see cref="IROComplexDoubleVector" /></summary> ///<param name="src"><c>ComplexDoubleVector</c> to deep copy into <c>ComplexDoubleVector</c>.</param> ///<exception cref="ArgumentNullException">Exception thrown if null passed as 'src' parameter.</exception> public ComplexFloatVector(IROComplexFloatVector src) { if (src == null) { throw new ArgumentNullException("IROComplexFloatVector cannot be null"); } if (src is ComplexFloatVector) { data = (ComplexFloat[]) (((ComplexFloatVector)src).data.Clone()); } else { data = new ComplexFloat[src.Length]; for (int i = 0; i < src.Length; ++i) { data[i] = src[i]; } } }
/// <overloads> /// Solve a symmetric square Toeplitz system. /// </overloads> /// <summary> /// Solve a symmetric square Toeplitz system with a right-side vector. /// </summary> /// <param name="T">The left-most column of the Toeplitz matrix.</param> /// <param name="Y">The right-side vector of the system.</param> /// <returns>The solution vector.</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 length of <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 /// vector and <B>Y</B> is a known vector. /// <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 ComplexFloatVector Solve(IROComplexFloatVector T, IROComplexFloatVector Y) { ComplexFloatVector 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.Length) { throw new RankException("The length of T and Y are not equal."); } else { // allocate memory int N = T.Length; X = new ComplexFloatVector(N); // solution vector ComplexFloat e; // prediction error // setup zero order solution e = T[0]; if (e == ComplexFloat.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } X[0] = Y[0] / T[0]; if (N > 1) { ComplexFloatVector a = new ComplexFloatVector(N - 1); // prediction coefficients ComplexFloatVector Z = new ComplexFloatVector(N - 1); // temporary storage vector ComplexFloat g; // reflection coefficient ComplexFloat inner; // inner product ComplexFloat k; int i, j, l; // 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 g = -(inner / e); for (j = 0, l = i - 2; j < i - 1; j++, l--) { Z[j] = a[j] + g * a[l]; } // copy vector for (j = 0; j < i - 1; j++) { a[j] = Z[j]; } a[i - 1] = g; e *= (ComplexFloat.One - g * g); if (e == ComplexFloat.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } // calculate second inner product inner = Y[i]; for (j = 0, l = i; j < i; j++, l--) { inner -= X[j] * T[l]; } // update solution vector k = inner / e; for (j = 0, l = i - 1; j < i; j++, l--) { X[j] = X[j] + k * a[l]; } X[j] = k; } } } return X; }
/// <summary> /// Solve the Yule-Walker equations for a symmetric square Toeplitz system /// </summary> /// <param name="R">The left-most column of the Toeplitz matrix.</param> /// <returns>The solution vector.</returns> /// <exception cref="ArgumentNullException"> /// <B>R</B> is a null reference. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// The length of <B>R</B> must be greater than one. /// </exception> /// <exception cref="SingularMatrixException"> /// The Toeplitz matrix or one of the the leading sub-matrices is singular. /// </exception> /// <remarks> /// This member is used to solve the Yule-Walker system <B>AX</B> = -<B>a</B>, /// where <B>A</B> is a symmetric square Toeplitz matrix, constructed /// from the elements <B>R[0]</B>, ..., <B>R[N-2]</B> and /// the vector <B>a</B> is constructed from the elements /// <B>R[1]</B>, ..., <B>R[N-1]</B>. /// <para> /// Durbin's algorithm is used to solve the linear system. It requires /// approximately the <b>N</b> squared FLOPS to calculate the /// solution (<b>N</b> is the matrix order). /// </para> /// </remarks> public static ComplexFloatVector YuleWalker(IROComplexFloatVector R) { ComplexFloatVector a; // check parameters if (R == null) { throw new System.ArgumentNullException("R"); } else if (R.Length < 2) { throw new System.ArgumentOutOfRangeException("R", "The length of R must be greater than 1."); } else { int N = R.Length - 1; a = new ComplexFloatVector(N); // prediction coefficients ComplexFloatVector Z = new ComplexFloatVector(N); // temporary storage vector ComplexFloat e; // predictor error ComplexFloat inner; // inner product ComplexFloat g; // reflection coefficient int i, j, l; // setup first order solution e = R[0]; if (e == ComplexFloat.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } g = -R[1] / R[0]; a[0] = g; // calculate solution for successive orders for (i = 1; i < N; i++) { e *= (ComplexFloat.One - g * g); if (e == ComplexFloat.Zero) { throw new SingularMatrixException("The Toeplitz matrix or one of the the leading sub-matrices is singular."); } // calculate inner product inner = R[i + 1]; for (j = 0, l = i; j < i; j++, l--) { inner += a[j] * R[l]; } // update prediction coefficients g = -(inner / e); for (j = 0, l = i - 1; j < i; j++, l--) { Z[j] = a[j] + g * a[l]; } // copy vector for (j = 0; j < i; j++) { a[j] = Z[j]; } a[i] = g; } } return(a); }