#define __normdf norm /* for now */ /* * double frexp(value, eptr) * double value; * int *eptr; * * returns significand (|significand| < 1) * in *eptr returns n such that value = significand * 2**n * * ++jrb bammi@dsrgsun.ces.cwru.edu * */ #include "flonum.h" #define BIAS 1023 #define B1 1022 double frexp(value, eptr) double value; #ifdef SHORTLIB short *eptr; #else int *eptr; #endif { struct bitdouble *res = (struct bitdouble *) &value; unsigned int expo, sign; #ifdef __STDC__ double __normdf( double, int, int, int ); #else extern double __normdf(); #endif expo = res->exp; sign = res->sign; res->exp = 0; res->sign = 0; *eptr = expo - B1; if(expo != 0) res->exp = 1; /* put in hidden bit */ else if((res->mant1 == 0) && (res->mant2 == 0)) { *eptr = 0; return 0.0; /* no point in normalizing (exp will be wrong) */ } return __normdf(value, B1, sign, 0); } #ifdef TEST /* combined test for frexp and ldexp */ /* 32 bit ints for this test please */ #ifdef __MSHORT__ #error "please run this test in 32 bit int mode" #endif #include #define NTEST 100000L #define MAXRAND 0x7fffffffL /* assuming 32 bit ints */ #define ABS(X) ( (X < 0) ? (-X) : X ) extern long rand(); int main() { double sig, e, expected, result, max_abs_err; int twoexp; register long i; register long errs = 0; register int s; #ifdef __STDC__ double ldexp(double, int); double frexp(double, int *); #else extern double ldexp(); extern double frexp(); #endif 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; sig = frexp(expected, &twoexp); if(ABS(sig) >= 1.0) { printf("sig > 1, %.4e: %.4e %d\n", expected, sig, twoexp); errs++; continue; } result = ldexp(sig, twoexp); e = (expected == 0.0) ? result : (result - expected)/expected; if(e < 0) e = (-e); if(e > 1.0e-6) { printf("%.8e: %.8e E %.8e\n", expected, 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 */