#include /*#include #include #include */ #include #include #include "nmglobal.h" #include "nbench1.h" /*********************** ** LU DECOMPOSITION ** ** (Linear Equations) ** ************************ ** These routines come from "Numerical Recipes in Pascal". ** Note that, as in the assignment algorithm, though we ** separately define LUARRAYROWS and LUARRAYCOLS, the two ** must be the same value (this routine depends on a square ** matrix). */ /********* ** DoLU ** ********** ** Perform the LU decomposition benchmark. */ void DoLU(void) { LUStruct *loclustruct; /* Local pointer to global data */ char *errorcontext; int systemerror; double *a; double *b; double *abase; double *bbase; LUdblptr ptra; int n; int i; unsigned long accumtime; double iterations; /* ** Link to global data */ loclustruct=&global_lustruct; /* ** Set error context. */ errorcontext="FPU:LU"; /* ** Our first step is to build a "solvable" problem. This ** will become the "seed" set that all others will be ** derived from. (I.E., we'll simply copy these arrays ** into the others. */ a=(double *)AllocateMemory(sizeof(double) * LUARRAYCOLS * LUARRAYROWS, &systemerror); b=(double *)AllocateMemory(sizeof(double) * LUARRAYROWS, &systemerror); n=LUARRAYROWS; /* ** We need to allocate a temp vector that is used by the LU ** algorithm. This removes the allocation routine from the ** timing. */ LUtempvv=(double *)AllocateMemory(sizeof(double)*LUARRAYROWS, &systemerror); /* ** Build a problem to be solved. */ ptra.ptrs.p=a; /* Gotta coerce linear array to 2D array */ build_problem(*ptra.ptrs.ap,n,b); /* ** Now that we have a problem built, see if we need to do ** auto-adjust. If so, repeatedly call the DoLUIteration routine, ** increasing the number of solutions per iteration as you go. */ if(loclustruct->adjust==0) { loclustruct->numarrays=0; for(i=1;i<=MAXLUARRAYS;i++) { abase=(double *)AllocateMemory(sizeof(double) * LUARRAYCOLS*LUARRAYROWS*(i+1),&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,(double *)NULL,(double *)NULL); ErrorExit(); } bbase=(double *)AllocateMemory(sizeof(double) * LUARRAYROWS*(i+1),&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,abase,(double *)NULL); ErrorExit(); } if(DoLUIteration(a,b,abase,bbase,i)>global_min_ticks) { loclustruct->numarrays=i; break; } /* ** Not enough arrays...free them all and try again */ FreeMemory((void *)abase,&systemerror); FreeMemory((void *)bbase,&systemerror); } /* ** Were we able to do it? */ if(loclustruct->numarrays==0) { printf("FPU:LU -- Array limit reached\n"); LUFreeMem(a,b,abase,bbase); ErrorExit(); } } else { /* ** Don't need to adjust -- just allocate the proper ** number of arrays and proceed. */ abase=(double *)AllocateMemory(sizeof(double) * LUARRAYCOLS*LUARRAYROWS*loclustruct->numarrays, &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,(double *)NULL,(double *)NULL); ErrorExit(); } bbase=(double *)AllocateMemory(sizeof(double) * LUARRAYROWS*loclustruct->numarrays,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,abase,(double *)NULL); ErrorExit(); } } /* ** All's well if we get here. Do the test. */ accumtime=0L; iterations=(double)0.0; do { accumtime+=DoLUIteration(a,b,abase,bbase, loclustruct->numarrays); iterations+=(double)loclustruct->numarrays; } while(TicksToSecs(accumtime)request_secs); /* ** Clean up, calculate results, and go home. Be sure to ** show that we don't have to rerun adjustment code. */ loclustruct->iterspersec=iterations / TicksToFracSecs(accumtime); if(loclustruct->adjust==0) loclustruct->adjust=1; LUFreeMem(a,b,abase,bbase); return; } /************** ** LUFreeMem ** *************** ** Release memory associated with LU benchmark. */ static void LUFreeMem(double *a, double *b, double *abase,double *bbase) { int systemerror; FreeMemory((void *)a,&systemerror); FreeMemory((void *)b,&systemerror); FreeMemory((void *)LUtempvv,&systemerror); if(abase!=(double *)NULL) FreeMemory((void *)abase,&systemerror); if(bbase!=(double *)NULL) FreeMemory((void *)bbase,&systemerror); return; } /****************** ** DoLUIteration ** ******************* ** Perform an iteration of the LU decomposition benchmark. ** An iteration refers to the repeated solution of several ** identical matrices. */ static unsigned long DoLUIteration(double *a,double *b, double *abase, double *bbase, unsigned long numarrays) { double *locabase; double *locbbase; LUdblptr ptra; /* For converting ptr to 2D array */ unsigned long elapsed; unsigned long j,i; /* Indexes */ /* ** Move the seed arrays (a & b) into the destination ** arrays; */ for(j=0;j big) big=fabs(a[i][j]); /* Bail out on singular matrix */ if(big==(double)0.0) return(0); LUtempvv[i]=1.0/big; } /* ** Crout's algorithm...loop over columns. */ for(j=0;j=big) { big=dum; imax=i; } } if(j!=imax) /* Interchange rows if necessary */ { for(k=0;k=0;i--) { sum=b[i]; if(i!=(n-1)) for(j=(i+1);j