1/**************************************************************** 2 3The author of this software is David M. Gay. 4 5Copyright (C) 1998 by Lucent Technologies 6All Rights Reserved 7 8Permission to use, copy, modify, and distribute this software and 9its documentation for any purpose and without fee is hereby 10granted, provided that the above copyright notice appear in all 11copies and that both that the copyright notice and this 12permission notice and warranty disclaimer appear in supporting 13documentation, and that the name of Lucent or any of its entities 14not be used in advertising or publicity pertaining to 15distribution of the software without specific, written prior 16permission. 17 18LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 19INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 20IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 21SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 23IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 24ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 25THIS SOFTWARE. 26 27****************************************************************/ 28 29/* Please send bug reports to David M. Gay (dmg at acm dot org, 30 * with " at " changed at "@" and " dot " changed to "."). */ 31 32#include "gdtoaimp.h" 33 34#ifdef USE_LOCALE 35#include "locale.h" 36#endif 37 38 int 39#ifdef KR_headers 40gethex(sp, fpi, exp, bp, sign) 41 CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign; 42#else 43gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign) 44#endif 45{ 46 Bigint *b; 47 CONST unsigned char *decpt, *s0, *s, *s1; 48 int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret; 49 ULong L, lostbits, *x; 50 Long e, e1; 51#ifdef USE_LOCALE 52 int i; 53#ifdef NO_LOCALE_CACHE 54 const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point; 55#else 56 const unsigned char *decimalpoint; 57 static unsigned char *decimalpoint_cache; 58 if (!(s0 = decimalpoint_cache)) { 59 s0 = (unsigned char*)localeconv()->decimal_point;
| 1/**************************************************************** 2 3The author of this software is David M. Gay. 4 5Copyright (C) 1998 by Lucent Technologies 6All Rights Reserved 7 8Permission to use, copy, modify, and distribute this software and 9its documentation for any purpose and without fee is hereby 10granted, provided that the above copyright notice appear in all 11copies and that both that the copyright notice and this 12permission notice and warranty disclaimer appear in supporting 13documentation, and that the name of Lucent or any of its entities 14not be used in advertising or publicity pertaining to 15distribution of the software without specific, written prior 16permission. 17 18LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 19INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 20IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 21SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 23IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 24ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 25THIS SOFTWARE. 26 27****************************************************************/ 28 29/* Please send bug reports to David M. Gay (dmg at acm dot org, 30 * with " at " changed at "@" and " dot " changed to "."). */ 31 32#include "gdtoaimp.h" 33 34#ifdef USE_LOCALE 35#include "locale.h" 36#endif 37 38 int 39#ifdef KR_headers 40gethex(sp, fpi, exp, bp, sign) 41 CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign; 42#else 43gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign) 44#endif 45{ 46 Bigint *b; 47 CONST unsigned char *decpt, *s0, *s, *s1; 48 int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret; 49 ULong L, lostbits, *x; 50 Long e, e1; 51#ifdef USE_LOCALE 52 int i; 53#ifdef NO_LOCALE_CACHE 54 const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point; 55#else 56 const unsigned char *decimalpoint; 57 static unsigned char *decimalpoint_cache; 58 if (!(s0 = decimalpoint_cache)) { 59 s0 = (unsigned char*)localeconv()->decimal_point;
|
203 k++; 204 b = Balloc(k); 205 x = b->x; 206 n = 0; 207 L = 0; 208#ifdef USE_LOCALE 209 for(i = 0; decimalpoint[i+1]; ++i); 210#endif 211 while(s1 > s0) { 212#ifdef USE_LOCALE 213 if (*--s1 == decimalpoint[i]) { 214 s1 -= i; 215 continue; 216 } 217#else 218 if (*--s1 == '.') 219 continue; 220#endif 221 if (n == ULbits) { 222 *x++ = L; 223 L = 0; 224 n = 0; 225 } 226 L |= (hexdig[*s1] & 0x0f) << n; 227 n += 4; 228 } 229 *x++ = L; 230 b->wds = n = x - b->x; 231 n = ULbits*n - hi0bits(L); 232 nbits = fpi->nbits; 233 lostbits = 0; 234 x = b->x; 235 if (n > nbits) { 236 n -= nbits; 237 if (any_on(b,n)) { 238 lostbits = 1; 239 k = n - 1; 240 if (x[k>>kshift] & 1 << (k & kmask)) { 241 lostbits = 2; 242 if (k > 0 && any_on(b,k)) 243 lostbits = 3; 244 } 245 } 246 rshift(b, n); 247 e += n; 248 } 249 else if (n < nbits) { 250 n = nbits - n; 251 b = lshift(b, n); 252 e -= n; 253 x = b->x; 254 } 255 if (e > fpi->emax) { 256 ovfl: 257 Bfree(b); 258 ovfl1: 259#ifndef NO_ERRNO 260 errno = ERANGE; 261#endif 262 return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; 263 } 264 irv = STRTOG_Normal; 265 if (e < fpi->emin) { 266 irv = STRTOG_Denormal; 267 n = fpi->emin - e; 268 if (n >= nbits) { 269 switch (fpi->rounding) { 270 case FPI_Round_near: 271 if (n == nbits && (n < 2 || any_on(b,n-1))) 272 goto one_bit; 273 break; 274 case FPI_Round_up: 275 if (!sign) 276 goto one_bit; 277 break; 278 case FPI_Round_down: 279 if (sign) { 280 one_bit: 281 x[0] = b->wds = 1; 282 dret: 283 *bp = b; 284 *exp = fpi->emin; 285#ifndef NO_ERRNO 286 errno = ERANGE; 287#endif 288 return STRTOG_Denormal | STRTOG_Inexhi 289 | STRTOG_Underflow; 290 } 291 } 292 Bfree(b); 293 retz: 294#ifndef NO_ERRNO 295 errno = ERANGE; 296#endif 297 return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow; 298 } 299 k = n - 1; 300 if (lostbits) 301 lostbits = 1; 302 else if (k > 0) 303 lostbits = any_on(b,k); 304 if (x[k>>kshift] & 1 << (k & kmask)) 305 lostbits |= 2; 306 nbits -= n; 307 rshift(b,n); 308 e = fpi->emin; 309 } 310 if (lostbits) { 311 up = 0; 312 switch(fpi->rounding) { 313 case FPI_Round_zero: 314 break; 315 case FPI_Round_near: 316 if (lostbits & 2
| 203 k++; 204 b = Balloc(k); 205 x = b->x; 206 n = 0; 207 L = 0; 208#ifdef USE_LOCALE 209 for(i = 0; decimalpoint[i+1]; ++i); 210#endif 211 while(s1 > s0) { 212#ifdef USE_LOCALE 213 if (*--s1 == decimalpoint[i]) { 214 s1 -= i; 215 continue; 216 } 217#else 218 if (*--s1 == '.') 219 continue; 220#endif 221 if (n == ULbits) { 222 *x++ = L; 223 L = 0; 224 n = 0; 225 } 226 L |= (hexdig[*s1] & 0x0f) << n; 227 n += 4; 228 } 229 *x++ = L; 230 b->wds = n = x - b->x; 231 n = ULbits*n - hi0bits(L); 232 nbits = fpi->nbits; 233 lostbits = 0; 234 x = b->x; 235 if (n > nbits) { 236 n -= nbits; 237 if (any_on(b,n)) { 238 lostbits = 1; 239 k = n - 1; 240 if (x[k>>kshift] & 1 << (k & kmask)) { 241 lostbits = 2; 242 if (k > 0 && any_on(b,k)) 243 lostbits = 3; 244 } 245 } 246 rshift(b, n); 247 e += n; 248 } 249 else if (n < nbits) { 250 n = nbits - n; 251 b = lshift(b, n); 252 e -= n; 253 x = b->x; 254 } 255 if (e > fpi->emax) { 256 ovfl: 257 Bfree(b); 258 ovfl1: 259#ifndef NO_ERRNO 260 errno = ERANGE; 261#endif 262 return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; 263 } 264 irv = STRTOG_Normal; 265 if (e < fpi->emin) { 266 irv = STRTOG_Denormal; 267 n = fpi->emin - e; 268 if (n >= nbits) { 269 switch (fpi->rounding) { 270 case FPI_Round_near: 271 if (n == nbits && (n < 2 || any_on(b,n-1))) 272 goto one_bit; 273 break; 274 case FPI_Round_up: 275 if (!sign) 276 goto one_bit; 277 break; 278 case FPI_Round_down: 279 if (sign) { 280 one_bit: 281 x[0] = b->wds = 1; 282 dret: 283 *bp = b; 284 *exp = fpi->emin; 285#ifndef NO_ERRNO 286 errno = ERANGE; 287#endif 288 return STRTOG_Denormal | STRTOG_Inexhi 289 | STRTOG_Underflow; 290 } 291 } 292 Bfree(b); 293 retz: 294#ifndef NO_ERRNO 295 errno = ERANGE; 296#endif 297 return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow; 298 } 299 k = n - 1; 300 if (lostbits) 301 lostbits = 1; 302 else if (k > 0) 303 lostbits = any_on(b,k); 304 if (x[k>>kshift] & 1 << (k & kmask)) 305 lostbits |= 2; 306 nbits -= n; 307 rshift(b,n); 308 e = fpi->emin; 309 } 310 if (lostbits) { 311 up = 0; 312 switch(fpi->rounding) { 313 case FPI_Round_zero: 314 break; 315 case FPI_Round_near: 316 if (lostbits & 2
|