1 /**************************************************************** 2 3 The author of this software is David M. Gay. 4 5 Copyright (C) 1998 by Lucent Technologies 6 All Rights Reserved 7 8 Permission to use, copy, modify, and distribute this software and 9 its documentation for any purpose and without fee is hereby 10 granted, provided that the above copyright notice appear in all 11 copies and that both that the copyright notice and this 12 permission notice and warranty disclaimer appear in supporting 13 documentation, and that the name of Lucent or any of its entities 14 not be used in advertising or publicity pertaining to 15 distribution of the software without specific, written prior 16 permission. 17 18 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 19 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 20 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 22 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 23 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 25 THIS 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 40 gethex(sp, fpi, exp, bp, sign) 41 CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign; 42 #else 43 gethex( 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; 60 if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { 61 strcpy(decimalpoint_cache, s0); 62 s0 = decimalpoint_cache; 63 } 64 } 65 decimalpoint = s0; 66 #endif 67 #endif 68 69 if (!hexdig['0']) 70 hexdig_init_D2A(); 71 *bp = 0; 72 havedig = 0; 73 s0 = *(CONST unsigned char **)sp + 2; 74 while(s0[havedig] == '0') 75 havedig++; 76 s0 += havedig; 77 s = s0; 78 decpt = 0; 79 zret = 0; 80 e = 0; 81 if (hexdig[*s]) 82 havedig++; 83 else { 84 zret = 1; 85 #ifdef USE_LOCALE 86 for(i = 0; decimalpoint[i]; ++i) { 87 if (s[i] != decimalpoint[i]) 88 goto pcheck; 89 } 90 decpt = s += i; 91 #else 92 if (*s != '.') 93 goto pcheck; 94 decpt = ++s; 95 #endif 96 if (!hexdig[*s]) 97 goto pcheck; 98 while(*s == '0') 99 s++; 100 if (hexdig[*s]) 101 zret = 0; 102 havedig = 1; 103 s0 = s; 104 } 105 while(hexdig[*s]) 106 s++; 107 #ifdef USE_LOCALE 108 if (*s == *decimalpoint && !decpt) { 109 for(i = 1; decimalpoint[i]; ++i) { 110 if (s[i] != decimalpoint[i]) 111 goto pcheck; 112 } 113 decpt = s += i; 114 #else 115 if (*s == '.' && !decpt) { 116 decpt = ++s; 117 #endif 118 while(hexdig[*s]) 119 s++; 120 }/*}*/ 121 if (decpt) 122 e = -(((Long)(s-decpt)) << 2); 123 pcheck: 124 s1 = s; 125 big = esign = 0; 126 switch(*s) { 127 case 'p': 128 case 'P': 129 switch(*++s) { 130 case '-': 131 esign = 1; 132 /* no break */ 133 case '+': 134 s++; 135 } 136 if ((n = hexdig[*s]) == 0 || n > 0x19) { 137 s = s1; 138 break; 139 } 140 e1 = n - 0x10; 141 while((n = hexdig[*++s]) !=0 && n <= 0x19) { 142 if (e1 & 0xf8000000) 143 big = 1; 144 e1 = 10*e1 + n - 0x10; 145 } 146 if (esign) 147 e1 = -e1; 148 e += e1; 149 } 150 *sp = (char*)s; 151 if (!havedig) 152 *sp = (char*)s0 - 1; 153 if (zret) 154 return STRTOG_Zero; 155 if (big) { 156 if (esign) { 157 switch(fpi->rounding) { 158 case FPI_Round_up: 159 if (sign) 160 break; 161 goto ret_tiny; 162 case FPI_Round_down: 163 if (!sign) 164 break; 165 goto ret_tiny; 166 } 167 goto retz; 168 ret_tiny: 169 b = Balloc(0); 170 b->wds = 1; 171 b->x[0] = 1; 172 goto dret; 173 } 174 switch(fpi->rounding) { 175 case FPI_Round_near: 176 goto ovfl1; 177 case FPI_Round_up: 178 if (!sign) 179 goto ovfl1; 180 goto ret_big; 181 case FPI_Round_down: 182 if (sign) 183 goto ovfl1; 184 goto ret_big; 185 } 186 ret_big: 187 nbits = fpi->nbits; 188 n0 = n = nbits >> kshift; 189 if (nbits & kmask) 190 ++n; 191 for(j = n, k = 0; j >>= 1; ++k); 192 *bp = b = Balloc(k); 193 b->wds = n; 194 for(j = 0; j < n0; ++j) 195 b->x[j] = ALL_ON; 196 if (n > n0) 197 b->x[j] = ULbits >> (ULbits - (nbits & kmask)); 198 *exp = fpi->emin; 199 return STRTOG_Normal | STRTOG_Inexlo; 200 } 201 n = s1 - s0 - 1; 202 for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) 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 317 && (lostbits | x[0]) & 1) 318 up = 1; 319 break; 320 case FPI_Round_up: 321 up = 1 - sign; 322 break; 323 case FPI_Round_down: 324 up = sign; 325 } 326 if (up) { 327 k = b->wds; 328 b = increment(b); 329 x = b->x; 330 if (irv == STRTOG_Denormal) { 331 if (nbits == fpi->nbits - 1 332 && x[nbits >> kshift] & 1 << (nbits & kmask)) 333 irv = STRTOG_Normal; 334 } 335 else if (b->wds > k 336 || ((n = nbits & kmask) !=0 337 && hi0bits(x[k-1]) < 32-n)) { 338 rshift(b,1); 339 if (++e > fpi->emax) 340 goto ovfl; 341 } 342 irv |= STRTOG_Inexhi; 343 } 344 else 345 irv |= STRTOG_Inexlo; 346 } 347 *bp = b; 348 *exp = e; 349 return irv; 350 } 351