gdtoaimp.h: update the Kmax definition. strtodg.c: initialize variables before use. general: Remove conditional sections for VAX and IBM mainframe. Remove conditional sections for pre-ANSI (K&R) function prototypes. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Daryl McDaniel <daryl.mcdaniel@intel.com> Reviewed-by: Erik Bjorge <erik.c.bjorge@intel.com> Reviewed-by: Jaben carsey <Jaben.carsey@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15874 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1022 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1022 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
  Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
 | 
						|
  This program and the accompanying materials are licensed and made available under
 | 
						|
  the terms and conditions of the BSD License that accompanies this distribution.
 | 
						|
  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
  *****************************************************************
 | 
						|
 | 
						|
  The author of this software is David M. Gay.
 | 
						|
 | 
						|
  Copyright (C) 1998-2001 by Lucent Technologies
 | 
						|
  All Rights Reserved
 | 
						|
 | 
						|
  Permission to use, copy, modify, and distribute this software and
 | 
						|
  its documentation for any purpose and without fee is hereby
 | 
						|
  granted, provided that the above copyright notice appear in all
 | 
						|
  copies and that both that the copyright notice and this
 | 
						|
  permission notice and warranty disclaimer appear in supporting
 | 
						|
  documentation, and that the name of Lucent or any of its entities
 | 
						|
  not be used in advertising or publicity pertaining to
 | 
						|
  distribution of the software without specific, written prior
 | 
						|
  permission.
 | 
						|
 | 
						|
  LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
 | 
						|
  IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
 | 
						|
  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 | 
						|
  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | 
						|
  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 | 
						|
  THIS SOFTWARE.
 | 
						|
 | 
						|
  Please send bug reports to David M. Gay (dmg at acm dot org,
 | 
						|
  with " at " changed at "@" and " dot " changed to ".").
 | 
						|
 | 
						|
  *****************************************************************
 | 
						|
 | 
						|
  NetBSD: strtodg.c,v 1.5.14.1 2008/04/08 21:10:55 jdc Exp
 | 
						|
**/
 | 
						|
#include  <LibConfig.h>
 | 
						|
 | 
						|
#include "gdtoaimp.h"
 | 
						|
 | 
						|
#ifdef USE_LOCALE
 | 
						|
#include "locale.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined(_MSC_VER)
 | 
						|
  // Disable warnings about assignment within conditional expressions.
 | 
						|
  #pragma warning ( disable : 4706 )
 | 
						|
#endif
 | 
						|
 | 
						|
 static CONST int
 | 
						|
fivesbits[] = {  0,  3,  5,  7, 10, 12, 14, 17, 19, 21,
 | 
						|
    24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
 | 
						|
    47, 49, 52
 | 
						|
#ifdef VAX
 | 
						|
    , 54, 56
 | 
						|
#endif
 | 
						|
    };
 | 
						|
 | 
						|
 Bigint *
 | 
						|
increment(Bigint *b)
 | 
						|
{
 | 
						|
  ULong *x, *xe;
 | 
						|
  Bigint *b1;
 | 
						|
#ifdef Pack_16
 | 
						|
  ULong carry = 1, y;
 | 
						|
#endif
 | 
						|
 | 
						|
  x = b->x;
 | 
						|
  xe = x + b->wds;
 | 
						|
#ifdef Pack_32
 | 
						|
  do {
 | 
						|
    if (*x < (ULong)0xffffffffL) {
 | 
						|
      ++*x;
 | 
						|
      return b;
 | 
						|
      }
 | 
						|
    *x++ = 0;
 | 
						|
    } while(x < xe);
 | 
						|
#else
 | 
						|
  do {
 | 
						|
    y = *x + carry;
 | 
						|
    carry = y >> 16;
 | 
						|
    *x++ = y & 0xffff;
 | 
						|
    if (!carry)
 | 
						|
      return b;
 | 
						|
    } while(x < xe);
 | 
						|
  if (carry)
 | 
						|
#endif
 | 
						|
  {
 | 
						|
    if (b->wds >= b->maxwds) {
 | 
						|
      b1 = Balloc(b->k+1);
 | 
						|
      if (b1 == NULL)
 | 
						|
        return NULL;
 | 
						|
      Bcopy(b1,b);
 | 
						|
      Bfree(b);
 | 
						|
      b = b1;
 | 
						|
      }
 | 
						|
    b->x[b->wds++] = 1;
 | 
						|
    }
 | 
						|
  return b;
 | 
						|
  }
 | 
						|
 | 
						|
 int
 | 
						|
decrement(Bigint *b)
 | 
						|
{
 | 
						|
  ULong *x, *xe;
 | 
						|
#ifdef Pack_16
 | 
						|
  ULong borrow = 1, y;
 | 
						|
#endif
 | 
						|
 | 
						|
  x = b->x;
 | 
						|
  xe = x + b->wds;
 | 
						|
#ifdef Pack_32
 | 
						|
  do {
 | 
						|
    if (*x) {
 | 
						|
      --*x;
 | 
						|
      break;
 | 
						|
      }
 | 
						|
    *x++ = 0xffffffffUL;
 | 
						|
    }
 | 
						|
    while(x < xe);
 | 
						|
#else
 | 
						|
  do {
 | 
						|
    y = *x - borrow;
 | 
						|
    borrow = (y & 0x10000) >> 16;
 | 
						|
    *x++ = y & 0xffff;
 | 
						|
    } while(borrow && x < xe);
 | 
						|
#endif
 | 
						|
  return STRTOG_Inexlo;
 | 
						|
  }
 | 
						|
 | 
						|
 static int
 | 
						|
all_on(CONST Bigint *b, int n)
 | 
						|
{
 | 
						|
  CONST ULong *x, *xe;
 | 
						|
 | 
						|
  x = b->x;
 | 
						|
  xe = x + ((unsigned int)n >> kshift);
 | 
						|
  while(x < xe)
 | 
						|
    if ((*x++ & ALL_ON) != ALL_ON)
 | 
						|
      return 0;
 | 
						|
  if (n &= kmask)
 | 
						|
    return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
 | 
						|
  return 1;
 | 
						|
  }
 | 
						|
 | 
						|
 Bigint *
 | 
						|
set_ones(Bigint *b, int n)
 | 
						|
{
 | 
						|
  int k;
 | 
						|
  ULong *x, *xe;
 | 
						|
 | 
						|
  k = (unsigned int)(n + ((1 << kshift) - 1)) >> kshift;
 | 
						|
  if (b->k < k) {
 | 
						|
    Bfree(b);
 | 
						|
    b = Balloc(k);
 | 
						|
    if (b == NULL)
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  k = (unsigned int)n >> kshift;
 | 
						|
  if (n &= kmask)
 | 
						|
    k++;
 | 
						|
  b->wds = k;
 | 
						|
  x = b->x;
 | 
						|
  xe = x + k;
 | 
						|
  while(x < xe)
 | 
						|
    *x++ = ALL_ON;
 | 
						|
  if (n)
 | 
						|
    x[-1] >>= ULbits - n;
 | 
						|
  return b;
 | 
						|
  }
 | 
						|
 | 
						|
 static int
 | 
						|
rvOK (
 | 
						|
  double d, CONST FPI *fpi, Long *expt, ULong *bits, int exact, int rd, int *irv
 | 
						|
)
 | 
						|
{
 | 
						|
  Bigint *b;
 | 
						|
  ULong carry, inex, lostbits;
 | 
						|
  int bdif, e, j, k, k1, nb, rv;
 | 
						|
 | 
						|
  carry = rv = 0;
 | 
						|
  b = d2b(d, &e, &bdif);
 | 
						|
  bdif -= nb = fpi->nbits;
 | 
						|
  e += bdif;
 | 
						|
  if (bdif <= 0) {
 | 
						|
    if (exact)
 | 
						|
      goto trunc;
 | 
						|
    goto ret;
 | 
						|
    }
 | 
						|
  if (P == nb) {
 | 
						|
    if (
 | 
						|
#ifndef IMPRECISE_INEXACT
 | 
						|
      exact &&
 | 
						|
#endif
 | 
						|
      fpi->rounding ==
 | 
						|
#ifdef RND_PRODQUOT
 | 
						|
          FPI_Round_near
 | 
						|
#else
 | 
						|
          Flt_Rounds
 | 
						|
#endif
 | 
						|
      ) goto trunc;
 | 
						|
    goto ret;
 | 
						|
    }
 | 
						|
  switch(rd) {
 | 
						|
    case 1:
 | 
						|
    goto trunc;
 | 
						|
    case 2:
 | 
						|
    break;
 | 
						|
    default: /* round near */
 | 
						|
    k = bdif - 1;
 | 
						|
    if (!k) {
 | 
						|
      if (!exact)
 | 
						|
        goto ret;
 | 
						|
      if (b->x[0] & 2)
 | 
						|
        break;
 | 
						|
      goto trunc;
 | 
						|
      }
 | 
						|
    if (b->x[(unsigned int)k>>kshift] & ((ULong)1 << (k & kmask)))
 | 
						|
      break;
 | 
						|
    goto trunc;
 | 
						|
    }
 | 
						|
  /* "break" cases: round up 1 bit, then truncate; bdif > 0 */
 | 
						|
  carry = 1;
 | 
						|
 trunc:
 | 
						|
  inex = lostbits = 0;
 | 
						|
  if (bdif > 0) {
 | 
						|
    if ( (lostbits = any_on(b, bdif)) !=0)
 | 
						|
      inex = STRTOG_Inexlo;
 | 
						|
    rshift(b, bdif);
 | 
						|
    if (carry) {
 | 
						|
      inex = STRTOG_Inexhi;
 | 
						|
      b = increment(b);
 | 
						|
      if ( (j = nb & kmask) !=0)
 | 
						|
        j = ULbits - j;
 | 
						|
      if (hi0bits(b->x[b->wds - 1]) != j) {
 | 
						|
        if (!lostbits)
 | 
						|
          lostbits = b->x[0] & 1;
 | 
						|
        rshift(b, 1);
 | 
						|
        e++;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  else if (bdif < 0)
 | 
						|
    b = lshift(b, -bdif);
 | 
						|
  if (e < fpi->emin) {
 | 
						|
    k = fpi->emin - e;
 | 
						|
    e = fpi->emin;
 | 
						|
    if (k > nb || fpi->sudden_underflow) {
 | 
						|
      inex = b->wds = 0;
 | 
						|
      *irv = STRTOG_Underflow | STRTOG_Inexlo;
 | 
						|
      }
 | 
						|
    else {
 | 
						|
      k1 = k - 1;
 | 
						|
      if (k1 > 0 && !lostbits)
 | 
						|
        lostbits = any_on(b, k1);
 | 
						|
      if (!lostbits && !exact)
 | 
						|
        goto ret;
 | 
						|
      lostbits |=
 | 
						|
        carry = b->x[(unsigned int)k1>>kshift] &
 | 
						|
                     (ULong)(1 << ((unsigned int)k1 & kmask));
 | 
						|
      rshift(b, k);
 | 
						|
      *irv = STRTOG_Denormal;
 | 
						|
      if (carry) {
 | 
						|
        b = increment(b);
 | 
						|
        inex = STRTOG_Inexhi | STRTOG_Underflow;
 | 
						|
        }
 | 
						|
      else if (lostbits)
 | 
						|
        inex = STRTOG_Inexlo | STRTOG_Underflow;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  else if (e > fpi->emax) {
 | 
						|
    e = fpi->emax + 1;
 | 
						|
    *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
 | 
						|
#ifndef NO_ERRNO
 | 
						|
    errno = ERANGE;
 | 
						|
#endif
 | 
						|
    inex = b->wds = 0;
 | 
						|
    }
 | 
						|
  *expt = e;
 | 
						|
  copybits(bits, nb, b);
 | 
						|
  *irv |= inex;
 | 
						|
  rv = 1;
 | 
						|
 ret:
 | 
						|
  Bfree(b);
 | 
						|
  return rv;
 | 
						|
  }
 | 
						|
 | 
						|
 static int
 | 
						|
mantbits(double d)
 | 
						|
{
 | 
						|
  ULong L;
 | 
						|
  if ( (L = word1(d)) !=0)
 | 
						|
    return P - lo0bits(&L);
 | 
						|
  L = word0(d) | Exp_msk1;
 | 
						|
  return P - 32 - lo0bits(&L);
 | 
						|
  }
 | 
						|
 | 
						|
 int
 | 
						|
strtodg (
 | 
						|
  CONST char *s00, char **se, CONST FPI *fpi, Long *expt, ULong *bits
 | 
						|
)
 | 
						|
{
 | 
						|
  int abe = 0, abits = 0, asub;
 | 
						|
  int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
 | 
						|
  int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
 | 
						|
  int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
 | 
						|
  int sudden_underflow = 0; /* pacify gcc */
 | 
						|
  CONST char *s, *s0, *s1;
 | 
						|
  double adj, adj0, rv, tol;
 | 
						|
  Long L;
 | 
						|
  ULong y, z;
 | 
						|
  Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
 | 
						|
 | 
						|
  e2 = 0; /* XXX gcc */
 | 
						|
 | 
						|
  irv = STRTOG_Zero;
 | 
						|
  denorm = sign = nz0 = nz = 0;
 | 
						|
  dval(rv) = 0.;
 | 
						|
  rvb = 0;
 | 
						|
  nbits = fpi->nbits;
 | 
						|
  for(s = s00;;s++) switch(*s) {
 | 
						|
    case '-':
 | 
						|
      sign = 1;
 | 
						|
      /* FALLTHROUGH */
 | 
						|
    case '+':
 | 
						|
      if (*++s)
 | 
						|
        goto break2;
 | 
						|
      /* FALLTHROUGH */
 | 
						|
    case 0:
 | 
						|
      sign = 0;
 | 
						|
      irv = STRTOG_NoNumber;
 | 
						|
      s = s00;
 | 
						|
      goto ret;
 | 
						|
    case '\t':
 | 
						|
    case '\n':
 | 
						|
    case '\v':
 | 
						|
    case '\f':
 | 
						|
    case '\r':
 | 
						|
    case ' ':
 | 
						|
      continue;
 | 
						|
    default:
 | 
						|
      goto break2;
 | 
						|
    }
 | 
						|
 break2:
 | 
						|
  if (*s == '0') {
 | 
						|
#ifndef NO_HEX_FP
 | 
						|
    switch(s[1]) {
 | 
						|
      case 'x':
 | 
						|
      case 'X':
 | 
						|
      irv = gethex(&s, fpi, expt, &rvb, sign);
 | 
						|
      if (irv == STRTOG_NoNumber) {
 | 
						|
        s = s00;
 | 
						|
        sign = 0;
 | 
						|
        }
 | 
						|
      goto ret;
 | 
						|
      }
 | 
						|
#endif
 | 
						|
    nz0 = 1;
 | 
						|
    while(*++s == '0') ;
 | 
						|
    if (!*s)
 | 
						|
      goto ret;
 | 
						|
    }
 | 
						|
  sudden_underflow = fpi->sudden_underflow;
 | 
						|
  s0 = s;
 | 
						|
  y = z = 0;
 | 
						|
  for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
 | 
						|
    if (nd < 9)
 | 
						|
      y = 10*y + c - '0';
 | 
						|
    else if (nd < 16)
 | 
						|
      z = 10*z + c - '0';
 | 
						|
  nd0 = nd;
 | 
						|
#ifdef USE_LOCALE
 | 
						|
  if (c == *localeconv()->decimal_point)
 | 
						|
#else
 | 
						|
  if (c == '.')
 | 
						|
#endif
 | 
						|
    {
 | 
						|
    decpt = 1;
 | 
						|
    c = *++s;
 | 
						|
    if (!nd) {
 | 
						|
      for(; c == '0'; c = *++s)
 | 
						|
        nz++;
 | 
						|
      if (c > '0' && c <= '9') {
 | 
						|
        s0 = s;
 | 
						|
        nf += nz;
 | 
						|
        nz = 0;
 | 
						|
        goto have_dig;
 | 
						|
        }
 | 
						|
      goto dig_done;
 | 
						|
      }
 | 
						|
    for(; c >= '0' && c <= '9'; c = *++s) {
 | 
						|
 have_dig:
 | 
						|
      nz++;
 | 
						|
      if (c -= '0') {
 | 
						|
        nf += nz;
 | 
						|
        for(i = 1; i < nz; i++)
 | 
						|
          if (nd++ < 9)
 | 
						|
            y *= 10;
 | 
						|
          else if (nd <= DBL_DIG + 1)
 | 
						|
            z *= 10;
 | 
						|
        if (nd++ < 9)
 | 
						|
          y = 10*y + c;
 | 
						|
        else if (nd <= DBL_DIG + 1)
 | 
						|
          z = 10*z + c;
 | 
						|
        nz = 0;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 dig_done:
 | 
						|
  e = 0;
 | 
						|
  if (c == 'e' || c == 'E') {
 | 
						|
    if (!nd && !nz && !nz0) {
 | 
						|
      irv = STRTOG_NoNumber;
 | 
						|
      s = s00;
 | 
						|
      goto ret;
 | 
						|
      }
 | 
						|
    s00 = s;
 | 
						|
    esign = 0;
 | 
						|
    switch(c = *++s) {
 | 
						|
      case '-':
 | 
						|
        esign = 1;
 | 
						|
        /* FALLTHROUGH */
 | 
						|
      case '+':
 | 
						|
        c = *++s;
 | 
						|
      }
 | 
						|
    if (c >= '0' && c <= '9') {
 | 
						|
      while(c == '0')
 | 
						|
        c = *++s;
 | 
						|
      if (c > '0' && c <= '9') {
 | 
						|
        L = c - '0';
 | 
						|
        s1 = s;
 | 
						|
        while((c = *++s) >= '0' && c <= '9')
 | 
						|
          L = 10*L + c - '0';
 | 
						|
        if (s - s1 > 8 || L > 19999)
 | 
						|
          /* Avoid confusion from exponents
 | 
						|
           * so large that e might overflow.
 | 
						|
           */
 | 
						|
          e = 19999; /* safe for 16 bit ints */
 | 
						|
        else
 | 
						|
          e = (int)L;
 | 
						|
        if (esign)
 | 
						|
          e = -e;
 | 
						|
        }
 | 
						|
      else
 | 
						|
        e = 0;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      s = s00;
 | 
						|
    }
 | 
						|
  if (!nd) {
 | 
						|
    if (!nz && !nz0) {
 | 
						|
#ifdef INFNAN_CHECK
 | 
						|
      /* Check for Nan and Infinity */
 | 
						|
      if (!decpt)
 | 
						|
       switch(c) {
 | 
						|
        case 'i':
 | 
						|
        case 'I':
 | 
						|
        if (match(&s,"nf")) {
 | 
						|
          --s;
 | 
						|
          if (!match(&s,"inity"))
 | 
						|
            ++s;
 | 
						|
          irv = STRTOG_Infinite;
 | 
						|
          goto infnanexp;
 | 
						|
          }
 | 
						|
        break;
 | 
						|
        case 'n':
 | 
						|
        case 'N':
 | 
						|
        if (match(&s, "an")) {
 | 
						|
          irv = STRTOG_NaN;
 | 
						|
          *expt = fpi->emax + 1;
 | 
						|
#ifndef No_Hex_NaN
 | 
						|
          if (*s == '(') /*)*/
 | 
						|
            irv = hexnan(&s, fpi, bits);
 | 
						|
#endif
 | 
						|
          goto infnanexp;
 | 
						|
          }
 | 
						|
        }
 | 
						|
#endif /* INFNAN_CHECK */
 | 
						|
      irv = STRTOG_NoNumber;
 | 
						|
      s = s00;
 | 
						|
      }
 | 
						|
    goto ret;
 | 
						|
    }
 | 
						|
 | 
						|
  irv = STRTOG_Normal;
 | 
						|
  e1 = e -= nf;
 | 
						|
  rd = 0;
 | 
						|
  switch(fpi->rounding & 3) {
 | 
						|
    case FPI_Round_up:
 | 
						|
    rd = 2 - sign;
 | 
						|
    break;
 | 
						|
    case FPI_Round_zero:
 | 
						|
    rd = 1;
 | 
						|
    break;
 | 
						|
    case FPI_Round_down:
 | 
						|
    rd = 1 + sign;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Now we have nd0 digits, starting at s0, followed by a
 | 
						|
   * decimal point, followed by nd-nd0 digits.  The number we're
 | 
						|
   * after is the integer represented by those digits times
 | 
						|
   * 10**e */
 | 
						|
 | 
						|
  if (!nd0)
 | 
						|
    nd0 = nd;
 | 
						|
  k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
 | 
						|
  dval(rv) = (double)y;
 | 
						|
  if (k > 9)
 | 
						|
    dval(rv) = tens[k - 9] * dval(rv) + z;
 | 
						|
  bd0 = 0;
 | 
						|
  if (nbits <= P && nd <= DBL_DIG) {
 | 
						|
    if (!e) {
 | 
						|
      if (rvOK(dval(rv), fpi, expt, bits, 1, rd, &irv))
 | 
						|
        goto ret;
 | 
						|
      }
 | 
						|
    else if (e > 0) {
 | 
						|
      if (e <= Ten_pmax) {
 | 
						|
        i = fivesbits[e] + mantbits(dval(rv)) <= P;
 | 
						|
        /* rv = */ rounded_product(dval(rv), tens[e]);
 | 
						|
        if (rvOK(dval(rv), fpi, expt, bits, i, rd, &irv))
 | 
						|
          goto ret;
 | 
						|
        e1 -= e;
 | 
						|
        goto rv_notOK;
 | 
						|
        }
 | 
						|
      i = DBL_DIG - nd;
 | 
						|
      if (e <= Ten_pmax + i) {
 | 
						|
        /* A fancier test would sometimes let us do
 | 
						|
         * this for larger i values.
 | 
						|
         */
 | 
						|
        e2 = e - i;
 | 
						|
        e1 -= i;
 | 
						|
        dval(rv) *= tens[i];
 | 
						|
        /* rv = */ rounded_product(dval(rv), tens[e2]);
 | 
						|
        if (rvOK(dval(rv), fpi, expt, bits, 0, rd, &irv))
 | 
						|
          goto ret;
 | 
						|
        e1 -= e2;
 | 
						|
        }
 | 
						|
      }
 | 
						|
#ifndef Inaccurate_Divide
 | 
						|
    else if (e >= -Ten_pmax) {
 | 
						|
      /* rv = */ rounded_quotient(dval(rv), tens[-e]);
 | 
						|
      if (rvOK(dval(rv), fpi, expt, bits, 0, rd, &irv))
 | 
						|
        goto ret;
 | 
						|
      e1 -= e;
 | 
						|
      }
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 rv_notOK:
 | 
						|
  e1 += nd - k;
 | 
						|
 | 
						|
  /* Get starting approximation = rv * 10**e1 */
 | 
						|
 | 
						|
  e2 = 0;
 | 
						|
  if (e1 > 0) {
 | 
						|
    if ( (i = e1 & 15) !=0)
 | 
						|
      dval(rv) *= tens[i];
 | 
						|
    if (e1 &= ~15) {
 | 
						|
      e1 = (unsigned int)e1 >> 4;
 | 
						|
      while(e1 >= (1 << (n_bigtens-1))) {
 | 
						|
        e2 += (unsigned int)((word0(rv) & Exp_mask)
 | 
						|
          >> Exp_shift1) - Bias;
 | 
						|
        word0(rv) &= ~Exp_mask;
 | 
						|
        word0(rv) |= Bias << Exp_shift1;
 | 
						|
        dval(rv) *= bigtens[n_bigtens-1];
 | 
						|
        e1 -= 1 << (n_bigtens-1);
 | 
						|
        }
 | 
						|
      e2 += (unsigned int)((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
 | 
						|
      word0(rv) &= ~Exp_mask;
 | 
						|
      word0(rv) |= Bias << Exp_shift1;
 | 
						|
      for(j = 0; e1 > 0; j++, e1 = (unsigned int)e1 >> 1)
 | 
						|
        if (e1 & 1)
 | 
						|
          dval(rv) *= bigtens[j];
 | 
						|
      }
 | 
						|
    }
 | 
						|
  else if (e1 < 0) {
 | 
						|
    e1 = -e1;
 | 
						|
    if ( (i = e1 & 15) !=0)
 | 
						|
      dval(rv) /= tens[i];
 | 
						|
    if (e1 &= ~15) {
 | 
						|
      e1 = (unsigned int)e1 >> 4;
 | 
						|
      while(e1 >= (1 << (n_bigtens-1))) {
 | 
						|
        e2 += (unsigned int)((word0(rv) & Exp_mask)
 | 
						|
          >> Exp_shift1) - Bias;
 | 
						|
        word0(rv) &= ~Exp_mask;
 | 
						|
        word0(rv) |= Bias << Exp_shift1;
 | 
						|
        dval(rv) *= tinytens[n_bigtens-1];
 | 
						|
        e1 -= 1 << (n_bigtens-1);
 | 
						|
        }
 | 
						|
      e2 += (unsigned int)((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
 | 
						|
      word0(rv) &= ~Exp_mask;
 | 
						|
      word0(rv) |= Bias << Exp_shift1;
 | 
						|
      for(j = 0; e1 > 0; j++, e1 = (unsigned int)e1 >> 1)
 | 
						|
        if (e1 & 1)
 | 
						|
          dval(rv) *= tinytens[j];
 | 
						|
      }
 | 
						|
    }
 | 
						|
  rvb = d2b(dval(rv), &rve, &rvbits); /* rv = rvb * 2^rve */
 | 
						|
  if (rvb == NULL)
 | 
						|
    return STRTOG_NoMemory;
 | 
						|
  rve += e2;
 | 
						|
  if ((j = rvbits - nbits) > 0) {
 | 
						|
    rshift(rvb, j);
 | 
						|
    rvbits = nbits;
 | 
						|
    rve += j;
 | 
						|
    }
 | 
						|
  bb0 = 0;  /* trailing zero bits in rvb */
 | 
						|
  e2 = rve + rvbits - nbits;
 | 
						|
  if (e2 > fpi->emax + 1)
 | 
						|
    goto huge;
 | 
						|
  rve1 = rve + rvbits - nbits;
 | 
						|
  if (e2 < (emin = fpi->emin)) {
 | 
						|
    denorm = 1;
 | 
						|
    j = rve - emin;
 | 
						|
    if (j > 0) {
 | 
						|
      rvb = lshift(rvb, j);
 | 
						|
      rvbits += j;
 | 
						|
      }
 | 
						|
    else if (j < 0) {
 | 
						|
      rvbits += j;
 | 
						|
      if (rvbits <= 0) {
 | 
						|
        if (rvbits < -1) {
 | 
						|
 ufl:
 | 
						|
          rvb->wds = 0;
 | 
						|
          rvb->x[0] = 0;
 | 
						|
          *expt = emin;
 | 
						|
          irv = STRTOG_Underflow | STRTOG_Inexlo;
 | 
						|
          goto ret;
 | 
						|
          }
 | 
						|
        rvb->x[0] = rvb->wds = rvbits = 1;
 | 
						|
        }
 | 
						|
      else
 | 
						|
        rshift(rvb, -j);
 | 
						|
      }
 | 
						|
    rve = rve1 = emin;
 | 
						|
    if (sudden_underflow && e2 + 1 < emin)
 | 
						|
      goto ufl;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Now the hard part -- adjusting rv to the correct value.*/
 | 
						|
 | 
						|
  /* Put digits into bd: true value = bd * 10^e */
 | 
						|
 | 
						|
  bd0 = s2b(s0, nd0, nd, y);
 | 
						|
 | 
						|
  for(;;) {
 | 
						|
    bd = Balloc(bd0->k);
 | 
						|
    if (bd == NULL)
 | 
						|
      return STRTOG_NoMemory;
 | 
						|
    Bcopy(bd, bd0);
 | 
						|
    bb = Balloc(rvb->k);
 | 
						|
    if (bb == NULL)
 | 
						|
      return STRTOG_NoMemory;
 | 
						|
    Bcopy(bb, rvb);
 | 
						|
    bbbits = rvbits - bb0;
 | 
						|
    bbe = rve + bb0;
 | 
						|
    bs = i2b(1);
 | 
						|
    if (bs == NULL)
 | 
						|
      return STRTOG_NoMemory;
 | 
						|
 | 
						|
    if (e >= 0) {
 | 
						|
      bb2 = bb5 = 0;
 | 
						|
      bd2 = bd5 = e;
 | 
						|
      }
 | 
						|
    else {
 | 
						|
      bb2 = bb5 = -e;
 | 
						|
      bd2 = bd5 = 0;
 | 
						|
      }
 | 
						|
    if (bbe >= 0)
 | 
						|
      bb2 += bbe;
 | 
						|
    else
 | 
						|
      bd2 -= bbe;
 | 
						|
    bs2 = bb2;
 | 
						|
    j = nbits + 1 - bbbits;
 | 
						|
    i = bbe + bbbits - nbits;
 | 
						|
    if (i < emin) /* denormal */
 | 
						|
      j += i - emin;
 | 
						|
    bb2 += j;
 | 
						|
    bd2 += j;
 | 
						|
    i = bb2 < bd2 ? bb2 : bd2;
 | 
						|
    if (i > bs2)
 | 
						|
      i = bs2;
 | 
						|
    if (i > 0) {
 | 
						|
      bb2 -= i;
 | 
						|
      bd2 -= i;
 | 
						|
      bs2 -= i;
 | 
						|
      }
 | 
						|
    if (bb5 > 0) {
 | 
						|
      bs = pow5mult(bs, bb5);
 | 
						|
      if (bs == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      bb1 = mult(bs, bb);
 | 
						|
      if (bb1 == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      Bfree(bb);
 | 
						|
      bb = bb1;
 | 
						|
      }
 | 
						|
    bb2 -= bb0;
 | 
						|
    if (bb2 > 0) {
 | 
						|
      bb = lshift(bb, bb2);
 | 
						|
      if (bb == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      }
 | 
						|
    else if (bb2 < 0)
 | 
						|
      rshift(bb, -bb2);
 | 
						|
    if (bd5 > 0) {
 | 
						|
      bd = pow5mult(bd, bd5);
 | 
						|
      if (bd == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      }
 | 
						|
    if (bd2 > 0) {
 | 
						|
      bd = lshift(bd, bd2);
 | 
						|
      if (bd == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      }
 | 
						|
    if (bs2 > 0) {
 | 
						|
      bs = lshift(bs, bs2);
 | 
						|
      if (bs == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      }
 | 
						|
    asub = 1;
 | 
						|
    inex = STRTOG_Inexhi;
 | 
						|
    delta = diff(bb, bd);
 | 
						|
    if (delta == NULL)
 | 
						|
      return STRTOG_NoMemory;
 | 
						|
    if (delta->wds <= 1 && !delta->x[0])
 | 
						|
      break;
 | 
						|
    dsign = delta->sign;
 | 
						|
    delta->sign = finished = 0;
 | 
						|
    L = 0;
 | 
						|
    i = cmp(delta, bs);
 | 
						|
    if (rd && i <= 0) {
 | 
						|
      irv = STRTOG_Normal;
 | 
						|
      if ( (finished = dsign ^ (rd&1)) !=0) {
 | 
						|
        if (dsign != 0) {
 | 
						|
          irv |= STRTOG_Inexhi;
 | 
						|
          goto adj1;
 | 
						|
          }
 | 
						|
        irv |= STRTOG_Inexlo;
 | 
						|
        if (rve1 == emin)
 | 
						|
          goto adj1;
 | 
						|
        for(i = 0, j = nbits; j >= ULbits;
 | 
						|
            i++, j -= ULbits) {
 | 
						|
          if (rvb->x[i] & ALL_ON)
 | 
						|
            goto adj1;
 | 
						|
          }
 | 
						|
        if (j > 1 && lo0bits(rvb->x + i) < j - 1)
 | 
						|
          goto adj1;
 | 
						|
        rve = rve1 - 1;
 | 
						|
        rvb = set_ones(rvb, rvbits = nbits);
 | 
						|
        if (rvb == NULL)
 | 
						|
          return STRTOG_NoMemory;
 | 
						|
        break;
 | 
						|
        }
 | 
						|
      irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
 | 
						|
      break;
 | 
						|
      }
 | 
						|
    if (i < 0) {
 | 
						|
      /* Error is less than half an ulp -- check for
 | 
						|
       * special case of mantissa a power of two.
 | 
						|
       */
 | 
						|
      irv = dsign
 | 
						|
        ? STRTOG_Normal | STRTOG_Inexlo
 | 
						|
        : STRTOG_Normal | STRTOG_Inexhi;
 | 
						|
      if (dsign || bbbits > 1 || denorm || rve1 == emin)
 | 
						|
        break;
 | 
						|
      delta = lshift(delta,1);
 | 
						|
      if (delta == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      if (cmp(delta, bs) > 0) {
 | 
						|
        irv = STRTOG_Normal | STRTOG_Inexlo;
 | 
						|
        goto drop_down;
 | 
						|
        }
 | 
						|
      break;
 | 
						|
      }
 | 
						|
    if (i == 0) {
 | 
						|
      /* exactly half-way between */
 | 
						|
      if (dsign) {
 | 
						|
        if (denorm && all_on(rvb, rvbits)) {
 | 
						|
          /*boundary case -- increment exponent*/
 | 
						|
          rvb->wds = 1;
 | 
						|
          rvb->x[0] = 1;
 | 
						|
          rve = emin + nbits - (rvbits = 1);
 | 
						|
          irv = STRTOG_Normal | STRTOG_Inexhi;
 | 
						|
          denorm = 0;
 | 
						|
          break;
 | 
						|
          }
 | 
						|
        irv = STRTOG_Normal | STRTOG_Inexlo;
 | 
						|
        }
 | 
						|
      else if (bbbits == 1) {
 | 
						|
        irv = STRTOG_Normal;
 | 
						|
 drop_down:
 | 
						|
        /* boundary case -- decrement exponent */
 | 
						|
        if (rve1 == emin) {
 | 
						|
          irv = STRTOG_Normal | STRTOG_Inexhi;
 | 
						|
          if (rvb->wds == 1 && rvb->x[0] == 1)
 | 
						|
            sudden_underflow = 1;
 | 
						|
          break;
 | 
						|
          }
 | 
						|
        rve -= nbits;
 | 
						|
        rvb = set_ones(rvb, rvbits = nbits);
 | 
						|
        if (rvb == NULL)
 | 
						|
          return STRTOG_NoMemory;
 | 
						|
        break;
 | 
						|
        }
 | 
						|
      else
 | 
						|
        irv = STRTOG_Normal | STRTOG_Inexhi;
 | 
						|
      if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
 | 
						|
        break;
 | 
						|
      if (dsign) {
 | 
						|
        rvb = increment(rvb);
 | 
						|
        if (rvb == NULL)
 | 
						|
          return STRTOG_NoMemory;
 | 
						|
        if ( (j = rvbits & kmask) !=0)
 | 
						|
          j = ULbits - j;
 | 
						|
        if (hi0bits(rvb->x[(unsigned int)(rvb->wds - 1)
 | 
						|
               >> kshift])
 | 
						|
            != j)
 | 
						|
          rvbits++;
 | 
						|
        irv = STRTOG_Normal | STRTOG_Inexhi;
 | 
						|
        }
 | 
						|
      else {
 | 
						|
        if (bbbits == 1)
 | 
						|
          goto undfl;
 | 
						|
        decrement(rvb);
 | 
						|
        irv = STRTOG_Normal | STRTOG_Inexlo;
 | 
						|
        }
 | 
						|
      break;
 | 
						|
      }
 | 
						|
    if ((dval(adj) = ratio(delta, bs)) <= 2.) {
 | 
						|
 adj1:
 | 
						|
      inex = STRTOG_Inexlo;
 | 
						|
      if (dsign) {
 | 
						|
        asub = 0;
 | 
						|
        inex = STRTOG_Inexhi;
 | 
						|
        }
 | 
						|
      else if (denorm && bbbits <= 1) {
 | 
						|
 undfl:
 | 
						|
        rvb->wds = 0;
 | 
						|
        rve = emin;
 | 
						|
        irv = STRTOG_Underflow | STRTOG_Inexlo;
 | 
						|
        break;
 | 
						|
        }
 | 
						|
      adj0 = dval(adj) = 1.;
 | 
						|
      }
 | 
						|
    else {
 | 
						|
      adj0 = dval(adj) *= 0.5;
 | 
						|
      if (dsign) {
 | 
						|
        asub = 0;
 | 
						|
        inex = STRTOG_Inexlo;
 | 
						|
        }
 | 
						|
      if (dval(adj) < 2147483647.) {
 | 
						|
        L = (Long)adj0;
 | 
						|
        adj0 -= L;
 | 
						|
        switch(rd) {
 | 
						|
          case 0:
 | 
						|
          if (adj0 >= .5)
 | 
						|
            goto inc_L;
 | 
						|
          break;
 | 
						|
          case 1:
 | 
						|
          if (asub && adj0 > 0.)
 | 
						|
            goto inc_L;
 | 
						|
          break;
 | 
						|
          case 2:
 | 
						|
          if (!asub && adj0 > 0.) {
 | 
						|
inc_L:
 | 
						|
            L++;
 | 
						|
            inex = STRTOG_Inexact - inex;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        dval(adj) = (double)L;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    y = rve + rvbits;
 | 
						|
 | 
						|
    /* adj *= ulp(dval(rv)); */
 | 
						|
    /* if (asub) rv -= adj; else rv += adj; */
 | 
						|
 | 
						|
    if (!denorm && rvbits < nbits) {
 | 
						|
      rvb = lshift(rvb, j = nbits - rvbits);
 | 
						|
      if (rvb == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      rve -= j;
 | 
						|
      rvbits = nbits;
 | 
						|
      }
 | 
						|
    ab = d2b(dval(adj), &abe, &abits);
 | 
						|
    if (ab == NULL)
 | 
						|
      return STRTOG_NoMemory;
 | 
						|
    if (abe < 0)
 | 
						|
      rshift(ab, -abe);
 | 
						|
    else if (abe > 0)
 | 
						|
      ab = lshift(ab, abe);
 | 
						|
    rvb0 = rvb;
 | 
						|
    if (asub) {
 | 
						|
      /* rv -= adj; */
 | 
						|
      j = hi0bits(rvb->x[rvb->wds-1]);
 | 
						|
      rvb = diff(rvb, ab);
 | 
						|
      if (rvb == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      k = rvb0->wds - 1;
 | 
						|
      if (denorm)
 | 
						|
        /* do nothing */;
 | 
						|
      else if (rvb->wds <= k
 | 
						|
        || hi0bits( rvb->x[k]) >
 | 
						|
           hi0bits(rvb0->x[k])) {
 | 
						|
        /* unlikely; can only have lost 1 high bit */
 | 
						|
        if (rve1 == emin) {
 | 
						|
          --rvbits;
 | 
						|
          denorm = 1;
 | 
						|
          }
 | 
						|
        else {
 | 
						|
          rvb = lshift(rvb, 1);
 | 
						|
          if (rvb == NULL)
 | 
						|
            return STRTOG_NoMemory;
 | 
						|
          --rve;
 | 
						|
          --rve1;
 | 
						|
          L = finished = 0;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    else {
 | 
						|
      rvb = sum(rvb, ab);
 | 
						|
      if (rvb == NULL)
 | 
						|
        return STRTOG_NoMemory;
 | 
						|
      k = rvb->wds - 1;
 | 
						|
      if (k >= rvb0->wds
 | 
						|
       || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
 | 
						|
        if (denorm) {
 | 
						|
          if (++rvbits == nbits)
 | 
						|
            denorm = 0;
 | 
						|
          }
 | 
						|
        else {
 | 
						|
          rshift(rvb, 1);
 | 
						|
          rve++;
 | 
						|
          rve1++;
 | 
						|
          L = 0;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    Bfree(ab);
 | 
						|
    Bfree(rvb0);
 | 
						|
    if (finished)
 | 
						|
      break;
 | 
						|
 | 
						|
    z = rve + rvbits;
 | 
						|
    if (y == z && L) {
 | 
						|
      /* Can we stop now? */
 | 
						|
      tol = dval(adj) * 5e-16; /* > max rel error */
 | 
						|
      dval(adj) = adj0 - .5;
 | 
						|
      if (dval(adj) < -tol) {
 | 
						|
        if (adj0 > tol) {
 | 
						|
          irv |= inex;
 | 
						|
          break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      else if (dval(adj) > tol && adj0 < 1. - tol) {
 | 
						|
        irv |= inex;
 | 
						|
        break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    bb0 = denorm ? 0 : trailz(rvb);
 | 
						|
    Bfree(bb);
 | 
						|
    Bfree(bd);
 | 
						|
    Bfree(bs);
 | 
						|
    Bfree(delta);
 | 
						|
    }
 | 
						|
  if (!denorm && (j = nbits - rvbits)) {
 | 
						|
    if (j > 0)
 | 
						|
      rvb = lshift(rvb, j);
 | 
						|
    else
 | 
						|
      rshift(rvb, -j);
 | 
						|
    rve -= j;
 | 
						|
    }
 | 
						|
  *expt = rve;
 | 
						|
  Bfree(bb);
 | 
						|
  Bfree(bd);
 | 
						|
  Bfree(bs);
 | 
						|
  Bfree(bd0);
 | 
						|
  Bfree(delta);
 | 
						|
  if (rve > fpi->emax) {
 | 
						|
 huge:
 | 
						|
    rvb->wds = 0;
 | 
						|
    irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
 | 
						|
#ifndef NO_ERRNO
 | 
						|
    errno = ERANGE;
 | 
						|
#endif
 | 
						|
#ifdef INFNAN_CHECK
 | 
						|
 infnanexp:
 | 
						|
#endif
 | 
						|
    *expt = fpi->emax + 1;
 | 
						|
    }
 | 
						|
 ret:
 | 
						|
  if (denorm) {
 | 
						|
    if (sudden_underflow) {
 | 
						|
      rvb->wds = 0;
 | 
						|
      irv = STRTOG_Underflow | STRTOG_Inexlo;
 | 
						|
      }
 | 
						|
    else  {
 | 
						|
      irv = (irv & ~STRTOG_Retmask) |
 | 
						|
        (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
 | 
						|
      if (irv & STRTOG_Inexact)
 | 
						|
        irv |= STRTOG_Underflow;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  if (se)
 | 
						|
    *se = __UNCONST(s);
 | 
						|
  if (sign)
 | 
						|
    irv |= STRTOG_Neg;
 | 
						|
  if (rvb) {
 | 
						|
    copybits(bits, nbits, rvb);
 | 
						|
    Bfree(rvb);
 | 
						|
    }
 | 
						|
  return irv;
 | 
						|
  }
 |