diff options
-rw-r--r-- | emfloat.c | 123 | ||||
-rw-r--r-- | emfloat.h | 34 | ||||
-rw-r--r-- | fpemulation.c | 92 |
3 files changed, 116 insertions, 133 deletions
@@ -26,11 +26,26 @@ #include <stdio.h> #include <string.h> -#include <time.h> #include "nmglobal.h" #include "randnum.h" #include "emfloat.h" +static void SetInternalFPFZero(InternalFPF *dest, + unsigned char sign); +static void SetInternalFPFInfinity(InternalFPF *dest, + unsigned char sign); +static void SetInternalFPFNaN(InternalFPF *dest); +static int IsMantissaZero(uint16_t *mant); +static void Add16Bits(uint16_t *carry,uint16_t *a,uint16_t b,uint16_t c); +static void Sub16Bits(uint16_t *borrow,uint16_t *a,uint16_t b,uint16_t c); +static void ShiftMantLeft1(uint16_t *carry,uint16_t *mantissa); +static void ShiftMantRight1(uint16_t *carry,uint16_t *mantissa); +static void StickyShiftRightMant(InternalFPF *ptr,int amount); +static void RoundInternalFPF(InternalFPF *ptr); +static void normalize(InternalFPF *ptr); +static void denormalize(InternalFPF *ptr,int minimum_exponent); +static void choose_nan(InternalFPF *x,InternalFPF *y,InternalFPF *z, + int intel_flag); /* ** Floating-point emulator. ** These routines are only "sort of" IEEE-compliant. All work is @@ -46,100 +61,6 @@ ** Computer Hobbyists" by Neill Graham. */ -/************************** -** SetupCPUEmFloatArrays ** -*************************** -** Set up the arrays that will be used in the emulated -** floating-point tests. -** This is done by loading abase and bbase elements with -** random numbers. We use our long-to-floating point -** routine to set them up. -** NOTE: We really don't need the pointer to cbase...cbase -** is overwritten in the benchmark. -*/ -void SetupCPUEmFloatArrays(InternalFPF *abase, - InternalFPF *bbase, - InternalFPF *cbase, - unsigned long arraysize) -{ -unsigned long i; -InternalFPF locFPF1,locFPF2; -/* -** Reset random number generator so things repeat. Inserted by Uwe F. Mayer. -*/ -extern int32_t randnum(int32_t lngval); -randnum(13); - -for(i=0;i<arraysize;i++) -{/* LongToInternalFPF(randwc(50000L),&locFPF1); */ - Int32ToInternalFPF(randwc(50000),&locFPF1); - /* LongToInternalFPF(randwc(50000L)+1L,&locFPF2); */ - Int32ToInternalFPF(randwc(50000)+1,&locFPF2); - DivideInternalFPF(&locFPF1,&locFPF2,abase+i); - /* LongToInternalFPF(randwc(50000L)+1L,&locFPF2); */ - Int32ToInternalFPF(randwc(50000)+1,&locFPF2); - DivideInternalFPF(&locFPF1,&locFPF2,bbase+i); -} -return; -} - -/*********************** -** DoEmFloatIteration ** -************************ -** Perform an iteration of the emulated floating-point -** benchmark. Note that "an iteration" can involve multiple -** loops through the benchmark. -*/ -unsigned long DoEmFloatIteration(InternalFPF *abase, - InternalFPF *bbase, - InternalFPF *cbase, - unsigned long arraysize, unsigned long loops) -{ - clock_t start, stop; -static unsigned char jtable[16] = {0,0,0,0,1,1,1,1,2,2,2,2,2,3,3,3}; -unsigned long i; - - start = clock(); - -/* -** 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; - } - } - - stop = clock(); - - return stop - start; -} - /*********************** ** SetInternalFPFZero ** ************************ @@ -433,7 +354,7 @@ return; ** The kind of rounding we do here is simplest...referred to as ** "chop". "Extraneous" rightmost bits are simply hacked off. */ -void RoundInternalFPF(InternalFPF *ptr) +void static RoundInternalFPF(InternalFPF *ptr) { /* int i; */ @@ -522,7 +443,7 @@ return; ** Internal-representation numbers pointed to by x and y are ** added/subtracted and the result returned in z. */ -static void AddSubInternalFPF(unsigned char operation, +void AddSubInternalFPF(unsigned char operation, InternalFPF *x, InternalFPF *y, InternalFPF *z) @@ -731,7 +652,7 @@ return; ** Two internal-representation numbers x and y are multiplied; the ** result is returned in z. */ -static void MultiplyInternalFPF(InternalFPF *x, +void MultiplyInternalFPF(InternalFPF *x, InternalFPF *y, InternalFPF *z) { @@ -893,7 +814,7 @@ return; *********************** ** Divide internal FPF number x by y. Return result in z. */ -static void DivideInternalFPF(InternalFPF *x, +void DivideInternalFPF(InternalFPF *x, InternalFPF *y, InternalFPF *z) { @@ -1046,13 +967,11 @@ RoundInternalFPF(z); } /********************** -** LongToInternalFPF ** ** Int32ToInternalFPF ** *********************** ** Convert a signed (long) 32-bit integer into an internal FPF number. */ -/* static void LongToInternalFPF(long mylong, */ -static void Int32ToInternalFPF(int32_t mylong, +void Int32ToInternalFPF(int32_t mylong, InternalFPF *dest) { int i; /* Index */ @@ -94,33 +94,7 @@ typedef struct /* ** PROTOTYPES */ -void SetupCPUEmFloatArrays(InternalFPF *abase, - InternalFPF *bbase, InternalFPF *cbase, unsigned long arraysize); -unsigned long DoEmFloatIteration(InternalFPF *abase, - InternalFPF *bbase, InternalFPF *cbase, - unsigned long arraysize, unsigned long loops); -static void SetInternalFPFZero(InternalFPF *dest, - unsigned char sign); -static void SetInternalFPFInfinity(InternalFPF *dest, - unsigned char sign); -static void SetInternalFPFNaN(InternalFPF *dest); -static int IsMantissaZero(uint16_t *mant); -static void Add16Bits(uint16_t *carry,uint16_t *a,uint16_t b,uint16_t c); -static void Sub16Bits(uint16_t *borrow,uint16_t *a,uint16_t b,uint16_t c); -static void ShiftMantLeft1(uint16_t *carry,uint16_t *mantissa); -static void ShiftMantRight1(uint16_t *carry,uint16_t *mantissa); -static void StickyShiftRightMant(InternalFPF *ptr,int amount); -static void normalize(InternalFPF *ptr); -static void denormalize(InternalFPF *ptr,int minimum_exponent); -void RoundInternalFPF(InternalFPF *ptr); -static void choose_nan(InternalFPF *x,InternalFPF *y,InternalFPF *z, - int intel_flag); -static void AddSubInternalFPF(unsigned char operation,InternalFPF *x, - InternalFPF *y,InternalFPF *z); -static void MultiplyInternalFPF(InternalFPF *x,InternalFPF *y, - InternalFPF *z); -static void DivideInternalFPF(InternalFPF *x,InternalFPF *y, - InternalFPF *z); -/* static void LongToInternalFPF(long mylong, */ -static void Int32ToInternalFPF(int32_t mylong, - InternalFPF *dest); +void AddSubInternalFPF(unsigned char operation,InternalFPF *x, InternalFPF *y, InternalFPF *z); +void MultiplyInternalFPF(InternalFPF *x,InternalFPF *y, InternalFPF *z); +void DivideInternalFPF(InternalFPF *x,InternalFPF *y, InternalFPF *z); +void Int32ToInternalFPF(int32_t mylong, InternalFPF *dest); diff --git a/fpemulation.c b/fpemulation.c index b655c0c..cac88ee 100644 --- a/fpemulation.c +++ b/fpemulation.c @@ -15,6 +15,10 @@ ** FLOATING-POINT EMULATION ** *****************************/ +static clock_t DoEmFloatIteration(InternalFPF *abase, InternalFPF *bbase, InternalFPF *cbase, + unsigned long arraysize, unsigned long loops); +static void SetupCPUEmFloatArrays(InternalFPF *abase, InternalFPF *bbase, unsigned long arraysize); + /************** ** DoEmFloat ** *************** @@ -55,7 +59,7 @@ DoEmFloat(void) exit(1); } - SetupCPUEmFloatArrays(abase, bbase, cbase, locemfloatstruct->arraysize); /* FIXME: ugly */ + SetupCPUEmFloatArrays(abase, bbase, locemfloatstruct->arraysize); /* FIXME: ugly */ /* See if we need to do self-adjusting code.*/ if (locemfloatstruct->adjust == FALSE) { @@ -104,3 +108,89 @@ DoEmFloat(void) locemfloatstruct->emflops = (double)(iterations * locemfloatstruct->loops * CLOCKS_PER_SEC) / (double)total_time; } + +/*********************** +** DoEmFloatIteration ** +************************ +** Perform an iteration of the emulated floating-point +** benchmark. Note that "an iteration" can involve multiple +** loops through the benchmark. +*/ +static clock_t +DoEmFloatIteration(InternalFPF *abase, + InternalFPF *bbase, + InternalFPF *cbase, + unsigned long arraysize, unsigned long loops) +{ + clock_t start, stop; +static unsigned char jtable[16] = {0,0,0,0,1,1,1,1,2,2,2,2,2,3,3,3}; +unsigned long i; + + start = clock(); + +/* +** 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; + } + } + + stop = clock(); + + return stop - start; +} + +/************************** +** SetupCPUEmFloatArrays ** +*************************** +** Set up the arrays that will be used in the emulated +** floating-point tests. +** This is done by loading abase and bbase elements with +** random numbers. We use our long-to-floating point +** routine to set them up. +*/ +static void +SetupCPUEmFloatArrays(InternalFPF *abase, InternalFPF *bbase, unsigned long arraysize) +{ + unsigned long i; + InternalFPF locFPF1,locFPF2; + /* + ** Reset random number generator so things repeat. Inserted by Uwe F. Mayer. + */ + randnum(13); + + for (i = 0; i < arraysize; i++) { + Int32ToInternalFPF(randwc(50000),&locFPF1); + Int32ToInternalFPF(randwc(50000)+1,&locFPF2); + DivideInternalFPF(&locFPF1,&locFPF2,abase+i); + Int32ToInternalFPF(randwc(50000)+1,&locFPF2); + DivideInternalFPF(&locFPF1,&locFPF2,bbase+i); + } +} |