home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / gnu / libsrc87 / fpprint.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-30  |  2.9 KB  |  144 lines

  1. /* formater for floating point numbers, called by printf and friends */
  2. /* written by Eric R. Smith */
  3. /* Please write something better! */
  4.  
  5. #include <ctype.h>
  6.  
  7. /* find the mantissa and exponent of a floating point number */
  8. /* this is similar to frexp, except we want to use base 10 instead of
  9.    base 2 */
  10. /* FIXME: there has GOT to be a better way to do this. */
  11.  
  12. /* Here is a (hopefully) new improved one, ++jrb */
  13.  
  14. /* bit struct of an ieee double */
  15. struct bitdouble {    
  16.     unsigned long sign  : 1;
  17.     unsigned long exp   : 11;
  18.     unsigned long mant1 : 20;
  19.     unsigned long mant2;
  20. };
  21.  
  22. static double decfrexp(value, exponent)
  23. double value;
  24. int *exponent;
  25. {
  26.     register struct bitdouble *p = (struct bitdouble *) &value;
  27.     register unsigned short e;
  28.     register short tene;
  29.     
  30.     tene = 0;
  31.     e =  p->exp;
  32.  
  33.     if(e > 1025)
  34.     {
  35.         for(; p->exp >= 1027; tene++)
  36.             value /= 10.0;
  37.         if((p->exp == 1026) && ( p->mant1 >= 0x40000))
  38.         {
  39.             value /= 10.0;
  40.             tene++;
  41.         }
  42.     }
  43.     else if(e < 1021)
  44.     {
  45.         for(; p->exp <= 1022; --tene)
  46.             value *= 10.0;
  47.     } 
  48.     /* else -- need to do nothing */
  49.  
  50.     *exponent = tene;
  51.     return value;
  52. }
  53.  
  54. /* format a floating point number */
  55.  
  56. void
  57. fp_print(value, format, precision, buf)
  58.     double     value;        /* the number to format */
  59.     int    format;        /* how to format it: really a char, for now */
  60.     int    precision;    /* precision, or # of places after '.' */
  61.     char    *buf;        /* buffer into which the result goes */
  62. {
  63.     int     digit;
  64.     int    exp;
  65.     double  mantissa;
  66.     int decpoint = 1;
  67.     int useexp = 1;
  68.     int ndigits;
  69.  
  70.     if(precision == -1) /* ++jrb, prec not spec, use default prec */
  71.         precision = 6;
  72.  
  73.     if (value < 0.0) {
  74.         *buf++ = '-';
  75.         value = -value;
  76.     }
  77.  
  78.     /* ++jrb   round off at prec + 1 */    
  79.     for(mantissa = 0.5, ndigits = 0; ndigits < precision; ndigits++) 
  80.         mantissa /= 10.0;
  81.     value += mantissa;
  82.  
  83.     mantissa = decfrexp(value, &exp);
  84.     switch(format) {
  85.        case 'e': case 'E':
  86.         ndigits = precision + 1; /* one place in front of decimal */
  87.         break;
  88.        case 'g': case 'G':
  89.        default:
  90.         ndigits = precision;
  91.               if (exp >= -3 && exp < precision)
  92.                       useexp = 0;             /* use f format */
  93.         break;
  94.        case 'f':
  95.         if (exp < 0)
  96.             ndigits = precision + 1;
  97.         else
  98.             ndigits = precision + exp + 1;
  99.         useexp = 0;
  100.         break;
  101.     }
  102.  
  103. /* preliminaries for f format */
  104.     if (!useexp) {
  105.         if (exp < 0) {
  106.             *buf++ = '0'; *buf++ = '.';
  107.             ndigits--;
  108.             while (++exp < 0 && ndigits > 0) {
  109.                 *buf++ = '0'; ndigits--;
  110.             }
  111.             decpoint = -1;
  112.         }
  113.         else {
  114.             decpoint = exp + 1;
  115.         }
  116.     }
  117.  
  118.     while (ndigits > 0) {
  119.         digit = (int) (mantissa);
  120.         mantissa = (mantissa - (double) digit) * 10;
  121.         *buf++ = digit + '0';
  122.         if (--decpoint == 0)
  123.             *buf++ = '.';
  124.         --ndigits;
  125.     };
  126.  
  127.     if (useexp) {
  128.         *buf++ = (isupper(format)) ? 'E' : 'e';
  129.         if (exp < 0) {
  130.             *buf++ = '-';
  131.             exp = -exp;
  132.         }
  133.         else
  134.             *buf++ = '+';
  135.         if((digit = exp/100) > 0) {
  136.             *buf++ = digit + '0';
  137.             exp %= 100;
  138.         }
  139.         *buf++ = (exp/10) + '0';
  140.         *buf++ = (exp%10) + '0';
  141.     }
  142.     *buf++ = '\0';
  143. }
  144.