home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3137 / frexp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-27  |  2.2 KB  |  110 lines

  1. /*
  2.  * double frexp(value, eptr)
  3.  * double value;
  4.  * int *eptr;
  5.  *
  6.  * returns significand (|significand| < 1)
  7.  *       in *eptr returns n such that value = significand * 2**n
  8.  *
  9.  * ++jrb    bammi@dsrgsun.ces.cwru.edu
  10.  *
  11.  */
  12. #include "flonum.h"
  13.  
  14. #define BIAS 1023
  15. #define B1   1022
  16.  
  17. double frexp(value, eptr)
  18. double value;
  19. #ifdef SHORTLIB
  20. short *eptr;
  21. #else
  22. int *eptr;
  23. #endif
  24. {
  25.     struct bitdouble *res = (struct bitdouble *) &value;
  26.     unsigned int expo, sign;
  27. #ifdef __STDC__
  28.     double norm( double, int, int, int );
  29. #else
  30.     extern double norm();
  31. #endif
  32.     
  33.     expo = res->exp;
  34.     sign = res->sign;
  35.     res->exp = 0;
  36.     res->sign = 0;
  37.     *eptr = expo - B1;
  38.     if(expo != 0)
  39.     res->exp = 1;    /* put in hidden bit */
  40.     else
  41.     if((res->mant1 == 0) && (res->mant2 == 0))
  42.     {
  43.         *eptr = 0;
  44.         return 0.0;    /* no point in normalizing (exp will be wrong) */
  45.     }
  46.  
  47.     return norm(value, B1, sign, 0);
  48. }
  49.  
  50. #ifdef TEST /* combined test for frexp and ldexp */
  51.     /* 32 bit ints for this test please */
  52.  
  53. #ifdef __MSHORT__
  54. #error "please run this test in 32 bit int mode"
  55. #endif
  56.  
  57. #include <stdio.h>
  58.  
  59. #define NTEST    100000L
  60. #define MAXRAND 0x7fffffffL    /* assuming 32 bit ints */
  61. #define ABS(X)    ( (X < 0) ? (-X) : X )
  62. extern long rand();
  63.  
  64. int main()
  65. {
  66.     double sig, e, expected, result, max_abs_err;
  67.     int twoexp;
  68.     register long i;
  69.     register long errs = 0;
  70.     register int s;
  71. #ifdef __STDC__
  72.     double ldexp(double, int);
  73.     double frexp(double, int *);
  74. #else
  75.     extern double ldexp();
  76.     extern double frexp();
  77. #endif
  78.  
  79.     max_abs_err = 0.0;
  80.     for(i = 0; i < NTEST; i++)
  81.     {
  82.     expected = ((double)(s = rand()) + (double)rand())/(double)(MAXRAND);
  83.     if(s > (MAXRAND >> 1)) expected = -expected;
  84.  
  85.     sig = frexp(expected, &twoexp);
  86.     if(ABS(sig) >= 1.0)
  87.     {
  88.         printf("sig > 1, %.4e: %.4e  %d\n", expected, sig, twoexp);
  89.         errs++;
  90.         continue;
  91.     }
  92.     
  93.     result = ldexp(sig, twoexp);
  94.     
  95.     e = (expected == 0.0) ? result : (result - expected)/expected;
  96.     if(e < 0) e = (-e);
  97.     if(e > 1.0e-6)
  98.     {
  99.         printf("%.8e: %.8e  E %.8e\n",
  100.            expected, result, e);
  101.         errs++;
  102.     }
  103.     if (e > max_abs_err) max_abs_err = e;
  104.     }
  105.     
  106.     printf("%ld Error(s), Max abs err %.14e\n", errs, max_abs_err);
  107.     return errs;
  108. }
  109. #endif /* TEST */
  110.