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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Conversion from binary to decimal floating point 31 */ 32 33 #pragma weak single_to_decimal = _single_to_decimal 34 #pragma weak double_to_decimal = _double_to_decimal 35 #pragma weak extended_to_decimal = _extended_to_decimal 36 #pragma weak quadruple_to_decimal = _quadruple_to_decimal 37 38 #include "synonyms.h" 39 #include <stdlib.h> 40 #include "base_conversion.h" 41 42 /* 43 * Any sensible programmer would inline the following routine where 44 * it is used below. Unfortunately, the Sun SPARC compilers are not 45 * consistent in generating efficient code for this, so inlining it 46 * as written can cause the *_to_decimal functions to take twice as 47 * long in some cases. 48 * 49 * We might be tempted, then, to rewrite the source to match the most 50 * efficient code the compilers generate and inline that. Alas, the 51 * most efficient code on SPARC uses 32x32->64 bit multiply, which 52 * can't be expressed directly in source code. We could use long long, 53 * which would imply 64x64->64 bit multiply; this would work perfectly 54 * well on SPARC in v8plus mode. But as of Solaris 10, libc for SPARC 55 * is still built in v8 mode, and of course, x86 is another story. 56 * 57 * We could also choose to use an inline template to get the most 58 * efficient code without incurring the full cost of a function call. 59 * Since I expect that would not buy much performance gain, and I 60 * prefer to avoid using inline templates for things that can be 61 * written in a perfectly straightforward way in C, I've settled 62 * for this implementation. I hope that someday the compilers will 63 * get less flaky and/or someone will come up with a better way to 64 * do this. 65 */ 66 static unsigned int 67 __quorem10000(unsigned int x, unsigned short *pr) 68 { 69 *pr = x % 10000; 70 return (x / 10000); 71 } 72 73 /* 74 * Convert the integer part of a nonzero base-2^16 _big_float *pb 75 * to base 10^4 in **ppd. The converted value is accurate to nsig 76 * significant digits. On exit, *sticky is nonzero if *pb had a 77 * nonzero fractional part. If pb->exponent > 0 and **ppd is not 78 * large enough to hold the final converted value (i.e., the con- 79 * verted significand scaled by 2^pb->exponent), then on exit, 80 * *ppd will point to a newly allocated _big_float, which must be 81 * freed by the caller. (The number of significant digits we need 82 * should fit in pd, but __big_float_times_power may allocate new 83 * storage anyway because we could be multiplying by as much as 84 * 2^16271, which would require more than 4000 digits.) 85 * 86 * This routine does not check that **ppd is large enough to hold 87 * the result of converting the significand of *pb. 88 */ 89 static void 90 __big_binary_to_big_decimal(_big_float *pb, int nsig, _big_float **ppd, 91 int *sticky) 92 { 93 _big_float *pd; 94 int i, j, len, s; 95 unsigned int carry; 96 97 pd = *ppd; 98 99 /* convert pb a digit at a time, most significant first */ 100 if (pb->bexponent + ((pb->blength - 1) << 4) >= 0) { 101 carry = pb->bsignificand[pb->blength - 1]; 102 pd->bsignificand[1] = __quorem10000(carry, 103 &pd->bsignificand[0]); 104 len = (pd->bsignificand[1])? 2 : 1; 105 for (i = pb->blength - 2; i >= 0 && 106 pb->bexponent + (i << 4) >= 0; i--) { 107 /* multiply pd by 2^16 and add next digit */ 108 carry = pb->bsignificand[i]; 109 for (j = 0; j < len; j++) { 110 carry += (unsigned int)pd->bsignificand[j] 111 << 16; 112 carry = __quorem10000(carry, 113 &pd->bsignificand[j]); 114 } 115 while (carry != 0) { 116 carry = __quorem10000(carry, 117 &pd->bsignificand[j]); 118 j++; 119 } 120 len = j; 121 } 122 } else { 123 i = pb->blength - 1; 124 len = 0; 125 } 126 127 /* convert any partial digit */ 128 if (i >= 0 && pb->bexponent + (i << 4) > -16) { 129 s = pb->bexponent + (i << 4) + 16; 130 /* multiply pd by 2^s and add partial digit */ 131 carry = pb->bsignificand[i] >> (16 - s); 132 for (j = 0; j < len; j++) { 133 carry += (unsigned int)pd->bsignificand[j] << s; 134 carry = __quorem10000(carry, &pd->bsignificand[j]); 135 } 136 while (carry != 0) { 137 carry = __quorem10000(carry, &pd->bsignificand[j]); 138 j++; 139 } 140 len = j; 141 s = pb->bsignificand[i] & ((1 << (16 - s)) - 1); 142 i--; 143 } else { 144 s = 0; 145 } 146 147 pd->blength = len; 148 pd->bexponent = 0; 149 150 /* continue accumulating sticky flag */ 151 while (i >= 0) 152 s |= pb->bsignificand[i--]; 153 *sticky = s; 154 155 if (pb->bexponent > 0) { 156 /* scale pd by 2^pb->bexponent */ 157 __big_float_times_power(pd, 2, pb->bexponent, nsig, ppd); 158 } 159 } 160 161 /* 162 * Convert a base-10^4 _big_float *pf to a decimal string in *pd, 163 * rounding according to the modes in *pm and recording any exceptions 164 * in *ps. If sticky is nonzero, then additional nonzero digits are 165 * assumed to follow those in *pf. pd->sign must have already been 166 * filled in, and pd->fpclass is not modified. The resulting string 167 * is stored in pd->ds, terminated by a null byte. The length of this 168 * string is stored in pd->ndigits, and the corresponding exponent 169 * is stored in pd->exponent. If the converted value is not exact, 170 * the inexact flag is set in *ps. 171 * 172 * When pm->df == fixed_form, we may discover that the result would 173 * have more than DECIMAL_STRING_LENGTH - 1 digits. In this case, 174 * we put DECIMAL_STRING_LENGTH - 1 digits into *pd, adjusting both 175 * the exponent and the decimal place at which the value is rounded 176 * as need be, and we set the overflow flag in *ps. (Raising overflow 177 * is a bug, but we have to do it to maintain backward compatibility.) 178 * 179 * *pf may be modified. 180 */ 181 static void 182 __big_decimal_to_string(_big_float *pf, int sticky, decimal_mode *pm, 183 decimal_record *pd, fp_exception_field_type *ps) 184 { 185 unsigned short d; 186 int e, er, efirst, elast, i, is, j; 187 char s[4], round; 188 189 /* set e = floor(log10(*pf)) */ 190 i = pf->blength - 1; 191 if (i < 0) { 192 e = pf->bexponent = -DECIMAL_STRING_LENGTH - 2; 193 } else { 194 e = pf->bexponent + (i << 2); 195 d = pf->bsignificand[i]; 196 if (d >= 1000) 197 e += 3; 198 else if (d >= 100) 199 e += 2; 200 else if (d >= 10) 201 e++; 202 } 203 204 /* 205 * Determine the power of ten after which to round and the 206 * powers corresponding to the first and last digits desired 207 * in the result. 208 */ 209 if (pm->df == fixed_form) { 210 /* F format */ 211 er = -pm->ndigits; 212 if (er < 0) { 213 efirst = (e >= 0)? e : -1; 214 elast = er; 215 } else { 216 efirst = (e >= er)? e : ((er > 0)? er - 1 : 0); 217 elast = 0; 218 } 219 220 /* check for possible overflow of pd->ds */ 221 if (efirst - elast >= DECIMAL_STRING_LENGTH - 1) { 222 efirst = e; 223 elast = e - DECIMAL_STRING_LENGTH + 2; 224 if (er < elast) 225 er = elast; 226 *ps |= 1 << fp_overflow; 227 } 228 } else { 229 /* E format */ 230 efirst = e; 231 elast = er = e - pm->ndigits + 1; 232 } 233 234 /* retrieve digits down to the (er - 1) place */ 235 is = 0; 236 for (e = efirst; e >= pf->bexponent + (pf->blength << 2) && 237 e >= er - 1; e--) 238 pd->ds[is++] = '0'; 239 240 i = pf->blength - 1; 241 j = 3 - ((e - pf->bexponent) & 3); 242 if (j > 0 && e >= er - 1) { 243 __four_digits_quick(pf->bsignificand[i], s); 244 while (j <= 3 && e >= er - 1) { 245 pd->ds[is++] = s[j++]; 246 e--; 247 } 248 while (j <= 3) 249 sticky |= (s[j++] - '0'); 250 i--; 251 } 252 253 while ((i | (e - er - 2)) >= 0) { /* i >= 0 && e >= er + 2 */ 254 __four_digits_quick(pf->bsignificand[i], pd->ds + is); 255 is += 4; 256 e -= 4; 257 i--; 258 } 259 260 if (i >= 0) { 261 if (e >= er - 1) { 262 __four_digits_quick(pf->bsignificand[i], s); 263 for (j = 0; e >= er - 1; j++) { 264 pd->ds[is++] = s[j]; 265 e--; 266 } 267 while (j <= 3) 268 sticky |= (s[j++] - '0'); 269 i--; 270 } 271 } else { 272 while (e-- >= er - 1) 273 pd->ds[is++] = '0'; 274 } 275 276 /* collect rounding information */ 277 round = pd->ds[--is]; 278 while (i >= 0) 279 sticky |= pf->bsignificand[i--]; 280 281 /* add more trailing zeroes if need be */ 282 for (e = er - 1; e >= elast; e--) 283 pd->ds[is++] = '0'; 284 285 pd->exponent = elast; 286 pd->ndigits = is; 287 pd->ds[is] = '\0'; 288 289 /* round */ 290 if (round == '0' && sticky == 0) 291 return; 292 293 *ps |= 1 << fp_inexact; 294 295 switch (pm->rd) { 296 case fp_nearest: 297 if (round < '5' || (round == '5' && sticky == 0 && 298 (is <= 0 || (pd->ds[is - 1] & 1) == 0))) 299 return; 300 break; 301 302 case fp_positive: 303 if (pd->sign) 304 return; 305 break; 306 307 case fp_negative: 308 if (!pd->sign) 309 return; 310 break; 311 312 default: 313 return; 314 } 315 316 /* round up */ 317 for (i = efirst - er; i >= 0 && pd->ds[i] == '9'; i--) 318 pd->ds[i] = '0'; 319 if (i >= 0) { 320 (pd->ds[i])++; 321 } else { 322 /* rounding carry out has occurred */ 323 pd->ds[0] = '1'; 324 if (pm->df == floating_form) { 325 pd->exponent++; 326 } else if (is == DECIMAL_STRING_LENGTH - 1) { 327 pd->exponent++; 328 *ps |= 1 << fp_overflow; 329 } else { 330 if (is > 0) 331 pd->ds[is] = '0'; 332 is++; 333 pd->ndigits = is; 334 pd->ds[is] = '\0'; 335 } 336 } 337 } 338 339 /* 340 * Convert a binary floating point value represented by *pf to a 341 * decimal record *pd according to the modes in *pm. Any exceptions 342 * incurred are passed back via *ps. 343 */ 344 static void 345 __bigfloat_to_decimal(_big_float *bf, decimal_mode *pm, decimal_record *pd, 346 fp_exception_field_type *ps) 347 { 348 _big_float *pbf, *pbd, d; 349 int sticky, powten, sigbits, sigdigits, i; 350 351 /* 352 * If pm->ndigits is too large or too small, set the overflow 353 * flag in *ps and do nothing. (Raising overflow is a bug, 354 * but we have to do it to maintain backward compatibility.) 355 */ 356 if (pm->ndigits >= DECIMAL_STRING_LENGTH || pm->ndigits <= 357 ((pm->df == floating_form)? 0 : -DECIMAL_STRING_LENGTH)) { 358 *ps = 1 << fp_overflow; 359 return; 360 } 361 362 pbf = bf; 363 powten = 0; 364 365 /* pre-scale to get the digits we want into the integer part */ 366 if (pm->df == fixed_form) { 367 /* F format */ 368 if (pm->ndigits >= 0 && bf->bexponent < 0) { 369 /* 370 * Scale by 10^min(-bf->bexponent, pm->ndigits + 1). 371 */ 372 powten = pm->ndigits + 1; 373 if (powten > -bf->bexponent) 374 powten = -bf->bexponent; 375 /* 376 * Take sigbits large enough to get all integral 377 * digits correct. 378 */ 379 sigbits = bf->bexponent + (bf->blength << 4) + 380 (((powten * 217706) + 65535) >> 16); 381 if (sigbits < 1) 382 sigbits = 1; 383 __big_float_times_power(bf, 10, powten, sigbits, &pbf); 384 } 385 sigdigits = DECIMAL_STRING_LENGTH + 1; 386 } else { 387 /* E format */ 388 if (bf->bexponent < 0) { 389 /* i is a lower bound on log2(x) */ 390 i = bf->bexponent + ((bf->blength - 1) << 4); 391 if (i <= 0 || ((i * 19728) >> 16) < pm->ndigits + 1) { 392 /* 393 * Scale by 10^min(-bf->bexponent, 394 * pm->ndigits + 1 + u) where u is 395 * an upper bound on -log10(x). 396 */ 397 powten = pm->ndigits + 1; 398 if (i < 0) 399 powten += ((-i * 19729) + 65535) >> 16; 400 else if (i > 0) 401 powten -= (i * 19728) >> 16; 402 if (powten > -bf->bexponent) 403 powten = -bf->bexponent; 404 /* 405 * Take sigbits large enough to get 406 * all integral digits correct. 407 */ 408 sigbits = i + 16 + 409 (((powten * 217706) + 65535) >> 16); 410 __big_float_times_power(bf, 10, powten, 411 sigbits, &pbf); 412 } 413 } 414 sigdigits = pm->ndigits + 2; 415 } 416 417 /* convert to base 10^4 */ 418 d.bsize = _BIG_FLOAT_SIZE; 419 pbd = &d; 420 __big_binary_to_big_decimal(pbf, sigdigits, &pbd, &sticky); 421 422 /* adjust pbd->bexponent based on the scale factor above */ 423 pbd->bexponent -= powten; 424 425 /* convert to ASCII */ 426 __big_decimal_to_string(pbd, sticky, pm, pd, ps); 427 428 if (pbf != bf) 429 (void) free((void *)pbf); 430 if (pbd != &d) 431 (void) free((void *)pbd); 432 } 433 434 /* remove trailing zeroes from the significand of p */ 435 static void 436 __shorten(_big_float *p) 437 { 438 int length = p->blength; 439 int zeros, i; 440 441 /* count trailing zeros */ 442 for (zeros = 0; zeros < length && p->bsignificand[zeros] == 0; zeros++) 443 ; 444 if (zeros) { 445 length -= zeros; 446 p->bexponent += zeros << 4; 447 for (i = 0; i < length; i++) 448 p->bsignificand[i] = p->bsignificand[i + zeros]; 449 p->blength = length; 450 } 451 } 452 453 /* 454 * Unpack a normal or subnormal double into a _big_float. 455 */ 456 static void 457 __double_to_bigfloat(double *px, _big_float *pf) 458 { 459 double_equivalence *x; 460 461 x = (double_equivalence *)px; 462 pf->bsize = _BIG_FLOAT_SIZE; 463 pf->bexponent = x->f.msw.exponent - DOUBLE_BIAS - 52; 464 pf->blength = 4; 465 pf->bsignificand[0] = x->f.significand2 & 0xffff; 466 pf->bsignificand[1] = x->f.significand2 >> 16; 467 pf->bsignificand[2] = x->f.msw.significand & 0xffff; 468 pf->bsignificand[3] = x->f.msw.significand >> 16; 469 if (x->f.msw.exponent == 0) { 470 pf->bexponent++; 471 while (pf->bsignificand[pf->blength - 1] == 0) 472 pf->blength--; 473 } else { 474 pf->bsignificand[3] += 0x10; 475 } 476 __shorten(pf); 477 } 478 479 /* 480 * Unpack a normal or subnormal extended into a _big_float. 481 */ 482 static void 483 __extended_to_bigfloat(extended *px, _big_float *pf) 484 { 485 extended_equivalence *x; 486 487 x = (extended_equivalence *)px; 488 pf->bsize = _BIG_FLOAT_SIZE; 489 pf->bexponent = x->f.msw.exponent - EXTENDED_BIAS - 63; 490 pf->blength = 4; 491 pf->bsignificand[0] = x->f.significand2 & 0xffff; 492 pf->bsignificand[1] = x->f.significand2 >> 16; 493 pf->bsignificand[2] = x->f.significand & 0xffff; 494 pf->bsignificand[3] = x->f.significand >> 16; 495 if (x->f.msw.exponent == 0) { 496 pf->bexponent++; 497 while (pf->bsignificand[pf->blength - 1] == 0) 498 pf->blength--; 499 } 500 __shorten(pf); 501 } 502 503 /* 504 * Unpack a normal or subnormal quad into a _big_float. 505 */ 506 static void 507 __quadruple_to_bigfloat(quadruple *px, _big_float *pf) 508 { 509 quadruple_equivalence *x; 510 511 x = (quadruple_equivalence *)px; 512 pf->bsize = _BIG_FLOAT_SIZE; 513 pf->bexponent = x->f.msw.exponent - QUAD_BIAS - 112; 514 pf->bsignificand[0] = x->f.significand4 & 0xffff; 515 pf->bsignificand[1] = x->f.significand4 >> 16; 516 pf->bsignificand[2] = x->f.significand3 & 0xffff; 517 pf->bsignificand[3] = x->f.significand3 >> 16; 518 pf->bsignificand[4] = x->f.significand2 & 0xffff; 519 pf->bsignificand[5] = x->f.significand2 >> 16; 520 pf->bsignificand[6] = x->f.msw.significand; 521 if (x->f.msw.exponent == 0) { 522 pf->blength = 7; 523 pf->bexponent++; 524 while (pf->bsignificand[pf->blength - 1] == 0) 525 pf->blength--; 526 } else { 527 pf->blength = 8; 528 pf->bsignificand[7] = 1; 529 } 530 __shorten(pf); 531 } 532 533 /* PUBLIC ROUTINES */ 534 535 void 536 single_to_decimal(single *px, decimal_mode *pm, decimal_record *pd, 537 fp_exception_field_type *ps) 538 { 539 single_equivalence *kluge; 540 _big_float bf; 541 fp_exception_field_type ef; 542 double x; 543 544 kluge = (single_equivalence *)px; 545 pd->sign = kluge->f.msw.sign; 546 547 /* decide what to do based on the class of x */ 548 if (kluge->f.msw.exponent == 0) { /* 0 or subnormal */ 549 if (kluge->f.msw.significand == 0) { 550 pd->fpclass = fp_zero; 551 *ps = 0; 552 return; 553 } else { 554 #if defined(__sparc) 555 int i; 556 557 pd->fpclass = fp_subnormal; 558 /* 559 * On SPARC, simply converting *px to double 560 * can flush a subnormal value to zero when 561 * nonstandard mode is enabled, so we have 562 * to go through all this nonsense instead. 563 */ 564 i = *(int *)px; 565 x = (double)(i & ~0x80000000); 566 if (i < 0) 567 x = -x; 568 x *= 1.401298464324817070923730e-45; /* 2^-149 */ 569 ef = 0; 570 if (__fast_double_to_decimal(&x, pm, pd, &ef)) { 571 __double_to_bigfloat(&x, &bf); 572 __bigfloat_to_decimal(&bf, pm, pd, &ef); 573 } 574 if (ef != 0) 575 __base_conversion_set_exception(ef); 576 *ps = ef; 577 return; 578 #else 579 pd->fpclass = fp_subnormal; 580 #endif 581 } 582 } else if (kluge->f.msw.exponent == 0xff) { /* inf or nan */ 583 if (kluge->f.msw.significand == 0) 584 pd->fpclass = fp_infinity; 585 else if (kluge->f.msw.significand >= 0x400000) 586 pd->fpclass = fp_quiet; 587 else 588 pd->fpclass = fp_signaling; 589 *ps = 0; 590 return; 591 } else { 592 pd->fpclass = fp_normal; 593 } 594 595 ef = 0; 596 x = *px; 597 if (__fast_double_to_decimal(&x, pm, pd, &ef)) { 598 __double_to_bigfloat(&x, &bf); 599 __bigfloat_to_decimal(&bf, pm, pd, &ef); 600 } 601 if (ef != 0) 602 __base_conversion_set_exception(ef); 603 *ps = ef; 604 } 605 606 void 607 double_to_decimal(double *px, decimal_mode *pm, decimal_record *pd, 608 fp_exception_field_type *ps) 609 { 610 double_equivalence *kluge; 611 _big_float bf; 612 fp_exception_field_type ef; 613 614 kluge = (double_equivalence *)px; 615 pd->sign = kluge->f.msw.sign; 616 617 /* decide what to do based on the class of x */ 618 if (kluge->f.msw.exponent == 0) { /* 0 or subnormal */ 619 if (kluge->f.msw.significand == 0 && 620 kluge->f.significand2 == 0) { 621 pd->fpclass = fp_zero; 622 *ps = 0; 623 return; 624 } else { 625 pd->fpclass = fp_subnormal; 626 } 627 } else if (kluge->f.msw.exponent == 0x7ff) { /* inf or nan */ 628 if (kluge->f.msw.significand == 0 && 629 kluge->f.significand2 == 0) 630 pd->fpclass = fp_infinity; 631 else if (kluge->f.msw.significand >= 0x80000) 632 pd->fpclass = fp_quiet; 633 else 634 pd->fpclass = fp_signaling; 635 *ps = 0; 636 return; 637 } else { 638 pd->fpclass = fp_normal; 639 } 640 641 ef = 0; 642 if (__fast_double_to_decimal(px, pm, pd, &ef)) { 643 __double_to_bigfloat(px, &bf); 644 __bigfloat_to_decimal(&bf, pm, pd, &ef); 645 } 646 if (ef != 0) 647 __base_conversion_set_exception(ef); 648 *ps = ef; 649 } 650 651 void 652 extended_to_decimal(extended *px, decimal_mode *pm, decimal_record *pd, 653 fp_exception_field_type *ps) 654 { 655 extended_equivalence *kluge; 656 _big_float bf; 657 fp_exception_field_type ef; 658 659 kluge = (extended_equivalence *)px; 660 pd->sign = kluge->f.msw.sign; 661 662 /* decide what to do based on the class of x */ 663 if (kluge->f.msw.exponent == 0) { /* 0 or subnormal */ 664 if ((kluge->f.significand | kluge->f.significand2) == 0) { 665 pd->fpclass = fp_zero; 666 *ps = 0; 667 return; 668 } else { 669 /* 670 * x could be a pseudo-denormal, but the distinction 671 * doesn't matter 672 */ 673 pd->fpclass = fp_subnormal; 674 } 675 } else if ((kluge->f.significand & 0x80000000) == 0) { 676 /* 677 * In Intel's extended format, if the exponent is 678 * nonzero but the explicit integer bit is zero, this 679 * is an "unsupported format" bit pattern; treat it 680 * like a signaling NaN. 681 */ 682 pd->fpclass = fp_signaling; 683 *ps = 0; 684 return; 685 } else if (kluge->f.msw.exponent == 0x7fff) { /* inf or nan */ 686 if (((kluge->f.significand & 0x7fffffff) | 687 kluge->f.significand2) == 0) 688 pd->fpclass = fp_infinity; 689 else if ((kluge->f.significand & 0x7fffffff) >= 0x40000000) 690 pd->fpclass = fp_quiet; 691 else 692 pd->fpclass = fp_signaling; 693 *ps = 0; 694 return; 695 } else { 696 pd->fpclass = fp_normal; 697 } 698 699 ef = 0; 700 __extended_to_bigfloat(px, &bf); 701 __bigfloat_to_decimal(&bf, pm, pd, &ef); 702 if (ef != 0) 703 __base_conversion_set_exception(ef); 704 *ps = ef; 705 } 706 707 void 708 quadruple_to_decimal(quadruple *px, decimal_mode *pm, decimal_record *pd, 709 fp_exception_field_type *ps) 710 { 711 quadruple_equivalence *kluge; 712 _big_float bf; 713 fp_exception_field_type ef; 714 715 kluge = (quadruple_equivalence *)px; 716 pd->sign = kluge->f.msw.sign; 717 718 /* decide what to do based on the class of x */ 719 if (kluge->f.msw.exponent == 0) { /* 0 or subnormal */ 720 if (kluge->f.msw.significand == 0 && 721 (kluge->f.significand2 | kluge->f.significand3 | 722 kluge->f.significand4) == 0) { 723 pd->fpclass = fp_zero; 724 *ps = 0; 725 return; 726 } else { 727 pd->fpclass = fp_subnormal; 728 } 729 } else if (kluge->f.msw.exponent == 0x7fff) { /* inf or nan */ 730 if (kluge->f.msw.significand == 0 && 731 (kluge->f.significand2 | kluge->f.significand3 | 732 kluge->f.significand4) == 0) 733 pd->fpclass = fp_infinity; 734 else if (kluge->f.msw.significand >= 0x8000) 735 pd->fpclass = fp_quiet; 736 else 737 pd->fpclass = fp_signaling; 738 *ps = 0; 739 return; 740 } else { 741 pd->fpclass = fp_normal; 742 } 743 744 ef = 0; 745 __quadruple_to_bigfloat(px, &bf); 746 __bigfloat_to_decimal(&bf, pm, pd, &ef); 747 if (ef != 0) 748 __base_conversion_set_exception(ef); 749 *ps = ef; 750 } 751