# This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by lll-zeus!seager on Tue Sep 30 11:14:49 PDT 1986 # Contents: READ.ME makefile dcgdrv.c dcg.c dcg.h dbatimes.c dbmsolve.c # dcgutil.c dblas.c echo x - READ.ME sed 's/^@//' > "READ.ME" <<'@//E*O*F READ.ME//' ********************************************************************** ********************************************************************** ********************************************************************** ******************** <<< DISCLAIMER >>> ********************** ********************************************************************** ********************************************************************** ********************************************************************** This document was prepared as an account of work sponsored by an agency of the United States Government. Neither the United States Government nor the University of California nor any of their employees, makes any warranty, express or implied, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately owned rights. Reference herein to any specific commercial products, process, or service by trade name, trademark, manufacturer, or otherwise, does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States Government or the University of California. The views and opinions of authors expressed herein do not necessarily state or reflect those of the United States Government thereof, and shall not be used for advertising or product endorsement purposes. ********************************************************************** ********************************************************************** ********************************************************************** This is the READ.ME for the DCG package. DCG is a Preconditioned Conjugate Gradient package written in C (double precision). It uses the modular approach of LINPACK. The necessary BLAS routines are included in blas.c. This package is also set up so that the user can define his/her own matrix data structure in dcg.h and write matrix multiply and matrix solve routines based on that matrix structure. Examples of both are found in dcg.h, dbatimes.c and dbmsolve.c for a banded matrix. A driver (dcgdrv.c) is also included and runs several simple minded examples. Feel free to modify all of the above routines for your purposes. Send comments, suggestions and bug-reports to: Dr. Mark K. Seager Lawrence Livermore Nat. Lab. PO Box 808, L-316 Livermore, CA 94550 (415) 423-3141 seager@lll-crg.Arpa @//E*O*F READ.ME// chmod u=rw,g=r,o=r READ.ME echo x - makefile sed 's/^@//' > "makefile" <<'@//E*O*F makefile//' # SID = "@(#)makefile 1.2 9/30/86" # This file makes the Preconditioned Conjugate Gradient routine. # Also, it makes the non-symmetric system solvers: ORTHOMIN(k) # Define DEBUG if it is necessary to get debug output. # CFLAGS=-g LDFLAGS=-lm SOBJ=scgdrv.o scg.o sbatimes.o sbmsolve.o scgutil.o DOBJ=dcgdrv.o dcg.o dbatimes.o dbmsolve.o dcgutil.o dblas.o DOBJN = dnsymdrv.o dorthomin.o dorthatimes.o # Single precsision (float) version.... scg: $(SOBJ) cc $(CFLAGS) -o scg $(SOBJ) $(LDFLAGS) scg.o: scg.c scg.h scgdrv.o: scgdrv.c scg.h scgutil.o : scgutil.c scg.h sbatimes.o : sbatimes.c scg.h sbmsolve.o : sbmsolve.c scg.h # Double precsision (double) version.... dcg: $(DOBJ) cc $(CFLAGS) -o dcg $(DOBJ) $(LDFLAGS) dcg.o: dcg.c dcg.h dcgdrv.o: dcgdrv.c dcg.h dcgutil.o : dcgutil.c dcg.h dbatimes.o : dbatimes.c dcg.h dbmsolve.o : dbmsolve.c dcg.h # Double precision Non-symmetric solver ORTHOMIN. dorthomin: $(DOBJN) cc $(CFLAGS) -o dorthomin $(DOBJN) $(LDFLAGS) dnsymdrv.o : dnsymdrv.c dorthomin.h dorthomin.o : dorthomin.c dorthomin.h dorthatimes.o : dorthatimes.c dorthomin.h # Clean up stuff. clean: rm -f scg dcg $(SOBJ) $(DOBJ) $(DOBJN) @//E*O*F makefile// chmod u=r,g=r,o=r makefile echo x - dcgdrv.c sed 's/^@//' > "dcgdrv.c" <<'@//E*O*F dcgdrv.c//' /* This routine generates a test problem for the preconditionded CG routine. */ #include #include #include "dcg.h" static char DCGDRVsid[] = "@(#)dcgdrv.c 1.3 9/30/86"; #define MAXMAT 1000 /* Maximum Matrix size. */ #define MATPRINT 26 /* Matricies <= MATPRINT in size are printed. */ #define VECPRINT 26 /* Vectors <= VECPRINT in size are printed. */ main(argc, argv) int argc; char *argv[]; { extern int *(dbatimes)(), *(dbmsolve)(); int i, j, n, itmax, test_type = 0; double *sol, *x, *b, err, err_est; struct DCGAMAT a; struct DCGMMAT m; double etime(), tary[2]; /* Total cpu time used in SECONDS. */ double job_time; /* Time to complete a task. */ double dnrm2(); /* Set up structures. */ if( argc <= 1 ) test_type++; /* Skip first test if no file is given. */ while( !matgen( &a, &m, &sol, &x, &b, ++test_type, argv[1] ) ) { n = a.rd; if( n>MAXMAT || n<1 ) { printf("Error return in matrix size. n=%d.\n",n); exit( 1 ); } /* Solve the system with Diagional Scaling. */ itmax = n; m.itype = 1; job_time = etime( tary ); j = dcg( n, dbatimes, &a, dbmsolve, &m, x, b, itmax, 1.0e-5, &err_est ); job_time = etime( tary ) - job_time; printf("\nCG(DS) Est err = %e. Took %d it (%e in sec).\n", err_est, j, job_time ); if( nhbw, &n ); mptr->hbw = aptr->hbw; aptr->rd = mptr->rd = n; printf("MATGEN: half-band-width = %d, System Size = %d\n",aptr->hbw, n); if( aptr->hbw >= MAXBND || n < 1 ) { printf("MATGEN: Bad hbw (%d) or n (%d).\n",aptr->hbw, n); return( 1 ); } fgets( chtmp, 81, fptr ); mptr->itype = 1; dosoln = 0; *sol = (double *)malloc( (unsigned)n*sizeof( double ) ); *b = (double *)malloc( (unsigned)n*sizeof( double ) ); if( *sol == NULL || *b == NULL ) { printf("MATGEN: Error in geting space for sol, b vectors.\n"); return( 1 ); } for( j=0; j<=aptr->hbw; j++ ) { aptr->diagptr[j] = (double *)malloc( (unsigned)n*sizeof( double ) ); mptr->diagptr[j] = (double *)malloc( (unsigned)n*sizeof( double ) ); if( aptr->diagptr[j] == NULL || mptr->diagptr[j] == NULL ) { printf("MATGEN: Can't get enouph space for matricies...\n"); return( 1 ); } } for( i=0; ihbw; j++ ) fscanf(fptr,"%le",aptr->diagptr[j]+i); fscanf( fptr, "%le",*sol+i); fscanf( fptr, "%le",*b+i); /* fgets( chtmp, 81, fptr ); */ /* Clear out rest of line. */ *(mptr->diagptr[0]+i) = *(aptr->diagptr[0]+i); /* Diag scaling pre-conditioning. */ } break; case 2: /* Small Tridiagional Matrix. */ n = 10; printf("\n\n**************************************************\n"); printf("Test case 2. Tridiagional system of size %d.\n", n ); aptr->hbw = 1; goto gen_space; case 3: /* Large Matrix. */ n = 400; aptr->hbw = 20; printf("\n\n**************************************************\n"); printf("Test case 3. System with %d upper diagionals and size %d.\n", aptr->hbw, n ); gen_space: mptr->hbw = aptr->hbw; mptr->itype = 1; aptr->rd = mptr->rd = n; if( (n>MAXMAT || n<2) || (aptr->hbw<1 || aptr->hbw>MAXBND)) { printf("MATGEN: Error in size of matrix.\n"); return( 1 ); } for( i=0; i<=aptr->hbw; i++ ) { aptr->diagptr[i] = (double *)malloc( (unsigned)n*sizeof( double ) ); mptr->diagptr[i] = (double *)malloc( (unsigned)n*sizeof( double ) ); if( aptr->diagptr[i] == NULL || mptr->diagptr[i] == NULL ) { printf("MATGEN: Can't get enouph space for matricies...\n"); return( 1 ); } } /* Set up Matrix main diagional elements and M (diag scaling). */ tmp1 = aptr->diagptr[0]; tmp2 = mptr->diagptr[0]; for( i=0; ihbw; j++ ) { tmp1 = aptr->diagptr[j]; for( i=0; i #include double etime( tary ) double tary[2]; /*********************************************************************** This routine returns the elapsed total (system+user) time used by this process in SECONDS. INPUT NONE OUTPUT tary[2] This array should be declaired by the user. The first element returned is the user time used. The second element returned is the system time used. RETURNS The total of system and user time in SECONDS. ***********************************************************************/ { struct tms buf; /* Buffer to hold system time. */ (void)times( &buf ); /* Get times (in HZ=1/60 sec) from the system. */ tary[0] = (double)buf.tms_utime / 60.0; /* User time in SECONDS. */ tary[1] = (double)buf.tms_stime / 60.0; /* System time in SECONDS. */ return( tary[0] + tary[1] ); /* Return Total time in SECONDS. */ } /**************************************************************************** **** This routine prints the (double) vector vec of lenght **** **** len to stdout with a heading head. **** ****************************************************************************/ int dumpdvec( len, vec, head ) int len; double *vec; char *head; { register int i; printf("\n%s\n 0>",head ); for( i=0; i",i); } } if( i % 5 != 0 ) printf("\n"); } /**************************************************************************** **** This routine prints the (float) vector vec of lenght **** **** len to stdout with a heading head. **** ****************************************************************************/ int dumpfvec( len, vec, head ) int len; float *vec; char *head; { register int i; printf("\n%s\n 0>",head ); for( i=0; i",i); } } if( i % 5 != 0 ) printf("\n"); } @//E*O*F dcgdrv.c// chmod u=r,g=r,o=r dcgdrv.c echo x - dcg.c sed 's/^@//' > "dcg.c" <<'@//E*O*F dcg.c//' /************************************************************************ *************************************************************************** ***************************************************************************** ***** ***** ***** Preconditioned Conjugate Gradient ***** ***** Double Precision (double) version. ***** ***** ***** ***************************************************************************** *************************************************************************** ************************************************************************/ #include "dcg.h" #include static char DCGsid[] = "@(#)dcg.c 1.2 5/19/86"; #define NULL 0 int dcg( n, atimes, aptr, msolve, mptr, x, b, itmax, eps, err ) struct DCGAMAT *aptr; struct DCGMMAT *mptr; int (*atimes)(), (*msolve)(); int n, itmax; double *x, *b, eps, *err; /* Purpose: This routine does preconditioned conjugate gradient iteration on the symmetric positive definte system Ax = b. Input: n Size of system to be iterated (ie A is nxn). aptr Pointer to the structure defining the matrix A. This structure need not be known by this routine. The structure is passed on to the atimes routine which does the matrix multiply. See below for the defintion of atimes. mptr Pointer to the structure defining the preconditioning matrix M. M should be chosen so that: Mz = r is easy to solve for z, given r (compared to Ax = b). Inv(M) is close to Inv(A). Inv = inverse. Obviously, the better choice of M the faster the convergence. x Initial guess of the solution. If no information on the solution is available then use a zero vector or b. b Right hand side. eps Requested error tollerence. System is iterated until ||b-Ax||/||b|| < eps. Normal choice is 1.0e-6. itmax Maximum number of iterations the user is willing to allow. Output: dcg Returns number of iterations taken. Error Returns follow: dcg = itmax May have not converged. Check err. dcg = -1 System size too small (n<2). dcg = -2 Could not get memory for tempory vectors. dcg = -3 Error tollerence requested too tight. dcg = -4 Divergence of iteration detected. dcg = -10 User declared error in atimes. dcg = -11 User declared error in msolve. err L2 norm of the relative residual error estimate ||b-Ax||/||b||. This estimate of the true error is not always very accurate. Note that err is a return value so the user must call dcg with a pointer to err. User Defined Functions and Structures. aptr The user defines an external structure DCGAMAT and hands this routine a pointer to that structure. The structure should contain all the information the user needs to calculate A times a vector. See DCG.H for an example. mptr The user defines an external structure DCGMMAT and hands this routine a pointer to that structure. The structure should contain all the information the user needs to solve the system Mz=r for z. See DCG.H for an example. int atimes( n, aptr, x, y ) The user should write a routine that calculates y = Ax, given an x vector. Return non-zero if an error occures. int msolve( n, mptr, z, r, atimes ) The user should write a routine that solves Mz=r for z, given a vector r. Return non-zero if an error occures. */ { char *malloc(); register int i; double *r, *z, *p; extern double ddot(); double bnorm, bknum, bkden, bk; double akden, ak; double toobig; /* When err est gets this big we signal divergence! */ /* Check input data and allocate temporary storage. */ if( n<2 ) return( -1 ); if( (r = (double *)malloc( n*sizeof(double) )) == NULL ) return( -2 ); if( (z = (double *)malloc( n*sizeof(double) )) == NULL ) return( -2 ); if( (p = (double *)malloc( n*sizeof(double) )) == NULL ) return( -2 ); if( eps < 1.0e-12 ) return( -3 ); /* Calculate norm of right hand size. */ bnorm = sqrt( ddot( n, b, 1, b, 1 ) ); /* Calculate r = b - Ax and initinal error. */ if( atimes( n, aptr, x, r ) ) return( -10 ); dexopy( n, r, b, r, 2 ); *err = sqrt( ddot(n, r, 1, r, 1 ) )/bnorm; if( *err < eps ) return( 0 ); toobig = *err * 1.0e2; /* Iterate!!! */ for( i=0; i toobig ) return( -4 ); } /* end for loop. */ return( itmax ); } /* end dcg. */ @//E*O*F dcg.c// chmod u=r,g=r,o=r dcg.c echo x - dcg.h sed 's/^@//' > "dcg.h" <<'@//E*O*F dcg.h//' /* SID "@(#)dcg.h 1.1 2/4/86" */ /************************************************************************ ***** ***** ***** Structure defintions for Preconditioned Conjugate Gradient ***** ***** Double precision (double). ***** ***** This file uses the example of a Symmetric Banded Matrix. ***** ***** ***** ************************************************************************/ /* The following gives an array (of length 10) of pointers to doubles. double *a[10]; Now assume that each a[i] has been given space for an array of doubles. Then the following is true: a[i] can be thought of as a pointer to the i-th array of doubles, *(a[i]+j) is the j-th element of the i-th array. In your user code you are at some point going to need to pass the DCGAMAT and DCGMMAT structures to a routine to do this declare struct DCGAMAT a; struct DCGMMAT m; Which sets aside storage for the matrix pointers. Then pass &a and &m to routines (e.g., dcg). Note that you must use the address operator here. Inside the called routines you declare: struct DCGAMAT *a; struct DCGMMAT *m; The following shows how to reference things for the definitions of DCGAMAT and DCGMMAT structures given below. a->hbw is the (value of, as apposed to a pointer to) half band width. a->diagptr[i] is a pointer to the i-th diagional (an array of doubles). *(a->diagptr[i]+j) is the j-th element of the i-th diagional (array). Here we think of the 0-th diagional as the main diagional, the 1-st diagional as the 1-st upper diagional and so on. */ #define MAXBND 100 /* Maximum number of bands(including diagional). */ struct DCGAMAT { /* Structure definition for the A matrix structure. */ int rd; /* Number of rows in the matrix. */ int hbw; /* Half band width. Number of bands = 2hbw + 1. */ /* Pointers to the main and upper diagionals. */ double *diagptr[MAXBND]; }; struct DCGMMAT { /* Struct definition for preconditioner matrix M. */ int itype; /* Type of msolve to do. The user may want code up several choices for M and then set this parameter before calling the iteration routine to specify which type to use. */ int rd; /* Number of rows in the matrix. */ int hbw; /* Half band width. Number of bands = 2hbw + 1. */ /* Pointers to diagionals. */ double *diagptr[MAXBND]; }; @//E*O*F dcg.h// chmod u=r,g=r,o=r dcg.h echo x - dbatimes.c sed 's/^@//' > "dbatimes.c" <<'@//E*O*F dbatimes.c//' /************************************************************************** ***** Sample atimes routine ***** ***** Designed for banded Matrices. ***** **************************************************************************/ #include "dcg.h" static char DBATIMESsid[] = "@(#)dbatimes.c 1.2 5/19/86"; int dbatimes( n, aptr, x, y ) int n; struct DCGAMAT *aptr; double *x, *y; /* Purpose To multiply A times a vector, viz., y = Ax. */ { register int i, j; register double *diag, *ytmp, *xtmp; /* Check input data.*/ if( n<1 ) return( 1 ); if( aptr->hbw < 1 ) return( 1 ); /* Do main diagional */ diag = aptr->diagptr[0]; xtmp = x; ytmp = y; for( i=0; ihbw; j++ ) { /* Upper diagional. */ diag = aptr->diagptr[j]; xtmp = x+j; ytmp = y; for( i=0; idiagptr[j]; xtmp = x; ytmp = y+j; for( i=0; i "dbmsolve.c" <<'@//E*O*F dbmsolve.c//' /************************************************************************** ***** Sample msolve routine ***** ***** Designed for BANDED matrices. ***** **************************************************************************/ #include "dcg.h" static char DBMSOLVEsid[] = "@(#)dbmsolve.c 1.2 5/19/86"; int dbmsolve( n, mptr, aptr, z, r, atimes ) int n; struct DCGMMAT *mptr; struct DCGAMAT *aptr; double *z, *r; int (*atimes)(); /* Purpose To calculate an approximate inverse of A times a vector. Types of inverses itype = 1 Diagional scaling. M=DIAG(A) = 2 Parameterized Incomplete Inverse (one matrix multiply). WARNING: The User must first diagionaly scale A before this approximat inverse is useful. User supplied routines int atimes( n, aptr, x, y ) The user should write a routine that calculates y = Ax. Return non-zero if an error occures. */ { register int i; register double *diag; double gam0, gam1, gam01; /* Check input data. */ if( n<1 ) return( 1 ); if( mptr->hbw < 1 ) return( 1 ); /* Options are as follows: */ switch( mptr->itype ) { case 1: /* Diagional Scaling. */ diag = mptr->diagptr[0]; /* z = r/DIAG(A). */ for( i=0; i "dcgutil.c" <<'@//E*O*F dcgutil.c//' /*************************************************************** ****************************************************************** **** Utilitie routines for CG.C **** ****************************************************************** ****************************************************************/ #include "dcg.h" static char DCGUTILsid[] = "@(#)dcgutil.c 1.2 5/19/86"; void dsbdumpmat( a, head ) struct DCGAMAT *a; char *head; /* This routine prints out a Double Symmetric Banded MATRIX with headding head. */ { register int i, j; int k, jj, ncolmod, ncolrem; jj = a->hbw+1; /* Must include diagional. */ ncolmod = jj / 6; ncolrem = jj - ncolmod*6; printf("%s\n", head ); for( i=0; ird; i++) { printf("%3d|", i ); j = 0; for( k=0; kdiagptr[j]+i)); printf("\n"); } /* Clean up remainder of this row. */ for( jj=0; jjdiagptr[j]+i)); printf("\n"); } printf("\n"); } /* End of SYM_BND_MATDUMP */ int dsbscale( n, aptr, mptr, x, b, scale, dox ) int n, scale, dox; struct DCGAMAT *aptr; struct DCGMMAT *mptr; double *x, *b; /* Purpose To (diagionaly) scale or unscale the matrix problem Ax=b. The structure of a is assumed to be Double precision (double) Symmetric Banded (SSB). Input n System size. aptr Pointer to the A matrix structure (this routine assumes a DIAGIONAL structure). mptr Pointer to the M matrix structure. This is used to hold the sqrt of the diagional diagional for unscaling. x Pointer to the solution (if known. See dox). b Pointer to the right hand side. scale Boolian which when true (non-zero) => scale, false => unscale. dox Boolian which when true (non-zero) => scale/unscale solution x. */ { register int i, j; double *t1, *t2; double sqrt(); if( n<2 ) return( 1 ); /* Check input parmaters. */ if( aptr->hbw<1 ) return( 1 ); if( scale ) { /* Set up for SCALING. */ t1 = mptr->diagptr[0]; t2 = aptr->diagptr[0]; for( i=0; idiagptr[0]; t2 = aptr->diagptr[0]; for( i=0; ihbw; j++ ) { t1 = mptr->diagptr[0]; t2 = aptr->diagptr[j]; for( i=0; idiagptr[0]; t2 = b; for( i=0; idiagptr[0]; t2 = x; for( i=0; ihbw; j++ ) printf("%15e",*(aptr->diagptr[j]+i)); printf("|%15e|%15e\n", *t1, *t2); } #endif return( 0 ); } @//E*O*F dcgutil.c// chmod u=r,g=r,o=r dcgutil.c echo x - dblas.c sed 's/^@//' > "dblas.c" <<'@//E*O*F dblas.c//' /*************************************************************** ***************************************************************** ******************************************************************* ***** ***** ***** BLAS ***** ***** Basic Linear Algebra Subroutines ***** ***** Written in the C Programming Language. ***** ***** << DOUBLE PRECISION VERSION >> ***** ***** ***** ***** Functions include: ***** ***** idamax, daxpy, daxpyx, dcopy, ddot, dnrm2, ***** ***** dexopy, dfill ***** ***** ***** ******************************************************************* ***************************************************************** ***************************************************************/ #include #ifndef SMALLdp #define SMALLdp 2.22507385850720e-308 /* Smallest (pos) binary float */ #endif #ifndef HUGEdp #define HUGEdp 1.79769313486232e+308 /* Largest binary float */ #endif int idamax( n, sx, incx ) double *sx; int n, incx; /* PURPOSE Finds the index of element having max. absolute value. INPUT n Number of elements to check. sx Vector to be checked. incx Every incx-th element is checked. */ { double smax = 0.0e0; int i, istmp = 0; #ifndef abs #define abs(x) ((x)>0.0?(x):-(x)) #endif if( n <= 1 ) return( istmp ); if( incx != 1 ) { /* Code for increment not equal to 1. */ if( incx < 0 ) sx = sx + ((-n+1)*incx + 1); istmp = 0; smax = abs( *sx ); sx += incx; for( i=1; i smax ) { istmp = i; smax = abs( *sx ); } return( istmp ); } /* Code for increment equal to 1. */ istmp = 0; smax = abs(*sx); sx++; for( i=1; i smax ) { istmp = i; smax = abs( *sx ); } return( istmp ); } void daxpy( n, sa, sx, incx, sy, incy ) double *sx, *sy, sa; int n, incx, incy; /* PURPOSE Vector times a scalar plus a vector. sy = sy + sa*sx. INPUT n Number of elements to multiply. sa Scalar to multiply by. sx Pointer to double vector to scale. incx Storage incrament for sx. sy Pointer to double vector to add. incy Storage incrament for sy. OUTPUT sy sy = sy + sa*sx */ { register int i; if( n<=0 || sa==0.0 ) return; if( incx == incy ) { if( incx == 1 ) { /* Both increments = 1 */ for( i=0; i0 ) { /* Equal, positive, non-unit increments. */ for( i=0; i0 ) { /* Equal, positive, non-unit increments. */ for( i=0; i 0 ) { /* Equal, positive, non-unit increments. */ for( i=0; i0 ) { /* Equal, positive, non-unit increments. */ for( i=0; i0). OUPUT snrm2 Euclidean norm of sx. Returns double due to `C' language features. REMARKS This algorithm proceeds in four steps. 1) scan zero components. 2) do phase 2 when component is near underflow. */ { register int i; int phase = 3; double sum = 0.0e0, cutlo, cuthi, hitst, r2mach(); double xmax; if( n<1 || incx<1 ) return( sum ); cutlo = sqrt( SMALLdp/r2mach() ); /* Calculate near underflow */ cuthi = sqrt( HUGEdp ); /* Calculate near overflow */ hitst = cuthi/(double) n; i = 0; /* Zero Sum. */ while( *sx == 0.0 && i=n ) return( sum ); START: if( abs( *sx ) > cutlo ) { for( ; i hitst ) goto GOT_LARGE; sum += (*sx) * (*sx); } sum = sqrt( sum ); return( sum ); /* Sum completed normaly. */ } else { /* Small sum prepare for phase 2. */ xmax = abs( *sx ); sx += incx; i++; sum += 1.0; for( ; i cutlo ) { /* Got normal elem. Rescale and process. */ sum = (sum*xmax)*xmax; goto START; } if( abs( *sx ) > xmax ) { sum = 1.0 + sum*(xmax /(*sx))*(xmax /(*sx)); xmax = abs( *sx ); continue; } sum += ((*sx)/xmax)*((*sx)/xmax); } return( (double)xmax*sqrt( sum ) ); } /* End of small sum. */ GOT_LARGE: sum = 1.0 + (sum/(*sx))/(*sx); /* Rescale and process. */ xmax = abs( *sx ); sx += incx; i++; for( ; i xmax ) { sum = 1.0 + sum*(xmax /(*sx))*(xmax /(*sx)); xmax = abs( *sx ); continue; } sum += ((*sx)/xmax)*((*sx)/xmax); } return( (double)xmax*sqrt( sum ) ); /* End of small sum. */ } /* End of ---DNRM2--- */ int dscal( n, sa, sx, incx ) double sa, *sx; int n, incx; /* PURPOSE Scales a vector by a constant. INPUT n Number of components to scale. sa Scale value. sx Vector to scale. incx Every incx-th element of sx will be scaled. OUTPUT sx Scaled vector. */ { register int i; if( n < 1 ) return( 1 ); /* Code for increment not equal to 1.*/ if( incx != 1 ) { if( incx < 0 ) sx += (-n+1)*incx; for( i=0; i '+' itype = 2 => '-' Output: v Result vector of x op y. */ { register int i; if( n<1 ) return; if( itype == 1 ) /* ADDITION. */ for( i=0; i $temp <<\!!! 45 284 2558 READ.ME 53 154 1169 makefile 314 1449 10369 dcgdrv.c 136 856 5250 dcg.c 52 376 2427 dcg.h 50 185 1252 dbatimes.c 63 267 1780 dbmsolve.c 124 461 3281 dcgutil.c 427 1640 10047 dblas.c 1264 5672 38133 total !!! wc READ.ME makefile dcgdrv.c dcg.c dcg.h dbatimes.c dbmsolve.c dcgutil.c dblas.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if [ -s $dtemp ] then echo "Ouch [diff of wc output]:" ; cat $dtemp else echo "No problems found." fi exit 0