private static void Main() //****************************************************************************80 // // Purpose: // // MAIN is the main program for LINPACK_BENCH. // // Discussion: // // LINPACK_BENCH drives the double precision LINPACK benchmark program. // // Modified: // // 30 November 2006 // // Parameters: // // N is the problem size. // { const int N = 1000; const int LDA = N + 1; const double cray = 0.056; int i; int j; double[] time = new double[6]; Console.WriteLine(""); Console.WriteLine("LINPACK_BENCH"); Console.WriteLine(""); Console.WriteLine(" The LINPACK benchmark."); Console.WriteLine(" Datatype: Double precision"); Console.WriteLine(" Matrix order N = " + N + ""); Console.WriteLine(" Leading matrix dimension LDA = " + LDA + ""); double ops = 2 * N * N * N / 3.0 + 2.0 * (N * N); // // Allocate space for arrays. // double[] a = typeMethods.r8mat_gen(LDA, N); double[] b = new double[N]; int[] ipvt = new int[N]; double[] resid = new double[N]; double[] rhs = new double[N]; double[] x = new double[N]; double a_max = 0.0; for (j = 0; j < N; j++) { for (i = 0; i < N; i++) { a_max = Math.Max(a_max, a[i + j * LDA]); } } for (i = 0; i < N; i++) { x[i] = 1.0; } for (i = 0; i < N; i++) { b[i] = 0.0; for (j = 0; j < N; j++) { b[i] += a[i + j * LDA] * x[j]; } } DateTime t1 = DateTime.Now; int info = DGEFA.dgefa(ref a, LDA, N, ref ipvt); if (info != 0) { Console.WriteLine(""); Console.WriteLine("LINPACK_BENCH - Fatal error!"); Console.WriteLine(" The matrix A is apparently singular."); Console.WriteLine(" Abnormal end of execution."); return; } DateTime t2 = DateTime.Now; time[0] = (t2 - t1).TotalSeconds; t1 = DateTime.Now; int job = 0; DGESL.dgesl(a, LDA, N, ipvt, ref b, job); t2 = DateTime.Now; time[1] = (t2 - t1).TotalSeconds; double total = time[0] + time[1]; // // Compute a residual to verify results. // a = typeMethods.r8mat_gen(LDA, N); for (i = 0; i < N; i++) { x[i] = 1.0; } for (i = 0; i < N; i++) { rhs[i] = 0.0; for (j = 0; j < N; j++) { rhs[i] += a[i + j * LDA] * x[j]; } } for (i = 0; i < N; i++) { resid[i] = -rhs[i]; for (j = 0; j < N; j++) { resid[i] += a[i + j * LDA] * b[j]; } } double resid_max = 0.0; for (i = 0; i < N; i++) { resid_max = Math.Max(resid_max, Math.Abs(resid[i])); } double b_max = 0.0; for (i = 0; i < N; i++) { b_max = Math.Max(b_max, Math.Abs(b[i])); } double eps = typeMethods.r8_epsilon(); double residn = resid_max / (N * a_max * b_max * eps); time[2] = total; time[3] = total switch {
public static double dgeco(ref double[] a, int lda, int n, ref int[] ipvt, ref double[] z) //****************************************************************************80 // // Purpose: // // DGECO factors a real matrix and estimates its condition number. // // Discussion: // // If RCOND is not needed, DGEFA is slightly faster. // // To solve A * X = B, follow DGECO by DGESL. // // To compute inverse ( A ) * C, follow DGECO by DGESL. // // To compute determinant ( A ), follow DGECO by DGEDI. // // To compute inverse ( A ), follow DGECO by DGEDI. // // For the system A * X = B, relative perturbations in A and B // of size EPSILON may cause relative perturbations in X of size // EPSILON/RCOND. // // If RCOND is so small that the logical expression // 1.0D+00 + RCOND == 1.0D+00 // is true, then A may be singular to working precision. In particular, // RCOND is zero if exact singularity is detected or the estimate // underflows. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 May 2005 // // Author: // // Original FORTRAN77 version by Jack Dongarra, Cleve Moler, Jim Bunch, // Pete Stewart. // C++ version by John Burkardt. // // Reference: // // Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart, // LINPACK User's Guide, // SIAM, (Society for Industrial and Applied Mathematics), // 3600 University City Science Center, // Philadelphia, PA, 19104-2688. // ISBN 0-89871-172-X // // Parameters: // // Input/output, double A[LDA*N]. On input, a matrix to be // factored. On output, the LU factorization of the matrix. // // Input, int LDA, the leading dimension of the array A. // // Input, int N, the order of the matrix A. // // Output, int IPVT[N], the pivot indices. // // Output, double Z[N], a work vector whose contents are usually // unimportant. If A is close to a singular matrix, then Z is an // approximate null vector in the sense that // norm ( A * Z ) = RCOND * norm ( A ) * norm ( Z ). // // Output, double DGECO, the value of RCOND, an estimate // of the reciprocal condition number of A. // { int i; int j; int k; int l; double rcond; double s; double t; // // Compute the L1 norm of A. // double anorm = 0.0; for (j = 1; j <= n; j++) { anorm = Math.Max(anorm, BLAS1D.dasum(n, a, 1, index: +0 + (j - 1) * lda)); } // // Compute the LU factorization. // DGEFA.dgefa(ref a, lda, n, ref ipvt); // // RCOND = 1 / ( norm(A) * (estimate of norm(inverse(A))) ) // // estimate of norm(inverse(A)) = norm(Z) / norm(Y) // // where // A * Z = Y // and // A' * Y = E // // The components of E are chosen to cause maximum local growth in the // elements of W, where U'*W = E. The vectors are frequently rescaled // to avoid overflow. // // Solve U' * W = E. // double ek = 1.0; for (i = 1; i <= n; i++) { z[i - 1] = 0.0; } for (k = 1; k <= n; k++) { if (z[k - 1] != 0.0) { ek *= typeMethods.r8_sign(-z[k - 1]); } if (Math.Abs(a[k - 1 + (k - 1) * lda]) < Math.Abs(ek - z[k - 1])) { s = Math.Abs(a[k - 1 + (k - 1) * lda]) / Math.Abs(ek - z[k - 1]); for (i = 1; i <= n; i++) { z[i - 1] = s * z[i - 1]; } ek = s * ek; } double wk = ek - z[k - 1]; double wkm = -ek - z[k - 1]; s = Math.Abs(wk); double sm = Math.Abs(wkm); if (a[k - 1 + (k - 1) * lda] != 0.0) { wk /= a[k - 1 + (k - 1) * lda]; wkm /= a[k - 1 + (k - 1) * lda]; } else { wk = 1.0; wkm = 1.0; } if (k + 1 <= n) { for (j = k + 1; j <= n; j++) { sm += Math.Abs(z[j - 1] + wkm * a[k - 1 + (j - 1) * lda]); z[j - 1] += wk * a[k - 1 + (j - 1) * lda]; s += Math.Abs(z[j - 1]); } if (s < sm) { t = wkm - wk; wk = wkm; for (i = k + 1; i <= n; i++) { z[i - 1] += t * a[k - 1 + (i - 1) * lda]; } } } z[k - 1] = wk; } t = BLAS1D.dasum(n, z, 1); for (i = 1; i <= n; i++) { z[i - 1] /= t; } // // Solve L' * Y = W // for (k = n; 1 <= k; k--) { z[k - 1] += BLAS1D.ddot(n - k, a, 1, z, 1, xIndex: +k + (k - 1) * lda, yIndex: +k); switch (Math.Abs(z[k - 1])) { case > 1.0: { t = Math.Abs(z[k - 1]); for (i = 1; i <= n; i++) { z[i - 1] /= t; } break; } } l = ipvt[k - 1]; t = z[l - 1]; z[l - 1] = z[k - 1]; z[k - 1] = t; } t = BLAS1D.dasum(n, z, 1); for (i = 1; i <= n; i++) { z[i - 1] /= t; } double ynorm = 1.0; // // Solve L * V = Y. // for (k = 1; k <= n; k++) { l = ipvt[k - 1]; t = z[l - 1]; z[l - 1] = z[k - 1]; z[k - 1] = t; for (i = k + 1; i <= n; i++) { z[i - 1] += t * a[i - 1 + (k - 1) * lda]; } switch (Math.Abs(z[k - 1])) { case > 1.0: { ynorm /= Math.Abs(z[k - 1]); t = Math.Abs(z[k - 1]); for (i = 1; i <= n; i++) { z[i - 1] /= t; } break; } } } s = BLAS1D.dasum(n, z, 1); for (i = 1; i <= n; i++) { z[i - 1] /= s; } ynorm /= s; // // Solve U * Z = V. // for (k = n; 1 <= k; k--) { if (Math.Abs(a[k - 1 + (k - 1) * lda]) < Math.Abs(z[k - 1])) { s = Math.Abs(a[k - 1 + (k - 1) * lda]) / Math.Abs(z[k - 1]); for (i = 1; i <= n; i++) { z[i - 1] = s * z[i - 1]; } ynorm = s * ynorm; } if (a[k - 1 + (k - 1) * lda] != 0.0) { z[k - 1] /= a[k - 1 + (k - 1) * lda]; } else { z[k - 1] = 1.0; } for (i = 1; i <= k - 1; i++) { z[i - 1] -= z[k - 1] * a[i - 1 + (k - 1) * lda]; } } // // Normalize Z in the L1 norm. // s = 1.0 / BLAS1D.dasum(n, z, 1); for (i = 1; i <= n; i++) { z[i - 1] = s * z[i - 1]; } ynorm = s * ynorm; if (anorm != 0.0) { rcond = ynorm / anorm; } else { rcond = 0.0; } return(rcond); }