/*********************** ** DoEmFloatIteration ** ************************ ** Perform an iteration of the emulated floating-point ** benchmark. Note that "an iteration" can involve multiple ** loops through the benchmark. */ ulong DoEmFloatIteration(InternalFPF *abase, InternalFPF *bbase, InternalFPF *cbase, ulong arraysize, ulong loops, double *wat_time) { ulong elapsed; /* For the stopwatch */ static uchar jtable[16] = {0,0,0,0,1,1,1,1,2,2,2,2,2,3,3,3}; ulong i; /* ** Begin timing */ elapsed=StartStopwatch(); TimerOn(); /* ** Each pass through the array performs operations in ** the followingratios: ** 4 adds, 4 subtracts, 5 multiplies, 3 divides ** (adds and subtracts being nearly the same operation) */ while(loops--) { for(i=0;i<arraysize;i++) switch(jtable[i % 16]) { case 0: /* Add */ AddSubInternalFPF(0,abase+i, bbase+i, cbase+i); break; case 1: /* Subtract */ AddSubInternalFPF(1,abase+i, bbase+i, cbase+i); break; case 2: /* Multiply */ MultiplyInternalFPF(abase+i, bbase+i, cbase+i); break; case 3: /* Divide */ DivideInternalFPF(abase+i, bbase+i, cbase+i); break; } } TimerOff(); elapsed = StopStopwatch(elapsed); if( wat_time ) { *wat_time = TimerElapsed(); } return(elapsed); }
/************************ ** InternalFPFToString ** ************************* ** FOR DEBUG PURPOSES ** This routine converts an internal floating point representation ** number to a string. Used in debugging the package. ** Returns length of converted number. ** NOTE: dest must point to a buffer big enough to hold the ** result. Also, this routine does append a null (an effect ** of using the sprintf() function). It also returns ** a length count. ** NOTE: This routine returns 5 significant digits. Thats ** about all I feel safe with, given the method of ** conversion. It should be more than enough for programmers ** to determine whether the package is properly ported. */ static int InternalFPFToString(char *dest, InternalFPF *src) { InternalFPF locFPFNum; /* Local for src (will be altered) */ InternalFPF IFPF10; /* Floating-point 10 */ InternalFPF IFPFComp; /* For doing comparisons */ int msign; /* Holding for mantissa sign */ int expcount; /* Exponent counter */ int ccount; /* Character counter */ int i,j,k; /* Index */ u16 carryaccum; /* Carry accumulator */ u16 mycarry; /* Local for carry */ /* ** Check first for the simple things...Nan, Infinity, Zero. ** If found, copy the proper string in and go home. */ switch(src->type) { case IFPF_IS_NAN: memcpy(dest,"NaN",3); return(3); case IFPF_IS_INFINITY: if(src->sign==0) memcpy(dest,"+Inf",4); else memcpy(dest,"-Inf",4); return(4); case IFPF_IS_ZERO: if(src->sign==0) memcpy(dest,"+0",2); else memcpy(dest,"-0",2); return(2); } /* ** Move the internal number into our local holding area, since ** we'll be altering it to print it out. */ memcpy((void *)&locFPFNum,(void *)src,sizeof(InternalFPF)); /* ** Set up a floating-point 10...which we'll use a lot in a minute. */ LongToInternalFPF(10L,&IFPF10); /* ** Save the mantissa sign and make it positive. */ msign=src->sign; src->sign=0; expcount=0; /* Init exponent counter */ /* ** See if the number is less than 10. If so, multiply ** the number repeatedly by 10 until it's not. For each ** multiplication, decrement a counter so we can keep track ** of the exponent. */ while(1) { AddSubInternalFPF(1,&locFPFNum,&IFPF10,&IFPFComp); if(IFPFComp.sign==0) break; MultiplyInternalFPF(&locFPFNum,&IFPF10,&IFPFComp); expcount--; memcpy((void *)&locFPFNum,(void *)&IFPFComp,sizeof(InternalFPF)); } /* ** Do the reverse of the above. As long as the number is ** greater than or equal to 10, divide it by 10. Increment the ** exponent counter for each multiplication. */ while(1) { AddSubInternalFPF(1,&locFPFNum,&IFPF10,&IFPFComp); if(IFPFComp.sign!=0) break; DivideInternalFPF(&locFPFNum,&IFPF10,&IFPFComp); expcount++; memcpy((void *)&locFPFNum,(void *)&IFPFComp,sizeof(InternalFPF)); } /* ** About time to start storing things. First, store the ** mantissa sign. */ ccount=1; /* Init character counter */ if(msign==0) *dest++='+'; else *dest++='-'; /* ** At this point we know that the number is in the range ** 10 > n >=1. We need to "strip digits" out of the ** mantissa. We do this by treating the mantissa as ** an integer and multiplying by 10. (Not a floating-point ** 10, but an integer 10. Since this is debug code and we ** could care less about speed, we'll do it the stupid ** way and simply add the number to itself 10 times. ** Anything that makes it to the left of the implied binary point ** gets stripped off and emitted. We'll do this for ** 5 significant digits (which should be enough to ** verify things). */ /* ** Re-position radix point */ carryaccum=0; while(locFPFNum.exp>0) { mycarry=0; ShiftMantLeft1(&mycarry,locFPFNum.mantissa); carryaccum=(carryaccum<<1); if(mycarry) carryaccum++; locFPFNum.exp--; } while(locFPFNum.exp<0) { mycarry=0; ShiftMantRight1(&mycarry,locFPFNum.mantissa); locFPFNum.exp++; } for(i=0;i<6;i++) if(i==1) { /* Emit decimal point */ *dest++='.'; ccount++; } else { /* Emit a digit */ *dest++=('0'+carryaccum); ccount++; carryaccum=0; memcpy((void *)&IFPF10, (void *)&locFPFNum, sizeof(InternalFPF)); /* Do multiply via repeated adds */ for(j=0;j<9;j++) { mycarry=0; for(k=(INTERNAL_FPF_PRECISION-1);k>=0;k--) Add16Bits(&mycarry,&(IFPFComp.mantissa[k]), locFPFNum.mantissa[k], IFPF10.mantissa[k]); carryaccum+=mycarry ? 1 : 0; memcpy((void *)&locFPFNum, (void *)&IFPFComp, sizeof(InternalFPF)); } } /* ** Now move the 'E', the exponent sign, and the exponent ** into the string. */ *dest++='E'; ccount+=sprintf(dest,"%4d",expcount); /* ** All done, go home. */ return(ccount); }
/*********************** ** DoEmFloatIteration ** ************************ ** Perform an iteration of the emulated floating-point ** benchmark. Note that "an iteration" can involve multiple ** loops through the benchmark. */ ulong DoEmFloatIteration(InternalFPF *abase, InternalFPF *bbase, InternalFPF *cbase, ulong arraysize, ulong loops) { ulong elapsed; /* For the stopwatch */ static uchar jtable[16] = {0,0,0,0,1,1,1,1,2,2,2,2,2,3,3,3}; ulong i; #ifdef DEBUG int number_of_loops; #endif /* ** Begin timing */ elapsed=StartStopwatch(); #ifdef DEBUG number_of_loops=loops-1; /* the index of the first loop we run */ #endif /* ** Each pass through the array performs operations in ** the followingratios: ** 4 adds, 4 subtracts, 5 multiplies, 3 divides ** (adds and subtracts being nearly the same operation) */ while(loops--) { for(i=0;i<arraysize;i++) switch(jtable[i % 16]) { case 0: /* Add */ AddSubInternalFPF(0,abase+i, bbase+i, cbase+i); break; case 1: /* Subtract */ AddSubInternalFPF(1,abase+i, bbase+i, cbase+i); break; case 2: /* Multiply */ MultiplyInternalFPF(abase+i, bbase+i, cbase+i); break; case 3: /* Divide */ DivideInternalFPF(abase+i, bbase+i, cbase+i); break; } #ifdef DEBUG { ulong j[8]; /* we test 8 entries */ int k; ulong i; char buffer[1024]; if (number_of_loops==loops) /* the first loop */ { j[0]=(ulong)2; j[1]=(ulong)6; j[2]=(ulong)10; j[3]=(ulong)14; j[4]=(ulong)(arraysize-14); j[5]=(ulong)(arraysize-10); j[6]=(ulong)(arraysize-6); j[7]=(ulong)(arraysize-2); for(k=0;k<8;k++){ i=j[k]; InternalFPFToString(buffer,abase+i); printf("%6ld: (%s) ",i,buffer); switch(jtable[i % 16]) { case 0: strcpy(buffer,"+"); break; case 1: strcpy(buffer,"-"); break; case 2: strcpy(buffer,"*"); break; case 3: strcpy(buffer,"/"); break; } printf("%s ",buffer); InternalFPFToString(buffer,bbase+i); printf("(%s) = ",buffer); InternalFPFToString(buffer,cbase+i); printf("%s\n",buffer); } } } #endif } return(StopStopwatch(elapsed)); }