home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_09_07 / 9n07077a < prev    next >
Text File  |  1991-02-12  |  5KB  |  141 lines

  1.  
  2. /*  4.xBSD and AT&T V.3 documented entry points are
  3. ** #define ecvt(arg,ndigs,decexp,neg) cvt(arg,ndigs,decexp,neg,0)
  4. **  #define fcvt(arg,ndigs,decexp,neg) cvt(arg,ndigs,decexp,neg,1)
  5. ** and gcvt, for which a simplified version is given which
  6. ** does not strip trailing .0000
  7. ** Microsoft gcvt() has only 3 arguments (?)
  8. **
  9. ** Nota Bene:
  10. ** AT&T sense of 4th argument */
  11. typedef int LOGICAL;
  12. #include <math.h>
  13. #include "float.h"
  14.  
  15. extern struct {
  16.     double n[308];
  17.     double p[DBL_MAX_10_EXP];
  18. }      dp10_;
  19.  
  20. char *ecvt(value, ndigit, decpt, sign)
  21.     double value;
  22.     int ndigit, *decpt, *sign;
  23. {
  24.     char *cvt();
  25.     return (cvt(value, ndigit, decpt, sign, 0 ));
  26. }
  27.  
  28. char *fcvt(value, ndigit, decpt, sign)
  29.     double value;
  30.     int ndigit, *decpt, *sign;
  31. {
  32.     char *cvt();
  33.     return (cvt(value, ndigit, decpt, sign, 1 ));
  34. }
  35.  
  36. char *cvt(arg, ndigs, decexp, neg, ffmt)
  37.     register double arg;
  38.     int ndigs, *decexp;
  39.     LOGICAL *neg, ffmt;
  40. {
  41.     static char buf[80];        /* shouldn't need more than 25 */
  42.     long high, low;             /* assumed wide enough for 9+ digits */
  43. #ifdef __STDC__
  44. #include <limits.h>
  45. #if (LONG_MAX < 999999999)      /* uncomment #error if possible */
  46. /*#error "code assumes 9 digits fit in long"*/
  47. #endif
  48. #include <stdlib.h>
  49. #define split(a,b) (r=ldiv(a,b))
  50. #else
  51.     typedef struct {
  52.         long quot;
  53.         long rem;
  54.     }      ldiv_t;
  55. #ifdef sun
  56. #define split(a,b) (r.rem=a-(r.quot=a/b)*b)
  57. #else
  58. #define split(a,b) (r.quot=a/b,r.rem=a%b)
  59. #endif
  60. #endif
  61.     ldiv_t r;
  62.     int scale, totdigs, scalarg, maxscale;
  63.     char *bufptr;
  64.     register double x, dri;     /* accumulate powers of 10 */
  65.     LOGICAL pneg;
  66.     register int i;
  67. #define ODD(i) ((i)&1)          /* like Pascal */
  68.  
  69.     *decexp = 3;                /* so gcvt won't add 0's or exponent */
  70. #define isnan(arg) (arg != arg)
  71.     if (isnan(arg))
  72.         return "NaN";           /* Sun library has isnan(),isinf() * but IEEE
  73.                                    compliant compiler would recognize defines *
  74.                                    #define isinf(arg) (arg==1/0.) */
  75.     arg = (*neg = (arg < 0)) ? -arg : arg;      /* only gcvt() actually
  76.                                                    inserts '-' */
  77.     if (arg >= DBL_MAX*2) {
  78.         *decexp = 8;
  79.         return "Infinity";
  80.     }
  81.     if (arg == 0) {             /* don't force weird e format for 0 */
  82.         *decexp = 1;
  83.         return "0";
  84.     }
  85. /* search in table can be used instead of log()
  86. ** need negative powers in table
  87. ** speed up search by using log10() to find approximate index */
  88.     scalarg = (int) log10(arg) + (arg > 1);     /* ceil() in line */
  89.     if (scalarg >= DBL_MIN_10_EXP & scalarg <= DBL_MAX_10_EXP)
  90.         scalarg += (arg >= dp10_.p[scalarg]) - (arg < dp10_.p[scalarg - 1]);    /* adjust */
  91.     if ((scale = ffmt ? ndigs : ndigs - scalarg) > (maxscale = 18 - scalarg)) {
  92. /* reduce ndigs for 18 max */
  93.         ndigs += maxscale - scale;
  94.         scale = maxscale;
  95.     }
  96.     if (scale >= 14) {          /* extend range by splitting high end off
  97.                                    first */
  98.         if (scale - 14 <= DBL_MAX_10_EXP)
  99.             arg *= dp10_.p[scale - 14];
  100.         else {                  /* avoid overflow */
  101.             arg *= dp10_.p[DBL_MAX_10_EXP / 2];
  102.             arg *= dp10_.p[scale - 14 - DBL_MAX_10_EXP / 2];
  103.         }                       /* can't compare accurately with original arg */
  104.         low = arg = (arg - (high = arg)) * 1e5; /* split off 4 digits */
  105.         high = high * 100000 + low;     /* add 5 more */
  106.         low = (arg - low) * 1e9 + .5;   /* round off last 9 */
  107.     } else if (scale < 9) {     /* split low end off first */
  108.         high = 0;
  109.         if ((ndigs > 9) | ffmt) /* prevents violating table
  110.                                                    boundary */
  111.             arg -= (high = arg / dp10_.p[9 - scale]) * dp10_.p[9 - scale];
  112.         low = (scale < 0 ? arg / dp10_.p[-scale] : arg * dp10_.p[scale]) + .5;
  113.     } else {                    /* 9 <= scale < 14 */
  114.         arg *= dp10_.p[scale - 9];
  115.         low = (arg - (high = arg)) * 1e9 + .5;
  116.     }
  117.     high += low >= 1000000000;  /* carry from rounding */
  118.  
  119.  /* convert high//low to string */
  120.     *(bufptr = buf + 19) = '\0';
  121.     for (i = 0; ++i <= 9;) {
  122.         split(low, 10);
  123.         *(--bufptr) = r.rem + '0';
  124.         low = r.quot;
  125.         split(high, 10);
  126.         *(bufptr - 9) = r.rem + '0';
  127.         high = r.quot;
  128.     }
  129. /* discard leading zero */
  130.     for (totdigs = 18, bufptr -= 9; (bufptr[0] == '0') & (bufptr[1] != '\0'); ++bufptr)
  131.         --totdigs;
  132. /* one trailing zero ought to be discarded, in the case where it
  133. ** is the result of rounding up, so that, if the carry goes all the way
  134. ** across, totdigs will not be greater than requested
  135. ** also, trailing zeros beyond DBL_DIG can degrade accuracy of conversion back to binary */
  136.  
  137.     *decexp = totdigs - (ffmt ? ndigs : scale);
  138.  
  139.     return bufptr;
  140. }
  141.