# include # include # include # include # include # include "differ.h" /******************************************************************************/ void differ_backward ( double h, int o, int p, double c[], double x[] ) /******************************************************************************/ /* Purpose: DIFFER_BACKWARD computes backward difference coefficients. Discussion: We determine coefficients C to approximate the derivative at X0 of order O and precision P, using equally spaced backward differences, so that d^o f(x)/dx^o = sum ( 0 <= i <= o+p-1 ) c(i) f(x-ih) + O(h^(p)) Licensing: This code is distributed under the MIT license. Modified: 10 November 2013 Author: John Burkardt Parameters: Input, double H, the spacing. 0 < H. Input, int O, the order of the derivative to be approximated. 1 <= O. Input, int P, the order of the error, as a power of H. Output, double C[O+P], the coefficients. Output, double X[O+P], the evaluation points. */ { double *b; int i; int info; int job; int n; double t; n = o + p; for ( i = 0; i < n; i++ ) { x[i] = ( double ) ( i + 1 - n ) * h; } b = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { b[i] = 0.0; } b[o] = 1.0; job = 0; r8vm_sl ( n, x, b, job, c, &info ); if ( info != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "DIFFER_BACKWARD - Fatal error!\n" ); fprintf ( stderr, " Vandermonde linear system is singular.\n" ); exit ( 1 ); } t = r8_factorial ( o ); for ( i = 0; i < n; i++ ) { c[i] = c[i] * t; } free ( b ); return; } /******************************************************************************/ void differ_central ( double h, int o, int p, double c[], double x[] ) /******************************************************************************/ /* Purpose: DIFFER_CENTRAL computes central difference coefficients. Discussion: We determine coefficients C to approximate the derivative at X0 of order O and precision P, using equally spaced central differences, so that d^o f(x)/dx^o = sum ( 0 <= i <= o+p-1 ) c(i) f(x+(2*i-o-p+1)*h/2) + O(h^(p)) Licensing: This code is distributed under the MIT license. Modified: 10 November 2013 Author: John Burkardt Parameters: Input, double H, the spacing. 0 < H. Input, int O, the order of the derivative to be approximated. 1 <= O. Input, int P, the order of the error, as a power of H. Output, double C[O+P], the coefficients. Output, double X[O+P], the evaluation points. */ { double *b; int i; int info; int job; int n; double t; n = o + p; for ( i = 0; i < n; i++ ) { x[i] = ( double ) ( - n + 1 + 2 * i ) * h / 2.0; } b = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { b[i] = 0.0; } b[o] = 1.0; job = 0; r8vm_sl ( n, x, b, job, c, &info ); if ( info != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "DIFFER_CENTRAL - Fatal error!\n" ); fprintf ( stderr, " Vandermonde linear system is singular.\n" ); exit ( 1 ); } t = r8_factorial ( o ); for ( i = 0; i < n; i++ ) { c[i] = c[i] * t; } free ( b ); return; } /******************************************************************************/ void differ_forward ( double h, int o, int p, double c[], double x[] ) /******************************************************************************/ /* Purpose: DIFFER_FORWARD computes forward difference coefficients. Discussion: We determine coefficients C to approximate the derivative at X0 of order O and precision P, using equally spaced forward differences, so that d^o f(x)/dx^o = sum ( 0 <= i <= o+p-1 ) c(i) f(x+ih) + O(h^(p)) Licensing: This code is distributed under the MIT license. Modified: 10 November 2013 Author: John Burkardt Parameters: Input, real H, the spacing. 0 < H. Input, integer O, the order of the derivative to be approximated. 1 <= O. Input, integer P, the order of the error, as a power of H. Output, real C[O+P], the coefficients. Output, real X[O+P], the evaluation points. */ { double *b; int i; int info; int job; int n; double t; n = o + p; for ( i = 0; i < n; i++ ) { x[i] = ( double ) ( i ) * h; } b = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { b[i] = 0.0; } b[o] = 1.0; job = 0; r8vm_sl ( n, x, b, job, c, &info ); if ( info != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "DIFFER_FORWARD - Fatal error!\n" ); fprintf ( stderr, " Vandermonde linear system is singular.\n" ); exit ( 1 ); } t = r8_factorial ( o ); for ( i = 0; i < n; i++ ) { c[i] = c[i] * t; } free ( b ); return; } /******************************************************************************/ double *differ_inverse ( int n, double stencil[] ) /******************************************************************************/ /* Purpose: DIFFER_INVERSE returns the inverse of the DIFFER matrix. Licensing: This code is distributed under the MIT license. Modified: 03 November 2013 Author: John Burkardt Parameters: Input, int N, the order of the matrix. Input, double STENCIL[N], the values that define A. Output, double DIFFER_INVERSE[N*N], the matrix. */ { double *a; int i; int indx; int j; int k; a = ( double * ) malloc ( n * n * sizeof ( double ) ); for ( j = 0; j < n; j++ ) { for ( i = 0; i < n; i++ ) { if ( j == 0 ) { a[i+j*n] = 1.0; } else { a[i+j*n] = 0.0; } } } for ( i = 0; i < n; i++ ) { indx = 0; for ( k = 0; k < n; k++ ) { if ( k != i ) { for ( j = indx + 1; 0 <= j; j-- ) { a[i+j*n] = - stencil[k] * a[i+j*n] / ( stencil[i] - stencil[k] ); if ( 0 < j ) { a[i+j*n] = a[i+j*n] + a[i+(j-1)*n] / ( stencil[i] - stencil[k] ); } } indx = indx + 1; } } } for ( j = 0; j < n; j++ ) { for ( i = 0; i < n; i++ ) { a[i+j*n] = a[i+j*n] / stencil[i]; } } return a; } /******************************************************************************/ double *differ_matrix ( int n, double stencil[] ) /******************************************************************************/ /* Purpose: DIFFER_MATRIX computes the stencil matrix from the stencil vector. Discussion: If N = 4, and STENCIL = ( -3, -2, -1, 1 ), then A will be -3 -2 -1 1 9 4 1 1 -27 -8 -1 1 81 16 1 1 This matrix is a generalized form of a Vandermonde matrix A2: 1 1 1 1 -3 -2 -1 1 9 4 1 1 -27 -8 -1 1 and if A * x = b, the A2 * x2 = b, where x2(i) = x(i) * stencil(i) Licensing: This code is distributed under the MIT license. Modified: 03 November 2013 Author: John Burkardt Parameters: Input, int N, the number of stencil points. Input, double STENCIL[N], the stencil vector. The entries in this vector must be distinct. No entry of STENCIL may be 0. Output, double DIFFER_MATRIX[N*N], the stencil matrix. */ { double *a; int i; int j; a = ( double * ) malloc ( n * n * sizeof ( double ) ); for ( j = 0; j < n; j++ ) { a[0+j*n] = stencil[j]; for ( i = 1; i < n; i++ ) { a[i+j*n] = a[i-1+j*n] * stencil[j]; } } return a; } /******************************************************************************/ double *differ_solve ( int n, double stencil[], int order ) /******************************************************************************/ /* Purpose: DIFFER_SOLVE solves for finite difference coefficients. Licensing: This code is distributed under the MIT license. Modified: 03 November 2013 Author: John Burkardt Parameters: Input, int N, the number of stencil points. Input, double STENCIL[N], the stencil vector. The entries in this vector must be distinct. No entry of STENCIL may be 0. Input, int ORDER, the order of the derivative to be approximated. 1 <= ORDER <= N. Output, double DIFFER_SOLVE[N], the coefficients to be used to multiply U(STENCIL(I))-U(0), so that the sum forms an approximation to the derivative of order ORDER, with error of order H^(N+1-ORDER). */ { double *a; double *b; double *c; int i; a = differ_matrix ( n, stencil ); b = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { b[i] = 0.0; } b[order-1] = 1.0; /* Solve A * C = B. */ c = r8mat_fs_new ( n, a, b ); free ( a ); free ( b ); return c; } /******************************************************************************/ void differ_stencil ( double x0, int o, int p, double x[], double c[] ) /******************************************************************************/ /* Purpose: DIFFER_STENCIL computes finite difference coefficients. Discussion: We determine coefficients C to approximate the derivative at X0 of order O and precision P, using finite differences, so that d^o f(x)/dx^o (x0) = sum ( 0 <= i <= o+p-1 ) c(i) f(x(i)) + O(h^(p)) where H is the maximum spacing between X0 and any X(I). Licensing: This code is distributed under the MIT license. Modified: 10 November 2013 Author: John Burkardt Parameters: Input, double X0, the point where the derivative is to be approximated. Input, int O, the order of the derivative to be approximated. 1 <= O. Input, int P, the order of the error, as a power of H. Input, double X[O+P], the evaluation points. Output, double C[O+P], the coefficients. */ { double *b; double *dx; int i; int info; int job; int n; double t; n = o + p; dx = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { dx[i] = x[i] - x0; } b = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { b[i] = 0.0; } b[o] = 1.0; job = 0; r8vm_sl ( n, dx, b, job, c, &info ); if ( info != 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "DIFFER_STENCIL - Fatal error!\n" ); fprintf ( stderr, " Vandermonde linear system is singular.\n" ); exit ( 1 ); } t = r8_factorial ( o ); for ( i = 0; i < n; i++ ) { c[i] = c[i] * t; } free ( b ); free ( dx ); return; } /******************************************************************************/ int i4_max ( int i1, int i2 ) /******************************************************************************/ /* Purpose: I4_MAX returns the maximum of two I4's. Licensing: This code is distributed under the MIT license. Modified: 29 August 2006 Author: John Burkardt Parameters: Input, int I1, I2, are two integers to be compared. Output, int I4_MAX, the larger of I1 and I2. */ { int value; if ( i2 < i1 ) { value = i1; } else { value = i2; } return value; } /******************************************************************************/ int i4_min ( int i1, int i2 ) /******************************************************************************/ /* Purpose: I4_MIN returns the smaller of two I4's. Licensing: This code is distributed under the MIT license. Modified: 29 August 2006 Author: John Burkardt Parameters: Input, int I1, I2, two integers to be compared. Output, int I4_MIN, the smaller of I1 and I2. */ { int value; if ( i1 < i2 ) { value = i1; } else { value = i2; } return value; } /******************************************************************************/ double inverse_error ( int n, double a[], double b[] ) /******************************************************************************/ /* Purpose: INVERSE_ERROR determines the error in an inverse matrix. Licensing: This code is distributed under the MIT license. Modified: 30 October 2013 Author: John Burkardt Parameters: Input, int N, the order of the matrix. Input, double A[N*N], the matrix. Input, double B[N*N], the inverse. Output, double ERROR_FROBENIUS, the Frobenius norm of (A*B-I) + (B*A-I). */ { double *c; int j; double value; c = r8mat_mm_new ( n, n, n, a, b ); for ( j = 0; j < n; j++ ) { c[j+j*n] = c[j+j*n] - 1.0; } value = r8mat_norm_fro ( n, n, c ); free ( c ); c = r8mat_mm_new ( n, n, n, b, a ); for ( j = 0; j < n; j++ ) { c[j+j*n] = c[j+j*n] - 1.0; } value = value + r8mat_norm_fro ( n, n, c ); free ( c ); return value; } /******************************************************************************/ double r8_factorial ( int n ) /******************************************************************************/ /* Purpose: R8_FACTORIAL computes the factorial of N. Discussion: factorial ( N ) = product ( 1 <= I <= N ) I Licensing: This code is distributed under the MIT license. Modified: 26 June 2008 Author: John Burkardt Parameters: Input, int N, the argument of the factorial function. If N is less than 1, the function value is returned as 1. Output, double R8_FACTORIAL, the factorial of N. */ { int i; double value; value = 1.0; for ( i = 1; i <= n; i++ ) { value = value * ( double ) ( i ); } return value; } /******************************************************************************/ double *r8mat_fs_new ( int n, double a[], double b[] ) /******************************************************************************/ /* Purpose: R8MAT_FS_NEW factors and solves a system with one right hand side. Discussion: This routine uses partial pivoting, but no pivot vector is required. This routine differs from R8MAT_FSS_NEW in two ways: * only one right hand side is allowed; * the input matrix A is not modified. An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. Licensing: This code is distributed under the MIT license. Modified: 21 January 2013 Author: John Burkardt Parameters: Input, int N, the order of the matrix. N must be positive. Input, double A[N*N], the coefficient matrix of the linear system. Input, double B[N], on input, the right hand side of the linear system. Output, double R8MAT_FS[N], the solution of the linear system. */ { double *a2; int i; int ipiv; int j; int jcol; double piv; double t; double *x; a2 = ( double * ) malloc ( n * n * sizeof ( double ) ); for ( j = 0; j < n; j++ ) { for ( i = 0; i < n; i++ ) { a2[i+j*n] = a[i+j*n]; } } x = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { x[i] = b[i]; } for ( jcol = 1; jcol <= n; jcol++ ) { /* Find the maximum element in column I. */ piv = fabs ( a2[jcol-1+(jcol-1)*n] ); ipiv = jcol; for ( i = jcol+1; i <= n; i++ ) { if ( piv < fabs ( a2[i-1+(jcol-1)*n] ) ) { piv = fabs ( a2[i-1+(jcol-1)*n] ); ipiv = i; } } if ( piv == 0.0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "R8MAT_FS_NEW - Fatal error!\n" ); fprintf ( stderr, " Zero pivot on step %d\n", jcol ); exit ( 1 ); } /* Switch rows JCOL and IPIV, and X. */ if ( jcol != ipiv ) { for ( j = 1; j <= n; j++ ) { t = a2[jcol-1+(j-1)*n]; a2[jcol-1+(j-1)*n] = a2[ipiv-1+(j-1)*n]; a2[ipiv-1+(j-1)*n] = t; } t = x[jcol-1]; x[jcol-1] = x[ipiv-1]; x[ipiv-1] = t; } /* Scale the pivot row. */ t = a2[jcol-1+(jcol-1)*n]; a2[jcol-1+(jcol-1)*n] = 1.0; for ( j = jcol+1; j <= n; j++ ) { a2[jcol-1+(j-1)*n] = a2[jcol-1+(j-1)*n] / t; } x[jcol-1] = x[jcol-1] / t; /* Use the pivot row to eliminate lower entries in that column. */ for ( i = jcol+1; i <= n; i++ ) { if ( a2[i-1+(jcol-1)*n] != 0.0 ) { t = - a2[i-1+(jcol-1)*n]; a2[i-1+(jcol-1)*n] = 0.0; for ( j = jcol+1; j <= n; j++ ) { a2[i-1+(j-1)*n] = a2[i-1+(j-1)*n] + t * a2[jcol-1+(j-1)*n]; } x[i-1] = x[i-1] + t * x[jcol-1]; } } } /* Back solve. */ for ( jcol = n; 2 <= jcol; jcol-- ) { for ( i = 1; i < jcol; i++ ) { x[i-1] = x[i-1] - a2[i-1+(jcol-1)*n] * x[jcol-1]; } } free ( a2 ); return x; } /******************************************************************************/ double *r8mat_mm_new ( int n1, int n2, int n3, double a[], double b[] ) /******************************************************************************/ /* Purpose: R8MAT_MM_NEW multiplies two matrices. Discussion: An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. For this routine, the result is returned as the function value. Licensing: This code is distributed under the MIT license. Modified: 08 April 2009 Author: John Burkardt Parameters: Input, int N1, N2, N3, the order of the matrices. Input, double A[N1*N2], double B[N2*N3], the matrices to multiply. Output, double R8MAT_MM_NEW[N1*N3], the product matrix C = A * B. */ { double *c; int i; int j; int k; c = ( double * ) malloc ( n1 * n3 * sizeof ( double ) ); for ( i = 0; i < n1; i++ ) { for ( j = 0; j < n3; j++ ) { c[i+j*n1] = 0.0; for ( k = 0; k < n2; k++ ) { c[i+j*n1] = c[i+j*n1] + a[i+k*n1] * b[k+j*n2]; } } } return c; } /******************************************************************************/ double *r8mat_mv_new ( int m, int n, double a[], double x[] ) /******************************************************************************/ /* Purpose: R8MAT_MV_NEW multiplies a matrix times a vector. Discussion: An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. For this routine, the result is returned as the function value. Licensing: This code is distributed under the MIT license. Modified: 11 April 2007 Author: John Burkardt Parameters: Input, int M, N, the number of rows and columns of the matrix. Input, double A[M,N], the M by N matrix. Input, double X[N], the vector to be multiplied by A. Output, double R8MAT_MV_NEW[M], the product A*X. */ { int i; int j; double *y; y = ( double * ) malloc ( m * sizeof ( double ) ); for ( i = 0; i < m; i++ ) { y[i] = 0.0; for ( j = 0; j < n; j++ ) { y[i] = y[i] + a[i+j*m] * x[j]; } } return y; } /******************************************************************************/ double r8mat_norm_fro ( int m, int n, double a[] ) /******************************************************************************/ /* Purpose: R8MAT_NORM_FRO returns the Frobenius norm of an R8MAT. Discussion: An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. The Frobenius norm is defined as R8MAT_NORM_FRO = sqrt ( sum ( 1 <= I <= M ) sum ( 1 <= j <= N ) A(I,J)^2 ) The matrix Frobenius norm is not derived from a vector norm, but is compatible with the vector L2 norm, so that: r8vec_norm_l2 ( A * x ) <= r8mat_norm_fro ( A ) * r8vec_norm_l2 ( x ). Licensing: This code is distributed under the MIT license. Modified: 26 July 2008 Author: John Burkardt Parameters: Input, int M, the number of rows in A. Input, int N, the number of columns in A. Input, double A[M*N], the matrix whose Frobenius norm is desired. Output, double R8MAT_NORM_FRO, the Frobenius norm of A. */ { int i; int j; double value; value = 0.0; for ( j = 0; j < n; j++ ) { for ( i = 0; i < m; i++ ) { value = value + pow ( a[i+j*m], 2 ); } } value = sqrt ( value ); return value; } /******************************************************************************/ void r8mat_print ( int m, int n, double a[], char *title ) /******************************************************************************/ /* Purpose: R8MAT_PRINT prints an R8MAT. Discussion: An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. Entry A(I,J) is stored as A[I+J*M] Licensing: This code is distributed under the MIT license. Modified: 28 May 2008 Author: John Burkardt Parameters: Input, int M, the number of rows in A. Input, int N, the number of columns in A. Input, double A[M*N], the M by N matrix. Input, char *TITLE, a title. */ { r8mat_print_some ( m, n, a, 1, 1, m, n, title ); return; } /******************************************************************************/ void r8mat_print_some ( int m, int n, double a[], int ilo, int jlo, int ihi, int jhi, char *title ) /******************************************************************************/ /* Purpose: R8MAT_PRINT_SOME prints some of an R8MAT. Discussion: An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. Licensing: This code is distributed under the MIT license. Modified: 26 June 2013 Author: John Burkardt Parameters: Input, int M, the number of rows of the matrix. M must be positive. Input, int N, the number of columns of the matrix. N must be positive. Input, double A[M*N], the matrix. Input, int ILO, JLO, IHI, JHI, designate the first row and column, and the last row and column to be printed. Input, char *TITLE, a title. */ { # define INCX 5 int i; int i2hi; int i2lo; int j; int j2hi; int j2lo; fprintf ( stdout, "\n" ); fprintf ( stdout, "%s\n", title ); if ( m <= 0 || n <= 0 ) { fprintf ( stdout, "\n" ); fprintf ( stdout, " (None)\n" ); return; } /* Print the columns of the matrix, in strips of 5. */ for ( j2lo = jlo; j2lo <= jhi; j2lo = j2lo + INCX ) { j2hi = j2lo + INCX - 1; if ( n < j2hi ) { j2hi = n; } if ( jhi < j2hi ) { j2hi = jhi; } fprintf ( stdout, "\n" ); /* For each column J in the current range... Write the header. */ fprintf ( stdout, " Col: "); for ( j = j2lo; j <= j2hi; j++ ) { fprintf ( stdout, " %7d ", j - 1 ); } fprintf ( stdout, "\n" ); fprintf ( stdout, " Row\n" ); fprintf ( stdout, "\n" ); /* Determine the range of the rows in this strip. */ if ( 1 < ilo ) { i2lo = ilo; } else { i2lo = 1; } if ( m < ihi ) { i2hi = m; } else { i2hi = ihi; } for ( i = i2lo; i <= i2hi; i++ ) { /* Print out (up to) 5 entries in row I, that lie in the current strip. */ fprintf ( stdout, "%5d:", i - 1 ); for ( j = j2lo; j <= j2hi; j++ ) { fprintf ( stdout, " %14g", a[i-1+(j-1)*m] ); } fprintf ( stdout, "\n" ); } } return; # undef INCX } /******************************************************************************/ double *r8mat_sub_new ( int m, int n, double a[], double b[] ) /******************************************************************************/ /* Purpose: R8MAT_SUB_NEW computes C = A - B. Discussion: An R8MAT is a doubly dimensioned array of R8 values, stored as a vector in column-major order. For this routine, the result is returned as the function value. Licensing: This code is distributed under the MIT license. Modified: 30 October 2013 Author: John Burkardt Parameters: Input, int M, N, the order of the matrices. Input, double A[M*N], double B[M*N], the matrices. Output, double R8MAT_SUB_NEW[M*N], the value of A-B. */ { double *c; int i; int j; c = ( double * ) malloc ( m * n * sizeof ( double ) ); for ( j = 0; j < n; j++ ) { for ( i = 0; i < n; i++ ) { c[i+j*m] = a[i+j*m] - b[i+j*m]; } } return c; } /******************************************************************************/ void r8vec_print ( int n, double a[], char *title ) /******************************************************************************/ /* Purpose: R8VEC_PRINT prints an R8VEC. Discussion: An R8VEC is a vector of R8's. Licensing: This code is distributed under the MIT license. Modified: 08 April 2009 Author: John Burkardt Parameters: Input, int N, the number of components of the vector. Input, double A[N], the vector to be printed. Input, char *TITLE, a title. */ { int i; fprintf ( stdout, "\n" ); fprintf ( stdout, "%s\n", title ); fprintf ( stdout, "\n" ); for ( i = 0; i < n; i++ ) { fprintf ( stdout, " %8d: %14g\n", i, a[i] ); } return; } /******************************************************************************/ double *r8vec_uniform_01_new ( int n, int *seed ) /******************************************************************************/ /* Purpose: R8VEC_UNIFORM_01_NEW returns a unit pseudorandom R8VEC. Discussion: This routine implements the recursion seed = 16807 * seed mod ( 2^31 - 1 ) unif = seed / ( 2^31 - 1 ) The integer arithmetic never requires more than 32 bits, including a sign bit. Licensing: This code is distributed under the MIT license. Modified: 19 August 2004 Author: John Burkardt Reference: Paul Bratley, Bennett Fox, Linus Schrage, A Guide to Simulation, Second Edition, Springer, 1987, ISBN: 0387964673, LC: QA76.9.C65.B73. Bennett Fox, Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators, ACM Transactions on Mathematical Software, Volume 12, Number 4, December 1986, pages 362-376. Pierre L'Ecuyer, Random Number Generation, in Handbook of Simulation, edited by Jerry Banks, Wiley, 1998, ISBN: 0471134031, LC: T57.62.H37. Peter Lewis, Allen Goodman, James Miller, A Pseudo-Random Number Generator for the System/360, IBM Systems Journal, Volume 8, Number 2, 1969, pages 136-143. Parameters: Input, int N, the number of entries in the vector. Input/output, int *SEED, a seed for the random number generator. Output, double R8VEC_UNIFORM_01_NEW[N], the vector of pseudorandom values. */ { int i; int i4_huge = 2147483647; int k; double *r; if ( *seed == 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "R8VEC_UNIFORM_01_NEW - Fatal error!\n" ); fprintf ( stderr, " Input value of SEED = 0.\n" ); exit ( 1 ); } r = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { k = *seed / 127773; *seed = 16807 * ( *seed - k * 127773 ) - k * 2836; if ( *seed < 0 ) { *seed = *seed + i4_huge; } r[i] = ( double ) ( *seed ) * 4.656612875E-10; } return r; } /******************************************************************************/ void r8vec2_print ( int n, double a1[], double a2[], char *title ) /******************************************************************************/ /* Purpose: R8VEC2_PRINT prints an R8VEC2. Discussion: An R8VEC2 is a dataset consisting of N pairs of real values, stored as two separate vectors A1 and A2. Licensing: This code is distributed under the MIT license. Modified: 26 March 2009 Author: John Burkardt Parameters: Input, int N, the number of components of the vector. Input, double A1[N], double A2[N], the vectors to be printed. Input, char *TITLE, a title. */ { int i; fprintf ( stdout, "\n" ); fprintf ( stdout, "%s\n", title ); fprintf ( stdout, "\n" ); for ( i = 0; i < n; i++ ) { fprintf ( stdout, " %4d: %14g %14g\n", i, a1[i], a2[i] ); } return; } /******************************************************************************/ void r8vm_sl ( int n, double a[], double b[], int job, double x[], int *info ) /******************************************************************************/ /* Purpose: R8VM_SL solves a R8VM system. Discussion: The R8VM storage format is used for an M by N Vandermonde matrix. An M by N Vandermonde matrix is defined by the values in its second row, which will be written here as X(1:N). The matrix has a first row of 1's, a second row equal to X(1:N), a third row whose entries are the squares of the X values, up to the M-th row whose entries are the (M-1)th powers of the X values. The matrix can be stored compactly by listing just the values X(1:N). Vandermonde systems are very close to singularity. The singularity gets worse as N increases, and as any pair of values defining the matrix get close. Even a system as small as N = 10 will involve the 9th power of the defining values. Licensing: This code is distributed under the MIT license. Modified: 27 January 2013 Author: Original FORTRAN77 version by Golub, VanLoan. C version by John Burkardt. Reference: Gene Golub, Charles Van Loan, Matrix Computations, Third Edition, Johns Hopkins, 1996. Parameters: Input, int N, the number of rows and columns of the matrix. Input, double A[N], the R8VM matrix. Input, double B[N], the right hand side. Input, int JOB, specifies the system to solve. 0, solve A * x = b. nonzero, solve A' * x = b. Output, double X[N], the solution of the linear system. Output, int *INFO. 0, no error. nonzero, at least two of the values in A are equal. */ { int i; int j; /* Check for explicit singularity. */ *info = 0; for ( j = 0; j < n; j++ ) { for ( i = j+1; i < n; i++ ) { if ( a[i] == a[j] ) { *info = 1; return; } } } for ( i = 0; i < n; i++ ) { x[i] = b[i]; } if ( job == 0 ) { for ( j = 1; j <= n-1; j++ ) { for ( i = n; j+1 <= i; i-- ) { x[i-1] = x[i-1] - a[j-1] * x[i-2]; } } for ( j = n-1; 1 <= j; j-- ) { for ( i = j+1; i <= n; i++ ) { x[i-1] = x[i-1] / ( a[i-1] - a[i-j-1] ); } for ( i = j; i <= n-1; i++ ) { x[i-1] = x[i-1] - x[i]; } } } else { for ( j = 1; j <= n-1; j++ ) { for ( i = n; j+1 <= i; i-- ) { x[i-1] = ( x[i-1] - x[i-2] ) / ( a[i-1] - a[i-j-1] ); } } for ( j = n-1; 1 <= j; j-- ) { for ( i = j; i <= n-1; i++ ) { x[i-1] = x[i-1] - x[i] * a[j-1]; } } } return; } /******************************************************************************/ double *r8vm_sl_new ( int n, double a[], double b[], int job, int *info ) /******************************************************************************/ /* Purpose: R8VM_SL_NEW solves a R8VM system. Discussion: The R8VM storage format is used for an M by N Vandermonde matrix. An M by N Vandermonde matrix is defined by the values in its second row, which will be written here as X(1:N). The matrix has a first row of 1's, a second row equal to X(1:N), a third row whose entries are the squares of the X values, up to the M-th row whose entries are the (M-1)th powers of the X values. The matrix can be stored compactly by listing just the values X(1:N). Vandermonde systems are very close to singularity. The singularity gets worse as N increases, and as any pair of values defining the matrix get close. Even a system as small as N = 10 will involve the 9th power of the defining values. Licensing: This code is distributed under the MIT license. Modified: 27 January 2013 Author: Original FORTRAN77 version by Golub, VanLoan. C version by John Burkardt. Reference: Gene Golub, Charles Van Loan, Matrix Computations, Third Edition, Johns Hopkins, 1996. Parameters: Input, int N, the number of rows and columns of the matrix. Input, double A[N], the R8VM matrix. Input, double B[N], the right hand side. Input, int JOB, specifies the system to solve. 0, solve A * x = b. nonzero, solve A' * x = b. Output, int *INFO. 0, no error. nonzero, at least two of the values in A are equal. Output, double R8VM_SL[N], the solution of the linear system. */ { int i; int j; double *x; /* Check for explicit singularity. */ *info = 0; for ( j = 0; j < n; j++ ) { for ( i = j+1; i < n; i++ ) { if ( a[i] == a[j] ) { *info = 1; return NULL; } } } x = ( double * ) malloc ( n * sizeof ( double ) ); for ( i = 0; i < n; i++ ) { x[i] = b[i]; } if ( job == 0 ) { for ( j = 1; j <= n-1; j++ ) { for ( i = n; j+1 <= i; i-- ) { x[i-1] = x[i-1] - a[j-1] * x[i-2]; } } for ( j = n-1; 1 <= j; j-- ) { for ( i = j+1; i <= n; i++ ) { x[i-1] = x[i-1] / ( a[i-1] - a[i-j-1] ); } for ( i = j; i <= n-1; i++ ) { x[i-1] = x[i-1] - x[i]; } } } else { for ( j = 1; j <= n-1; j++ ) { for ( i = n; j+1 <= i; i-- ) { x[i-1] = ( x[i-1] - x[i-2] ) / ( a[i-1] - a[i-j-1] ); } } for ( j = n-1; 1 <= j; j-- ) { for ( i = j; i <= n-1; i++ ) { x[i-1] = x[i-1] - x[i] * a[j-1]; } } } return x; } /******************************************************************************/ void timestamp ( ) /******************************************************************************/ /* Purpose: TIMESTAMP prints the current YMDHMS date as a time stamp. Example: 31 May 2001 09:45:54 AM Licensing: This code is distributed under the MIT license. Modified: 24 September 2003 Author: John Burkardt Parameters: None */ { # define TIME_SIZE 40 static char time_buffer[TIME_SIZE]; const struct tm *tm; time_t now; now = time ( NULL ); tm = localtime ( &now ); strftime ( time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm ); fprintf ( stdout, "%s\n", time_buffer ); return; # undef TIME_SIZE }