home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / unix / bsd / 4248 < prev    next >
Encoding:
Text File  |  1992-08-16  |  6.8 KB  |  281 lines

  1. Newsgroups: comp.unix.bsd
  2. Path: sparky!uunet!zaphod.mps.ohio-state.edu!menudo.uh.edu!sugar!karl
  3. From: karl@NeoSoft.com (Karl Lehenbauer)
  4. Subject: Bug Report: Missing strtod in 386BSD, plus code
  5. Organization: NeoSoft Communications Services -- (713) 684-5900
  6. Date: Sun, 16 Aug 1992 21:50:06 GMT
  7. Message-ID: <1992Aug16.215006.16480@NeoSoft.com>
  8. Lines: 271
  9.  
  10. The Texas chapter of Friends of 386BSD sends its greetings!  :-)
  11.  
  12. The strtod function is documented in /usr/src/lib/libc/stdlib/strtod.3,
  13. but the manpage says the function is not currently available, and
  14. it isn't.
  15.  
  16. Here is the free strtod.c from the Berkeley Tcl 6.4 release:
  17.  
  18. /* 
  19.  * strtod.c --
  20.  *
  21.  *    Source code for the "strtod" library procedure.
  22.  *
  23.  * Copyright 1988-1992 Regents of the University of California
  24.  * Permission to use, copy, modify, and distribute this
  25.  * software and its documentation for any purpose and without
  26.  * fee is hereby granted, provided that the above copyright
  27.  * notice appear in all copies.  The University of California
  28.  * makes no representations about the suitability of this
  29.  * software for any purpose.  It is provided "as is" without
  30.  * express or implied warranty.
  31.  */
  32.  
  33. #ifndef lint
  34. static char rcsid[] = "$Header: /user6/ouster/tcl/compat/RCS/strtod.c,v 1.1 92/01/03 16:39:02 ouster Exp $ SPRITE (Berkeley)";
  35. #endif /* not lint */
  36.  
  37. #include <stdlib.h>
  38. #include <ctype.h>
  39.  
  40. #ifndef TRUE
  41. #define TRUE 1
  42. #define FALSE 0
  43. #endif
  44. #ifndef NULL
  45. #define NULL 0
  46. #endif
  47.  
  48. static int maxExponent = 511;    /* Largest possible base 10 exponent.  Any
  49.                  * exponent larger than this will already
  50.                  * produce underflow or overflow, so there's
  51.                  * no need to worry about additional digits.
  52.                  */
  53. static double powersOf10[] = {    /* Table giving binary powers of 10.  Entry */
  54.     10.,            /* is 10^2^i.  Used to convert decimal */
  55.     100.,            /* exponents into floating-point numbers. */
  56.     1.0e4,
  57.     1.0e8,
  58.     1.0e16,
  59.     1.0e32,
  60.     1.0e64,
  61.     1.0e128,
  62.     1.0e256
  63. };
  64.  
  65. /*
  66.  *----------------------------------------------------------------------
  67.  *
  68.  * strtod --
  69.  *
  70.  *    This procedure converts a floating-point number from an ASCII
  71.  *    decimal representation to internal double-precision format.
  72.  *
  73.  * Results:
  74.  *    The return value is the double-precision floating-point
  75.  *    representation of the characters in string.  If endPtr isn't
  76.  *    NULL, then *endPtr is filled in with the address of the
  77.  *    next character after the last one that was part of the
  78.  *    floating-point number.
  79.  *
  80.  * Side effects:
  81.  *    None.
  82.  *
  83.  *----------------------------------------------------------------------
  84.  */
  85.  
  86. double
  87. strtod(string, endPtr)
  88.     char *string;        /* A decimal ASCII floating-point number,
  89.                  * optionally preceded by white space.
  90.                  * Must have form "-I.FE-X", where I is the
  91.                  * integer part of the mantissa, F is the
  92.                  * fractional part of the mantissa, and X
  93.                  * is the exponent.  Either of the signs
  94.                  * may be "+", "-", or omitted.  Either I
  95.                  * or F may be omitted, or both.  The decimal
  96.                  * point isn't necessary unless F is present.
  97.                  * The "E" may actually be an "e".  E and X
  98.                  * may both be omitted (but not just one).
  99.                  */
  100.     char **endPtr;        /* If non-NULL, store terminating character's
  101.                  * address here. */
  102. {
  103.     int sign, expSign = FALSE;
  104.     double fraction, dblExp, *d;
  105.     register char *p, c;
  106.     int exp = 0;        /* Exponent read from "EX" field. */
  107.     int fracExp = 0;        /* Exponent that derives from the fractional
  108.                  * part.  Under normal circumstatnces, it is
  109.                  * the negative of the number of digits in F.
  110.                  * However, if I is very long, the last digits
  111.                  * of I get dropped (otherwise a long I with a
  112.                  * large negative exponent could cause an
  113.                  * unnecessary overflow on I alone).  In this
  114.                  * case, fracExp is incremented one for each
  115.                  * dropped digit.
  116.                  */
  117.     int mantSize;        /* Number of digits in mantissa. */
  118.     int decPt;            /* Number of mantissa digits BEFORE decimal
  119.                  * point.
  120.                  */
  121.     char *pExp;            /* Temporarily holds location of exponent
  122.                  * in string.
  123.                  */
  124.  
  125.     /*
  126.      * Strip off leading blanks and check for a sign.
  127.      */
  128.  
  129.     p = string;
  130.     while (isspace(*p)) {
  131.     p += 1;
  132.     }
  133.     if (*p == '-') {
  134.     sign = TRUE;
  135.     p += 1;
  136.     } else {
  137.     if (*p == '+') {
  138.         p += 1;
  139.     }
  140.     sign = FALSE;
  141.     }
  142.  
  143.     /*
  144.      * Count the number of digits in the mantissa (including the decimal
  145.      * point), and also locate the decimal point.
  146.      */
  147.  
  148.     decPt = -1;
  149.     for (mantSize = 0; ; mantSize += 1)
  150.     {
  151.     c = *p;
  152.     if (!isdigit(c)) {
  153.         if ((c != '.') || (decPt >= 0)) {
  154.         break;
  155.         }
  156.         decPt = mantSize;
  157.     }
  158.     p += 1;
  159.     }
  160.  
  161.     /*
  162.      * Now suck up the digits in the mantissa.  Use two integers to
  163.      * collect 9 digits each (this is faster than using floating-point).
  164.      * If the mantissa has more than 18 digits, ignore the extras, since
  165.      * they can't affect the value anyway.
  166.      */
  167.     
  168.     pExp  = p;
  169.     p -= mantSize;
  170.     if (decPt < 0) {
  171.     decPt = mantSize;
  172.     } else {
  173.     mantSize -= 1;            /* One of the digits was the point. */
  174.     }
  175.     if (mantSize > 18) {
  176.     fracExp = decPt - 18;
  177.     mantSize = 18;
  178.     } else {
  179.     fracExp = decPt - mantSize;
  180.     }
  181.     if (mantSize == 0) {
  182.     fraction = 0.0;
  183.     p = string;
  184.     goto done;
  185.     } else {
  186.     int frac1, frac2;
  187.     frac1 = 0;
  188.     for ( ; mantSize > 9; mantSize -= 1)
  189.     {
  190.         c = *p;
  191.         p += 1;
  192.         if (c == '.') {
  193.         c = *p;
  194.         p += 1;
  195.         }
  196.         frac1 = 10*frac1 + (c - '0');
  197.     }
  198.     frac2 = 0;
  199.     for (; mantSize > 0; mantSize -= 1)
  200.     {
  201.         c = *p;
  202.         p += 1;
  203.         if (c == '.') {
  204.         c = *p;
  205.         p += 1;
  206.         }
  207.         frac2 = 10*frac2 + (c - '0');
  208.     }
  209.     fraction = (1.0e9 * frac1) + frac2;
  210.     }
  211.  
  212.     /*
  213.      * Skim off the exponent.
  214.      */
  215.  
  216.     p = pExp;
  217.     if ((*p == 'E') || (*p == 'e')) {
  218.     p += 1;
  219.     if (*p == '-') {
  220.         expSign = TRUE;
  221.         p += 1;
  222.     } else {
  223.         if (*p == '+') {
  224.         p += 1;
  225.         }
  226.         expSign = FALSE;
  227.     }
  228.     while (isdigit(*p)) {
  229.         exp = exp * 10 + (*p - '0');
  230.         p += 1;
  231.     }
  232.     }
  233.     if (expSign) {
  234.     exp = fracExp - exp;
  235.     } else {
  236.     exp = fracExp + exp;
  237.     }
  238.  
  239.     /*
  240.      * Generate a floating-point number that represents the exponent.
  241.      * Do this by processing the exponent one bit at a time to combine
  242.      * many powers of 2 of 10. Then combine the exponent with the
  243.      * fraction.
  244.      */
  245.     
  246.     if (exp < 0) {
  247.     expSign = TRUE;
  248.     exp = -exp;
  249.     } else {
  250.     expSign = FALSE;
  251.     }
  252.     if (exp > maxExponent) {
  253.     exp = maxExponent;
  254.     }
  255.     dblExp = 1.0;
  256.     for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
  257.     if (exp & 01) {
  258.         dblExp *= *d;
  259.     }
  260.     }
  261.     if (expSign) {
  262.     fraction /= dblExp;
  263.     } else {
  264.     fraction *= dblExp;
  265.     }
  266.  
  267. done:
  268.     if (endPtr != NULL) {
  269.     *endPtr = p;
  270.     }
  271.  
  272.     if (sign) {
  273.     return -fraction;
  274.     }
  275.     return fraction;
  276. }
  277. -- 
  278. -- Email info@NeoSoft.com for info on getting interactive Internet access.
  279. You will now awaken feeling relaxed and refreshed, remembering everything 
  280. you've read except the details of the Omega contingency plan.
  281.