EigenvalueDecomposition( double[] d, double[] e) { /* TODO: unit test missing for EigenvalueDecomposition constructor. */ _n = d.Length; _v = Matrix.CreateMatrixData(_n, _n); _d = new double[_n]; Array.Copy(d, 0, _d, 0, _n); _e = new double[_n]; Array.Copy(e, 0, _e, 1, _n - 1); for (int i = 0; i < _n; i++) { _v[i][i] = 1; } SymmetricDiagonalize(); _eigenValuesReal = new Vector(_d); _eigenValuesImag = new Vector(_e); _eigenValues = ComplexVector.Create(_d, _e); InitOnDemandComputations(); }
ComputeOrthogonalFactor() { double[][] Q = Matrix.CreateMatrixData(m, Math.Min(m, n)); for (int k = Math.Min(m, n) - 1; k >= 0; k--) { Q[k][k] = 1.0; for (int j = k; j < Math.Min(m, n); j++) { if (QR[k][k] == 0.0) { continue; } double s = 0.0; for (int i = k; i < m; i++) { s += QR[i][k] * Q[i][j]; } s = (-s) / QR[k][k]; for (int i = k; i < m; i++) { Q[i][j] += s * QR[i][k]; } } double columnSign = Math.Sign(Rdiag[k]); for (int i = 0; i < m; i++) { Q[i][k] *= columnSign; } } return(new Matrix(Q)); }
ComputeOrthogonalFactor() { double[][] q = Matrix.CreateMatrixData(M, Math.Min(M, N)); for (int k = Math.Min(M, N) - 1; k >= 0; k--) { q[k][k] = 1.0; for (int j = k; j < Math.Min(M, N); j++) { if (_qr[k][k] == 0.0) { continue; } double s = 0.0; for (int i = k; i < M; i++) { s += _qr[i][k] * q[i][j]; } s = (-s) / _qr[k][k]; for (int i = k; i < M; i++) { q[i][j] += s * _qr[i][k]; } } double columnSign = Math.Sign(_rDiag[k]); for (int i = 0; i < M; i++) { q[i][k] *= columnSign; } } return(new Matrix(q)); }
ComputeOrthogonalFactor() { double[][] Q = Matrix.CreateMatrixData(m, n); for (int k = n - 1; k >= 0; k--) { for (int i = 0; i < m; i++) { Q[i][k] = 0.0; } Q[k][k] = 1.0; for (int j = k; j < n; j++) { if (QR[k][k] != 0) { double s = 0.0; for (int i = k; i < m; i++) { s += QR[i][k] * Q[i][j]; } s = (-s) / QR[k][k]; for (int i = k; i < m; i++) { Q[i][j] += s * QR[i][k]; } } } } return(new Matrix(Q)); }
ComputeUpperTriangularFactor() { double[][] R = Matrix.CreateMatrixData(Math.Min(n, m), n); for (int i = 0; i < Math.Min(n, m); i++) { double rowSign = Math.Sign(Rdiag[i]); double[] Ri = R[i]; for (int j = 0; j < Ri.Length; j++) { if (i < j) { Ri[j] = rowSign * QR[i][j]; } else if (i == j) { Ri[j] = rowSign * Rdiag[i]; } else { Ri[j] = 0.0; } } } return(new Matrix(R)); }
ComputeUpperTriangularFactor() { double[][] r = Matrix.CreateMatrixData(Math.Min(N, M), N); for (int i = 0; i < Math.Min(N, M); i++) { double rowSign = Math.Sign(_rDiag[i]); double[] ri = r[i]; for (int j = 0; j < ri.Length; j++) { if (i < j) { ri[j] = rowSign * _qr[i][j]; } else if (i == j) { ri[j] = rowSign * _rDiag[i]; } else { ri[j] = 0.0; } } } return(new Matrix(r)); }
EigenvalueDecomposition( double[] d, double[] e ) { // TODO: unit test missing for EigenvalueDecomposition constructor. n = d.Length; V = Matrix.CreateMatrixData(n, n); this.d = new double[n]; Array.Copy(d, 0, this.d, 0, n); this.e = new double[n]; Array.Copy(e, 0, this.e, 1, n - 1); for (int i = 0; i < n; i++) { V[i][i] = 1; } SymmetricDiagonalize(); InitOnDemandComputations(); }
EigenvalueDecomposition( Matrix Arg ) { double[][] A = Arg; n = Arg.ColumnCount; V = Matrix.CreateMatrixData(n, n); d = new double[n]; e = new double[n]; isSymmetric = true; for (int j = 0; (j < n) & isSymmetric; j++) { for (int i = 0; (i < n) & isSymmetric; i++) { isSymmetric &= (A[i][j] == A[j][i]); } } if (isSymmetric) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { V[i][j] = A[i][j]; } } SymmetricTridiagonalize(); SymmetricDiagonalize(); } else { H = new double[n][]; for (int i = 0; i < n; i++) { double[] Hi = new double[n]; double[] Ai = A[i]; for (int j = 0; j < n; j++) { Hi[j] = Ai[j]; } H[i] = Hi; } NonsymmetricReduceToHessenberg(); NonsymmetricReduceHessenberToRealSchur(); } _eigenValuesReal = new Vector(d); _eigenValuesImag = new Vector(e); _eigenValues = ComplexVector.Create(d, e); InitOnDemandComputations(); }
EigenvalueDecomposition(Matrix arg) { double[][] a = arg; _n = arg.ColumnCount; _v = Matrix.CreateMatrixData(_n, _n); _d = new double[_n]; _e = new double[_n]; _isSymmetric = true; for (int j = 0; (j < _n) & _isSymmetric; j++) { for (int i = 0; (i < _n) & _isSymmetric; i++) { _isSymmetric &= (a[i][j] == a[j][i]); } } if (_isSymmetric) { for (int i = 0; i < _n; i++) { for (int j = 0; j < _n; j++) { _v[i][j] = a[i][j]; } } SymmetricTridiagonalize(); SymmetricDiagonalize(); } else { _h = new double[_n][]; for (int i = 0; i < _n; i++) { double[] hi = new double[_n]; double[] ai = a[i]; for (int j = 0; j < _n; j++) { hi[j] = ai[j]; } _h[i] = hi; } NonsymmetricReduceToHessenberg(); NonsymmetricReduceHessenberToRealSchur(); } _eigenValuesReal = new Vector(_d); _eigenValuesImag = new Vector(_e); _eigenValues = ComplexVector.Create(_d, _e); InitOnDemandComputations(); }
ToColumnMatrix() { double[][] m = Matrix.CreateMatrixData(_length, 1); for (int i = 0; i < m.Length; i++) { m[i][0] = _data[i]; } return(new Matrix(m)); }
ToRowMatrix() { double[][] m = Matrix.CreateMatrixData(1, _length); for (int i = 0; i < m.Length; i++) { m[0][i] = _data[i]; } return(new Matrix(m)); }
ComputePermutationMatrix() { int[] pivot = Pivot; double[][] perm = Matrix.CreateMatrixData(pivot.Length, pivot.Length); for (int i = 0; i < pivot.Length; i++) { perm[pivot[i]][i] = 1.0; } return(new Matrix(perm)); }
Solve( Matrix B ) { if (B.RowCount != _l.RowCount) { throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "B"); } if (!_isSymmetricPositiveDefinite) { throw new InvalidOperationException(Resources.ArgumentMatrixSymmetricPositiveDefinite); } int nx = B.ColumnCount; double[][] L = _l; double[][] BB = B; double[][] X = Matrix.CreateMatrixData(L.Length, nx); // Solve L*Y = B for (int i = 0; i < X.Length; i++) { for (int j = 0; j < nx; j++) { double sum = BB[i][j]; for (int k = i - 1; k >= 0; k--) { sum -= L[i][k] * X[k][j]; } X[i][j] = sum / L[i][i]; } } // Solve L'*x = y for (int i = X.Length - 1; i >= 0; i--) { for (int j = 0; j < nx; j++) { double sum = X[i][j]; for (int k = i + 1; k < X.Length; k++) { sum -= L[k][i] * X[k][j]; } X[i][j] = sum / L[i][i]; } } return(new Matrix(X)); }
EigenvalueDecomposition( Matrix Arg ) { double[][] A = Arg; n = Arg.ColumnCount; V = Matrix.CreateMatrixData(n, n); d = new double[n]; e = new double[n]; isSymmetric = true; for (int j = 0; (j < n) & isSymmetric; j++) { for (int i = 0; (i < n) & isSymmetric; i++) { isSymmetric = (A[i][j] == A[j][i]); } } if (isSymmetric) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { V[i][j] = A[i][j]; } } SymmetricTridiagonalize(); SymmetricDiagonalize(); } else { H = Matrix.CreateMatrixData(n, n); ort = new double[n]; for (int j = 0; j < n; j++) { for (int i = 0; i < n; i++) { H[i][j] = A[i][j]; } } NonsymmetricReduceToHessenberg(); NonsymmetricReduceHessenberToRealSchur(); } InitOnDemandComputations(); }
Solve(Matrix b) { if (b.RowCount != _l.RowCount) { throw new ArgumentException(Properties.LocalStrings.ArgumentMatrixSameRowDimension, "B"); } if (!_isSymmetricPositiveDefinite) { throw new InvalidOperationException(Properties.LocalStrings.ArgumentMatrixSymmetricPositiveDefinite); } int nx = b.ColumnCount; double[][] l = _l; double[][] bb = b; double[][] x = Matrix.CreateMatrixData(l.Length, nx); // Solve L*Y = B for (int i = 0; i < x.Length; i++) { for (int j = 0; j < nx; j++) { double sum = bb[i][j]; for (int k = i - 1; k >= 0; k--) { sum -= l[i][k] * x[k][j]; } x[i][j] = sum / l[i][i]; } } // Solve L'*x = y for (int i = x.Length - 1; i >= 0; i--) { for (int j = 0; j < nx; j++) { double sum = x[i][j]; for (int k = i + 1; k < x.Length; k++) { sum -= l[k][i] * x[k][j]; } x[i][j] = sum / l[i][i]; } } return(new Matrix(x)); }
ComputeUpperTriangularFactor() { double[][] u = Matrix.CreateMatrixData(_columnCount, _columnCount); for (int i = 0; i < _columnCount; i++) { for (int j = 0; j < _columnCount; j++) { u[i][j] = (i <= j) ? _lu[i][j] : 0.0; } } return(new Matrix(u)); }
ComputeHouseholderVectors() { double[][] h = Matrix.CreateMatrixData(M, N); for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { h[i][j] = (i >= j) ? _qr[i][j] : 0.0; } } return(new Matrix(h)); }
ComputeDiagonalSingularValues() { double[][] X = Matrix.CreateMatrixData(n, n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { X[i][j] = 0.0; } X[i][i] = this.s[i]; } return(new Matrix(X)); }
DyadicProduct( IVector u, IVector v ) { double[][] m = Matrix.CreateMatrixData(u.Length, v.Length); for (int i = 0; i < u.Length; i++) { for (int j = 0; j < v.Length; j++) { m[i][j] = u[i] * v[j]; } } return(new Matrix(m)); }
CholeskyDecomposition( Matrix m ) { if (m.RowCount != m.ColumnCount) { throw new InvalidOperationException(Resources.ArgumentMatrixSquare); } double[][] A = m; double[][] L = Matrix.CreateMatrixData(m.RowCount, m.RowCount); _isSymmetricPositiveDefinite = true; // ensure square for (int i = 0; i < L.Length; i++) { double diagonal = 0.0; for (int j = 0; j < i; j++) { double sum = A[i][j]; for (int k = 0; k < j; k++) { sum -= L[j][k] * L[i][k]; } L[i][j] = sum /= L[j][j]; diagonal += sum * sum; _isSymmetricPositiveDefinite &= (A[j][i] == A[i][j]); // ensure symmetry } diagonal = A[i][i] - diagonal; L[i][i] = Math.Sqrt(Math.Max(diagonal, 0.0)); _isSymmetricPositiveDefinite &= (diagonal > 0.0); // ensure positive definite // zero out resulting upper triangle. for (int j = i + 1; j < L.Length; j++) { L[i][j] = 0.0; } } _l = new Matrix(L); }
CholeskyDecomposition(Matrix m) { if (m.RowCount != m.ColumnCount) { throw new InvalidOperationException(Properties.LocalStrings.ArgumentMatrixSquare); } double[][] a = m; double[][] l = Matrix.CreateMatrixData(m.RowCount, m.RowCount); _isSymmetricPositiveDefinite = true; // ensure square for (int i = 0; i < l.Length; i++) { double diagonal = 0.0; for (int j = 0; j < i; j++) { double sum = a[i][j]; for (int k = 0; k < j; k++) { sum -= l[j][k] * l[i][k]; } l[i][j] = sum /= l[j][j]; diagonal += sum * sum; _isSymmetricPositiveDefinite &= (a[j][i] == a[i][j]); // ensure symmetry } diagonal = a[i][i] - diagonal; l[i][i] = Math.Sqrt(Math.Max(diagonal, 0.0)); _isSymmetricPositiveDefinite &= (diagonal > 0.0); // ensure positive definite // zero out resulting upper triangle. for (int j = i + 1; j < l.Length; j++) { l[i][j] = 0.0; } } _l = new Matrix(l); }
ComputeHouseholderVectors() { double[][] H = Matrix.CreateMatrixData(m, n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i >= j) { H[i][j] = QR[i][j]; } else { H[i][j] = 0.0; } } } return(new Matrix(H)); }
ComputeUpperTriangularFactor() { double[][] U = Matrix.CreateMatrixData(_columnCount, _columnCount); for (int i = 0; i < _columnCount; i++) { for (int j = 0; j < _columnCount; j++) { if (i <= j) { U[i][j] = LU[i][j]; } else { U[i][j] = 0.0; } } } return(new Matrix(U)); }
ComputeBlockDiagonalMatrix() { double[][] D = Matrix.CreateMatrixData(n, n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { D[i][j] = 0.0; } D[i][i] = d[i]; if (e[i] > 0) { D[i][i + 1] = e[i]; } else if (e[i] < 0) { D[i][i - 1] = e[i]; } } return(new Matrix(D)); }
ComputeUpperTriangularFactor() { double[][] R = Matrix.CreateMatrixData(n, n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i < j) { R[i][j] = QR[i][j]; } else if (i == j) { R[i][j] = Rdiag[i]; } else { R[i][j] = 0.0; } } } return(new Matrix(R)); }
ComputeLowerTriangularFactor() { double[][] L = Matrix.CreateMatrixData(_rowCount, _columnCount); for (int i = 0; i < L.Length; i++) { for (int j = 0; j < _columnCount; j++) { if (i > j) { L[i][j] = LU[i][j]; } else if (i == j) { L[i][j] = 1.0; } else { L[i][j] = 0.0; } } } return(new Matrix(L)); }
ComputeBlockDiagonalMatrix() { double[][] d = Matrix.CreateMatrixData(_n, _n); for (int i = 0; i < _n; i++) { for (int j = 0; j < _n; j++) { d[i][j] = 0.0; } d[i][i] = _d[i]; if (_e[i] > 0) { d[i][i + 1] = _e[i]; } else if (_e[i] < 0) { d[i][i - 1] = _e[i]; } } return(new Matrix(d)); }
SingularValueDecomposition(IMatrix <double> arg) { _transpose = (arg.RowCount < arg.ColumnCount); // Derived from LINPACK code. // Initialize. double[][] a; if (_transpose) { // copy of internal data, independent of Arg a = Matrix.Transpose(arg).GetArray(); _m = arg.ColumnCount; _n = arg.RowCount; } else { a = arg.CopyToJaggedArray(); _m = arg.RowCount; _n = arg.ColumnCount; } int nu = Math.Min(_m, _n); double[] s = new double[Math.Min(_m + 1, _n)]; double[][] u = Matrix.CreateMatrixData(_m, nu); double[][] v = Matrix.CreateMatrixData(_n, _n); double[] e = new double[_n]; double[] work = new double[_m]; /* * Reduce A to bidiagonal form, storing the diagonal elements * in s and the super-diagonal elements in e. */ int nct = Math.Min(_m - 1, _n); int nrt = Math.Max(0, Math.Min(_n - 2, _m)); for (int k = 0; k < Math.Max(nct, nrt); k++) { if (k < nct) { // Compute the transformation for the k-th column and // place the k-th diagonal in s[k]. // Compute 2-norm of k-th column without under/overflow. s[k] = 0; for (int i = k; i < _m; i++) { s[k] = Fn.Hypot(s[k], a[i][k]); } if (s[k] != 0.0) { if (a[k][k] < 0.0) { s[k] = -s[k]; } for (int i = k; i < _m; i++) { a[i][k] /= s[k]; } a[k][k] += 1.0; } s[k] = -s[k]; } for (int j = k + 1; j < _n; j++) { if ((k < nct) & (s[k] != 0.0)) { /* Apply the transformation */ double t = 0; for (int i = k; i < _m; i++) { t += a[i][k] * a[i][j]; } t = (-t) / a[k][k]; for (int i = k; i < _m; i++) { a[i][j] += t * a[i][k]; } } /* * Place the k-th row of A into e for the * subsequent calculation of the row transformation. */ e[j] = a[k][j]; } if (k < nct) { /* * Place the transformation in U for subsequent back * multiplication. */ for (int i = k; i < _m; i++) { u[i][k] = a[i][k]; } } if (k < nrt) { // Compute the k-th row transformation and place the // k-th super-diagonal in e[k]. // Compute 2-norm without under/overflow. e[k] = 0; for (int i = k + 1; i < _n; i++) { e[k] = Fn.Hypot(e[k], e[i]); } if (e[k] != 0.0) { if (e[k + 1] < 0.0) { e[k] = -e[k]; } for (int i = k + 1; i < _n; i++) { e[i] /= e[k]; } e[k + 1] += 1.0; } e[k] = -e[k]; if ((k + 1 < _m) & (e[k] != 0.0)) { /* Apply the transformation */ for (int i = k + 1; i < _m; i++) { work[i] = 0.0; } for (int j = k + 1; j < _n; j++) { for (int i = k + 1; i < _m; i++) { work[i] += e[j] * a[i][j]; } } for (int j = k + 1; j < _n; j++) { double t = (-e[j]) / e[k + 1]; for (int i = k + 1; i < _m; i++) { a[i][j] += t * work[i]; } } } /* * Place the transformation in V for subsequent * back multiplication. */ for (int i = k + 1; i < _n; i++) { v[i][k] = e[i]; } } } /* Set up the final bidiagonal matrix or order p. */ int p = Math.Min(_n, _m + 1); if (nct < _n) { s[nct] = a[nct][nct]; } if (_m < p) { s[p - 1] = 0.0; } if (nrt + 1 < p) { e[nrt] = a[nrt][p - 1]; } e[p - 1] = 0.0; /* If required, generate U */ for (int j = nct; j < nu; j++) { for (int i = 0; i < _m; i++) { u[i][j] = 0.0; } u[j][j] = 1.0; } for (int k = nct - 1; k >= 0; k--) { if (s[k] != 0.0) { for (int j = k + 1; j < nu; j++) { double t = 0; for (int i = k; i < _m; i++) { t += u[i][k] * u[i][j]; } t = (-t) / u[k][k]; for (int i = k; i < _m; i++) { u[i][j] += t * u[i][k]; } } for (int i = k; i < _m; i++) { u[i][k] = -u[i][k]; } u[k][k] = 1.0 + u[k][k]; for (int i = 0; i < k - 1; i++) { u[i][k] = 0.0; } } else { for (int i = 0; i < _m; i++) { u[i][k] = 0.0; } u[k][k] = 1.0; } } /* If required, generate V */ for (int k = _n - 1; k >= 0; k--) { if ((k < nrt) & (e[k] != 0.0)) { for (int j = k + 1; j < nu; j++) { double t = 0; for (int i = k + 1; i < _n; i++) { t += v[i][k] * v[i][j]; } t = (-t) / v[k + 1][k]; for (int i = k + 1; i < _n; i++) { v[i][j] += t * v[i][k]; } } } for (int i = 0; i < _n; i++) { v[i][k] = 0.0; } v[k][k] = 1.0; } /* Main iteration loop for the singular values */ int pp = p - 1; int iter = 0; double eps = Number.PositiveRelativeAccuracy; while (p > 0) { int k; IterationStep step; /* Here is where a test for too many iterations would go */ /* * This section of the program inspects for * negligible elements in the s and e arrays. On * completion the variables kase and k are set as follows. * * DeflateNeglible: if s[p] and e[k-1] are negligible and k<p * SplitAtNeglible: if s[k] is negligible and k<p * QR: if e[k-1] is negligible, k<p, and s[k], ..., s[p] are not negligible. * Convergence: if e[p-1] is negligible. */ for (k = p - 2; k >= 0; k--) { if (Math.Abs(e[k]) <= eps * (Math.Abs(s[k]) + Math.Abs(s[k + 1]))) { e[k] = 0.0; break; } } if (k == p - 2) { step = IterationStep.Convergence; } else { int ks; for (ks = p - 1; ks >= k; ks--) { if (ks == k) { break; } double t = (ks != p ? Math.Abs(e[ks]) : 0.0) + (ks != k + 1 ? Math.Abs(e[ks - 1]) : 0.0); if (Math.Abs(s[ks]) <= eps * t) { s[ks] = 0.0; break; } } if (ks == k) { step = IterationStep.QR; } else if (ks == p - 1) { step = IterationStep.DeflateNeglible; } else { step = IterationStep.SplitAtNeglible; k = ks; } } k++; /* Perform the task indicated by 'step'. */ switch (step) { // Deflate negligible s(p). case IterationStep.DeflateNeglible: { double f = e[p - 2]; e[p - 2] = 0.0; for (int j = p - 2; j >= k; j--) { double t = Fn.Hypot(s[j], f); double cs = s[j] / t; double sn = f / t; s[j] = t; if (j != k) { f = (-sn) * e[j - 1]; e[j - 1] = cs * e[j - 1]; } for (int i = 0; i < _n; i++) { t = (cs * v[i][j]) + (sn * v[i][p - 1]); v[i][p - 1] = ((-sn) * v[i][j]) + (cs * v[i][p - 1]); v[i][j] = t; } } } break; // Split at negligible s(k) case IterationStep.SplitAtNeglible: { double f = e[k - 1]; e[k - 1] = 0.0; for (int j = k; j < p; j++) { double t = Fn.Hypot(s[j], f); double cs = s[j] / t; double sn = f / t; s[j] = t; f = (-sn) * e[j]; e[j] = cs * e[j]; for (int i = 0; i < _m; i++) { t = (cs * u[i][j]) + (sn * u[i][k - 1]); u[i][k - 1] = ((-sn) * u[i][j]) + (cs * u[i][k - 1]); u[i][j] = t; } } } break; // Perform one qr step. case IterationStep.QR: { /* Calculate the shift */ double scale = Math.Max(Math.Max(Math.Max(Math.Max(Math.Abs(s[p - 1]), Math.Abs(s[p - 2])), Math.Abs(e[p - 2])), Math.Abs(s[k])), Math.Abs(e[k])); double sp = s[p - 1] / scale; double spm1 = s[p - 2] / scale; double epm1 = e[p - 2] / scale; double sk = s[k] / scale; double ek = e[k] / scale; double b = (((spm1 + sp) * (spm1 - sp)) + (epm1 * epm1)) / 2.0; double c = (sp * epm1) * (sp * epm1); double shift = 0.0; if ((b != 0.0) | (c != 0.0)) { shift = Math.Sqrt((b * b) + c); if (b < 0.0) { shift = -shift; } shift = c / (b + shift); } double f = ((sk + sp) * (sk - sp)) + shift; double g = sk * ek; /* Chase zeros */ for (int j = k; j < p - 1; j++) { double t = Fn.Hypot(f, g); double cs = f / t; double sn = g / t; if (j != k) { e[j - 1] = t; } f = (cs * s[j]) + (sn * e[j]); e[j] = (cs * e[j]) - (sn * s[j]); g = sn * s[j + 1]; s[j + 1] = cs * s[j + 1]; for (int i = 0; i < _n; i++) { t = (cs * v[i][j]) + (sn * v[i][j + 1]); v[i][j + 1] = ((-sn) * v[i][j]) + (cs * v[i][j + 1]); v[i][j] = t; } t = Fn.Hypot(f, g); cs = f / t; sn = g / t; s[j] = t; f = (cs * e[j]) + (sn * s[j + 1]); s[j + 1] = ((-sn) * e[j]) + (cs * s[j + 1]); g = sn * e[j + 1]; e[j + 1] = cs * e[j + 1]; if (j < _m - 1) { for (int i = 0; i < _m; i++) { t = (cs * u[i][j]) + (sn * u[i][j + 1]); u[i][j + 1] = ((-sn) * u[i][j]) + (cs * u[i][j + 1]); u[i][j] = t; } } } e[p - 2] = f; iter = iter + 1; } break; // Convergence. case IterationStep.Convergence: { /* Make the singular values positive */ if (s[k] <= 0.0) { s[k] = (s[k] < 0.0 ? -s[k] : 0.0); for (int i = 0; i <= pp; i++) { v[i][k] = -v[i][k]; } } /* Order the singular values */ while (k < pp) { if (s[k] >= s[k + 1]) { break; } double t = s[k]; s[k] = s[k + 1]; s[k + 1] = t; if (k < _n - 1) { for (int i = 0; i < _n; i++) { t = v[i][k + 1]; v[i][k + 1] = v[i][k]; v[i][k] = t; } } if (k < _m - 1) { for (int i = 0; i < _m; i++) { t = u[i][k + 1]; u[i][k + 1] = u[i][k]; u[i][k] = t; } } k++; } iter = 0; p--; } break; } } // (vermorel) transposing the results if needed if (_transpose) { // swaping U and V double[][] temp = v; v = u; u = temp; } _u = new Matrix(u); _v = new Matrix(v); _singular = new Vector(s); InitOnDemandComputations(); }
SingularValueDecomposition( Matrix Arg ) { transpose = (Arg.RowCount < Arg.ColumnCount); // Derived from LINPACK code. // Initialize. double[][] A; if (transpose) { // copy of internal data, independent of Arg A = Matrix.Transpose(Arg).GetArray(); m = Arg.ColumnCount; n = Arg.RowCount; } else { A = Arg.CopyToJaggedArray(); m = Arg.RowCount; n = Arg.ColumnCount; } int nu = Math.Min(m, n); double[] s = new double[Math.Min(m + 1, n)]; double[][] U = Matrix.CreateMatrixData(m, nu); double[][] V = Matrix.CreateMatrixData(n, n); double[] e = new double[n]; double[] work = new double[m]; bool wantu = true; bool wantv = true; // Reduce A to bidiagonal form, storing the diagonal elements // in s and the super-diagonal elements in e. int nct = Math.Min(m - 1, n); int nrt = Math.Max(0, Math.Min(n - 2, m)); for (int k = 0; k < Math.Max(nct, nrt); k++) { if (k < nct) { // Compute the transformation for the k-th column and // place the k-th diagonal in s[k]. // Compute 2-norm of k-th column without under/overflow. s[k] = 0; for (int i = k; i < m; i++) { s[k] = Fn.Hypot(s[k], A[i][k]); } if (s[k] != 0.0) { if (A[k][k] < 0.0) { s[k] = -s[k]; } for (int i = k; i < m; i++) { A[i][k] /= s[k]; } A[k][k] += 1.0; } s[k] = -s[k]; } for (int j = k + 1; j < n; j++) { if ((k < nct) & (s[k] != 0.0)) { // Apply the transformation. double t = 0; for (int i = k; i < m; i++) { t += A[i][k] * A[i][j]; } t = (-t) / A[k][k]; for (int i = k; i < m; i++) { A[i][j] += t * A[i][k]; } } // Place the k-th row of A into e for the // subsequent calculation of the row transformation. e[j] = A[k][j]; } if (wantu & (k < nct)) { // Place the transformation in U for subsequent back // multiplication. for (int i = k; i < m; i++) { U[i][k] = A[i][k]; } } if (k < nrt) { // Compute the k-th row transformation and place the // k-th super-diagonal in e[k]. // Compute 2-norm without under/overflow. e[k] = 0; for (int i = k + 1; i < n; i++) { e[k] = Fn.Hypot(e[k], e[i]); } if (e[k] != 0.0) { if (e[k + 1] < 0.0) { e[k] = -e[k]; } for (int i = k + 1; i < n; i++) { e[i] /= e[k]; } e[k + 1] += 1.0; } e[k] = -e[k]; if ((k + 1 < m) & (e[k] != 0.0)) { // Apply the transformation. for (int i = k + 1; i < m; i++) { work[i] = 0.0; } for (int j = k + 1; j < n; j++) { for (int i = k + 1; i < m; i++) { work[i] += e[j] * A[i][j]; } } for (int j = k + 1; j < n; j++) { double t = (-e[j]) / e[k + 1]; for (int i = k + 1; i < m; i++) { A[i][j] += t * work[i]; } } } if (wantv) { // Place the transformation in V for subsequent // back multiplication. for (int i = k + 1; i < n; i++) { V[i][k] = e[i]; } } } } // Set up the final bidiagonal matrix or order p. int p = Math.Min(n, m + 1); if (nct < n) { s[nct] = A[nct][nct]; } if (m < p) { s[p - 1] = 0.0; } if (nrt + 1 < p) { e[nrt] = A[nrt][p - 1]; } e[p - 1] = 0.0; // If required, generate U. if (wantu) { for (int j = nct; j < nu; j++) { for (int i = 0; i < m; i++) { U[i][j] = 0.0; } U[j][j] = 1.0; } for (int k = nct - 1; k >= 0; k--) { if (s[k] != 0.0) { for (int j = k + 1; j < nu; j++) { double t = 0; for (int i = k; i < m; i++) { t += U[i][k] * U[i][j]; } t = (-t) / U[k][k]; for (int i = k; i < m; i++) { U[i][j] += t * U[i][k]; } } for (int i = k; i < m; i++) { U[i][k] = -U[i][k]; } U[k][k] = 1.0 + U[k][k]; for (int i = 0; i < k - 1; i++) { U[i][k] = 0.0; } } else { for (int i = 0; i < m; i++) { U[i][k] = 0.0; } U[k][k] = 1.0; } } } // If required, generate V. if (wantv) { for (int k = n - 1; k >= 0; k--) { if ((k < nrt) & (e[k] != 0.0)) { for (int j = k + 1; j < nu; j++) { double t = 0; for (int i = k + 1; i < n; i++) { t += V[i][k] * V[i][j]; } t = (-t) / V[k + 1][k]; for (int i = k + 1; i < n; i++) { V[i][j] += t * V[i][k]; } } } for (int i = 0; i < n; i++) { V[i][k] = 0.0; } V[k][k] = 1.0; } } // Main iteration loop for the singular values. int pp = p - 1; int iter = 0; double eps = Number.PositiveRelativeAccuracy; while (p > 0) { int k, kase; // Here is where a test for too many iterations would go. // This section of the program inspects for // negligible elements in the s and e arrays. On // completion the variables kase and k are set as follows. // kase = 1 if s(p) and e[k-1] are negligible and k<p // kase = 2 if s(k) is negligible and k<p // kase = 3 if e[k-1] is negligible, k<p, and // s(k), ..., s(p) are not negligible (qr step). // kase = 4 if e(p-1) is negligible (convergence). for (k = p - 2; k >= -1; k--) { if (k == -1) { break; } if (Math.Abs(e[k]) <= eps * (Math.Abs(s[k]) + Math.Abs(s[k + 1]))) { e[k] = 0.0; break; } } if (k == p - 2) { kase = 4; } else { int ks; for (ks = p - 1; ks >= k; ks--) { if (ks == k) { break; } double t = (ks != p ? Math.Abs(e[ks]) : 0.0) + (ks != k + 1 ? Math.Abs(e[ks - 1]) : 0.0); if (Math.Abs(s[ks]) <= eps * t) { s[ks] = 0.0; break; } } if (ks == k) { kase = 3; } else if (ks == p - 1) { kase = 1; } else { kase = 2; k = ks; } } k++; // Perform the task indicated by kase. switch (kase) { // Deflate negligible s(p). case 1: { double f = e[p - 2]; e[p - 2] = 0.0; for (int j = p - 2; j >= k; j--) { double t = Fn.Hypot(s[j], f); double cs = s[j] / t; double sn = f / t; s[j] = t; if (j != k) { f = (-sn) * e[j - 1]; e[j - 1] = cs * e[j - 1]; } if (wantv) { for (int i = 0; i < n; i++) { t = cs * V[i][j] + sn * V[i][p - 1]; V[i][p - 1] = (-sn) * V[i][j] + cs * V[i][p - 1]; V[i][j] = t; } } } } break; // Split at negligible s(k) case 2: { double f = e[k - 1]; e[k - 1] = 0.0; for (int j = k; j < p; j++) { double t = Fn.Hypot(s[j], f); double cs = s[j] / t; double sn = f / t; s[j] = t; f = (-sn) * e[j]; e[j] = cs * e[j]; if (wantu) { for (int i = 0; i < m; i++) { t = cs * U[i][j] + sn * U[i][k - 1]; U[i][k - 1] = (-sn) * U[i][j] + cs * U[i][k - 1]; U[i][j] = t; } } } } break; // Perform one qr step. case 3: { // Calculate the shift. double scale = Math.Max(Math.Max(Math.Max(Math.Max(Math.Abs(s[p - 1]), Math.Abs(s[p - 2])), Math.Abs(e[p - 2])), Math.Abs(s[k])), Math.Abs(e[k])); double sp = s[p - 1] / scale; double spm1 = s[p - 2] / scale; double epm1 = e[p - 2] / scale; double sk = s[k] / scale; double ek = e[k] / scale; double b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2.0; double c = (sp * epm1) * (sp * epm1); double shift = 0.0; if ((b != 0.0) | (c != 0.0)) { shift = Math.Sqrt(b * b + c); if (b < 0.0) { shift = -shift; } shift = c / (b + shift); } double f = (sk + sp) * (sk - sp) + shift; double g = sk * ek; // Chase zeros. for (int j = k; j < p - 1; j++) { double t = Fn.Hypot(f, g); double cs = f / t; double sn = g / t; if (j != k) { e[j - 1] = t; } f = cs * s[j] + sn * e[j]; e[j] = cs * e[j] - sn * s[j]; g = sn * s[j + 1]; s[j + 1] = cs * s[j + 1]; if (wantv) { for (int i = 0; i < n; i++) { t = cs * V[i][j] + sn * V[i][j + 1]; V[i][j + 1] = (-sn) * V[i][j] + cs * V[i][j + 1]; V[i][j] = t; } } t = Fn.Hypot(f, g); cs = f / t; sn = g / t; s[j] = t; f = cs * e[j] + sn * s[j + 1]; s[j + 1] = (-sn) * e[j] + cs * s[j + 1]; g = sn * e[j + 1]; e[j + 1] = cs * e[j + 1]; if (wantu && (j < m - 1)) { for (int i = 0; i < m; i++) { t = cs * U[i][j] + sn * U[i][j + 1]; U[i][j + 1] = (-sn) * U[i][j] + cs * U[i][j + 1]; U[i][j] = t; } } } e[p - 2] = f; iter = iter + 1; } break; // Convergence. case 4: { // Make the singular values positive. if (s[k] <= 0.0) { s[k] = (s[k] < 0.0 ? -s[k] : 0.0); if (wantv) { for (int i = 0; i <= pp; i++) { V[i][k] = -V[i][k]; } } } // Order the singular values. while (k < pp) { if (s[k] >= s[k + 1]) { break; } double t = s[k]; s[k] = s[k + 1]; s[k + 1] = t; if (wantv && (k < n - 1)) { for (int i = 0; i < n; i++) { t = V[i][k + 1]; V[i][k + 1] = V[i][k]; V[i][k] = t; } } if (wantu && (k < m - 1)) { for (int i = 0; i < m; i++) { t = U[i][k + 1]; U[i][k + 1] = U[i][k]; U[i][k] = t; } } k++; } iter = 0; p--; } break; } } // (vermorel) transposing the results if needed if (transpose) { // swaping U and V double[][] T = V; V = U; U = T; } _u = new Matrix(U); _v = new Matrix(V); _singular = new Vector(s); InitOnDemandComputations(); }