#define __normdf norm /* for now */ /* * double modf(value, iptr) * double value; * double *iptr; * * returns fractional part of value * in *iptr returns the integral part * such that (*iptr + fractional) == value * * ++jrb bammi@dsrgsun.ces.cwru.edu * * special thanks to peter housel housel@ecn.purdue.edu * this (improved) version is based on his X86 code * */ #include "flonum.h" #define BIAS 1023 #define B1 1022 /* BIAS - 1 */ #define B2 1075 /* (BIAS - 1) + 53 == max bias for integ part */ #define B3 1011 /* (BIAS - 1) - 11 == the max bias for a frac. # */ struct ldouble { unsigned long hi, lo; }; /* another alias for double */ double modf(value, iptr) double value, *iptr; { struct bitdouble *bd = (struct bitdouble *)&value; unsigned int expo = bd->exp; #ifdef __STDC__ double __normdf( double, int, int, int ); #else extern double __normdf(); #endif if(expo <= B1) /* all frac, no integ */ { *iptr = 0.0; return value; } if(expo >= B2) /* all integ, no frac */ { *iptr = value; return 0.0; } /* both integ and frac */ { register unsigned long i0, i1; /* integral part accumulator */ register unsigned long f0, f1; /* fractional part accumulator */ unsigned int sign = bd->sign; i0 = bd->mant1 | 0x00100000L; i1 = bd->mant2; f0 = f1 = 0L; do { /* shift R integ/frac, with bit falling into frac acc */ asm volatile(" lsrl #1,%1; roxrl #1,%0" : "=d" (i1), "=d" (i0) : "0" (i1), "1" (i0) ); asm volatile(" roxrl #1,%1; roxrl #1,%0" : "=d" (f1), "=d" (f0) : "0" (f1), "1" (f0) ); } while(++expo < B2); /* stuff the results, and normalize */ ((struct ldouble *)&value)->hi = i0; /* integral part */ ((struct ldouble *)&value)->lo = i1; *iptr = __normdf(value, expo, sign , 0); /* dont call norm if frac is all zero, as B3 exp will screw it up */ if((f0 == 0) && (f1 == 0)) return 0.0; ((struct ldouble *)&value)->hi = f0; /* fractional part */ ((struct ldouble *)&value)->lo = f1; return __normdf(value, B3, sign, 0); } } #ifdef TEST #include #ifdef __MSHORT__ #error "please run this test in 32 bit int mode" #endif #define NTEST 100000L #define MAXRAND 0x7fffffffL /* assuming 32 bit ints */ #define ABS(X) ( (X < 0) ? (-X) : X ) extern long rand(); int main() { double frac, integ, e, expected, result, max_abs_err; register long i; register long errs = 0; register int s; max_abs_err = 0.0; for(i = 0; i < NTEST; i++) { expected = ((double)(s = rand()) + (double)rand())/(double)(MAXRAND); if(s > (MAXRAND >> 1)) expected = -expected; frac = modf(expected, &integ); if(ABS(frac) >= 1.0) { printf("|frac| >= 1, %.6e: integ %.6e frac %.6e\n", expected, integ, frac); errs++; continue; } if( (integ != 0) && (ABS(integ) < 1.0) ) { printf("|integ| < 1, %.6e: integ %.6e frac %.6e\n", expected, integ, frac); errs++; continue; } result = integ + frac; e = (expected == 0.0) ? result : (result - expected)/expected; if(e < 0) e = (-e); if(e > 1.0e-6) { printf("%.4e: I %.4e F %.4e R %.4e E %.8e\n", expected, integ, frac, result, e); errs++; } if (e > max_abs_err) max_abs_err = e; } printf("%ld Error(s), Max abs err %.14e\n", errs, max_abs_err); return errs; } #endif /* TEST */