1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1988-1995, by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* Conversion between binary and decimal floating point. */ 30 31 #include "base_conversion.h" 32 33 void 34 decimal_to_binary_integer(ds, ndigs, nzeros, nsig, pb) 35 char ds[]; /* Input decimal integer string. */ 36 unsigned ndigs; /* Input number of explicit digits in ds. */ 37 unsigned nzeros; /* Input number of implicit trailing zeros. */ 38 unsigned nsig; /* Input number of significant bits required. */ 39 _big_float *pb; /* Pointer to big_float to receive result. */ 40 41 /* 42 * Converts a decimal integer string ds with ndigs explicit leading digits 43 * and nzeros implicit trailing zeros to a _big_float **pb, which only 44 * requires nsig significand bits. 45 */ 46 /* Inexactness is indicated by pb->bsignificand[0] |= 1. */ 47 /* 48 * If the input is too big for a big_float, pb->bexponent is set to 0x7fff. 49 */ 50 51 { 52 unsigned nzout; 53 _big_float d, *pbout; 54 55 d.bsize = _BIG_FLOAT_SIZE; 56 _integerstring_to_big_decimal(ds, ndigs, nzeros, &nzout, &d); 57 _big_decimal_to_big_binary(&d, pb); 58 if (nzout != 0) { 59 _big_float_times_power(pb, 10, (int) nzout, (int) nsig, &pbout); 60 switch ((unsigned int)pbout) { 61 case ((unsigned int)BIG_FLOAT_TIMES_TOOBIG): 62 #ifdef DEBUG 63 (void) printf(" decimal_to_binary_integer: decimal exponent %d too large for tables ", nzout); 64 #endif 65 pb->bexponent = 0x7fff; 66 break; 67 case ((unsigned int)BIG_FLOAT_TIMES_NOMEM): 68 { 69 char bcastring[80]; 70 71 (void) sprintf(bcastring, " decimal exponent %d ", nzout); 72 _base_conversion_abort(ENOMEM, bcastring); 73 break; 74 } 75 default: 76 #ifdef DEBUG 77 if (pbout != pb) 78 (void) printf(" decimal_to_binary_integer: large decimal exponent %d needs heap buffer \n", nzout); 79 printf(" decimal_to_binary_integer: product "); 80 _display_big_float(pb, 2); 81 #endif 82 if (pbout != pb) { /* We don't really need such 83 * a large product; the 84 * target can't be more than 85 * a quad! */ 86 int i, allweneed; 87 88 allweneed = 2 + (nsig + 2) / 16; 89 for (i = 0; i < allweneed; i++) 90 pb->bsignificand[i] = pbout->bsignificand[i + pbout->blength - allweneed]; 91 for (i = 0; (pbout->bsignificand[i] == 0); i++); 92 if (i < (pbout->blength - allweneed)) 93 pb->bsignificand[0] |= 1; /* Stick discarded bits. */ 94 95 pb->blength = allweneed; 96 pb->bexponent = pbout->bexponent + 16 * (pbout->blength - allweneed); 97 #ifdef DEBUG 98 printf(" decimal_to_binary_integer: removed %d excess digits from product \n", pbout->blength - allweneed); 99 _display_big_float(pb, 2); 100 #endif 101 _free_big_float(pbout); 102 } 103 break; 104 } 105 } 106 } 107 108 void 109 decimal_to_binary_fraction(ds, ndigs, nzeros, nsig, pb) 110 char ds[]; /* Decimal integer string input. */ 111 unsigned ndigs; /* Number of explicit digits to read. */ 112 unsigned nzeros; /* Number of implicit leading zeros before 113 * digits. */ 114 unsigned nsig; /* Number of significant bits needed. */ 115 _big_float *pb; /* Pointer to intended big_float result. */ 116 117 /* 118 * Converts an explicit decimal string *ds[0]..*ds[ndigs-1] preceded by 119 * nzeros implicit leading zeros after the point into a big_float at *pb. If 120 * the input does not fit exactly in a big_float, the least significant bit 121 * of pbout->significand is stuck on. If the input is too big for the base 122 * conversion tables, pb->bexponent is set to 0x7fff. 123 */ 124 125 { 126 unsigned twopower, twosig; 127 int i, excess; 128 _big_float d, *pdout; 129 130 d.bsize = _BIG_FLOAT_SIZE; 131 _fractionstring_to_big_decimal(ds, ndigs, nzeros, &d); 132 133 twopower = nsig + 3 + (((nzeros + 1) * (unsigned long) 217706) >> 16); 134 twosig = 1 + (((nsig + 2) * (unsigned long) 19729) >> 16); 135 136 #ifdef DEBUG 137 printf(" decimal_to_binary_fraction sigbits %d twopower %d twosig %d \n", 138 nsig, twopower, twosig); 139 #endif 140 _big_float_times_power(&d, 2, (int) twopower, (int) twosig, &pdout); 141 switch ((unsigned int)pdout) { 142 case ((unsigned int)BIG_FLOAT_TIMES_TOOBIG): 143 #ifdef DEBUG 144 (void) printf(" decimal_to_binary_fraction binary exponent %d too large for tables ", twopower); 145 #endif 146 pb->bexponent = 0x7fff; 147 goto ret; 148 case ((unsigned int)BIG_FLOAT_TIMES_NOMEM): 149 { 150 char bcastring[80]; 151 152 (void) sprintf(bcastring, " binary exponent %d ", twopower); 153 _base_conversion_abort(ENOMEM, bcastring); 154 break; 155 } 156 default: 157 #ifdef DEBUG 158 if (&d != pdout) 159 printf(" decimal_to_binary_fraction large binary exponent %d needs heap buffer \n", twopower); 160 printf(" product "); 161 _display_big_float(pdout, 10); 162 #endif 163 break; 164 } 165 166 167 if (pdout->bexponent <= -4) { 168 /* Have computed appropriate decimal part; now toss fraction. */ 169 excess = (-pdout->bexponent) / 4; 170 #ifdef DEBUG 171 printf(" discard %d excess fraction digits \n", 4 * excess); 172 #endif 173 for (i = 0; (i < excess) && ((pdout)->bsignificand[i] == 0); i++); 174 if (i < excess) 175 (pdout)->bsignificand[excess] |= 1; /* Sticky bit for 176 * discarded fraction. */ 177 for (i = excess; i < (pdout)->blength; i++) 178 (pdout)->bsignificand[i - excess] = (pdout)->bsignificand[i]; 179 180 (pdout)->blength -= excess; 181 (pdout)->bexponent += 4 * excess; 182 } 183 _big_decimal_to_big_binary(pdout, pb); 184 if (pdout != &d) 185 _free_big_float(pdout); 186 pb->bexponent = -twopower; 187 188 ret: 189 return; 190 } 191 192 void 193 decimal_to_unpacked(px, pd, significant_bits) 194 unpacked *px; 195 decimal_record *pd; 196 unsigned significant_bits; 197 198 /* 199 * Converts *pd to *px so that *px can be correctly rounded. significant_bits 200 * tells how many bits will be significant in the final result to avoid 201 * superfluous computation. Inexactness is communicated by sticking on the 202 * lsb of px->significand[UNPACKED_SIZE-1]. Integer buffer overflow is 203 * indicated with a huge positive exponent. 204 */ 205 206 { 207 int frac_bits, sigint; 208 unsigned length, ndigs, ntz, nlz, ifrac, nfrac; 209 _big_float bi, bf, *ptounpacked = &bi; 210 211 px->sign = pd->sign; 212 px->fpclass = pd->fpclass; 213 if ((px->fpclass != fp_normal) && (px->fpclass != fp_subnormal)) 214 goto ret; 215 for (length = 0; pd->ds[length] != 0; length++); 216 if (length == 0) { /* A zero significand slipped by. */ 217 px->fpclass = fp_zero; 218 goto ret; 219 } 220 /* Length contains the number of explicit digits in string. */ 221 if (pd->exponent >= 0) {/* All integer digits. */ 222 ndigs = length; 223 ntz = pd->exponent; /* Trailing zeros. */ 224 ifrac = 0; 225 nfrac = 0; /* No fraction digits. */ 226 nlz = 0; 227 } else if (length <= -pd->exponent) { /* No integer digits. */ 228 ndigs = 0; 229 ntz = 0; 230 ifrac = 0; 231 nfrac = length; 232 nlz = -pd->exponent - length; /* Leading zeros. */ 233 } else { /* Some integer digits, some fraction digits. */ 234 ndigs = length + pd->exponent; 235 ntz = 0; 236 ifrac = ndigs; 237 nfrac = -pd->exponent; 238 nlz = 0; 239 while ((pd->ds[ifrac] == '0') && (nfrac != 0)) { 240 ifrac++; 241 nfrac--; 242 nlz++; 243 } /* Remove leading zeros. */ 244 } 245 if (ndigs != 0) { /* Convert integer digits. */ 246 247 bi.bsize = _BIG_FLOAT_SIZE; 248 decimal_to_binary_integer(pd->ds, ndigs, ntz, significant_bits, &bi); 249 if (bi.bexponent == 0x7fff) { /* Too big for buffer. */ 250 px->exponent = 0x000fffff; 251 px->significand[0] = 0x80000000; 252 goto ret; 253 } 254 sigint = 16 * (bi.blength + bi.bexponent - 1); 255 if (sigint < 0) 256 sigint = 0; 257 } else { /* No integer digits. */ 258 bi.blength = 0; 259 bi.bsignificand[0] = 0; 260 bi.bexponent = 0; 261 sigint = 0; 262 } 263 frac_bits = significant_bits - sigint + 2; 264 bf.blength = 0; 265 if ((nfrac != 0) && (frac_bits > 0)) { /* Convert fraction digits, 266 * even if we only need a 267 * round or sticky. */ 268 269 bf.bsize = _BIG_FLOAT_SIZE; 270 decimal_to_binary_fraction(&(pd->ds[ifrac]), nfrac, nlz, (unsigned) frac_bits, &bf); 271 } else { /* Only need fraction bits for sticky. */ 272 if (nfrac != 0) 273 bi.bsignificand[0] |= 1; /* Stick for fraction. */ 274 } 275 if (bi.blength == 0) { /* No integer digits; all fraction. */ 276 if (bf.bexponent == 0x7fff) { /* Buffer overflowed. */ 277 px->exponent = -0x000fffff; 278 px->significand[0] = 0x80000000; 279 goto ret; 280 } 281 ptounpacked = &bf; /* Exceptional case - all fraction. */ 282 goto punpack; 283 } 284 if (bf.blength != 0) { /* Combine integer and fraction bits. */ 285 int expdiff = bi.bexponent - (bf.bexponent + 16 * (bf.blength - 1)); /* Exponent difference. */ 286 int uneeded = 2 + (significant_bits + 2) / 16; /* Number of big float 287 * digits needed. */ 288 int nmove, leftshift, i, if0; 289 290 #ifdef DEBUG 291 printf(" bi+bf exponent diff is %d \n", expdiff); 292 printf(" need %d big float digits \n", uneeded); 293 assert(bi.blength != 0); 294 assert(bf.blength != 0); 295 assert(bi.bsignificand[bi.blength - 1] != 0); /* Normalized bi. */ 296 assert(bf.bsignificand[bf.blength - 1] != 0); /* Normalized bf. */ 297 assert(bi.bexponent >= 0); /* bi is all integer */ 298 assert(((-bf.bexponent - 16 * (bf.blength - 1)) >= 16) || 299 ((bf.bsignificand[bf.blength - 1] >> (-bf.bexponent - 16 * (bf.blength - 1))) == 0)); 300 /* assert either bf << 1 or bf < 1 */ 301 /* 302 * Assert that integer and fraction parts don't overlap by 303 * more than one big digit. 304 */ 305 assert(expdiff > 0); 306 assert(uneeded <= (2 * UNPACKED_SIZE)); 307 #endif 308 309 310 if (bi.blength >= uneeded) { /* bi will overflow unpacked, 311 * so bf is just a sticky. */ 312 bi.bsignificand[0] |= 1; 313 goto punpack; 314 } 315 leftshift = 16 - (expdiff % 16); 316 if (leftshift > 0) { /* shift bf to align with bi. */ 317 expdiff += 16 * bf.blength; 318 _left_shift_base_two(&bf, (short unsigned) leftshift); 319 expdiff -= 16 * bf.blength; /* If bf.blength is 320 * longer, adjust 321 * expdiff. */ 322 } 323 expdiff += leftshift; 324 expdiff /= 16; /* Remaining expdiff in _BIG_FLOAT_DIGITS. */ 325 expdiff--; 326 #ifdef DEBUG 327 assert(expdiff >= 0); /* expdiff is now equal to the size 328 * of the hole between bi and bf. */ 329 #endif 330 nmove = uneeded - bi.blength; 331 /* nmove is the number of words to add to bi. */ 332 if (nmove < 0) 333 nmove = 0; 334 if (nmove > (expdiff + bf.blength)) 335 nmove = (expdiff + bf.blength); 336 #ifdef DEBUG 337 printf(" increase bi by %d words to merge \n", nmove); 338 #endif 339 if (nmove == 0) 340 i = -1; 341 else 342 for (i = (bi.blength - 1 + nmove); i >= nmove; i--) 343 bi.bsignificand[i] = bi.bsignificand[i - nmove]; 344 for (; (i >= 0) && (expdiff > 0); i--) { /* Fill hole with zeros. */ 345 expdiff--; 346 bi.bsignificand[i] = 0; 347 } 348 if0 = i; 349 for (; i >= 0; i--) 350 bi.bsignificand[i] = bf.bsignificand[i + bf.blength - 1 - if0]; 351 for (i = (bf.blength - 2 - if0); bf.bsignificand[i] == 0; i--); 352 /* Find first non-zero. */ 353 if (i >= 0) 354 bi.bsignificand[0] |= 1; /* If non-zero found, 355 * stick it. */ 356 bi.blength += nmove; 357 bi.bexponent -= 16 * nmove; 358 goto punpack; 359 } 360 punpack: 361 ptounpacked->bsignificand[0] |= pd->more; /* Stick in any lost 362 * digits. */ 363 364 #ifdef DEBUG 365 printf(" merged bi and bf: "); 366 _display_big_float(ptounpacked, 2); 367 #endif 368 369 _big_binary_to_unpacked(ptounpacked, px); 370 371 ret: 372 return; 373 } 374 375 /* PUBLIC FUNCTIONS */ 376 377 /* 378 * decimal_to_floating routines convert the decimal record at *pd to the 379 * floating type item at *px, observing the modes specified in *pm and 380 * setting exceptions in *ps. 381 * 382 * pd->sign and pd->fpclass are always taken into account. 383 * 384 * pd->exponent, pd->ds and pd->ndigits are used when pd->fpclass is 385 * fp_normal or fp_subnormal. In these cases pd->ds is expected to 386 * contain one or more ascii digits followed by a null and pd->ndigits 387 * is assumed to be the length of the string pd->ds. Notice that for 388 * efficiency reasons, the assumption that pd->ndigits == strlen(pd->ds) 389 * is NEVER verified. 390 * 391 * px is set to a correctly rounded approximation to 392 * (sign)*(ds)*10**(exponent) If pd->more != 0 then additional nonzero digits 393 * are assumed to follow those in ds; fp_inexact is set accordingly. 394 * 395 * Thus if pd->exponent == -2 and pd->ds = "1234", *px will get 12.34 rounded to 396 * storage precision. 397 * 398 * px is correctly rounded according to the IEEE rounding modes in pm->rd. *ps 399 * is set to contain fp_inexact, fp_underflow, or fp_overflow if any of these 400 * arise. 401 * 402 * pm->df and pm->ndigits are never used. 403 * 404 */ 405 406 void 407 decimal_to_single(px, pm, pd, ps) 408 single *px; 409 decimal_mode *pm; 410 decimal_record *pd; 411 fp_exception_field_type *ps; 412 { 413 single_equivalence kluge; 414 unpacked u; 415 416 *ps = 0; /* Initialize to no floating-point 417 * exceptions. */ 418 kluge.f.msw.sign = pd->sign ? 1 : 0; 419 switch (pd->fpclass) { 420 case fp_zero: 421 kluge.f.msw.exponent = 0; 422 kluge.f.msw.significand = 0; 423 break; 424 case fp_infinity: 425 kluge.f.msw.exponent = 0xff; 426 kluge.f.msw.significand = 0; 427 break; 428 case fp_quiet: 429 kluge.f.msw.exponent = 0xff; 430 kluge.f.msw.significand = 0x7fffff; 431 break; 432 case fp_signaling: 433 kluge.f.msw.exponent = 0xff; 434 kluge.f.msw.significand = 0x3fffff; 435 break; 436 default: 437 if (pd->exponent > SINGLE_MAXE) { /* Guaranteed overflow. */ 438 u.sign = pd->sign == 0 ? 0 : 1; 439 u.fpclass = fp_normal; 440 u.exponent = 0x000fffff; 441 u.significand[0] = 0x80000000; 442 } else if (pd->exponent >= -SINGLE_MAXE) { /* Guaranteed in range. */ 443 goto inrange; 444 } else if (pd->exponent <= (-SINGLE_MAXE - DECIMAL_STRING_LENGTH)) { /* Guaranteed deep 445 * underflow. */ 446 goto underflow; 447 } else { /* Deep underflow possible, depending on 448 * string length. */ 449 int i; 450 451 for (i = 0; (pd->ds[i] != 0) && (i < (-pd->exponent - SINGLE_MAXE)); i++); 452 if (i < (-pd->exponent - SINGLE_MAXE)) { /* Deep underflow */ 453 underflow: 454 u.sign = pd->sign == 0 ? 0 : 1; 455 u.fpclass = fp_normal; 456 u.exponent = -0x000fffff; 457 u.significand[0] = 0x80000000; 458 } else {/* In range. */ 459 inrange: 460 decimal_to_unpacked(&u, pd, 24); 461 } 462 } 463 _fp_current_exceptions = 0; 464 _fp_current_direction = pm->rd; 465 _pack_single(&u, &kluge.x); 466 *ps = _fp_current_exceptions; 467 } 468 *px = kluge.x; 469 } 470 471 void 472 decimal_to_double(px, pm, pd, ps) 473 double *px; 474 decimal_mode *pm; 475 decimal_record *pd; 476 fp_exception_field_type *ps; 477 { 478 double_equivalence kluge; 479 unpacked u; 480 481 *ps = 0; /* Initialize to no floating-point 482 * exceptions. */ 483 kluge.f.msw.sign = pd->sign ? 1 : 0; 484 switch (pd->fpclass) { 485 case fp_zero: 486 kluge.f.msw.exponent = 0; 487 kluge.f.msw.significand = 0; 488 kluge.f.significand2 = 0; 489 break; 490 case fp_infinity: 491 kluge.f.msw.exponent = 0x7ff; 492 kluge.f.msw.significand = 0; 493 kluge.f.significand2 = 0; 494 break; 495 case fp_quiet: 496 kluge.f.msw.exponent = 0x7ff; 497 kluge.f.msw.significand = 0xfffff; 498 kluge.f.significand2 = 0xffffffff; 499 break; 500 case fp_signaling: 501 kluge.f.msw.exponent = 0x7ff; 502 kluge.f.msw.significand = 0x7ffff; 503 kluge.f.significand2 = 0xffffffff; 504 break; 505 default: 506 if (pd->exponent > DOUBLE_MAXE) { /* Guaranteed overflow. */ 507 u.sign = pd->sign == 0 ? 0 : 1; 508 u.fpclass = fp_normal; 509 u.exponent = 0x000fffff; 510 u.significand[0] = 0x80000000; 511 } else if (pd->exponent >= -DOUBLE_MAXE) { /* Guaranteed in range. */ 512 goto inrange; 513 } else if (pd->exponent <= (-DOUBLE_MAXE - DECIMAL_STRING_LENGTH)) { /* Guaranteed deep 514 * underflow. */ 515 goto underflow; 516 } else { /* Deep underflow possible, depending on 517 * string length. */ 518 int i; 519 520 for (i = 0; (pd->ds[i] != 0) && (i < (-pd->exponent - DOUBLE_MAXE)); i++); 521 if (i < (-pd->exponent - DOUBLE_MAXE)) { /* Deep underflow */ 522 underflow: 523 u.sign = pd->sign == 0 ? 0 : 1; 524 u.fpclass = fp_normal; 525 u.exponent = -0x000fffff; 526 u.significand[0] = 0x80000000; 527 } else {/* In range. */ 528 inrange: 529 decimal_to_unpacked(&u, pd, 53); 530 } 531 } 532 _fp_current_exceptions = 0; 533 _fp_current_direction = pm->rd; 534 _pack_double(&u, &kluge.x); 535 *ps = _fp_current_exceptions; 536 } 537 *px = kluge.x; 538 } 539 540 void 541 decimal_to_extended(px, pm, pd, ps) 542 extended *px; 543 decimal_mode *pm; 544 decimal_record *pd; 545 fp_exception_field_type *ps; 546 { 547 extended_equivalence kluge; 548 unpacked u; 549 550 *ps = 0; /* Initialize to no floating-point 551 * exceptions. */ 552 kluge.f.msw.sign = pd->sign ? 1 : 0; 553 switch (pd->fpclass) { 554 case fp_zero: 555 kluge.f.msw.exponent = 0; 556 kluge.f.significand = 0; 557 kluge.f.significand2 = 0; 558 break; 559 case fp_infinity: 560 kluge.f.msw.exponent = 0x7fff; 561 kluge.f.significand = 0; 562 kluge.f.significand2 = 0; 563 break; 564 case fp_quiet: 565 kluge.f.msw.exponent = 0x7fff; 566 kluge.f.significand = 0xffffffff; 567 kluge.f.significand2 = 0xffffffff; 568 break; 569 case fp_signaling: 570 kluge.f.msw.exponent = 0x7fff; 571 kluge.f.significand = 0x3fffffff; 572 kluge.f.significand2 = 0xffffffff; 573 break; 574 default: 575 if (pd->exponent > EXTENDED_MAXE) { /* Guaranteed overflow. */ 576 u.sign = pd->sign == 0 ? 0 : 1; 577 u.fpclass = fp_normal; 578 u.exponent = 0x000fffff; 579 u.significand[0] = 0x80000000; 580 } else if (pd->exponent >= -EXTENDED_MAXE) { /* Guaranteed in range. */ 581 goto inrange; 582 } else if (pd->exponent <= (-EXTENDED_MAXE - DECIMAL_STRING_LENGTH)) { /* Guaranteed deep 583 * underflow. */ 584 goto underflow; 585 } else { /* Deep underflow possible, depending on 586 * string length. */ 587 int i; 588 589 for (i = 0; (pd->ds[i] != 0) && (i < (-pd->exponent - EXTENDED_MAXE)); i++); 590 if (i < (-pd->exponent - EXTENDED_MAXE)) { /* Deep underflow */ 591 underflow: 592 u.sign = pd->sign == 0 ? 0 : 1; 593 u.fpclass = fp_normal; 594 u.exponent = -0x000fffff; 595 u.significand[0] = 0x80000000; 596 } else {/* In range. */ 597 inrange: 598 decimal_to_unpacked(&u, pd, 64); 599 } 600 } 601 _fp_current_exceptions = 0; 602 _fp_current_direction = pm->rd; 603 _fp_current_precision = fp_extended; 604 _pack_extended(&u, px); 605 *ps = _fp_current_exceptions; 606 return; 607 } 608 (*px)[0] = kluge.x[0]; 609 (*px)[1] = kluge.x[1]; 610 (*px)[2] = kluge.x[2]; 611 } 612 613 void 614 decimal_to_quadruple(px, pm, pd, ps) 615 quadruple *px; 616 decimal_mode *pm; 617 decimal_record *pd; 618 fp_exception_field_type *ps; 619 { 620 quadruple_equivalence kluge; 621 unpacked u; 622 int i; 623 624 *ps = 0; /* Initialize to no floating-point 625 * exceptions. */ 626 kluge.f.msw.sign = pd->sign ? 1 : 0; 627 switch (pd->fpclass) { 628 case fp_zero: 629 kluge.f.msw.exponent = 0; 630 kluge.f.msw.significand = 0; 631 kluge.f.significand2 = 0; 632 kluge.f.significand3 = 0; 633 kluge.f.significand4 = 0; 634 break; 635 case fp_infinity: 636 kluge.f.msw.exponent = 0x7fff; 637 kluge.f.msw.significand = 0; 638 kluge.f.significand2 = 0; 639 kluge.f.significand3 = 0; 640 kluge.f.significand4 = 0; 641 break; 642 case fp_quiet: 643 kluge.f.msw.exponent = 0x7fff; 644 kluge.f.msw.significand = 0xffff; 645 kluge.f.significand2 = 0xffffffff; 646 kluge.f.significand3 = 0xffffffff; 647 kluge.f.significand4 = 0xffffffff; 648 break; 649 case fp_signaling: 650 kluge.f.msw.exponent = 0x7fff; 651 kluge.f.msw.significand = 0x7fff; 652 kluge.f.significand2 = 0xffffffff; 653 kluge.f.significand3 = 0xffffffff; 654 kluge.f.significand4 = 0xffffffff; 655 break; 656 default: 657 if (pd->exponent > QUAD_MAXE) { /* Guaranteed overflow. */ 658 u.sign = pd->sign == 0 ? 0 : 1; 659 u.fpclass = fp_normal; 660 u.exponent = 0x000fffff; 661 u.significand[0] = 0x80000000; 662 } else if (pd->exponent >= -QUAD_MAXE) { /* Guaranteed in range. */ 663 goto inrange; 664 } else if (pd->exponent <= (-QUAD_MAXE - DECIMAL_STRING_LENGTH)) { /* Guaranteed deep 665 * underflow. */ 666 goto underflow; 667 } else { /* Deep underflow possible, depending on 668 * string length. */ 669 670 for (i = 0; (pd->ds[i] != 0) && (i < (-pd->exponent - QUAD_MAXE)); i++); 671 if (i < (-pd->exponent - QUAD_MAXE)) { /* Deep underflow */ 672 underflow: 673 u.sign = pd->sign == 0 ? 0 : 1; 674 u.fpclass = fp_normal; 675 u.exponent = -0x000fffff; 676 u.significand[0] = 0x80000000; 677 } else {/* In range. */ 678 inrange: 679 decimal_to_unpacked(&u, pd, 113); 680 } 681 } 682 _fp_current_exceptions = 0; 683 _fp_current_direction = pm->rd; 684 _pack_quadruple(&u, px); 685 *ps = _fp_current_exceptions; 686 return; 687 } 688 #ifdef __STDC__ 689 *px = kluge.x; 690 #else 691 for (i = 0; i < 4; i++) 692 px->u[i] = kluge.x.u[i]; 693 #endif 694 } 695