private double snrm(int n, VecDoub sx, int itol) { /***************************** * Compute one of two norms for a vector sx[1..n] as signaled by itol. Used by linbcg. ****************************/ int isamax; int i; double ans; if (itol <= 3) { ans = 0.0; for (i = 0; i < n; i++) { ans += sx[i] * sx[i]; //Vector magnitude norm. } return(Math.Sqrt(ans)); } else { isamax = 1; for (i = 0; i < n; i++) { //Largest component norm if (Math.Abs(sx[i]) > Math.Abs(sx[isamax])) { isamax = i; } } return(Math.Abs(sx[isamax])); } }
/// <summary> /// Solve Ax = b for a vector x using the psudoinverse of A as obtained by SVD. /// If positive, thresh is the threshold value below which singular values /// as considered to be zero. If thresh is negative, a default based on roundoff error is used. /// </summary> /// <param name="b"></param> /// <param name="x"></param> /// <param name="thresh"></param> //void solve(VecDoub_I &b, VecDoub_O &x, double thresh); public void solve(VecDoub b, VecDoub x, double thresh) { int i, j, jj; double s; if (b.size() != m || x.size() != n) { throw new Exception("SVD::solve bad sizes"); } VecDoub tmp = new VecDoub(n); tsh = (thresh >= 0.0 ? thresh : 0.5 * Math.Sqrt(m + n + 1.0) * w[0] * eps); for (j = 0; j < n; j++) { s = 0.0; if (w[j] > tsh) { for (i = 0; i < m; i++) { s += u[i][j] * b[i]; } s /= w[j]; } tmp[j] = s; } for (j = 0; j < n; j++) { s = 0.0; for (jj = 0; jj < n; jj++) { s += v[j][jj] * tmp[jj]; } x[j] = s; } }
private void asolve(int n, VecDoub b, VecDoub x, int itrnsp) { int i; for (i = 0; i < n; i++) { x[i] = (sa[i] != 0.0 ? b[i] / sa[i] : b[i]); //The matrix A is the diagonal part of A, } //stored in the first n elements of sa. Since the transpose matrix has the same diagonal, the flag itrnsp is not used. }
private void atimes(int n, VecDoub x, VecDoub r, int itrnsp) { if (itrnsp > 0) { sprstx(sa, ija, x, r, n); } else { sprsax(sa, ija, x, r, n); } }
/// <summary> /// Constructor. The single argument is A. The SVD computation is done by /// decompose(), and the results are sorted by reorder(). /// </summary> /// <param name="a">The matrix to decompose.</param> public SVD(MatDoub a) { m = (a.nrows()); n = (a.ncols()); u = new MatDoub(a); v = new MatDoub(n, n); w = new VecDoub(n); eps = double.Epsilon; decompose(); reorder(); tsh = 0.5 * Math.Sqrt(m + n + 1.0) * w[0] * eps; // Default threshold for nonzero singular values; }
//For theory see 31st Jan notes public Vander(VecDoub x, double[] w, double[] q) { // Solves the Vandermonde linear system PN1 // iD0 xk i wi D qk .k D 0; : : : ; N 1/. Input consists // of the vectors x[0..n-1] and q[0..n-1]; the vector w[0..n-1] is output. int i, j, k, n = q.Length; double b, s, t, xx; VecDoub c = new VecDoub(n); if (n == 1) { w[0] = q[0]; } else { for (i = 0; i < n; i++) { c[i] = 0.0; // Initialize array. } c[n - 1] = -x[0]; // Coefficients of the master polynomial are found. for (i = 1; i < n; i++) { // by recursion. xx = -x[i]; for (j = (n - 1 - i); j < (n - 1); j++) { c[j] += xx * c[j + 1]; } c[n - 1] += xx; } for (i = 0; i < n; i++) { // Each subfactor in turn xx = x[i]; t = b = 1.0; s = q[n - 1]; for (k = n - 1; k > 0; k--) { // Is synthetically divided. b = c[k] + xx * b; //This is just the synthetic division formula. s += q[k - 1] * b; // Matrix-multiplied by the right-hand side. t = xx * t + b; } w[i] = s / t; // and supplied with a denominator. } } }
private void sprsax(VecDoub sa, VecLong ija, VecDoub x, VecDoub b, int n) { if (ija[1] != n + 2) { new Exception("sprsax: mismatched vector and matrix"); } int i; long k; for (i = 0; i < n; i++) { b[i] = sa[i] * x[i]; //Diagonal entries for (k = ija[i]; k <= ija[i + 1] - 1; k++) //TODO: Verify this. { b[i] += sa[(int)k] * x[(int)ija[(int)k]]; //Off diagonal entries. Multiply the entry of the matrix by the x of the corresponding column. } //TODO: Find out how to reference arrays in C# with some thing that could be > 2 billion (max value of integer). } }
private void sprstx(VecDoub sa, VecLong ija, VecDoub x, VecDoub b, int n) { int i, j; long k; if (ija[1] != n + 2) { new Exception("mismatched vector and matrix in sprstx"); } for (i = 0; i < n; i++) { b[i] = sa[i] * x[i]; //First come the diagonal terms } for (i = 0; i < n; i++) {//Now loop over the off diagonal terms. for (k = ija[i]; k <= ija[i + 1] - 1; k++) { j = (int)ija[(int)k]; b[j] += sa[(int)k] * x[i]; //Because this is multiplication by the transpose, the indices of b and x interchange. } } }
public Sprsin(MatDoub a)//TODO: make a VecULong type to further save on space. { /************************************ * Converts a square matrix a[1..n][1..n] into row-indexed sparse storage mode. * Only elements of a with magnitude ≥thresh are retained. Output is in two linear arrays * with dimension nmax (an input parameter): sa[1..] contains array values, indexed by ija[1..]. * The number of elements filled of sa and ija on output are both ija[ija[1]-1]-1 ************************************/ sa = new VecDoub(new double[nmax]); ija = new VecLong(18, new long[nmax], 0); n = a.nrows(); int i, j, k; for (j = 0; j < n; j++) { sa[j] = a[j][j]; //Store the diagonal elements. } ija[0] = n + 1; //Index to the first off diagonal element if any. k = n; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (Math.Abs(a[i][j]) >= thresh && i != j) { if (++k > (int)nmax) { throw new Exception("sprsin: nmax too small"); } sa[k] = a[i][j]; //Store off diagonal elements. ija[k] = j; //And their column indices. } } ija[i + 1] = k + 1; //As each row is completed, store index to next } this.numelements = k + 1; }
/// <summary> /// Solve m sets of n equations AX=B using the pseudoinverse of A. /// The right-hand sides are input as b[0..n-1][0..m-1], while /// x[0..n-1][0..m-1] return the solutions. /// If positive, thresh is the threshold value below which singular values /// as considered to be zero. If thresh is negative, a default based on rounodd error is used. /// </summary> /// <param name="b"></param> /// <param name="x"></param> /// <param name="thresh"></param> //void solve(MatDoub_I &b, MatDoub_O &x, double thresh); public void solve(MatDoub b, MatDoub x, double thresh) { int i, j, m = b.ncols(); if (b.nrows() != n || x.nrows() != n || b.ncols() != x.ncols()) { throw new Exception("SVD::solve bad sizes"); } VecDoub xx = new VecDoub(n); for (j = 0; j < m; j++) { for (i = 0; i < n; i++) { xx[i] = b[i][j]; } solve(xx, xx, thresh); for (i = 0; i < n; i++) { x[i][j] = xx[i]; } } }
private bool sing; // Indicates whether A is singular. public QRdcmp(MatDoub a) { n = a.nrows(); MatDoub qt = new MatDoub(n, n); MatDoub r = new MatDoub(a); sing = (false); int i, j, k; VecDoub c = new VecDoub(n); VecDoub d = new VecDoub(n); double scale, sigma, sum, tau; for (k = 0; k < n - 1; k++) { scale = 0.0; for (i = k; i < n; i++) { scale = Math.Max(scale, Math.Abs(r[i][k])); } if (scale == 0.0) { // Singular case. sing = true; c[k] = d[k] = 0.0; } else { // Form Qk and Qk A. for (i = k; i < n; i++) { r[i][k] /= scale; } for (sum = 0.0, i = k; i < n; i++) { sum += r[i][k] * r[i][k]; } sigma = NR.SIGN(Math.Sqrt(sum), r[k][k]); r[k][k] += sigma; c[k] = sigma * r[k][k]; d[k] = -scale * sigma; for (j = k + 1; j < n; j++) { for (sum = 0.0, i = k; i < n; i++) { sum += r[i][k] * r[i][j]; } tau = sum / c[k]; for (i = k; i < n; i++) { r[i][j] -= tau * r[i][k]; } } } } d[n - 1] = r[n - 1][n - 1]; if (d[n - 1] == 0.0) { sing = true; } /////////////////////////// for (i = 0; i < n; i++) { // Form QT explicitly. for (j = 0; j < n; j++) { qt[i][j] = 0.0; } qt[i][i] = 1.0; } for (k = 0; k < n - 1; k++) { if (c[k] != 0.0) { for (j = 0; j < n; j++) { sum = 0.0; for (i = k; i < n; i++) { sum += r[i][k] * qt[i][j]; } sum /= c[k]; for (i = k; i < n; i++) { qt[i][j] -= sum * r[i][k]; } } } } for (i = 0; i < n; i++) { // Form R explicitly. r[i][i] = d[i]; for (j = 0; j < i; j++) { r[i][j] = 0.0; } } }
/// <summary> /// Solve with (apply the pseudoinverse to) one or more right-hand sides. /// </summary> /// <param name="b">The RHS to solve.</param> /// <param name="x">The result.</param> public void solve(VecDoub b, VecDoub x) { solve(b, x, -1.0); }
//void reorder(); private void reorder() { int i, j, k, s, inc = 1; double sw; VecDoub su = new VecDoub(m), sv = new VecDoub(n); do { inc *= 3; inc++; } while (inc <= n); do { inc /= 3; for (i = inc; i < n; i++) { sw = w[i]; for (k = 0; k < m; k++) { su[k] = u[k][i]; } for (k = 0; k < n; k++) { sv[k] = v[k][i]; } j = i; while (w[j - inc] < sw) { w[j] = w[j - inc]; for (k = 0; k < m; k++) { u[k][j] = u[k][j - inc]; } for (k = 0; k < n; k++) { v[k][j] = v[k][j - inc]; } j -= inc; if (j < inc) { break; } } w[j] = sw; for (k = 0; k < m; k++) { u[k][j] = su[k]; } for (k = 0; k < n; k++) { v[k][j] = sv[k]; } } } while (inc > 1); for (k = 0; k < n; k++) { s = 0; for (i = 0; i < m; i++) { if (u[i][k] < 0.0) { s++; } } for (j = 0; j < n; j++) { if (v[j][k] < 0.0) { s++; } } if (s > (m + n) / 2) { for (i = 0; i < m; i++) { u[i][k] = -u[i][k]; } for (j = 0; j < n; j++) { v[j][k] = -v[j][k]; } } } }
/*************************************** * View these equations in a latex editor. They are referenced in the comments. These are the bi-conjugate gradient with pre-conditioning matrix equations. \[\alpha_k = \frac{\vec rr_k^T \vec z_k}{\vec pp_k^T.A. \vec p_k} \tag{1}\] \[\vec r_{k+1} = \vec r_k - \alpha_k . A . \vec p_k \tag{2}\] \[\vec rr_k = \vec rr_k - \alpha_kA^T \vec pp_k \tag{3}\] \[\vec z_k = \widetilde{A}^{-1}. \vec r_k \tag{4}\] \[\vec zz_k = \widetilde{A}^{-T} \vec rr_k \tag{5}\] \[\beta_k = \frac{\vec rr_k^T.\vec z_{k+1}}{\vec rr_k ^T \vec z_k} \tag{6}\] \[\vec p_{k+1} = \vec z_{k+a} + \beta_k \vec p_k \tag{7}\] \[\vec pp_{k+1} = \vec zz_{k+1} + \beta_k. \vec pp_k \tag{8}\] \[\vec x_{k+a} = \vec x_k + \alpha_k. \vec p_k \tag{9}\] ***************************************/ public void linbcg(VecDoub b, VecDoub x, int itol, double tol, int itmax, ref int iter, ref double err) { VecDoub p = new VecDoub(n); VecDoub pp = new VecDoub(n); VecDoub r = new VecDoub(n); VecDoub rr = new VecDoub(n); VecDoub z = new VecDoub(n); VecDoub zz = new VecDoub(n); iter = 0; atimes(n, x, r, 0); double ak, akden, bk, bkden = 0, bknum = 0, bnrm, dxnrm, xnrm, zm1nrm, znrm = 0; int j; for (j = 0; j < n; j++) { //Initialize r and rr. The vectors corresponding to A and A^T. r[j] = b[j] - r[j]; rr[j] = r[j]; } /*atimes(n, r, rr, 0); */ //Uncomment this line to get maximum residual variant of the algorithm. if (itol == 1) { bnrm = snrm(n, b, itol); //Equation (4) asolve(n, r, z, 0); //Input is r[1..n], output is z[1..n]; the final 0 indicates that A and not its transpose is used. } else if (itol == 2) { asolve(n, b, z, 0); bnrm = snrm(n, z, itol); asolve(n, r, z, 0); } else if (itol == 3 || itol == 4) { asolve(n, b, z, 0); bnrm = snrm(n, z, itol); asolve(n, r, z, 0); znrm = snrm(n, z, itol); } else { throw new Exception("illegal itol in linbcg"); } while (iter <= itmax) //Main loop. { ++iter; //Equation (5) asolve(n, rr, zz, 1); //Final 1 indicates use of transpose matrix AT for (bknum = 0.0, j = 0; j < n; j++) { bknum += z[j] * rr[j]; //Numerator of equation (6) } if (iter == 1) { for (j = 0; j < n; j++) { p[j] = z[j]; pp[j] = zz[j]; } } else { bk = bknum / bkden; //beta for (j = 0; j < n; j++) { p[j] = bk * p[j] + z[j]; //Equation (7) pp[j] = bk * pp[j] + zz[j]; //Equation (8) } } bkden = bknum; //Denominator of equation (6) atimes(n, p, z, 0); //Since z has been used, we change its definition to save space. for (akden = 0.0, j = 0; j < n; j++) //Denominator of equation (1) { akden += z[j] * pp[j]; } ak = bknum / akden; //Equation (1) atimes(n, pp, zz, 1); //Since zz has been used, we can changte the definition to save space. for (j = 0; j < n; j++) { x[j] += ak * p[j]; //Equation (9) r[j] -= ak * z[j]; //Equation (2) rr[j] -= ak * zz[j]; //Equation (3) } asolve(n, r, z, 0); //Equation (4) if (itol == 1) { err = snrm(n, r, itol) / bnrm; } else if (itol == 2) { err = snrm(n, z, itol) / bnrm; } else if (itol == 3 || itol == 4) { zm1nrm = znrm; znrm = snrm(n, z, itol); if (Math.Abs(zm1nrm - znrm) > EPS * znrm) { dxnrm = Math.Abs(ak) * snrm(n, p, itol); err = znrm / Math.Abs(zm1nrm - znrm) * dxnrm; } else { err = znrm / bnrm; //Error may not be accurate, so loop again. continue; } xnrm = snrm(n, x, itol); if (err <= 0.5 * xnrm) { err /= xnrm; } else { err = znrm / bnrm; //Error may not be accurate, so loop again. continue; } } System.Console.WriteLine("iteration : " + iter + " ;error : " + err); if (err <= tol) { break; } } }
//void decompose(); private void decompose() { bool flag; int i, its, j, jj, k, nm = int.MinValue; int l = int.MinValue; double anorm, c, f, g, h, s, scale, x, y, z; VecDoub rv1 = new VecDoub(n); g = scale = anorm = 0.0; for (i = 0; i < n; i++) { l = i + 2; rv1[i] = scale * g; g = s = scale = 0.0; if (i < m) { for (k = i; k < m; k++) { scale += Math.Abs(u[k][i]); } if (scale != 0.0) { for (k = i; k < m; k++) { u[k][i] /= scale; s += u[k][i] * u[k][i]; } f = u[i][i]; g = -NR.SIGN(Math.Sqrt(s), f); h = f * g - s; u[i][i] = f - g; for (j = l - 1; j < n; j++) { for (s = 0.0, k = i; k < m; k++) { s += u[k][i] * u[k][j]; } f = s / h; for (k = i; k < m; k++) { u[k][j] += f * u[k][i]; } } for (k = i; k < m; k++) { u[k][i] *= scale; } } } w[i] = scale * g; g = s = scale = 0.0; if (i + 1 <= m && i + 1 != n) { for (k = l - 1; k < n; k++) { scale += Math.Abs(u[i][k]); } if (scale != 0.0) { for (k = l - 1; k < n; k++) { u[i][k] /= scale; s += u[i][k] * u[i][k]; } f = u[i][l - 1]; g = -NR.SIGN(Math.Sqrt(s), f); h = f * g - s; u[i][l - 1] = f - g; for (k = l - 1; k < n; k++) { rv1[k] = u[i][k] / h; } for (j = l - 1; j < m; j++) { for (s = 0.0, k = l - 1; k < n; k++) { s += u[j][k] * u[i][k]; } for (k = l - 1; k < n; k++) { u[j][k] += s * rv1[k]; } } for (k = l - 1; k < n; k++) { u[i][k] *= scale; } } } anorm = Math.Max(anorm, (Math.Abs(w[i]) + Math.Abs(rv1[i]))); } for (i = n - 1; i >= 0; i--) { if (i < n - 1) { if (g != 0.0) { for (j = l; j < n; j++) { v[j][i] = (u[i][j] / u[i][l]) / g; } for (j = l; j < n; j++) { for (s = 0.0, k = l; k < n; k++) { s += u[i][k] * v[k][j]; } for (k = l; k < n; k++) { v[k][j] += s * v[k][i]; } } } for (j = l; j < n; j++) { v[i][j] = v[j][i] = 0.0; } } v[i][i] = 1.0; g = rv1[i]; l = i; } for (i = Math.Min(m, n) - 1; i >= 0; i--) { l = i + 1; g = w[i]; for (j = l; j < n; j++) { u[i][j] = 0.0; } if (g != 0.0) { g = 1.0 / g; for (j = l; j < n; j++) { for (s = 0.0, k = l; k < m; k++) { s += u[k][i] * u[k][j]; } f = (s / u[i][i]) * g; for (k = i; k < m; k++) { u[k][j] += f * u[k][i]; } } for (j = i; j < m; j++) { u[j][i] *= g; } } else { for (j = i; j < m; j++) { u[j][i] = 0.0; } } ++u[i][i]; } for (k = n - 1; k >= 0; k--) { for (its = 0; its < 30; its++) { flag = true; for (l = k; l >= 0; l--) { nm = l - 1; if (l == 0 || Math.Abs(rv1[l]) <= eps * anorm) { flag = false; break; } if (Math.Abs(w[nm]) <= eps * anorm) { break; } } if (flag) { c = 0.0; s = 1.0; for (i = l; i < k + 1; i++) { f = s * rv1[i]; rv1[i] = c * rv1[i]; if (Math.Abs(f) <= eps * anorm) { break; } g = w[i]; h = pythag(f, g); w[i] = h; h = 1.0 / h; c = g * h; s = -f * h; for (j = 0; j < m; j++) { y = u[j][nm]; z = u[j][i]; u[j][nm] = y * c + z * s; u[j][i] = z * c - y * s; } } } z = w[k]; if (l == k) { if (z < 0.0) { w[k] = -z; for (j = 0; j < n; j++) { v[j][k] = -v[j][k]; } } break; } if (its == 29) { throw new Exception("no convergence in 30 svdcmp iterations"); } x = w[l]; nm = k - 1; y = w[nm]; g = rv1[nm]; h = rv1[k]; f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y); g = pythag(f, 1.0); f = ((x - z) * (x + z) + h * ((y / (f + NR.SIGN(g, f))) - h)) / x; c = s = 1.0; for (j = l; j <= nm; j++) { i = j + 1; g = rv1[i]; y = w[i]; h = s * g; g = c * g; z = pythag(f, h); rv1[j] = z; c = f / z; s = h / z; f = x * c + g * s; g = g * c - x * s; h = y * s; y *= c; for (jj = 0; jj < n; jj++) { x = v[jj][j]; z = v[jj][i]; v[jj][j] = x * c + z * s; v[jj][i] = z * c - x * s; } z = pythag(f, h); w[j] = z; if (z != 0.0) { z = 1.0 / z; c = f * z; s = h * z; } f = c * g + s * y; x = c * y - s * g; for (jj = 0; jj < m; jj++) { y = u[jj][j]; z = u[jj][i]; u[jj][j] = y * c + z * s; u[jj][i] = z * c - y * s; } } rv1[l] = 0.0; rv1[k] = f; w[k] = x; } } }
public static void _Main(String[] args) { var array2D = new Double[, ] { { 3.0, 0.0, 1.0, 0.0, 0.0 }, { 0.0, 4.0, 0.0, 0.0, 0.0 }, { 0.0, 7.0, 5.0, 9.0, 0.0 }, { 0.0, 0.0, 0.0, 0.0, 2.0 }, { 0.0, 0.0, 0.0, 6.0, 5.0 } }; MatDoub a = new MatDoub(5, 5); MatUtils.fillMat(a, array2D); MatUtils.printmatrix(a); MatDoub b = new MatDoub(5, 5); MatUtils.fillMat(b, array2D); MatUtils.fillMat(a, array2D); GaussJordan.gaussj(a, b); MatUtils.printmatrix(a); LUdcmp lu = new LUdcmp(a); MatDoub aInv = new MatDoub(5, 5);//A container for the inverse of a. lu.inverse(aInv); MatUtils.printmatrix(aInv); MatUtils.fillMat(a, array2D); Sprsin sprs = new Sprsin(a); System.Console.Write("\n###################\n Sparse matrix \n###################\n"); for (int i = 0; i < sprs.numelements; i++) { System.Console.Write(sprs.sa[i] + (i + 1 < sprs.numelements ? "," : "\n")); } for (int i = 0; i < sprs.numelements; i++) { System.Console.Write(sprs.ija[i] + (i + 1 < sprs.numelements ? "," : "\n")); } ////////////////////////// /// Now lets solve the system of linear equations. ///////////////////////// VecDoub b1 = new VecDoub(new double[] { 1, 1, 1, 1, 1 }); VecDoub x1 = new VecDoub(new double[] { 0.14, 0.3, 0.5, -0.25, 0.7 }); int iter = 0; double err = 0; System.Console.Write("\n###################\n Solution of sparse system \n###################\n"); sprs.linbcg(b1, x1, 1, 1e-4d, 30, ref iter, ref err); for (int i = 0; i < 5; i++) { System.Console.Write(x1[i] + (i + 1 < 5 ? "," : "\n")); } ////////////////////////// /// Vandermonde matrices. ///////////////////////// System.Console.Write("\n###################\n Vandermonde matrices \n###################\n"); VecDoub x_v = new VecDoub(new double[] { 2, 3, 5 }); double[] w = new double[] { 1, 1, 1 }; double[] q = new double[] { 1, 1, 1 }; Vander va = new Vander(x_v, w, q); for (int i = 0; i < w.Length; i++) { System.Console.Write(w[i] + (i + 1 < w.Length?",":"\n")); } ////////////////////////// /// Toeplitz matrices. ///////////////////////// System.Console.Write("\n###################\n Toeplitz matrices \n###################\n"); VecDoub x_t = new VecDoub(new double[] { 1.3, 2, 3.7, 4, 5.2 }); Toeplitz to = new Toeplitz(x_t, w, q); for (int i = 0; i < w.Length; i++) { System.Console.Write(w[i] + (i + 1 < w.Length ? "," : "\n")); } System.Console.WriteLine("End"); System.Console.Read(); }
//Toeplitz matrices tend to occur in deconvolution and signal processing. public Toeplitz(VecDoub r, double[] x, double[] y) { // Solves the Toeplitz system // PN1 // jD0 R.N1Cij/xj D yi .i D 0; : : : ; N 1/. The Toeplitz // matrix need not be symmetric. y[0..n-1] and r[0..2*n-2] are input // arrays; x[0..n-1] is the output array. int j, k, m, m1, m2, n1, n = y.Length; double pp, pt1, pt2, qq, qt1, qt2, sd, sgd, sgn, shn, sxn; n1 = n - 1; if (r[n1] == 0.0) { throw new Exception("toeplz-1 singular principal minor"); } ////<Initialize x, g and h> x[0] = y[0] / r[n1]; if (n1 == 0) { return; } VecDoub g = new VecDoub(n1), h = new VecDoub(n1); g[0] = r[n1 - 1] / r[n1]; h[0] = r[n1 + 1] / r[n1]; ////</Initialize x, g and h> ////<Main loop of the recursion> for (m = 0; m < n; m++) { m1 = m + 1; ////<Compute numerator and denominator for x_{m+1} 2.8.19> sxn = -y[m1]; sd = -r[n1]; for (j = 0; j < m + 1; j++) { sxn += r[n1 + m1 - j] * x[j]; sd += r[n1 + m1 - j] * g[m - j]; } if (sd == 0.0) { throw new Exception("toeplz-2 singular principal minor"); } x[m1] = sxn / sd; ////</Compute numerator and denominator for x_{m+1} 2.8.19> ////<Compute x_{j} 2.8.15> for (j = 0; j < m + 1; j++) { // Eq. (2.8.16). x[j] -= x[m1] * g[m - j]; } ////</Compute x_{j} 2.8.15> if (m1 == n1) { return; } ////<Compute numerator and denominator for G and H, Equations 2.8.23 and 2.8.24> sgn = -r[n1 - m1 - 1]; shn = -r[n1 + m1 + 1]; sgd = -r[n1]; for (j = 0; j < m + 1; j++) { sgn += r[n1 + j - m1] * g[j]; shn += r[n1 + m1 - j] * h[j]; sgd += r[n1 + j - m1] * h[m - j]; } if (sgd == 0.0) { throw new Exception("toeplz-3 singular principal minor"); } g[m1] = sgn / sgd; // whence G and H. h[m1] = shn / sd; ////</Compute numerator and denominator for G and H, Equations 2.8.23 and 2.8.24> ////<Compute G_j and H_j for j = 1 to m Equation 2.8.25> k = m; m2 = (m + 2) >> 1; pp = g[m1]; qq = h[m1]; for (j = 0; j < m2; j++) {//We split the two equations in 2.8.25 into 4 equations by replacing j by M+1-j. Double the equations mean half the iterations. pt1 = g[j]; pt2 = g[k]; qt1 = h[j]; qt2 = h[k]; g[j] = pt1 - pp * qt2; g[k] = pt2 - pp * qt1; h[j] = qt1 - qq * pt2; h[k--] = qt2 - qq * pt1; } ////<Compute G_j and H_j for j = 1 to m Equation 2.8.25> } // Back for another recurrence. throw new Exception("toeplz - should not arrive here!"); }