1f9f848faSopenharmony_ci/**************************************************************** 2f9f848faSopenharmony_ci 3f9f848faSopenharmony_ciThe author of this software is David M. Gay. 4f9f848faSopenharmony_ci 5f9f848faSopenharmony_ciCopyright (C) 1998 by Lucent Technologies 6f9f848faSopenharmony_ciAll Rights Reserved 7f9f848faSopenharmony_ci 8f9f848faSopenharmony_ciPermission to use, copy, modify, and distribute this software and 9f9f848faSopenharmony_ciits documentation for any purpose and without fee is hereby 10f9f848faSopenharmony_cigranted, provided that the above copyright notice appear in all 11f9f848faSopenharmony_cicopies and that both that the copyright notice and this 12f9f848faSopenharmony_cipermission notice and warranty disclaimer appear in supporting 13f9f848faSopenharmony_cidocumentation, and that the name of Lucent or any of its entities 14f9f848faSopenharmony_cinot be used in advertising or publicity pertaining to 15f9f848faSopenharmony_cidistribution of the software without specific, written prior 16f9f848faSopenharmony_cipermission. 17f9f848faSopenharmony_ci 18f9f848faSopenharmony_ciLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 19f9f848faSopenharmony_ciINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 20f9f848faSopenharmony_ciIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 21f9f848faSopenharmony_ciSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 22f9f848faSopenharmony_ciWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 23f9f848faSopenharmony_ciIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 24f9f848faSopenharmony_ciARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 25f9f848faSopenharmony_ciTHIS SOFTWARE. 26f9f848faSopenharmony_ci 27f9f848faSopenharmony_ci****************************************************************/ 28f9f848faSopenharmony_ci 29f9f848faSopenharmony_ci/* Please send bug reports to David M. Gay (dmg at acm dot org, 30f9f848faSopenharmony_ci * with " at " changed at "@" and " dot " changed to "."). */ 31f9f848faSopenharmony_ci 32f9f848faSopenharmony_ci#include "gdtoaimp.h" 33f9f848faSopenharmony_ci 34f9f848faSopenharmony_ci#ifdef USE_LOCALE 35f9f848faSopenharmony_ci#include "locale.h" 36f9f848faSopenharmony_ci#endif 37f9f848faSopenharmony_ci 38f9f848faSopenharmony_ci int 39f9f848faSopenharmony_ci#ifdef KR_headers 40f9f848faSopenharmony_cigethex(sp, fpi, exp, bp, sign) 41f9f848faSopenharmony_ci CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign; 42f9f848faSopenharmony_ci#else 43f9f848faSopenharmony_cigethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign) 44f9f848faSopenharmony_ci#endif 45f9f848faSopenharmony_ci{ 46f9f848faSopenharmony_ci Bigint *b; 47f9f848faSopenharmony_ci CONST unsigned char *decpt, *s0, *s, *s1; 48f9f848faSopenharmony_ci int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret; 49f9f848faSopenharmony_ci ULong L, lostbits, *x; 50f9f848faSopenharmony_ci Long e, e1; 51f9f848faSopenharmony_ci#ifdef USE_LOCALE 52f9f848faSopenharmony_ci int i; 53f9f848faSopenharmony_ci#ifdef NO_LOCALE_CACHE 54f9f848faSopenharmony_ci const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point; 55f9f848faSopenharmony_ci#else 56f9f848faSopenharmony_ci const unsigned char *decimalpoint; 57f9f848faSopenharmony_ci static unsigned char *decimalpoint_cache; 58f9f848faSopenharmony_ci if (!(s0 = decimalpoint_cache)) { 59f9f848faSopenharmony_ci s0 = (unsigned char*)localeconv()->decimal_point; 60f9f848faSopenharmony_ci if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { 61f9f848faSopenharmony_ci strcpy(decimalpoint_cache, s0); 62f9f848faSopenharmony_ci s0 = decimalpoint_cache; 63f9f848faSopenharmony_ci } 64f9f848faSopenharmony_ci } 65f9f848faSopenharmony_ci decimalpoint = s0; 66f9f848faSopenharmony_ci#endif 67f9f848faSopenharmony_ci#endif 68f9f848faSopenharmony_ci 69f9f848faSopenharmony_ci if (!hexdig['0']) 70f9f848faSopenharmony_ci hexdig_init_D2A(); 71f9f848faSopenharmony_ci *bp = 0; 72f9f848faSopenharmony_ci havedig = 0; 73f9f848faSopenharmony_ci s0 = *(CONST unsigned char **)sp + 2; 74f9f848faSopenharmony_ci while(s0[havedig] == '0') 75f9f848faSopenharmony_ci havedig++; 76f9f848faSopenharmony_ci s0 += havedig; 77f9f848faSopenharmony_ci s = s0; 78f9f848faSopenharmony_ci decpt = 0; 79f9f848faSopenharmony_ci zret = 0; 80f9f848faSopenharmony_ci e = 0; 81f9f848faSopenharmony_ci if (hexdig[*s]) 82f9f848faSopenharmony_ci havedig++; 83f9f848faSopenharmony_ci else { 84f9f848faSopenharmony_ci zret = 1; 85f9f848faSopenharmony_ci#ifdef USE_LOCALE 86f9f848faSopenharmony_ci for(i = 0; decimalpoint[i]; ++i) { 87f9f848faSopenharmony_ci if (s[i] != decimalpoint[i]) 88f9f848faSopenharmony_ci goto pcheck; 89f9f848faSopenharmony_ci } 90f9f848faSopenharmony_ci decpt = s += i; 91f9f848faSopenharmony_ci#else 92f9f848faSopenharmony_ci if (*s != '.') 93f9f848faSopenharmony_ci goto pcheck; 94f9f848faSopenharmony_ci decpt = ++s; 95f9f848faSopenharmony_ci#endif 96f9f848faSopenharmony_ci if (!hexdig[*s]) 97f9f848faSopenharmony_ci goto pcheck; 98f9f848faSopenharmony_ci while(*s == '0') 99f9f848faSopenharmony_ci s++; 100f9f848faSopenharmony_ci if (hexdig[*s]) 101f9f848faSopenharmony_ci zret = 0; 102f9f848faSopenharmony_ci havedig = 1; 103f9f848faSopenharmony_ci s0 = s; 104f9f848faSopenharmony_ci } 105f9f848faSopenharmony_ci while(hexdig[*s]) 106f9f848faSopenharmony_ci s++; 107f9f848faSopenharmony_ci#ifdef USE_LOCALE 108f9f848faSopenharmony_ci if (*s == *decimalpoint && !decpt) { 109f9f848faSopenharmony_ci for(i = 1; decimalpoint[i]; ++i) { 110f9f848faSopenharmony_ci if (s[i] != decimalpoint[i]) 111f9f848faSopenharmony_ci goto pcheck; 112f9f848faSopenharmony_ci } 113f9f848faSopenharmony_ci decpt = s += i; 114f9f848faSopenharmony_ci#else 115f9f848faSopenharmony_ci if (*s == '.' && !decpt) { 116f9f848faSopenharmony_ci decpt = ++s; 117f9f848faSopenharmony_ci#endif 118f9f848faSopenharmony_ci while(hexdig[*s]) 119f9f848faSopenharmony_ci s++; 120f9f848faSopenharmony_ci }/*}*/ 121f9f848faSopenharmony_ci if (decpt) 122f9f848faSopenharmony_ci e = -(((Long)(s-decpt)) << 2); 123f9f848faSopenharmony_ci pcheck: 124f9f848faSopenharmony_ci s1 = s; 125f9f848faSopenharmony_ci big = esign = 0; 126f9f848faSopenharmony_ci switch(*s) { 127f9f848faSopenharmony_ci case 'p': 128f9f848faSopenharmony_ci case 'P': 129f9f848faSopenharmony_ci switch(*++s) { 130f9f848faSopenharmony_ci case '-': 131f9f848faSopenharmony_ci esign = 1; 132f9f848faSopenharmony_ci /* no break */ 133f9f848faSopenharmony_ci case '+': 134f9f848faSopenharmony_ci s++; 135f9f848faSopenharmony_ci } 136f9f848faSopenharmony_ci if ((n = hexdig[*s]) == 0 || n > 0x19) { 137f9f848faSopenharmony_ci s = s1; 138f9f848faSopenharmony_ci break; 139f9f848faSopenharmony_ci } 140f9f848faSopenharmony_ci e1 = n - 0x10; 141f9f848faSopenharmony_ci while((n = hexdig[*++s]) !=0 && n <= 0x19) { 142f9f848faSopenharmony_ci if (e1 & 0xf8000000) 143f9f848faSopenharmony_ci big = 1; 144f9f848faSopenharmony_ci e1 = 10*e1 + n - 0x10; 145f9f848faSopenharmony_ci } 146f9f848faSopenharmony_ci if (esign) 147f9f848faSopenharmony_ci e1 = -e1; 148f9f848faSopenharmony_ci e += e1; 149f9f848faSopenharmony_ci } 150f9f848faSopenharmony_ci *sp = (char*)s; 151f9f848faSopenharmony_ci if (!havedig) 152f9f848faSopenharmony_ci *sp = (char*)s0 - 1; 153f9f848faSopenharmony_ci if (zret) 154f9f848faSopenharmony_ci return STRTOG_Zero; 155f9f848faSopenharmony_ci if (big) { 156f9f848faSopenharmony_ci if (esign) { 157f9f848faSopenharmony_ci switch(fpi->rounding) { 158f9f848faSopenharmony_ci case FPI_Round_up: 159f9f848faSopenharmony_ci if (sign) 160f9f848faSopenharmony_ci break; 161f9f848faSopenharmony_ci goto ret_tiny; 162f9f848faSopenharmony_ci case FPI_Round_down: 163f9f848faSopenharmony_ci if (!sign) 164f9f848faSopenharmony_ci break; 165f9f848faSopenharmony_ci goto ret_tiny; 166f9f848faSopenharmony_ci } 167f9f848faSopenharmony_ci goto retz; 168f9f848faSopenharmony_ci ret_tiny: 169f9f848faSopenharmony_ci b = Balloc(0); 170f9f848faSopenharmony_ci b->wds = 1; 171f9f848faSopenharmony_ci b->x[0] = 1; 172f9f848faSopenharmony_ci goto dret; 173f9f848faSopenharmony_ci } 174f9f848faSopenharmony_ci switch(fpi->rounding) { 175f9f848faSopenharmony_ci case FPI_Round_near: 176f9f848faSopenharmony_ci goto ovfl1; 177f9f848faSopenharmony_ci case FPI_Round_up: 178f9f848faSopenharmony_ci if (!sign) 179f9f848faSopenharmony_ci goto ovfl1; 180f9f848faSopenharmony_ci goto ret_big; 181f9f848faSopenharmony_ci case FPI_Round_down: 182f9f848faSopenharmony_ci if (sign) 183f9f848faSopenharmony_ci goto ovfl1; 184f9f848faSopenharmony_ci goto ret_big; 185f9f848faSopenharmony_ci } 186f9f848faSopenharmony_ci ret_big: 187f9f848faSopenharmony_ci nbits = fpi->nbits; 188f9f848faSopenharmony_ci n0 = n = nbits >> kshift; 189f9f848faSopenharmony_ci if (nbits & kmask) 190f9f848faSopenharmony_ci ++n; 191f9f848faSopenharmony_ci for(j = n, k = 0; j >>= 1; ++k); 192f9f848faSopenharmony_ci *bp = b = Balloc(k); 193f9f848faSopenharmony_ci b->wds = n; 194f9f848faSopenharmony_ci for(j = 0; j < n0; ++j) 195f9f848faSopenharmony_ci b->x[j] = ALL_ON; 196f9f848faSopenharmony_ci if (n > n0) 197f9f848faSopenharmony_ci b->x[j] = ULbits >> (ULbits - (nbits & kmask)); 198f9f848faSopenharmony_ci *exp = fpi->emin; 199f9f848faSopenharmony_ci return STRTOG_Normal | STRTOG_Inexlo; 200f9f848faSopenharmony_ci } 201f9f848faSopenharmony_ci n = s1 - s0 - 1; 202f9f848faSopenharmony_ci for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) 203f9f848faSopenharmony_ci k++; 204f9f848faSopenharmony_ci b = Balloc(k); 205f9f848faSopenharmony_ci x = b->x; 206f9f848faSopenharmony_ci n = 0; 207f9f848faSopenharmony_ci L = 0; 208f9f848faSopenharmony_ci#ifdef USE_LOCALE 209f9f848faSopenharmony_ci for(i = 0; decimalpoint[i+1]; ++i); 210f9f848faSopenharmony_ci#endif 211f9f848faSopenharmony_ci while(s1 > s0) { 212f9f848faSopenharmony_ci#ifdef USE_LOCALE 213f9f848faSopenharmony_ci if (*--s1 == decimalpoint[i]) { 214f9f848faSopenharmony_ci s1 -= i; 215f9f848faSopenharmony_ci continue; 216f9f848faSopenharmony_ci } 217f9f848faSopenharmony_ci#else 218f9f848faSopenharmony_ci if (*--s1 == '.') 219f9f848faSopenharmony_ci continue; 220f9f848faSopenharmony_ci#endif 221f9f848faSopenharmony_ci if (n == ULbits) { 222f9f848faSopenharmony_ci *x++ = L; 223f9f848faSopenharmony_ci L = 0; 224f9f848faSopenharmony_ci n = 0; 225f9f848faSopenharmony_ci } 226f9f848faSopenharmony_ci L |= (hexdig[*s1] & 0x0f) << n; 227f9f848faSopenharmony_ci n += 4; 228f9f848faSopenharmony_ci } 229f9f848faSopenharmony_ci *x++ = L; 230f9f848faSopenharmony_ci b->wds = n = x - b->x; 231f9f848faSopenharmony_ci n = ULbits*n - hi0bits(L); 232f9f848faSopenharmony_ci nbits = fpi->nbits; 233f9f848faSopenharmony_ci lostbits = 0; 234f9f848faSopenharmony_ci x = b->x; 235f9f848faSopenharmony_ci if (n > nbits) { 236f9f848faSopenharmony_ci n -= nbits; 237f9f848faSopenharmony_ci if (any_on(b,n)) { 238f9f848faSopenharmony_ci lostbits = 1; 239f9f848faSopenharmony_ci k = n - 1; 240f9f848faSopenharmony_ci if (x[k>>kshift] & 1 << (k & kmask)) { 241f9f848faSopenharmony_ci lostbits = 2; 242f9f848faSopenharmony_ci if (k > 0 && any_on(b,k)) 243f9f848faSopenharmony_ci lostbits = 3; 244f9f848faSopenharmony_ci } 245f9f848faSopenharmony_ci } 246f9f848faSopenharmony_ci rshift(b, n); 247f9f848faSopenharmony_ci e += n; 248f9f848faSopenharmony_ci } 249f9f848faSopenharmony_ci else if (n < nbits) { 250f9f848faSopenharmony_ci n = nbits - n; 251f9f848faSopenharmony_ci b = lshift(b, n); 252f9f848faSopenharmony_ci e -= n; 253f9f848faSopenharmony_ci x = b->x; 254f9f848faSopenharmony_ci } 255f9f848faSopenharmony_ci if (e > fpi->emax) { 256f9f848faSopenharmony_ci ovfl: 257f9f848faSopenharmony_ci Bfree(b); 258f9f848faSopenharmony_ci ovfl1: 259f9f848faSopenharmony_ci#ifndef NO_ERRNO 260f9f848faSopenharmony_ci errno = ERANGE; 261f9f848faSopenharmony_ci#endif 262f9f848faSopenharmony_ci return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; 263f9f848faSopenharmony_ci } 264f9f848faSopenharmony_ci irv = STRTOG_Normal; 265f9f848faSopenharmony_ci if (e < fpi->emin) { 266f9f848faSopenharmony_ci irv = STRTOG_Denormal; 267f9f848faSopenharmony_ci n = fpi->emin - e; 268f9f848faSopenharmony_ci if (n >= nbits) { 269f9f848faSopenharmony_ci switch (fpi->rounding) { 270f9f848faSopenharmony_ci case FPI_Round_near: 271f9f848faSopenharmony_ci if (n == nbits && (n < 2 || any_on(b,n-1))) 272f9f848faSopenharmony_ci goto one_bit; 273f9f848faSopenharmony_ci break; 274f9f848faSopenharmony_ci case FPI_Round_up: 275f9f848faSopenharmony_ci if (!sign) 276f9f848faSopenharmony_ci goto one_bit; 277f9f848faSopenharmony_ci break; 278f9f848faSopenharmony_ci case FPI_Round_down: 279f9f848faSopenharmony_ci if (sign) { 280f9f848faSopenharmony_ci one_bit: 281f9f848faSopenharmony_ci x[0] = b->wds = 1; 282f9f848faSopenharmony_ci dret: 283f9f848faSopenharmony_ci *bp = b; 284f9f848faSopenharmony_ci *exp = fpi->emin; 285f9f848faSopenharmony_ci#ifndef NO_ERRNO 286f9f848faSopenharmony_ci errno = ERANGE; 287f9f848faSopenharmony_ci#endif 288f9f848faSopenharmony_ci return STRTOG_Denormal | STRTOG_Inexhi 289f9f848faSopenharmony_ci | STRTOG_Underflow; 290f9f848faSopenharmony_ci } 291f9f848faSopenharmony_ci } 292f9f848faSopenharmony_ci Bfree(b); 293f9f848faSopenharmony_ci retz: 294f9f848faSopenharmony_ci#ifndef NO_ERRNO 295f9f848faSopenharmony_ci errno = ERANGE; 296f9f848faSopenharmony_ci#endif 297f9f848faSopenharmony_ci return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow; 298f9f848faSopenharmony_ci } 299f9f848faSopenharmony_ci k = n - 1; 300f9f848faSopenharmony_ci if (lostbits) 301f9f848faSopenharmony_ci lostbits = 1; 302f9f848faSopenharmony_ci else if (k > 0) 303f9f848faSopenharmony_ci lostbits = any_on(b,k); 304f9f848faSopenharmony_ci if (x[k>>kshift] & 1 << (k & kmask)) 305f9f848faSopenharmony_ci lostbits |= 2; 306f9f848faSopenharmony_ci nbits -= n; 307f9f848faSopenharmony_ci rshift(b,n); 308f9f848faSopenharmony_ci e = fpi->emin; 309f9f848faSopenharmony_ci } 310f9f848faSopenharmony_ci if (lostbits) { 311f9f848faSopenharmony_ci up = 0; 312f9f848faSopenharmony_ci switch(fpi->rounding) { 313f9f848faSopenharmony_ci case FPI_Round_zero: 314f9f848faSopenharmony_ci break; 315f9f848faSopenharmony_ci case FPI_Round_near: 316f9f848faSopenharmony_ci if (lostbits & 2 317f9f848faSopenharmony_ci && (lostbits | x[0]) & 1) 318f9f848faSopenharmony_ci up = 1; 319f9f848faSopenharmony_ci break; 320f9f848faSopenharmony_ci case FPI_Round_up: 321f9f848faSopenharmony_ci up = 1 - sign; 322f9f848faSopenharmony_ci break; 323f9f848faSopenharmony_ci case FPI_Round_down: 324f9f848faSopenharmony_ci up = sign; 325f9f848faSopenharmony_ci } 326f9f848faSopenharmony_ci if (up) { 327f9f848faSopenharmony_ci k = b->wds; 328f9f848faSopenharmony_ci b = increment(b); 329f9f848faSopenharmony_ci x = b->x; 330f9f848faSopenharmony_ci if (irv == STRTOG_Denormal) { 331f9f848faSopenharmony_ci if (nbits == fpi->nbits - 1 332f9f848faSopenharmony_ci && x[nbits >> kshift] & 1 << (nbits & kmask)) 333f9f848faSopenharmony_ci irv = STRTOG_Normal; 334f9f848faSopenharmony_ci } 335f9f848faSopenharmony_ci else if (b->wds > k 336f9f848faSopenharmony_ci || ((n = nbits & kmask) !=0 337f9f848faSopenharmony_ci && hi0bits(x[k-1]) < 32-n)) { 338f9f848faSopenharmony_ci rshift(b,1); 339f9f848faSopenharmony_ci if (++e > fpi->emax) 340f9f848faSopenharmony_ci goto ovfl; 341f9f848faSopenharmony_ci } 342f9f848faSopenharmony_ci irv |= STRTOG_Inexhi; 343f9f848faSopenharmony_ci } 344f9f848faSopenharmony_ci else 345f9f848faSopenharmony_ci irv |= STRTOG_Inexlo; 346f9f848faSopenharmony_ci } 347f9f848faSopenharmony_ci *bp = b; 348f9f848faSopenharmony_ci *exp = e; 349f9f848faSopenharmony_ci return irv; 350f9f848faSopenharmony_ci } 351