missing/strtod.c


DEFINITIONS

This source file includes following functions.
  1. strtod


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