mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 14:27:52 +00:00 
			
		
		
		
	 a0d367299f
			
		
	
	
		a0d367299f
		
	
	
	
	
		
			
			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;
 | |
|   }
 |