#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; fardouble *a; fardouble *b; fardouble *abase; fardouble *bbase; LUdblptr ptra; int n; int i; ulong 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=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYCOLS * LUARRAYROWS, &systemerror); b=(fardouble *)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=(fardouble *)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=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYCOLS*LUARRAYROWS*(i+1),&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,(fardouble *)NULL,(fardouble *)NULL); ErrorExit(); } bbase=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYROWS*(i+1),&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,abase,(fardouble *)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((farvoid *)abase,&systemerror); FreeMemory((farvoid *)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=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYCOLS*LUARRAYROWS*loclustruct->numarrays, &systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,(fardouble *)NULL,(fardouble *)NULL); ErrorExit(); } bbase=(fardouble *)AllocateMemory(sizeof(double) * LUARRAYROWS*loclustruct->numarrays,&systemerror); if(systemerror) { ReportError(errorcontext,systemerror); LUFreeMem(a,b,abase,(fardouble *)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(fardouble *a, fardouble *b, fardouble *abase,fardouble *bbase) { int systemerror; FreeMemory((farvoid *)a,&systemerror); FreeMemory((farvoid *)b,&systemerror); FreeMemory((farvoid *)LUtempvv,&systemerror); if(abase!=(fardouble *)NULL) FreeMemory((farvoid *)abase,&systemerror); if(bbase!=(fardouble *)NULL) FreeMemory((farvoid *)bbase,&systemerror); return; } /****************** ** DoLUIteration ** ******************* ** Perform an iteration of the LU decomposition benchmark. ** An iteration refers to the repeated solution of several ** identical matrices. */ static ulong DoLUIteration(fardouble *a,fardouble *b, fardouble *abase, fardouble *bbase, ulong numarrays) { fardouble *locabase; fardouble *locbbase; LUdblptr ptra; /* For converting ptr to 2D array */ ulong elapsed; ulong 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