home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / OS2 / EMXFIX04.ZIP / CVT.C < prev    next >
C/C++ Source or Header  |  1994-01-24  |  3KB  |  129 lines

  1. /* cvt.c (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes */
  2.  
  3. #include <sys/emx.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #include <float.h>
  8.  
  9.  
  10. /* Convert a non-zero floating point number to a string of decimal
  11.    digits and an exponent.  The position of the decimal point is
  12.    assumed to be after the first digit.  Examples:
  13.  
  14.    1234567890123456789 --> 1234567890123456789, xp = 18
  15.    123                 --> 1230000000000000000, xp =  2
  16.    12                  --> 1200000000000000000, xp =  1
  17.    1.2                 --> 1200000000000000000, xp =  0
  18.    0.12                --> 1200000000000000000, xp = -1
  19.  
  20.    This function assumes that
  21.  
  22.      LDBL_MANT_DIG <= 8 * sizeof (unsigned long long)
  23.  
  24.    which is true for the extended real format (64-bit mantissa).
  25.    There are algothms which are more precise, but they're MUCH more
  26.    complicated. */
  27.  
  28. int _cvt_float_decimal (DOUBLE x, char *dst)
  29. {
  30.   DOUBLE scaled;
  31.   unsigned long long intg;
  32.   int xp, len;
  33.  
  34.   xp = (int)FLOOR (LOG10 (x));
  35.   scaled = x * POW (10.0, DIG - 1 - xp);
  36.  
  37.   intg = (unsigned long long)scaled;
  38.   _ulltoa (intg, dst, 10);
  39.  
  40.   len = strlen (dst);
  41.   if (len > DIG + 1)
  42.     abort ();
  43.   else if (len == DIG + 1)
  44.     {
  45.       ++xp;
  46.       dst[DIG] = 0;
  47.     }
  48.   else if (len < DIG)
  49.     {
  50.       xp -= DIG - len;
  51.       memset (dst + len, '0', DIG - len);
  52.       dst[DIG] = 0;
  53.     }
  54.  
  55.   return (xp);
  56. }
  57.  
  58.  
  59. /* Round a string of digits for truncating after PREC digits.  Adjust
  60.    the exponent (pointed to by PXP) if required (for instance when
  61.    rounding "9999" to "1000"). */
  62.  
  63. void _cvt_round (char *dst, int *pxp, int prec, int lim)
  64. {
  65.  
  66.   /* Reduce the number of digits to the number of significant digits.
  67.    This is used to print zeros instead of `random' digits when
  68.    converting `double' floats with `long double' precision. */
  69.  
  70.   if (prec > lim)
  71.     prec = lim;                 /* LIM is always <= DIG */
  72.   if (prec < 1)
  73.     prec = 1;
  74.  
  75.   if (dst[prec] >= '5')
  76.     {
  77.       int i = prec;
  78.       while (i != 0 && dst[i-1] == '9')
  79.         {
  80.           dst[i-1] = '0';
  81.           --i;
  82.         }
  83.       if (i != 0)
  84.         ++dst[i-1];
  85.       else
  86.         {
  87.           memmove (dst + 1, dst, DIG - 1);
  88.           dst[0] = '1';
  89.           ++*pxp;
  90.         }
  91.     }
  92.   memset (dst + prec, '0', DIG - prec);
  93. }
  94.  
  95.  
  96. /* Remove trailing zeros from DIGITS for the "%g" format.  Keep at
  97.    least KEEP digits at the start of DIGITS. */
  98.  
  99. void _cvt_remove_zeros (char *digits, int keep)
  100. {
  101.   int i;
  102.  
  103.   i = strlen (digits) - 1;
  104.   while (i >= keep && digits[i] == '0')
  105.     --i;
  106.   digits[i+1] = 0;
  107. }
  108.  
  109.  
  110. const char *_cvt_nan (int xam)
  111. {
  112.   switch (xam)
  113.     {
  114.     case FX_P_NAN:
  115.     case FX_N_NAN:
  116.       return ("#NAN");
  117.     case FX_P_INFINITY:
  118.       return ("#INF");
  119.     case FX_N_INFINITY:
  120.       return ("-#INF");
  121.     case FX_P_EMPTY:
  122.       return ("#EMP");
  123.     case FX_N_EMPTY:
  124.       return ("-#EMP");
  125.     default:
  126.       return (NULL);
  127.     }
  128. }
  129.