internal static void Compute(Order order, int m, int n, Complex alpha, Complex[] X, int incx, Complex[] Y, int incy, Complex[] A, int lda) { ArgumentCheck(order, m, n, X, X.Length, ref incx, Y, Y.Length, ref incy, A, A.Length, lda); #if MANAGED Complex temp; if (order == Order.RowMajor) { for (int i = 0, ix = 0; i < m; ++i, ix += incx) { temp = alpha * X[ix]; for (int j = 0, jy = 0; j < n; ++j, jy += incy) { A[i * lda + j] += temp * ComplexMath.Conjugate(Y[jy]); } } } else { for (int j = 0, jy = 0; j < n; ++j, jy += incy) { temp = alpha * ComplexMath.Conjugate(Y[jy]); for (int i = 0, ix = 0; i < m; ++i, ix += incx) { A[lda * j + i] += temp * X[ix]; } } } #else dna_blas_zgerc(order, m, n, ref alpha, X, incx, Y, incy, A, lda); #endif }
///<summary>Calculates the inverse of the matrix.</summary> ///<returns>the inverse of the matrix.</returns> ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception> public ComplexDoubleMatrix GetInverse() { Compute(); if (!ispd) { throw new NotPositiveDefiniteException(); } else { #if MANAGED var ret = ComplexDoubleMatrix.CreateIdentity(order); ret = Solve(ret); return(ret); #else Complex[] inverse = new Complex[l.data.Length]; Array.Copy(l.data, inverse, l.data.Length); Lapack.Potri.Compute(Lapack.UpLo.Lower, order, inverse, order); ComplexDoubleMatrix ret = new ComplexDoubleMatrix(order, order); ret.data = inverse; for (int i = 0; i < order; i++) { for (int j = 0; j < order; j++) { if (j > i) { ret.data[j * order + i] = ComplexMath.Conjugate(ret.data[i * order + j]); } } } return(ret); #endif } }
internal static void Compute(Order order, Transpose transA, int m, int n, int kl, int ku, Complex alpha, Complex[] A, int lda, Complex[] X, int incx, Complex beta, Complex[] Y, int incy) { ArgumentCheck(order, transA, ku + kl + 1, m, n, A, A.Length, lda, X, X.Length, ref incx, Y, Y.Length, ref incy); if (alpha == Complex.Zero && beta == Complex.One) { return; } #if MANAGED if ((order == Order.RowMajor && transA == Transpose.NoTrans) || (order == Order.ColumnMajor && transA != Transpose.NoTrans)) { for (int i = 0; i < m; ++i) { Y[i * incy] *= beta; for (int j = 0; j < ku + kl + 1; ++j) { Y[i * incy] += alpha * A[j + i * lda] * X[(System.Math.Max(i - kl, 0) + j) * incx]; } } } else if (order == Order.RowMajor && transA == Transpose.ConjTrans) { for (int i = 0; i < m; ++i) { Y[i * incy] *= beta; for (int j = 0; j < ku + kl + 1; ++j) { Y[i * incy] += alpha * ComplexMath.Conjugate(A[j + i * lda]) * X[(System.Math.Max(i - kl, 0) + j) * incx]; } } } else if (order == Order.ColumnMajor && transA == Transpose.ConjTrans) { for (int i = 0; i < System.Math.Min(m, n); ++i) { int ti = i * incy; Y[ti] *= beta; for (int k = -System.Math.Min(i, kl); k <= System.Math.Min(m - 1 - i, ku); ++k) { Y[ti] += alpha * ComplexMath.Conjugate(A[(i + k) * lda + ku - k]) * X[incx * (i + k)]; } } } else { // corresponds to the case ( (colMajor && noTranspose) || (rowMajor && transpose)) - no conjugates here for (int i = 0; i < System.Math.Min(m, n); ++i) { int ti = i * incy; Y[ti] *= beta; for (int k = -System.Math.Min(i, kl); k <= System.Math.Min(m - 1 - i, ku); ++k) { Y[ti] += alpha * A[(i + k) * lda + ku - k] * X[incx * (i + k)]; } } } #else dna_blas_zgbmv(order, transA, m, n, kl, ku, ref alpha, A, lda, X, incx, ref beta, Y, incy); #endif }
public static double Compute(Complex a, Complex b) { Complex temp = a * ComplexMath.Conjugate(a); temp += (b * ComplexMath.Conjugate(b)); double ret = ComplexMath.Absolute(temp); return(System.Math.Sqrt(ret)); }
public static float Compute(ComplexFloat a, ComplexFloat b) { ComplexFloat temp = a * ComplexMath.Conjugate(a); temp += (b * ComplexMath.Conjugate(b)); float ret = ComplexMath.Absolute(temp); return((float)System.Math.Sqrt(ret)); }
///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary> ///<param name="B">RHS side of the system.</param> ///<returns>the solution matrix, X.</returns> ///<exception cref="ArgumentNullException">B is null.</exception> ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception> ///<exception cref="ArgumentException">The number of rows of A and B must be the same.</exception> public ComplexDoubleMatrix Solve(IROComplexDoubleMatrix B) { if (B == null) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if (!ispd) { throw new NotPositiveDefiniteException(); } else { if (B.Rows != order) { throw new System.ArgumentException("Matrix row dimensions must agree."); } #if MANAGED // Copy right hand side. int cols = B.Columns; var X = new ComplexDoubleMatrix(B); for (int c = 0; c < cols; c++) { // Solve L*Y = B; for (int i = 0; i < order; i++) { Complex sum = B[i, c]; for (int k = i - 1; k >= 0; k--) { sum -= l.data[i][k] * X.data[k][c]; } X.data[i][c] = sum / l.data[i][i]; } // Solve L'*X = Y; for (int i = order - 1; i >= 0; i--) { Complex sum = X.data[i][c]; for (int k = i + 1; k < order; k++) { sum -= ComplexMath.Conjugate(l.data[k][i]) * X.data[k][c]; } X.data[i][c] = sum / ComplexMath.Conjugate(l.data[i][i]); } } return(X); #else Complex[] rhs = ComplexDoubleMatrix.ToLinearComplexArray(B); Lapack.Potrs.Compute(Lapack.UpLo.Lower, order, B.Columns, l.data, order, rhs, B.Rows); ComplexDoubleMatrix ret = new ComplexDoubleMatrix(order, B.Columns); ret.data = rhs; return(ret); #endif } }
private static Complex zdotc(ComplexDoubleMatrix A, int Col1, int Col2, int Start) { Complex z = Complex.Zero; for (int i = Start; i < A.RowLength; i++) { z += A[i, Col2] * ComplexMath.Conjugate(A[i, Col1]); } return(z); }
///<summary>Computes the algorithm.</summary> protected override void InternalCompute() { #if MANAGED l = new ComplexDoubleMatrix(matrix); for (int j = 0; j < order; j++) { Complex[] rowj = l.data[j]; double d = 0.0; for (int k = 0; k < j; k++) { Complex[] rowk = l.data[k]; Complex s = Complex.Zero; for (int i = 0; i < k; i++) { s += rowk[i] * rowj[i]; } rowj[k] = s = (matrix.data[j][k] - s) / l.data[k][k]; d = d + (s * ComplexMath.Conjugate(s)).Real; } d = matrix.data[j][j].Real - d; if (d <= 0.0) { ispd = false; return; } l.data[j][j] = new Complex(System.Math.Sqrt(d)); for (int k = j + 1; k < order; k++) { l.data[j][k] = Complex.Zero; } } #else Complex[] factor = new Complex[matrix.data.Length]; Array.Copy(matrix.data, factor, matrix.data.Length); int status = Lapack.Potrf.Compute(Lapack.UpLo.Lower, order, factor, order); if (status != 0) { ispd = false; } l = new ComplexDoubleMatrix(order); l.data = factor; for (int i = 0; i < order; i++) { for (int j = 0; j < order; j++) { if (j > i) { l.data[j * order + i] = 0; } } } #endif }
private static double dznrm2Column(ComplexDoubleMatrix A, int Col, int Start) { // dznrm2Column returns the euclidean norm of a vector, // which is a part of column Col in matrix A, beginning from Start to end of column // so that dznrm2Column := sqrt( conjg( matrix' )*matrix ) double s = 0; for (int i = Start; i < A.RowLength; i++) { s += (A[i, Col] * ComplexMath.Conjugate(A[i, Col])).Real; } return(System.Math.Sqrt(s)); }
private static double dznrm2Vector(ComplexDoubleVector A, int Start) { // dznrm2Vector returns the euclidean norm of a vector, // which is a part of A, beginning from Start to end of vector // so that dznrm2Vector := sqrt( conjg( matrix' )*matrix ) double s = 0; for (int i = Start; i < A.Length; i++) { s += (A[i] * ComplexMath.Conjugate(A[i])).Real; } return(System.Math.Sqrt(s)); }
///<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 ComplexDoubleVector Solve(IROComplexDoubleVector 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 ComplexDoubleVector(B); // Solve L*Y = B; for (int i = 0; i < order; i++) { Complex 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--) { Complex 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 Complex[] rhs = ComplexDoubleMatrix.ToLinearComplexArray(B); Lapack.Potrs.Compute(Lapack.UpLo.Lower, order, 1, l.data, order, rhs, B.Length); ComplexDoubleVector ret = new ComplexDoubleVector(order, B.Length); ret.data = rhs; return(ret); #endif } }
public static ComplexFloatVector GenerateColumn(IComplexFloatMatrix A, int r1, int r2, int c) { int ru = r2 - r1 + 1; ComplexFloatVector u = new ComplexFloatVector(r2 - r1 + 1); for (int i = r1; i <= r2; i++) { u[i - r1] = A[i, c]; A[i, c] = ComplexFloat.Zero; } float norm = u.GetNorm(); if (r1 == r2 || norm == 0) { A[r1, c] = new ComplexFloat(-u[0]); u[0] = (float)System.Math.Sqrt(2); return(u); } ComplexFloat scale = new ComplexFloat(1 / norm, 0); ComplexFloat t = ComplexFloat.Zero; ComplexFloat t1 = ComplexFloat.Zero; if (u[0].Real != 0 || u[0].Imag != 0) { t = u[0]; t1 = ComplexMath.Conjugate(u[0]); t = ComplexMath.Absolute(t); t = t1 / t; scale = scale * t; } A[r1, c] = -ComplexFloat.One / scale; for (int i = 0; i < ru; i++) { u[i] = u[i] * scale; } u[0] = new ComplexFloat(u[0].Real + 1, 0); float s = (float)System.Math.Sqrt(1 / u[0].Real); for (int i = 0; i < ru; i++) { u[i] = new ComplexFloat(s * u[i].Real, s * u[i].Imag); } return(u); }
public static ComplexDoubleVector GenerateRow(IComplexDoubleMatrix A, int r, int c1, int c2) { int cu = c2 - c1 + 1; ComplexDoubleVector u = new ComplexDoubleVector(cu); for (int j = c1; j <= c2; j++) { u[j - c1] = A[r, j]; A[r, j] = Complex.Zero; } double norm = u.GetNorm(); if (c1 == c2 || norm == 0) { A[r, c1] = new Complex(-u[0].Real, -u[0].Imag); u[0] = System.Math.Sqrt(2); return(u); } Complex scale = new Complex(1 / norm); Complex t = Complex.Zero; Complex t1 = Complex.Zero; if (u[0].Real != 0 || u[0].Imag != 0) { t = u[0]; t1 = ComplexMath.Conjugate(u[0]); t = ComplexMath.Absolute(t); t = t1 / t; scale = scale * t; } A[r, c1] = -Complex.One / scale; for (int j = 0; j < cu; j++) { u[j] *= scale; } u[0] = new Complex(u[0].Real + 1); double s = System.Math.Sqrt(1 / u[0].Real); for (int j = 0; j < cu; j++) { u[j] = new Complex(s * u[j].Real, -s * u[j].Imag); } return(u); }
public void Conjugate() { Complex cd1 = new Complex(1.1, -2.2); Complex cd2 = new Complex(0, -2.2); Complex cd3 = new Complex(1.1, 0); Complex cd4 = new Complex(-1.1, 2.2); ComplexFloat cf1 = new ComplexFloat(1.1f, -2.2f); ComplexFloat cf2 = new ComplexFloat(0, -2.2f); ComplexFloat cf3 = new ComplexFloat(1.1f, 0); ComplexFloat cf4 = new ComplexFloat(-1.1f, 2.2f); Assert.AreEqual(ComplexMath.Conjugate(cd1), new Complex(1.1, 2.2)); Assert.AreEqual(ComplexMath.Conjugate(cd2), new Complex(0, 2.2)); Assert.AreEqual(ComplexMath.Conjugate(cd3), new Complex(1.1, 0)); Assert.AreEqual(ComplexMath.Conjugate(cd4), new Complex(-1.1, -2.2)); Assert.AreEqual(ComplexMath.Conjugate(cf1), new ComplexFloat(1.1f, 2.2f)); Assert.AreEqual(ComplexMath.Conjugate(cf2), new ComplexFloat(0, 2.2f)); Assert.AreEqual(ComplexMath.Conjugate(cf3), new ComplexFloat(1.1f, 0)); Assert.AreEqual(ComplexMath.Conjugate(cf4), new ComplexFloat(-1.1f, -2.2f)); }
internal static double Compute(int n, Complex[] X, int incx) { ArgumentCheck(n, X, X.Length, ref incx); double ret = 0; #if MANAGED var temp = new Complex(0); int ix = 0; for (int i = 0; i < n; ++i) { temp += (X[ix] * ComplexMath.Conjugate(X[ix])); ix += incx; } ret = System.Math.Sqrt(ComplexMath.Absolute(temp)); #else ret = dna_blas_dznrm2(n, X, incx); #endif return(ret); }
internal static float Compute(int n, ComplexFloat[] X, int incx) { ArgumentCheck(n, X, X.Length, ref incx); float ret = 0; #if MANAGED ComplexFloat temp = new ComplexFloat(0); int ix = 0; for (int i = 0; i < n; ++i) { temp += (X[ix] * ComplexMath.Conjugate(X[ix])); ix += incx; } ret = (float)System.Math.Sqrt(ComplexMath.Absolute(temp)); #else ret = dna_blas_scnrm2(n, X, incx); #endif return(ret); }
///<summary>Compute the function of this class</summary> internal static ComplexFloat Compute(int n, ComplexFloat[] X, int incx, ComplexFloat[] Y, int incy) { if (n < 0) { return(ComplexFloat.Zero); } ArgumentCheck(n, X, X.Length, ref incx, Y, Y.Length, ref incy); ComplexFloat ret = new ComplexFloat(0); #if MANAGED int ix = 0; int iy = 0; for (int i = 0; i < n; ++i) { ret += (ComplexMath.Conjugate(X[ix]) * Y[iy]); ix += incx; iy += incy; } #else dna_blas_cdotc(n, X, incx, Y, incy, ref ret); #endif return(ret); }
/// <summary>Finds the least squares solution of <c>A*X = B</c>, where <c>m >= n</c></summary> /// <param name="B">A matrix with as many rows as A and any number of columns.</param> /// <returns>X that minimizes the two norm of <c>Q*R*X-B</c>.</returns> /// <exception cref="ArgumentException">Matrix row dimensions must agree.</exception> /// <exception cref="InvalidOperationException">Matrix is rank deficient or <c>m < n</c>.</exception> public ComplexDoubleMatrix Solve(ComplexDoubleMatrix B) { if (B.RowLength != matrix.Rows) { throw new ArgumentException("Matrix row dimensions must agree."); } if (matrix.Rows < matrix.Columns) { throw new System.InvalidOperationException("A must have at lest as a many rows as columns."); } Compute(); if (!this.isFullRank) { throw new System.InvalidOperationException("Matrix is rank deficient."); } // Copy right hand side int m = matrix.Rows; int n = matrix.Columns; int nx = B.ColumnLength; ComplexDoubleMatrix ret = new ComplexDoubleMatrix(n, nx); #if MANAGED ComplexDoubleMatrix X = new ComplexDoubleMatrix(B); // Compute Y = transpose(Q)*B Complex[] column = new Complex[q_.RowLength]; for (int j = 0; j < nx; j++) { for (int k = 0; k < m; k++) { column[k] = X.data[k][j]; } for (int i = 0; i < m; i++) { Complex s = Complex.Zero; for (int k = 0; k < m; k++) { s += ComplexMath.Conjugate(q_.data[k][i]) * column[k]; } X.data[i][j] = s; } } // Solve R*X = Y; for (int k = n - 1; k >= 0; k--) { for (int j = 0; j < nx; j++) { X.data[k][j] /= r_.data[k][k]; } for (int i = 0; i < k; i++) { for (int j = 0; j < nx; j++) { X.data[i][j] -= X.data[k][j] * r_.data[i][k]; } } } for (int i = 0; i < n; i++) { for (int j = 0; j < nx; j++) { ret.data[i][j] = X.data[i][j]; } } #else Complex[] c = new Complex[B.data.Length]; Array.Copy(B.data, 0, c, 0, B.data.Length); Lapack.Unmqr.Compute(Lapack.Side.Left, Lapack.Transpose.ConjTrans, m, nx, n, qr, m, tau, c, m); Blas.Trsm.Compute(Blas.Order.ColumnMajor, Blas.Side.Left, Blas.UpLo.Upper, Blas.Transpose.NoTrans, Blas.Diag.NonUnit, n, nx, 1, qr, m, c, m); for (int i = 0; i < n; i++) { for (int j = 0; j < nx; j++) { ret.data[j * n + i] = c[j * m + (jpvt[i] - 1)]; } } #endif return(ret); }
internal static void Compute(Order order, Transpose transA, int m, int n, Complex alpha, Complex[] A, int lda, Complex[] X, int incx, Complex beta, Complex[] Y, int incy) { ArgumentCheck(order, transA, m, n, A, A.Length, lda, X, X.Length, ref incx, Y, Y.Length, ref incy); #if MANAGED int lenX = m; int lenY = n; if (transA == Transpose.NoTrans) { lenX = n; lenY = m; } if (beta == Complex.Zero) { for (int i = 0, iy = 0; i < lenY; ++i, iy += incy) { Y[iy] = 0; } } else if (beta != Complex.One) { for (int i = 0, iy = 0; i < lenY; ++i, iy += incy) { Y[iy] *= beta; } } if (alpha == Complex.Zero) { return; } Complex add_val = new Complex(0); if ((order == Order.RowMajor && transA == Transpose.NoTrans) || (order == Order.ColumnMajor && transA == Transpose.Trans)) { for (int i = 0, iy = 0; i < lenY; ++i, iy += incy) { add_val = 0; for (int j = 0, jx = 0; j < lenX; ++j, jx += incx) { add_val += X[jx] * A[i * lda + j]; } Y[iy] += alpha * add_val; } } else if ((order == Order.RowMajor && transA == Transpose.Trans) || (order == Order.ColumnMajor && transA == Transpose.NoTrans)) { for (int j = 0, jx = 0; j < lenX; ++j, jx += incx) { add_val = alpha * X[jx]; if (add_val != Complex.Zero) { for (int i = 0, iy = 0; i < lenY; ++i, iy += incy) { Y[iy] += add_val * A[j * lda + i]; } } } } else if (order == Order.RowMajor && transA == Transpose.ConjTrans) { for (int j = 0, jx = 0; j < lenX; ++j, jx += incx) { add_val = alpha * X[jx]; if (add_val != Complex.Zero) { for (int i = 0, iy = 0; i < lenY; ++i, iy += incy) { Y[iy] += add_val * ComplexMath.Conjugate(A[j * lda + i]); } } } } else { for (int i = 0, iy = 0; i < lenY; ++i, iy += incy) { add_val = 0; for (int j = 0, jx = 0; j < lenX; ++j, jx += incx) { add_val += X[jx] * ComplexMath.Conjugate(A[i * lda + j]); } Y[iy] += alpha * add_val; } } #else dna_blas_zgemv(order, transA, m, n, ref alpha, A, lda, X, incx, ref beta, Y, incy); #endif }
///<summary>Computes the algorithm.</summary> protected override void InternalCompute() { rows = matrix.RowLength; cols = matrix.ColumnLength; int mm = System.Math.Min(rows + 1, cols); s = new ComplexDoubleVector(mm); // singular values #if MANAGED // Derived from LINPACK code. // Initialize. u = new ComplexDoubleMatrix(rows, rows); // left vectors v = new ComplexDoubleMatrix(cols, cols); // right vectors ComplexDoubleVector e = new ComplexDoubleVector(cols); ComplexDoubleVector work = new ComplexDoubleVector(rows); int i, iter, j, k, kase, l, lp1, ls = 0, lu, m, nct, nctp1, ncu, nrt, nrtp1; double b, c, cs = 0.0, el, emm1, f, g, scale, shift, sl, sm, sn = 0.0, smm1, t1, test, ztest, xnorm, enorm; Complex t, r; ncu = rows; // reduce matrix to bidiagonal form, storing the diagonal elements // in s and the super-diagonal elements in e. int info = 0; nct = System.Math.Min(rows - 1, cols); nrt = System.Math.Max(0, System.Math.Min(cols - 2, rows)); lu = System.Math.Max(nct, nrt); for (l = 0; l < lu; l++) { lp1 = l + 1; if (l < nct) { // compute the transformation for the l-th column and // place the l-th diagonal in s[l]. xnorm = dznrm2Column(matrix, l, l); s[l] = new Complex(xnorm, (double)0.0); if (dcabs1(s[l]) != 0.0) { if (dcabs1(matrix[l, l]) != 0.0) { s[l] = csign(s[l], matrix[l, l]); } zscalColumn(matrix, l, l, 1.0 / s[l]); matrix[l, l] = Complex.One + matrix[l, l]; } s[l] = -s[l]; } for (j = lp1; j < cols; j++) { if (l < nct) { if (dcabs1(s[l]) != 0.0) { // apply the transformation. t = -zdotc(matrix, l, j, l) / matrix[l, l]; for (int ii = l; ii < matrix.RowLength; ii++) { matrix[ii, j] += t * matrix[ii, l]; } } } //place the l-th row of matrix into e for the //subsequent calculation of the row transformation. e[j] = ComplexMath.Conjugate(matrix[l, j]); } if (computeVectors && l < nct) { // place the transformation in u for subsequent back multiplication. for (i = l; i < rows; i++) { u[i, l] = matrix[i, l]; } } if (l < nrt) { // compute the l-th row transformation and place the l-th super-diagonal in e(l). enorm = dznrm2Vector(e, lp1); e[l] = new Complex(enorm, 0.0); if (dcabs1(e[l]) != 0.0) { if (dcabs1(e[lp1]) != 0.0) { e[l] = csign(e[l], e[lp1]); } zscalVector(e, lp1, 1.0 / e[l]); e[lp1] = Complex.One + e[lp1]; } e[l] = ComplexMath.Conjugate(-e[l]); if (lp1 < rows && dcabs1(e[l]) != 0.0) { // apply the transformation. for (i = lp1; i < rows; i++) { work[i] = Complex.Zero; } for (j = lp1; j < cols; j++) { for (int ii = lp1; ii < matrix.RowLength; ii++) { work[ii] += e[j] * matrix[ii, j]; } } for (j = lp1; j < cols; j++) { Complex ww = ComplexMath.Conjugate(-e[j] / e[lp1]); for (int ii = lp1; ii < matrix.RowLength; ii++) { matrix[ii, j] += ww * work[ii]; } } } if (computeVectors) { // place the transformation in v for subsequent back multiplication. for (i = lp1; i < cols; i++) { v[i, l] = e[i]; } } } } // set up the final bidiagonal matrix or order m. m = System.Math.Min(cols, rows + 1); nctp1 = nct + 1; nrtp1 = nrt + 1; if (nct < cols) { s[nctp1 - 1] = matrix[nctp1 - 1, nctp1 - 1]; } if (rows < m) { s[m - 1] = Complex.Zero; } if (nrtp1 < m) { e[nrtp1 - 1] = matrix[nrtp1 - 1, m - 1]; } e[m - 1] = Complex.Zero; // if required, generate u. if (computeVectors) { for (j = nctp1 - 1; j < ncu; j++) { for (i = 0; i < rows; i++) { u[i, j] = Complex.Zero; } u[j, j] = Complex.One; } for (l = nct - 1; l >= 0; l--) { if (dcabs1(s[l]) != 0.0) { for (j = l + 1; j < ncu; j++) { t = -zdotc(u, l, j, l) / u[l, l]; for (int ii = l; ii < u.RowLength; ii++) { u[ii, j] += t * u[ii, l]; } } zscalColumn(u, l, l, -Complex.One); u[l, l] = Complex.One + u[l, l]; for (i = 0; i < l; i++) { u[i, l] = Complex.Zero; } } else { for (i = 0; i < rows; i++) { u[i, l] = Complex.Zero; } u[l, l] = Complex.One; } } } // if it is required, generate v. if (computeVectors) { for (l = cols - 1; l >= 0; l--) { lp1 = l + 1; if (l < nrt) { if (dcabs1(e[l]) != 0.0) { for (j = lp1; j < cols; j++) { t = -zdotc(v, l, j, lp1) / v[lp1, l]; for (int ii = l; ii < v.RowLength; ii++) { v[ii, j] += t * v[ii, l]; } } } } for (i = 0; i < cols; i++) { v[i, l] = Complex.Zero; } v[l, l] = Complex.One; } } // transform s and e so that they are double . for (i = 0; i < m; i++) { if (dcabs1(s[i]) != 0.0) { t = new Complex(ComplexMath.Absolute(s[i]), 0.0); r = s[i] / t; s[i] = t; if (i < m - 1) { e[i] = e[i] / r; } if (computeVectors) { zscalColumn(u, i, 0, r); } } // ...exit if (i == m - 1) { break; } if (dcabs1(e[i]) != 0.0) { t = new Complex(ComplexMath.Absolute(e[i]), 0.0); r = t / e[i]; e[i] = t; s[i + 1] = s[i + 1] * r; if (computeVectors) { zscalColumn(v, i + 1, 0, r); } } } // main iteration loop for the singular values. mm = m; iter = 0; while (m > 0) { // quit if all the singular values have been found. // if too many iterations have been performed, set // flag and return. if (iter >= MAXITER) { info = m; // ......exit break; } // this section of the program inspects for // negligible elements in the s and e arrays. on // completion the variables kase and l are set as follows. // kase = 1 if s[m] and e[l-1] are negligible and l < m // kase = 2 if s[l] is negligible and l < m // kase = 3 if e[l-1] is negligible, l < m, and // s[l, ..., s[m] are not negligible (qr step). // kase = 4 if e[m-1] is negligible (convergence). for (l = m - 2; l >= 0; l--) { test = ComplexMath.Absolute(s[l]) + ComplexMath.Absolute(s[l + 1]); ztest = test + ComplexMath.Absolute(e[l]); if (ztest == test) { e[l] = Complex.Zero; break; } } if (l == m - 2) { kase = 4; } else { for (ls = m - 1; ls > l; ls--) { test = 0.0; if (ls != m - 1) { test = test + ComplexMath.Absolute(e[ls]); } if (ls != l + 1) { test = test + ComplexMath.Absolute(e[ls - 1]); } ztest = test + ComplexMath.Absolute(s[ls]); if (ztest == test) { s[ls] = Complex.Zero; break; } } if (ls == l) { kase = 3; } else if (ls == m - 1) { kase = 1; } else { kase = 2; l = ls; } } l = l + 1; // perform the task indicated by kase. switch (kase) { // deflate negligible s[m]. case 1: f = e[m - 2].Real; e[m - 2] = Complex.Zero; for (k = m - 2; k >= 0; k--) { t1 = s[k].Real; drotg(ref t1, ref f, ref cs, ref sn); s[k] = new Complex(t1, 0.0); if (k != l) { f = -sn * e[k - 1].Real; e[k - 1] = cs * e[k - 1]; } if (computeVectors) { zdrot(v, k, m - 1, cs, sn); } } break; // split at negligible s[l]. case 2: f = e[l - 1].Real; e[l - 1] = Complex.Zero; for (k = l; k < m; k++) { t1 = s[k].Real; drotg(ref t1, ref f, ref cs, ref sn); s[k] = new Complex(t1, 0.0); f = -sn * e[k].Real; e[k] = cs * e[k]; if (computeVectors) { zdrot(u, k, l - 1, cs, sn); } } break; // perform one qr step. case 3: // calculate the shift. scale = 0.0; scale = System.Math.Max(scale, ComplexMath.Absolute(s[m - 1])); scale = System.Math.Max(scale, ComplexMath.Absolute(s[m - 2])); scale = System.Math.Max(scale, ComplexMath.Absolute(e[m - 2])); scale = System.Math.Max(scale, ComplexMath.Absolute(s[l])); scale = System.Math.Max(scale, ComplexMath.Absolute(e[l])); sm = s[m - 1].Real / scale; smm1 = s[m - 2].Real / scale; emm1 = e[m - 2].Real / scale; sl = s[l].Real / scale; el = e[l].Real / scale; b = ((smm1 + sm) * (smm1 - sm) + emm1 * emm1) / 2.0; c = (sm * emm1) * (sm * emm1); shift = 0.0; if (b != 0.0 || c != 0.0) { shift = System.Math.Sqrt(b * b + c); if (b < 0.0) { shift = -shift; } shift = c / (b + shift); } f = (sl + sm) * (sl - sm) + shift; g = sl * el; // chase zeros. for (k = l; k < m - 1; k++) { drotg(ref f, ref g, ref cs, ref sn); if (k != l) { e[k - 1] = new Complex(f, 0.0); } f = cs * s[k].Real + sn * e[k].Real; e[k] = cs * e[k] - sn * s[k]; g = sn * s[k + 1].Real; s[k + 1] = cs * s[k + 1]; if (computeVectors) { zdrot(v, k, k + 1, cs, sn); } drotg(ref f, ref g, ref cs, ref sn); s[k] = new Complex(f, 0.0); f = cs * e[k].Real + sn * s[k + 1].Real; s[k + 1] = -sn * e[k] + cs * s[k + 1]; g = sn * e[k + 1].Real; e[k + 1] = cs * e[k + 1]; if (computeVectors && k < rows) { zdrot(u, k, k + 1, cs, sn); } } e[m - 2] = new Complex(f, 0.0); iter = iter + 1; break; // convergence. case 4: // make the singular value positive if (s[l].Real < 0.0) { s[l] = -s[l]; if (computeVectors) { zscalColumn(v, l, 0, -Complex.One); } } // order the singular value. while (l != mm - 1) { if (s[l].Real >= s[l + 1].Real) { break; } t = s[l]; s[l] = s[l + 1]; s[l + 1] = t; if (computeVectors && l < cols) { zswap(v, l, l + 1); } if (computeVectors && l < rows) { zswap(u, l, l + 1); } l = l + 1; } iter = 0; m = m - 1; break; } } // make matrix w from vector s // there is no constructor, creating diagonal matrix from vector // doing it ourselves mm = System.Math.Min(matrix.RowLength, matrix.ColumnLength); #else double[] d = new double[mm]; u = new ComplexDoubleMatrix(rows); v = new ComplexDoubleMatrix(cols); Complex[] a = new Complex[matrix.data.Length]; Array.Copy(matrix.data, a, matrix.data.Length); Lapack.Gesvd.Compute(rows, cols, a, d, u.data, v.data); v.ConjugateTranspose(); for (int i = 0; i < d.Length; i++) { s[i] = d[i]; } #endif w = new ComplexDoubleMatrix(matrix.RowLength, matrix.ColumnLength); for (int ii = 0; ii < matrix.RowLength; ii++) { for (int jj = 0; jj < matrix.ColumnLength; jj++) { if (ii == jj) { w[ii, ii] = s[ii]; } } } double eps = System.Math.Pow(2.0, -52.0); double tol = System.Math.Max(matrix.RowLength, matrix.ColumnLength) * s[0].Real * eps; rank = 0; for (int h = 0; h < mm; h++) { if (s[h].Real > tol) { rank++; } } if (!computeVectors) { u = null; v = null; } matrix = null; }