/* ** The library program module ** lib.cpp ** TID time_step(int num) ** calculates start and stop time and returns the difference. ** Input data: ** int number = 1 for start - zero return values ** = 2 for stop - return time from last start ** TID run - returns the time difference. void **matrix(int row, int col, int num_bytes) ** reserves dynamic memory for a two-dimensional matrix ** using the C++ command new . No initialization of the elements. ** Input data: ** int row - number of rows ** int col - number of columns ** int num_bytes- number of bytes for each ** element ** Returns a void **pointer to the reserved memory location. void free_matrix(void **matr) ** releases the memory reserved by the function matrix() ** for the two-dimensional matrix[][] ** Input data: ** void **matr - pointer to the matrix void rk4(double *y, double *dydx, int n, double x, double h, double *yout, void (*derivs)(double, double *, double *)) ** takes a set of variables y[1:n] for the function y(x) together with the ** reserves dynamic memory for a two-dimensional matrix ** using the C++ command new . No initialization of the elements. ** Input data: ** int row - number of rows ** int col - number of columns Æ* int num_bytes- number of bytes for each ** element ** Returns a void **pointer to the reserved memory location. void free_matrix(void **matr) ** releases the memory reserved by the function matrix() for t ** derivatives dydx[1:n] and uses the fourth-order Runge-Kutta method to ** advance the solution over an interval h and return incremented variables ** as yout[1:n], which not need to be a disstinct arra from y[1:n]. The ** users supply the routine derivs(x,y,dydx), which returns the derivatives ** dydx at x. void ludcmp(double **a, int n, int *indx, double *d) ** takes as input a two-dimensional matrix a[][] of dimension n and ** replaces it by the LU decomposition of a rowwise permutation of ** itself. The results is stored in a[][] in the form given by ** eq. (2.3.14) in "Numerical Recipe", sect. 2.3, page 45. The vector ** indx[] records the row permutation effected by the partial pivoting; ** d is output as +1 or -1 depending on whether the number of row ** interchanges was even or odd, respectively. This routine is used in ** combination with the function lubksb() to solve linear equations or ** invert a matrix. The function is slightly modified from the version ** in in Numerical recipe and uses memory allocation functions in the ** present module. void lubksb(double **a, int n, int *indx, double *b) ** solves the set of linear equations A X = B of dimension n. ** a[][] is input, not as the matrix A[][] but rather as ** its LU decomposition, determined by the function ludcmp(), ** indx[] is input as the permutation vector returned by ** ludcmp(). b[] is input as the right-hand side vector B, ** The solution X is returned in B. The input data a[][], ** n and indx[] are not modified. This routine take into ** account the possibility that b[] will begin with many ** zero elements, so it is efficient for use in matrix ** inversion. ** The function is slightly modified from the version in ** in Numerical recipe. void tqli(double d[], double e[], int n, double **z) ** determine eigenvalues and eigenvectors of a real symmetric ** tri-diagonal matrix, or a real, symmetric matrix previously ** reduced by function tred2[] to tri-diagonal form. On input, ** d[] contains the diagonal element and e[] the sub-diagonal ** of the tri-diagonal matrix. On output d[] contains the ** eigenvalues and e[] is destroyed. If eigenvectors are ** desired z[][] on input contains the identity matrix. If ** eigenvectors of a matrix reduced by tred2() are required, ** then z[][] on input is the matrix output from tred2(). ** On output, the k'th column returns the normalized eigenvector ** corresponding to d[k]. ** The function is modified from the version in Numerical recipe. void tred2(double **a, int n, double d[], double e[]) ** perform a Housholder reduction of a real symmetric matrix ** a[][]. On output a[][] is replaced by the orthogonal matrix ** effecting the transformation. d[] returns the diagonal elements ** of the tri-diagonal matrix, and e[] the off-diagonal elements, ** with e[0] = 0. ** The function is modified from the version in Numerical recipe. double pythag(double a, double b) ** The function is modified from the version in Numerical recipe. void gauleg(double x1, double x2, double x[], double w[], int n) ** takes the lower and upper limits of integration x1, x2, calculates ** and return the abcissas in x[0,...,n - 1] and the weights in w[0,...,n - 1] ** of length n of the Gauss--Legendre n--point quadrature formulae. void spline(double x[], double y[], int n, double yp1, double yp2, double y2[]) ** takes as input x[0,..,n - 1] and y[0,..,n - 1] containing a tabulation ** y_i = f(x_i) with x_0 < x_1 < .. < x_(n - 1) together with yp_1 and yp2 ** for first derivatives f(x) at x_0 and x_(n-1), respectively. Then the ** function returns y2[0,..,n-1] which contanin the second derivatives of ** f(x_i)at each point x_i. If yp1 and/or yp2 is larger than the constant ** INFINITY the function will put corresponding second derivatives to zero. void splint(double xa[], double ya[], double y2a[], int n, double x, double *y) ** takes xa[0,..,n - 1] and y[0,..,n - 1] which tabulates a function ** (with the xa[i]'s in order) and given ya[0,..,n - 1], which is the ** output from function spline() and with given value of x returns a ** cubic--spline interpolation value y. void polint(double xa[], double ya[], int n, double x, double *y, double *dy) ** takes as input xa[0,..,n-1] and ya[0,..,n-1] together with a given value ** of x and returns a value y and an error estimate dy. If P(x) is a polynomial ** of degree N - 1 such that P(xa_i) = ya_i, i = 0,..,n-1, then the returned ** value is y = P(x). double rtbis(double (*func)(double), double x1, double x2, double xacc) ** calculates a root between x1 and x2 of a function ** pointed to by (*func) using the method of bisection ** The root is returned with an accuracy of +- xacc. double rtsec(double (*func)(double), double x1, double x2, double xacc) ** calculates a root between x1 and x2 of a function ** pointed to by (*func) using the secant method. ** The root is returned with an accuracy of +- xacc. double rtnewt(void (*funcd)(double, double *, double *), double x1, double x2, double xacc) ** calculates a root between x1 and x2 of a function pointed to ** by (*funcd) using the Newton-Raphson method. The user-defined ** function funcd() returns both the function value and its first ** derivative at the point x, ** The root is returned with an accuracy of +- xacc. double zbrent(double (*func)(double), double x1, double x2, double xacc) ** calculates a root between x1 and x2 of a function ** pointed to by (*funcd) using the Brent's method. ** The root is returned with an accuracy of +- xacc. double ran0(long *idum) ** is an "Minimal" random number generator of Park and Miller ** (see Numerical recipe page 279). Set or reset the input value ** idum to any integer value (except the unlikely value MASK) ** to initialize the sequence; idum must not be altered between ** calls for sucessive deviates in a sequence. ** The function returns a uniform deviate between 0.0 and 1.0. double ran1(long *idum) ** is an "Minimal" random number generator of Park and Miller ** (see Numerical recipe page 280) with Bays-Durham shuffle and ** added safeguards. Call with idum a negative integer to initialize; ** thereafter, do not alter idum between sucessive deviates in a ** sequence. RNMX should approximate the largest floating point value ** that is less than 1. ** The function returns a uniform deviate between 0.0 and 1.0 ** (exclusive of end-point values). double ran2(long *idum) ** is a long periode (> 2 x 10^18) random number generator of ** L'Ecuyer and Bays-Durham shuffle and added safeguards. ** Call with idum a negative integer to initialize; thereafter, ** do not alter idum between sucessive deviates in a ** sequence. RNMX should approximate the largest floating point value ** that is less than 1. ** The function returns a uniform deviate between 0.0 and 1.0 ** (exclusive of end-point values). double ran3(long *idum) ** returns a uniform random number deviate between 0.0 and 1.0. Set ** the idum to any negative value to initialize or reinitialize the ** sequence. Any large MBIG, and any small (but still large) MSEED ** can be substituted for the present values. */ #include "lib.h" /* ** The function ** TID time_step(..) ** calculates start and stop time and returns the difference. ** Input data: ** int number = 1 for start - zero return values ** = 2 for stop - return time from last start ** TID run - returns the time difference. */ TID time_step(int num) { unsigned long long int num_sec; static long zsec = 0, zusec = 0; double retval; TID ex_time; struct timeval tp; if(num == 1) { // initialization of time zsec = tp.tv_sec; zusec = tp.tv_usec; ex_time.sec = 0; ex_time.min = 0; ex_time.hour = 0; } else if(num == 2) { retval = (double)(tp.tv_sec - zsec) + (tp.tv_usec - zusec) * 0.000001; num_sec = (unsigned long long int)retval; ex_time.sec = num_sec % 60; ex_time.min = num_sec / 60; ex_time.hour = ex_time.min/ 60; ex_time.min = ex_time.min % 60; } else { printf("\n\nError in function time_step(): "); printf("\nInput data num = %d is wrong !!\n\n", num); exit(1); } return ex_time; } // End: function time_step() /* * The function * void **matrix() * reserves dynamic memory for a two-dimensional matrix * using the C++ command new . No initialization of the elements. * Input data: * int row - number of rows * int col - number of columns * int num_bytes- number of bytes for each * element * Returns a void **pointer to the reserved memory location. */ void **matrix(int row, int col, int num_bytes) { int i, num; char **pointer, *ptr; pointer = new(nothrow) char* [row]; if(!pointer) { cout << "Exception handling: Memory allocation failed"; cout << " for "<< row << "row addresses !" << endl; return NULL; } i = (row * col * num_bytes)/sizeof(char); pointer[0] = new(nothrow) char [i]; if(!pointer[0]) { cout << "Exception handling: Memory allocation failed"; cout << " for address to " << i << " characters !" << endl; return NULL; } ptr = pointer[0]; num = col * num_bytes; for(i = 0; i < row; i++, ptr += num ) { pointer[i] = ptr; } return (void **)pointer; } // end: function void **matrix() /* * The function * void free_matrix() * releases the memory reserved by the function matrix() *for the two-dimensional matrix[][] * Input data: * void far **matr - pointer to the matrix */ void free_matrix(void **matr) { delete [] (char *) matr[0]; delete [] matr; } // End: function free_matrix() /* ** The function ** rk4() ** takes a set of variables y[1:n] for the function y(x) together with the ** derivatives dydx[1:n] and uses the fourth-order Runge-Kutta method to ** advance the solution over an interval h and return incremented variables ** as yout[1:n], which not need to be a disstinct arra from y[1:n]. The ** users supply the routine derivs(x,y,dydx), which returns the derivatives ** dydx at x. */ void rk4(double *y, double *dydx, int n, double x, double h, double *yout, void (*derivs)(double, double *, double *)) { int i; double xh,hh,h6,*dym,*dyt,*yt; // local memory allocation dym = new(nothrow) double [n]; if(!dym) { printf("\n\nError in function rk4():"); printf("\nNot enough memory for dym[%d]\n",n); exit(1); } dyt = new(nothrow) double [n]; if(!dyt) { printf("\n\nError in function rk4():"); printf("\nNot enough memory for dyt[%d]\n",n); exit(1); } yt = new(nothrow) double [n]; if(!yt) { printf("\n\nError in function rk4():"); printf("\nNot enough memory for yt[%d]\n",n); exit(1); } hh = h * 0.5; h6 = h/6.0; xh = x+hh; for(i = 0; i < n; i++) { // first step yt[i] = y[i] + hh * dydx[i]; } (*derivs)(xh, yt, dyt); // second step for(i = 0; i < n; i++) { yt[i] = y[i] + hh * dyt[i]; } (*derivs)(xh, yt, dym); // third step for(i = 0; i < n; i++) { yt[i] = y[i] + h * dym[i]; dym[i] += dyt[i]; } (*derivs)(x+h,yt,dyt); // fourth step // acummulate increments with proper weights for(i = 0; i< n; i++) { yout[i] = y[i] + h6 *(dydx[i] + dyt[i] + 2.0 * dym[i]); } delete [] yt; // release local memory delete [] dyt; delete [] dym; } // End: function rk4() /* ** The function ** ludcmp() ** takes as input a two-dimensional matrix a[][] of dimension n and ** replaces it by the LU decomposition of a rowwise permutation of ** itself. The results is stored in a[][] in the form given by ** eq. (2.3.14) in "Numerical Recipe", sect. 2.3, page 45. The vector ** indx[] records the row permutation effected by the partial pivoting; ** d is output as +1 or -1 depending on whether the number of row ** interchanges was even or odd, respectively. This routine is used in ** combination with the function lubksb() to solve linear equations or ** invert a matrix. The function is slightly modified from the version ** in in Numerical recipe and uses memory allocation functions in the ** present module. */ void ludcmp(double **a, int n, int *indx, double *d) { int i, imax, j, k; double big, dum, sum, temp, *vv; vv = new(nothrow) double [n]; if(!vv) { printf("\n\nError in function ludcm():"); printf("\nNot enough memory for vv[%d]\n",n); exit(1); } *d = 1.0; // no row interchange yet for(i = 0; i < n; i++) { // loop over rows to get scaling information big = ZERO; for(j = 0; j < n; j++) { if((temp = fabs(a[i][j])) > big) big = temp; } if(big == ZERO) { printf("\n\nSingular matrix in routine ludcmp()\n"); exit(1); } vv[i] = 1.0/big; // save scaling */ } // end i-loop */ for(j = 0; j < n; j++) { // loop over columns of Crout's method for(i = 0; i< j; i++) { // not i = j sum = a[i][j]; for(k = 0; k < i; k++) sum -= a[i][k]*a[k][j]; a[i][j] = sum; } big = ZERO; // initialization for search for largest pivot element for(i = j; i< n; i++) { sum = a[i][j]; for(k = 0; k < j; k++) sum -= a[i][k]*a[k][j]; a[i][j] = sum; if((dum = vv[i]*fabs(sum)) >= big) { big = dum; imax = i; } } // end i-loop if(j != imax) { // do we need to interchange rows ? for(k = 0;k< n; k++) { // yes dum = a[imax][k]; a[imax][k] = a[j][k]; a[j][k] = dum; } (*d) *= -1; // and change the parit of d vv[imax] = vv[j]; // also interchange scaling factor } indx[j] = imax; if(fabs(a[j][j]) < ZERO) a[j][j] = ZERO; /* ** if the pivot element is zero the matrix is singular ** (at least to the precision of the algorithm). For ** some application of singular matrices, it is desirable ** to substitute ZERO for zero, */ if(j < (n - 1)) { // divide by pivot element dum = 1.0/a[j][j]; for(i=j+1;i < n; i++) a[i][j] *= dum; } } // end j-loop over columns delete [] vv; // release local memory } // End: function ludcmp() /* ** The function ** lubksb() ** solves the set of linear equations A X = B of dimension n. ** a[][] is input, not as the matrix A[][] but rather as ** its LU decomposition, determined by the function ludcmp(), ** indx[] is input as the permutation vector returned by ** ludcmp(). b[] is input as the right-hand side vector B, ** The solution X is returned in B. The input data a[][], ** n and indx[] are not modified. This routine take into ** account the possibility that b[] will begin with many ** zero elements, so it is efficient for use in matrix ** inversion. ** The function is slightly modified from the version in ** in Numerical recipe. */ void lubksb(double **a, int n, int *indx, double *b) { int i, ii = -1, ip, j; double sum; for(i = 0; i< n; i++) { ip = indx[i]; sum = b[ip]; b[ip] = b[i]; if(ii > -1) for(j = ii; j < i; j++) sum -= a[i][j] * b[j]; else if(sum) ii = i; b[i] = sum; } for(i = n - 1; i >= 0; i--) { sum = b[i]; for(j = i+1; j < n; j++) sum -= a[i][j] * b[j]; b[i] = sum/a[i][i]; } } // End: function lubksb() /* ** The function ** tqli() ** determine eigenvalues and eigenvectors of a real symmetric ** tri-diagonal matrix, or a real, symmetric matrix previously ** reduced by function tred2[] to tri-diagonal form. On input, ** d[] contains the diagonal element and e[] the sub-diagonal ** of the tri-diagonal matrix. On output d[] contains the ** eigenvalues and e[] is destroyed. If eigenvectors are ** desired z[][] on input contains the identity matrix. If ** eigenvectors of a matrix reduced by tred2() are required, ** then z[][] on input is the matrix output from tred2(). ** On output, the k'th column returns the normalized eigenvector ** corresponding to d[k]. ** The function is modified from the version in Numerical recipe. */ #define SIGN(a,b) ((b)<0 ? -fabs(a) : fabs(a)) void tqli(double *d, double *e, int n, double **z) { int iter,i,k,l,m; double b,c,dd,f,g,p,r,s; for (l=0;l=l;i--) { f=s*e[i];b=c*e[i]; if (fabs(f) >= fabs(g)) { c=g/f;r=sqrt((c*c)+1.0); e[i+1]=f*r; c *= (s=1.0/r); } else { s=f/g;r=sqrt((s*s)+1.0); e[i+1]=g*r; s *= (c=1.0/r); } g=d[i+1]-p; r=(d[i]-g)*s+2.0*c*b; p=s*r; d[i+1]=g+p; g=c*r-b; for (k=0;k= l; i--) { f = s * e[i]; b = c*e[i]; e[i+1] = (r=pythag(f,g)); if(r == 0.0) { d[i+1] -= p; e[m] = 0.0; break; } s = f/r; c = g/r; g = d[i+1] - p; r = (d[i] - g) * s + 2.0 * c * b; d[i+1] = g + (p = s * r); g = c * r - b; for(k = 0; k < n; k++) { f = z[k][i+1]; z[k][i+1] = s * z[k][i] + c * f; z[k][i] = c * z[k][i] - s * f; } } if(r == 0.0 && i >= l) continue; d[l] -= p; e[l] = g; e[m] = 0.0; } } while(m != l); } } */ /* ** The function ** tred2() ** perform a Housholder reduction of a real symmetric matrix ** a[][]. On output a[][] is replaced by the orthogonal matrix ** effecting the transformation. d[] returns the diagonal elements ** of the tri-diagonal matrix, and e[] the off-diagonal elements, ** with e[0] = 0. ** The function is modified from the version in Numerical recipe. */ void tred2(double **a, int n, double *d, double *e) { int i,j,k,l; double f,g,h,hh,scale; for (i=n-1;i>0;i--) { l=i-1;h=scale=0.0; if (l>0) { for (k=0;k<=l;k++) scale+=fabs(a[i][k]); if (scale==0.0) {e[i]=a[i][l];continue;}// .....skip transformation // .............................. use scaled a's for transformation for (k=0;k<=l;k++) { a[i][k]/=scale;h+=a[i][k]*a[i][k];} f=a[i][l]; g=sqrt(h); if (f>0.0) g=-g; e[i]=scale*g; h-=f*g; a[i][l]=f-g; f=0.0; for (j=0;j<=l;j++) { a[j][i]=a[i][j]/h;g=0.0; for (k=0;k<=j;k++) g+=a[j][k]*a[i][k]; for (k=j+1;k<=l;k++) g+=a[k][j]*a[i][k]; e[j]=g/h; f += e[j]*a[i][j]; } hh=f/(h+h); for (j=0;j<=l;j++) { f=a[i][j];e[j]=g=e[j]-hh*f; for (k=0;k<=j;k++) a[j][k]-=(f*e[k]+g*a[i][k]); } } else e[i]=a[i][l]; d[i]=h; } // ............................................................ eigenvectors d[0]=0.0;e[0]=0.0; for (i=0;i 0; i--) { l = i-1; h = scale= 0.0; if(l > 0) { for(k = 0; k <= l; k++) scale += fabs(a[i][k]); if(scale == 0.0) // skip transformation e[i] = a[i][l]; else { for(k = 0; k <= l; k++) { a[i][k] /= scale; // used scaled a's for transformation h += a[i][k]*a[i][k]; } f = a[i][l]; g = (f >= 0.0 ? -sqrt(h) : sqrt(h)); e[i] = scale*g; h -= f * g; a[i][l] = f - g; f = 0.0; for(j = 0;j <= l;j++) { a[j][i] = a[i][j]/h; // can be omitted if eigenvector not wanted g = 0.0; for(k = 0; k <= j; k++) { g += a[j][k]*a[i][k]; } for(k = j+1; k <= l; k++) g += a[k][j]*a[i][k]; e[j]=g/h; f += e[j]*a[i][j]; } hh=f/(h+h); for(j = 0; j <= l;j++) { f = a[i][j]; e[j]=g=e[j]-hh*f; for(k = 0; k <= j; k++) a[j][k] -= (f*e[k]+g*a[i][k]); } } // end k-loop } // end if-loop for l > 1 else { e[i]=a[i][l]; } d[i]=h; } // end i-loop d[0] = 0.0; e[0] = 0.0; for(i = 0; i < n; i++) { l = i-1; if(d[i]) { for(j = 0; j <= l; j++) { g= 0.0; for(k = 0; k <= l; k++) { g += a[i][k] * a[k][j]; } for (k = 0; k <= l; k++) { a[k][j] -= g * a[k][i]; } } } d[i] = a[i][i]; a[i][i] = 1.0; for(j = 0; j <= l; j++) { a[j][i]=a[i][j] = 0.0; } } } // End: function tred2(), (C) Copr. 1986-92 Numerical Recipes Software ) */ double pythag(double a, double b) { double absa,absb; absa=fabs(a); absb=fabs(b); if (absa > absb) return absa*sqrt(1.0+SQR(absb/absa)); else return (absb == 0.0 ? 0.0 : absb*sqrt(1.0+SQR(absa/absb))); } // End: function pythag(), (C) Copr. 1986-92 Numerical Recipes Software )%. /* ** The function ** gauleg() ** takes the lower and upper limits of integration x1, x2, calculates ** and return the abcissas in x[0,...,n - 1] and the weights in w[0,...,n - 1] ** of length n of the Gauss--Legendre n--point quadrature formulae. */ void gauleg(double x1, double x2, double x[], double w[], int n) { int m,j,i; double z1,z,xm,xl,pp,p3,p2,p1; double const pi = 3.14159265359; double *x_low, *x_high, *w_low, *w_high; m = (n + 1)/2; // roots are symmetric in the interval xm = 0.5 * (x2 + x1); xl = 0.5 * (x2 - x1); x_low = x; // pointer initialization x_high = x + n - 1; w_low = w; w_high = w + n - 1; for(i = 1; i <= m; i++) { // loops over desired roots z = cos(pi * (i - 0.25)/(n + 0.5)); /* ** Starting with the above approximation to the ith root ** we enter the mani loop of refinement bt Newtons method. */ do { p1 =1.0; p2 =0.0; /* ** loop up recurrence relation to get the ** Legendre polynomial evaluated at x */ for(j = 1; j <= n; j++) { p3 = p2; p2 = p1; p1 = ((2.0 * j - 1.0) * z * p2 - (j - 1.0) * p3)/j; } /* ** p1 is now the desired Legrendre polynomial. Next compute ** ppp its derivative by standard relation involving also p2, ** polynomial of one lower order. */ pp = n * (z * p1 - p2)/(z * z - 1.0); z1 = z; z = z1 - p1/pp; // Newton's method } while(fabs(z - z1) > ZERO); /* ** Scale the root to the desired interval and put in its symmetric ** counterpart. Compute the weight and its symmetric counterpart */ *(x_low++) = xm - xl * z; *(x_high--) = xm + xl * z; *w_low = 2.0 * xl/((1.0 - z * z) * pp * pp); *(w_high--) = *(w_low++); } } // End_ function gauleg() /* ** The function ** spline() ** takes as input x[0,..,n - 1] and y[0,..,n - 1] containing a tabulation ** y_i = f(x_i) with x_0 < x_1 < .. < x_(n - 1) together with yp_1 and yp2 ** for first derivatives f(x) at x_0 and x_(n-1), respectively. Then the ** function returns y2[0,..,n-1] which contanin the second derivatives of ** f(x_i)at each point x_i. If yp1 and/or yp2 is larger than the constant ** INFINITY the function will put corresponding second derivatives to zero. */ void spline(double x[], double y[], int n, double yp1, double yp2, double y2[]) { int i,k; double p,qn,sig,un,*u; u = new(nothrow) double [n]; if(!u) { printf("\n\nError in function spline():"); printf("\nNot enough memory for u[%d]\n",n); exit(1); } if(yp1 > INFINITY) y2[0] = u[0] = 0.0; else { y2[0] = -0.5; u[0] = (3.0/(x[1] - x[0])) * ((y[1] - y[0])/(x[1] - x[0]) - yp1); } for(i = 1; i < (n - 1); i++) { sig = (x[i] - x[i - 1])/(x[i + 1] - x[i - 1]); p = sig * y2[i - 1] + 2.0; y2[i] = (sig - 1.0)/p; u[i] = (y[i + 1] - y[i])/(x[i + 1] - x[i]) - (y[i] - y[i - 1])/(x[i] - x[i - 1]); u[i] = (6.0 * u[i]/(x[i + 1] - x[i - 1]) - sig*u[i - 1])/p; } if(yp2 > INFINITY) qn = un = ZERO; else { qn = 0.5; un = (3.0/(x[n - 1] - x[n - 2])) * (yp2 - (y[n - 1] - y[n - 2])/(x[n - 1] - x[n - 2])); } y2[n - 1] = (un - qn * u[n - 2])/(qn * y2[n - 2] + 1.0); for(k = n - 2; k >= 0; k--) { y2[k] = y2[k]*y2[k+1]+u[k]; } delete [] u; ; } // End: function spline() /* ** The function ** splint() ** takes xa[0,..,n - 1] and y[0,..,n - 1] which tabulates a function ** (with the xa[i]'s in order) and given ya[0,..,n - 1], which is the ** output from function spline() and with given value of x returns a ** cubic--spline interpolation value y. */ void splint(double xa[], double ya[], double y2a[], int n, double x, double *y) { int klo,khi,k; double h,b,a; klo = 0; khi = n - 1; while((khi - klo) > 1) { // binary search k = (khi + klo) >> 1; if(xa[k] > x) khi = k; else klo = k; } h = xa[khi] - xa[klo]; if(fabs(h) < ZERO) { printf("\n\n Error in function splint(): "); printf("\n The difference h = %4.1E -- too small\n",h); exit(1); } a = (xa[khi] - x)/h; b = (x - xa[klo])/h; *y = a * ya[klo] + b * ya[khi] + ((a * a * a - a) * y2a[klo] + (b * b * b - b) * y2a[khi]) * (h * h)/6.0; } // End: function splint() /* ** The function ** polint() ** takes as input xa[0,..,n-1] and ya[0,..,n-1] together with a given value ** of x and returns a value y and an error estimate dy. If P(x) is a polynomial ** of degree N - 1 such that P(xa_i) = ya_i, i = 0,..,n-1, then the returned ** value is y = P(x). */ void polint(double xa[], double ya[], int n, double x, double *y, double *dy) { int i, m, ns = 1; double den,dif,dift,ho,hp,w; double *c,*d; dif = fabs(x - xa[0]); c = new(nothrow) double [n]; if(!c) { printf("\n\nError in function polint():"); printf("\nNot enough memory for c[%d]\n",n); exit(1); } d = new(nothrow) double [n]; if(!d) { printf("\n\nError in function polint():"); printf("\nNot enough memory for d[%d]\n",n); exit(1); } for(i = 0; i < n; i++) { if((dift = fabs(x - xa[i])) < dif) { ns = i; dif = dift; } c[i] = ya[i]; d[i] = ya[i]; } *y = ya[ns--]; for(m = 0; m < (n - 1); m++) { for(i = 0; i < n - m; i++) { ho = xa[i] - x; hp = xa[i + m] - x; w = c[i + 1] - d[i]; if((den = ho - hp) < ZERO) { printf("\n\n Error in function polint(): "); printf("\nden = ho - hp = %4.1E -- too small\n",den); exit(1); } den = w/den; d[i] = hp * den; c[i] = ho * den; } *y += (*dy = (2 * ns < (n - m) ? c[ns + 1] : d[ns--])); } delete [] d; delete [] c; } // End: function polint() /* ** The function ** rtbis() ** calculates a root between x1 and x2 of a function ** pointed to by (*func) using the method of bisection ** The root is returned with an accuracy of +- xacc. */ #define MAXIT 40 // max iterations double rtbis(double (*func)(double), double x1, double x2, double xacc) { int j; double dx, f, fmid, xmid, rtb; f = (*func)(x1); fmid = (*func)(x2); if(f*fmid >= 0.0) { printf("\n\nError in function rtbis():"); printf("\nroot in function must be within"); printf("x1 = %f and x2 = %f\n", x1, x2); exit(1); } rtb = f < 0.0 ? (dx = x2 - x1, x1) : (dx = x1 - x2, x2); for(j = 0; j < MAXIT; j++) { fmid = (*func)(xmid = rtb + (dx *= 0.5)); if (fmid <= 0.0) rtb=xmid; if(fabs(dx) < xacc || fmid == 0.0) return rtb; } printf("\n\nError in function rtbis():"); // should never reach this point printf("\nToo many bisections!!!\n"); exit(1); } #undef MAXIT // End: function rtbis() /* ** The function ** rtsec() ** calculates a root between x1 and x2 of a function ** pointed to by (*func) using the secant method. ** The root is returned with an accuracy of +- xacc. */ #define MAXIT 30 // max iterations double rtsec(double (*func)(double), double x1, double x2, double xacc) { int j; double fl, f, dx, swap, xl, rts; fl = (*func)(x1); f = (*func)(x2); if(fabs(fl) < fabs(f)) { rts = x1; xl = x2; swap = fl; fl = f; f = swap; } else { xl = x1; rts = x2; } for(j = 0; j < MAXIT; j++) { dx = (xl - rts) * f/(f - fl); xl = rts; fl = f; rts += dx; f = (*func)(rts); if(fabs(dx) < xacc || f == 0.0) return rts; } printf("\n\nError in function rtsec():"); // should never reach this point printf("\nToo many iterations!!!\n"); exit(1); } #undef MAXIT // End: function rtsec() /* ** The function ** rtnewt() ** calculates a root between x1 and x2 of a function pointed to ** by (*funcd) using the Newton-Raphson method. The user-defined ** function funcd() returns both the function value and its first ** derivative at the point x, ** The root is returned with an accuracy of +- xacc. */ #define MAXIT 20 // max iterations double rtnewt(void (*funcd)(double, double *, double *), double x1, double x2, double xacc) { int j; double df, dx, f, rtn; rtn = 0.5 * (x1 + x2); // initial guess for(j = 0; j < MAXIT; j++) { (*funcd)(rtn, &f, &df); dx = f/df; rtn -= dx; if((x1 - rtn) * (rtn - x2) < 0.0) { printf("\n\nError in function rtnewt():"); printf("\nJump out of interval bracket\n"); exit(1); } if (fabs(dx) < xacc) return rtn; } printf("\n\nError in function rtnewt():"); // should never reach this point printf("\nToo many iterations!!!\n"); exit(1); } #undef MAXIT // End: function rtnewt() /* ** The function ** zbrent() ** calculates a root between x1 and x2 of a function ** pointed to by (*funcd) using the Brent's method. ** The root is returned with an accuracy of +- xacc. */ #define MAXIT 20 // max iterations #define EPS 3.0E-8 double zbrent(double (*func)(double), double x1, double x2, double xacc) { int iter; double a = x1, b = x2, c = x2, d, e, min1, min2; double fa = (*func)(a), fb= (*func)(b), fc, p, q, r, s, xacc1, xm; if((fa > 0.0 && fb > 0.0) || (fa < 0.0 && fb < 0.0)) { printf("\n\nError in function zbrent();"); printf("\nRoot must be bracketed in zbrent()\n"); exit(1); } fc = fb; for(iter = 1; iter <= MAXIT; iter++) { if((fb > 0.0 && fc > 0.0) || (fb < 0.0 && fc < 0.0)) { c = a; fc = fa; e = d = b - a; } if(fabs(fc) < fabs(fb)) { a = b; b = c; c = a; fa = fb; fb = fc; fc = fa; } xacc1 = 2.0 * EPS* fabs(b) + 0.5 * xacc; xm = 0.5 * (c - b); if(fabs(xm) <= xacc1 || fb == 0.0) return b; if (fabs(e) >= xacc1 && fabs(fa) > fabs(fb)) { s = fb / fa; if(a == c) { p = 2.0 * xm * s; q = 1.0 - s; } else { q = fa / fc; r = fb / fc; p = s * (2.0 * xm * q * (q - r) - (b - a) * (r - 1.0)); q = (q - 1.0) * (r - 1.0) *(s - 1.0); } if(p > 0.0) q = -q; p = fabs(p); min1 = 3.0 * xm * q - fabs(xacc1 * q); min2 = fabs(e*q); if (2.0*p < (min1 < min2 ? min1 : min2)) { e = d; d = p / q; } else { d = xm; e = d; } } else { d = xm; e = d; } a = b; fa = fb; if(fabs(d) > xacc1) b += d; else b += SIGN(xacc1,xm); fb=(*func)(b); } printf("\n\nError in function zbrent():"); // should never reach this point printf("\nToo many iterations!!!\n"); exit(1); } #undef MAXIT #undef EPS // End: function zbrent() /* ** The function ** ran0() ** is an "Minimal" random number generator of Park and Miller ** (see Numerical recipe page 279). Set or reset the input value ** idum to any integer value (except the unlikely value MASK) ** to initialize the sequence; idum must not be altered between ** calls for sucessive deviates in a sequence. ** The function returns a uniform deviate between 0.0 and 1.0. */ #define IA 16807 #define IM 2147483647 #define AM (1.0/IM) #define IQ 127773 #define IR 2836 #define MASK 123459876 double ran0(long *idum) { long k; double ans; *idum ^= MASK; k = (*idum)/IQ; *idum = IA*(*idum - k*IQ) - IR*k; if(*idum < 0) *idum += IM; ans=AM*(*idum); *idum ^= MASK; return ans; } #undef IA #undef IM #undef AM #undef IQ #undef IR #undef MASK // End: function ran0() /* ** The function ** ran1() ** is an "Minimal" random number generator of Park and Miller ** (see Numerical recipe page 280) with Bays-Durham shuffle and ** added safeguards. Call with idum a negative integer to initialize; ** thereafter, do not alter idum between sucessive deviates in a ** sequence. RNMX should approximate the largest floating point value ** that is less than 1. ** The function returns a uniform deviate between 0.0 and 1.0 ** (exclusive of end-point values). */ #define IA 16807 #define IM 2147483647 #define AM (1.0/IM) #define IQ 127773 #define IR 2836 #define NTAB 32 #define NDIV (1+(IM-1)/NTAB) #define EPS 1.2e-7 #define RNMX (1.0-EPS) double ran1(long *idum) { int j; long k; static long iy=0; static long iv[NTAB]; double temp; if (*idum <= 0 || !iy) { if (-(*idum) < 1) *idum=1; else *idum = -(*idum); for(j = NTAB + 7; j >= 0; j--) { k = (*idum)/IQ; *idum = IA*(*idum - k*IQ) - IR*k; if(*idum < 0) *idum += IM; if(j < NTAB) iv[j] = *idum; } iy = iv[0]; } k = (*idum)/IQ; *idum = IA*(*idum - k*IQ) - IR*k; if(*idum < 0) *idum += IM; j = iy/NDIV; iy = iv[j]; iv[j] = *idum; if((temp=AM*iy) > RNMX) return RNMX; else return temp; } #undef IA #undef IM #undef AM #undef IQ #undef IR #undef NTAB #undef NDIV #undef EPS #undef RNMX // End: function ran1() /* ** The function ** ran2() ** is a long periode (> 2 x 10^18) random number generator of ** L'Ecuyer and Bays-Durham shuffle and added safeguards. ** Call with idum a negative integer to initialize; thereafter, ** do not alter idum between sucessive deviates in a ** sequence. RNMX should approximate the largest floating point value ** that is less than 1. ** The function returns a uniform deviate between 0.0 and 1.0 ** (exclusive of end-point values). */ #define IM1 2147483563 #define IM2 2147483399 #define AM (1.0/IM1) #define IMM1 (IM1-1) #define IA1 40014 #define IA2 40692 #define IQ1 53668 #define IQ2 52774 #define IR1 12211 #define IR2 3791 #define NTAB 32 #define NDIV (1+IMM1/NTAB) #define EPS 1.2e-7 #define RNMX (1.0-EPS) double ran2(long *idum) { int j; long k; static long idum2 = 123456789; static long iy=0; static long iv[NTAB]; double temp; if(*idum <= 0) { if(-(*idum) < 1) *idum = 1; else *idum = -(*idum); idum2 = (*idum); for(j = NTAB + 7; j >= 0; j--) { k = (*idum)/IQ1; *idum = IA1*(*idum - k*IQ1) - k*IR1; if(*idum < 0) *idum += IM1; if(j < NTAB) iv[j] = *idum; } iy=iv[0]; } k = (*idum)/IQ1; *idum = IA1*(*idum - k*IQ1) - k*IR1; if(*idum < 0) *idum += IM1; k = idum2/IQ2; idum2 = IA2*(idum2 - k*IQ2) - k*IR2; if(idum2 < 0) idum2 += IM2; j = iy/NDIV; iy = iv[j] - idum2; iv[j] = *idum; if(iy < 1) iy += IMM1; if((temp = AM*iy) > RNMX) return RNMX; else return temp; } #undef IM1 #undef IM2 #undef AM #undef IMM1 #undef IA1 #undef IA2 #undef IQ1 #undef IQ2 #undef IR1 #undef IR2 #undef NTAB #undef NDIV #undef EPS #undef RNMX // End: function ran2() /* ** The function ** ran3() ** returns a uniform random number deviate between 0.0 and 1.0. Set ** the idum to any negative value to initialize or reinitialize the ** sequence. Any large MBIG, and any small (but still large) MSEED ** can be substituted for the present values. */ #define MBIG 1000000000 #define MSEED 161803398 #define MZ 0 #define FAC (1.0/MBIG) double ran3(long *idum) { static int inext, inextp; static long ma[56]; // value 56 is special, do not modify static int iff = 0; long mj, mk; int i, ii, k; if(*idum < 0 || iff == 0) { // initialization iff = 1; mj = MSEED - (*idum < 0 ? -*idum : *idum); mj %= MBIG; ma[55] = mj; // initialize ma[55] for(i = 1, mk = 1; i <= 54; i++) { // initialize rest of table ii = (21*i) % 55; ma[ii] = mk; mk = mj - mk; if(mk < MZ) mk += MBIG; mj = ma[ii]; } for(k = 1; k <= 4; k++) { // randimize by "warming up" the generator for(i = 1; i <= 55; i++) { ma[i] -= ma[1 + (i + 30) % 55]; if(ma[i] < MZ) ma[i] += MBIG; } } inext = 0; // prepare indices for first generator number inextp = 31; // 31 is special *idum = 1; } if(++inext == 56) inext = 1; if(++inextp == 56) inextp = 1; mj = ma[inext] - ma[inextp]; if(mj < MZ) mj += MBIG; ma[inext] = mj; return mj*FAC; } #undef MBIG #undef MSEED #undef MZ #undef FAC // End: function ran3()