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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 23 */ 24 /* 25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #include "libm.h" 30 #include "xpg6.h" /* __xpg6 */ 31 #include <stdio.h> 32 #include <float.h> /* DBL_MAX, DBL_MIN */ 33 #include <unistd.h> /* write */ 34 #if defined(__x86) 35 #include <ieeefp.h> 36 #undef fp_class 37 #define fp_class fpclass 38 #define fp_quiet FP_QNAN 39 #endif 40 #include <errno.h> 41 #undef fflush 42 #include <sys/isa_defs.h> 43 44 /* INDENT OFF */ 45 /* 46 * Report libm exception error according to System V Interface Definition 47 * (SVID). 48 * Error mapping: 49 * 1 -- acos(|x|>1) 50 * 2 -- asin(|x|>1) 51 * 3 -- atan2(+-0,+-0) 52 * 4 -- hypot overflow 53 * 5 -- cosh overflow 54 * 6 -- exp overflow 55 * 7 -- exp underflow 56 * 8 -- y0(0) 57 * 9 -- y0(-ve) 58 * 10-- y1(0) 59 * 11-- y1(-ve) 60 * 12-- yn(0) 61 * 13-- yn(-ve) 62 * 14-- lgamma(finite) overflow 63 * 15-- lgamma(-integer) 64 * 16-- log(0) 65 * 17-- log(x<0) 66 * 18-- log10(0) 67 * 19-- log10(x<0) 68 * 20-- pow(0.0,0.0) 69 * 21-- pow(x,y) overflow 70 * 22-- pow(x,y) underflow 71 * 23-- pow(0,negative) 72 * 24-- pow(neg,non-integral) 73 * 25-- sinh(finite) overflow 74 * 26-- sqrt(negative) 75 * 27-- fmod(x,0) 76 * 28-- remainder(x,0) 77 * 29-- acosh(x<1) 78 * 30-- atanh(|x|>1) 79 * 31-- atanh(|x|=1) 80 * 32-- scalb overflow 81 * 33-- scalb underflow 82 * 34-- j0(|x|>X_TLOSS) 83 * 35-- y0(x>X_TLOSS) 84 * 36-- j1(|x|>X_TLOSS) 85 * 37-- y1(x>X_TLOSS) 86 * 38-- jn(|x|>X_TLOSS, n) 87 * 39-- yn(x>X_TLOSS, n) 88 * 40-- gamma(finite) overflow 89 * 41-- gamma(-integer) 90 * 42-- pow(NaN,0.0) return NaN for SVID/XOPEN 91 * 43-- log1p(-1) 92 * 44-- log1p(x<-1) 93 * 45-- logb(0) 94 * 46-- nextafter overflow 95 * 47-- scalb(x,inf) 96 */ 97 /* INDENT ON */ 98 99 static double setexception(int, double); 100 101 static const union { 102 unsigned x[2]; 103 double d; 104 } C[] = { 105 #ifdef _LITTLE_ENDIAN 106 { 0xffffffff, 0x7fffffff }, 107 { 0x54442d18, 0x400921fb }, 108 #else 109 { 0x7fffffff, 0xffffffff }, 110 { 0x400921fb, 0x54442d18 }, 111 #endif 112 }; 113 114 #define NaN C[0].d 115 #define PI_RZ C[1].d 116 117 #define __HI(x) ((unsigned *)&x)[HIWORD] 118 #define __LO(x) ((unsigned *)&x)[LOWORD] 119 #undef Inf 120 #define Inf HUGE_VAL 121 122 double 123 _SVID_libm_err(double x, double y, int type) { 124 struct exception exc; 125 double t, w, ieee_retval = 0; 126 enum version lib_version = _lib_version; 127 int iy; 128 129 /* force libm_ieee behavior in SUSv3 mode */ 130 if ((__xpg6 & _C99SUSv3_math_errexcept) != 0) 131 lib_version = libm_ieee; 132 if (lib_version == c_issue_4) { 133 (void) fflush(stdout); 134 } 135 exc.arg1 = x; 136 exc.arg2 = y; 137 switch (type) { 138 case 1: 139 /* acos(|x|>1) */ 140 exc.type = DOMAIN; 141 exc.name = "acos"; 142 ieee_retval = setexception(3, 1.0); 143 exc.retval = 0.0; 144 if (lib_version == strict_ansi) { 145 errno = EDOM; 146 } else if (!matherr(&exc)) { 147 if (lib_version == c_issue_4) { 148 (void) write(2, "acos: DOMAIN error\n", 19); 149 } 150 errno = EDOM; 151 } 152 break; 153 case 2: 154 /* asin(|x|>1) */ 155 exc.type = DOMAIN; 156 exc.name = "asin"; 157 exc.retval = 0.0; 158 ieee_retval = setexception(3, 1.0); 159 if (lib_version == strict_ansi) { 160 errno = EDOM; 161 } else if (!matherr(&exc)) { 162 if (lib_version == c_issue_4) { 163 (void) write(2, "asin: DOMAIN error\n", 19); 164 } 165 errno = EDOM; 166 } 167 break; 168 case 3: 169 /* atan2(+-0,+-0) */ 170 exc.arg1 = y; 171 exc.arg2 = x; 172 exc.type = DOMAIN; 173 exc.name = "atan2"; 174 ieee_retval = copysign(1.0, x) == 1.0 ? y : 175 copysign(PI_RZ + DBL_MIN, y); 176 exc.retval = 0.0; 177 if (lib_version == strict_ansi) { 178 errno = EDOM; 179 } else if (!matherr(&exc)) { 180 if (lib_version == c_issue_4) { 181 (void) write(2, "atan2: DOMAIN error\n", 20); 182 } 183 errno = EDOM; 184 } 185 break; 186 case 4: 187 /* hypot(finite,finite) overflow */ 188 exc.type = OVERFLOW; 189 exc.name = "hypot"; 190 ieee_retval = Inf; 191 if (lib_version == c_issue_4) 192 exc.retval = HUGE; 193 else 194 exc.retval = HUGE_VAL; 195 if (lib_version == strict_ansi) 196 errno = ERANGE; 197 else if (!matherr(&exc)) 198 errno = ERANGE; 199 break; 200 case 5: 201 /* cosh(finite) overflow */ 202 exc.type = OVERFLOW; 203 exc.name = "cosh"; 204 ieee_retval = setexception(2, 1.0); 205 if (lib_version == c_issue_4) 206 exc.retval = HUGE; 207 else 208 exc.retval = HUGE_VAL; 209 if (lib_version == strict_ansi) 210 errno = ERANGE; 211 else if (!matherr(&exc)) 212 errno = ERANGE; 213 break; 214 case 6: 215 /* exp(finite) overflow */ 216 exc.type = OVERFLOW; 217 exc.name = "exp"; 218 ieee_retval = setexception(2, 1.0); 219 if (lib_version == c_issue_4) 220 exc.retval = HUGE; 221 else 222 exc.retval = HUGE_VAL; 223 if (lib_version == strict_ansi) 224 errno = ERANGE; 225 else if (!matherr(&exc)) 226 errno = ERANGE; 227 break; 228 case 7: 229 /* exp(finite) underflow */ 230 exc.type = UNDERFLOW; 231 exc.name = "exp"; 232 ieee_retval = setexception(1, 1.0); 233 exc.retval = 0.0; 234 if (lib_version == strict_ansi) 235 errno = ERANGE; 236 else if (!matherr(&exc)) 237 errno = ERANGE; 238 break; 239 case 8: 240 /* y0(0) = -inf */ 241 exc.type = DOMAIN; /* should be SING for IEEE */ 242 exc.name = "y0"; 243 ieee_retval = setexception(0, -1.0); 244 if (lib_version == c_issue_4) 245 exc.retval = -HUGE; 246 else 247 exc.retval = -HUGE_VAL; 248 if (lib_version == strict_ansi) { 249 errno = EDOM; 250 } else if (!matherr(&exc)) { 251 if (lib_version == c_issue_4) { 252 (void) write(2, "y0: DOMAIN error\n", 17); 253 } 254 errno = EDOM; 255 } 256 break; 257 case 9: 258 /* y0(x<0) = NaN */ 259 exc.type = DOMAIN; 260 exc.name = "y0"; 261 ieee_retval = setexception(3, 1.0); 262 if (lib_version == c_issue_4) 263 exc.retval = -HUGE; 264 else 265 exc.retval = -HUGE_VAL; 266 if (lib_version == strict_ansi) { 267 errno = EDOM; 268 } else if (!matherr(&exc)) { 269 if (lib_version == c_issue_4) { 270 (void) write(2, "y0: DOMAIN error\n", 17); 271 } 272 errno = EDOM; 273 } 274 break; 275 case 10: 276 /* y1(0) = -inf */ 277 exc.type = DOMAIN; /* should be SING for IEEE */ 278 exc.name = "y1"; 279 ieee_retval = setexception(0, -1.0); 280 if (lib_version == c_issue_4) 281 exc.retval = -HUGE; 282 else 283 exc.retval = -HUGE_VAL; 284 if (lib_version == strict_ansi) { 285 errno = EDOM; 286 } else if (!matherr(&exc)) { 287 if (lib_version == c_issue_4) { 288 (void) write(2, "y1: DOMAIN error\n", 17); 289 } 290 errno = EDOM; 291 } 292 break; 293 case 11: 294 /* y1(x<0) = NaN */ 295 exc.type = DOMAIN; 296 exc.name = "y1"; 297 ieee_retval = setexception(3, 1.0); 298 if (lib_version == c_issue_4) 299 exc.retval = -HUGE; 300 else 301 exc.retval = -HUGE_VAL; 302 if (lib_version == strict_ansi) { 303 errno = EDOM; 304 } else if (!matherr(&exc)) { 305 if (lib_version == c_issue_4) { 306 (void) write(2, "y1: DOMAIN error\n", 17); 307 } 308 errno = EDOM; 309 } 310 break; 311 case 12: 312 /* yn(n,0) = -inf */ 313 exc.type = DOMAIN; /* should be SING for IEEE */ 314 exc.name = "yn"; 315 ieee_retval = setexception(0, -1.0); 316 if (lib_version == c_issue_4) 317 exc.retval = -HUGE; 318 else 319 exc.retval = -HUGE_VAL; 320 if (lib_version == strict_ansi) { 321 errno = EDOM; 322 } else if (!matherr(&exc)) { 323 if (lib_version == c_issue_4) { 324 (void) write(2, "yn: DOMAIN error\n", 17); 325 } 326 errno = EDOM; 327 } 328 break; 329 case 13: 330 /* yn(x<0) = NaN */ 331 exc.type = DOMAIN; 332 exc.name = "yn"; 333 ieee_retval = setexception(3, 1.0); 334 if (lib_version == c_issue_4) 335 exc.retval = -HUGE; 336 else 337 exc.retval = -HUGE_VAL; 338 if (lib_version == strict_ansi) { 339 errno = EDOM; 340 } else if (!matherr(&exc)) { 341 if (lib_version == c_issue_4) { 342 (void) write(2, "yn: DOMAIN error\n", 17); 343 } 344 errno = EDOM; 345 } 346 break; 347 case 14: 348 /* lgamma(finite) overflow */ 349 exc.type = OVERFLOW; 350 exc.name = "lgamma"; 351 ieee_retval = setexception(2, 1.0); 352 if (lib_version == c_issue_4) 353 exc.retval = HUGE; 354 else 355 exc.retval = HUGE_VAL; 356 if (lib_version == strict_ansi) 357 errno = ERANGE; 358 else if (!matherr(&exc)) 359 errno = ERANGE; 360 break; 361 case 15: 362 /* lgamma(-integer) or lgamma(0) */ 363 exc.type = SING; 364 exc.name = "lgamma"; 365 ieee_retval = setexception(0, 1.0); 366 if (lib_version == c_issue_4) 367 exc.retval = HUGE; 368 else 369 exc.retval = HUGE_VAL; 370 if (lib_version == strict_ansi) { 371 errno = EDOM; 372 } else if (!matherr(&exc)) { 373 if (lib_version == c_issue_4) { 374 (void) write(2, "lgamma: SING error\n", 19); 375 } 376 errno = EDOM; 377 } 378 break; 379 case 16: 380 /* log(0) */ 381 exc.type = SING; 382 exc.name = "log"; 383 ieee_retval = setexception(0, -1.0); 384 if (lib_version == c_issue_4) 385 exc.retval = -HUGE; 386 else 387 exc.retval = -HUGE_VAL; 388 if (lib_version == strict_ansi) { 389 errno = ERANGE; 390 } else if (!matherr(&exc)) { 391 if (lib_version == c_issue_4) { 392 (void) write(2, "log: SING error\n", 16); 393 errno = EDOM; 394 } else { 395 errno = ERANGE; 396 } 397 } 398 break; 399 case 17: 400 /* log(x<0) */ 401 exc.type = DOMAIN; 402 exc.name = "log"; 403 ieee_retval = setexception(3, 1.0); 404 if (lib_version == c_issue_4) 405 exc.retval = -HUGE; 406 else 407 exc.retval = -HUGE_VAL; 408 if (lib_version == strict_ansi) { 409 errno = EDOM; 410 } else if (!matherr(&exc)) { 411 if (lib_version == c_issue_4) { 412 (void) write(2, "log: DOMAIN error\n", 18); 413 } 414 errno = EDOM; 415 } 416 break; 417 case 18: 418 /* log10(0) */ 419 exc.type = SING; 420 exc.name = "log10"; 421 ieee_retval = setexception(0, -1.0); 422 if (lib_version == c_issue_4) 423 exc.retval = -HUGE; 424 else 425 exc.retval = -HUGE_VAL; 426 if (lib_version == strict_ansi) { 427 errno = ERANGE; 428 } else if (!matherr(&exc)) { 429 if (lib_version == c_issue_4) { 430 (void) write(2, "log10: SING error\n", 18); 431 errno = EDOM; 432 } else { 433 errno = ERANGE; 434 } 435 } 436 break; 437 case 19: 438 /* log10(x<0) */ 439 exc.type = DOMAIN; 440 exc.name = "log10"; 441 ieee_retval = setexception(3, 1.0); 442 if (lib_version == c_issue_4) 443 exc.retval = -HUGE; 444 else 445 exc.retval = -HUGE_VAL; 446 if (lib_version == strict_ansi) { 447 errno = EDOM; 448 } else if (!matherr(&exc)) { 449 if (lib_version == c_issue_4) { 450 (void) write(2, "log10: DOMAIN error\n", 20); 451 } 452 errno = EDOM; 453 } 454 break; 455 case 20: 456 /* pow(0.0,0.0) */ 457 /* error only if lib_version == c_issue_4 */ 458 exc.type = DOMAIN; 459 exc.name = "pow"; 460 exc.retval = 0.0; 461 ieee_retval = 1.0; 462 if (lib_version != c_issue_4) { 463 exc.retval = 1.0; 464 } else if (!matherr(&exc)) { 465 (void) write(2, "pow(0,0): DOMAIN error\n", 23); 466 errno = EDOM; 467 } 468 break; 469 case 21: 470 /* pow(x,y) overflow */ 471 exc.type = OVERFLOW; 472 exc.name = "pow"; 473 exc.retval = (lib_version == c_issue_4)? HUGE : HUGE_VAL; 474 if (signbit(x)) { 475 t = rint(y); 476 if (t == y) { 477 w = rint(0.5 * y); 478 if (t != w + w) { /* y is odd */ 479 exc.retval = -exc.retval; 480 } 481 } 482 } 483 ieee_retval = setexception(2, exc.retval); 484 if (lib_version == strict_ansi) 485 errno = ERANGE; 486 else if (!matherr(&exc)) 487 errno = ERANGE; 488 break; 489 case 22: 490 /* pow(x,y) underflow */ 491 exc.type = UNDERFLOW; 492 exc.name = "pow"; 493 exc.retval = 0.0; 494 if (signbit(x)) { 495 t = rint(y); 496 if (t == y) { 497 w = rint(0.5 * y); 498 if (t != w + w) /* y is odd */ 499 exc.retval = -exc.retval; 500 } 501 } 502 ieee_retval = setexception(1, exc.retval); 503 if (lib_version == strict_ansi) 504 errno = ERANGE; 505 else if (!matherr(&exc)) 506 errno = ERANGE; 507 break; 508 case 23: 509 /* (+-0)**neg */ 510 exc.type = DOMAIN; 511 exc.name = "pow"; 512 ieee_retval = setexception(0, 1.0); 513 { 514 int ahy, k, j, yisint, ly, hx; 515 /* INDENT OFF */ 516 /* 517 * determine if y is an odd int when x = -0 518 * yisint = 0 ... y is not an integer 519 * yisint = 1 ... y is an odd int 520 * yisint = 2 ... y is an even int 521 */ 522 /* INDENT ON */ 523 hx = __HI(x); 524 ahy = __HI(y)&0x7fffffff; 525 ly = __LO(y); 526 527 yisint = 0; 528 if (ahy >= 0x43400000) { 529 yisint = 2; /* even integer y */ 530 } else if (ahy >= 0x3ff00000) { 531 k = (ahy >> 20) - 0x3ff; /* exponent */ 532 if (k > 20) { 533 j = ly >> (52 - k); 534 if ((j << (52 - k)) == ly) 535 yisint = 2 - (j & 1); 536 } else if (ly == 0) { 537 j = ahy >> (20 - k); 538 if ((j << (20 - k)) == ahy) 539 yisint = 2 - (j & 1); 540 } 541 } 542 if (hx < 0 && yisint == 1) 543 ieee_retval = -ieee_retval; 544 } 545 if (lib_version == c_issue_4) 546 exc.retval = 0.0; 547 else 548 exc.retval = -HUGE_VAL; 549 if (lib_version == strict_ansi) { 550 errno = EDOM; 551 } else if (!matherr(&exc)) { 552 if (lib_version == c_issue_4) { 553 (void) write(2, "pow(0,neg): DOMAIN error\n", 554 25); 555 } 556 errno = EDOM; 557 } 558 break; 559 case 24: 560 /* neg**non-integral */ 561 exc.type = DOMAIN; 562 exc.name = "pow"; 563 ieee_retval = setexception(3, 1.0); 564 if (lib_version == c_issue_4) 565 exc.retval = 0.0; 566 else 567 exc.retval = ieee_retval; /* X/Open allow NaN */ 568 if (lib_version == strict_ansi) { 569 errno = EDOM; 570 } else if (!matherr(&exc)) { 571 if (lib_version == c_issue_4) { 572 (void) write(2, 573 "neg**non-integral: DOMAIN error\n", 32); 574 } 575 errno = EDOM; 576 } 577 break; 578 case 25: 579 /* sinh(finite) overflow */ 580 exc.type = OVERFLOW; 581 exc.name = "sinh"; 582 ieee_retval = copysign(Inf, x); 583 if (lib_version == c_issue_4) 584 exc.retval = x > 0.0 ? HUGE : -HUGE; 585 else 586 exc.retval = x > 0.0 ? HUGE_VAL : -HUGE_VAL; 587 if (lib_version == strict_ansi) 588 errno = ERANGE; 589 else if (!matherr(&exc)) 590 errno = ERANGE; 591 break; 592 case 26: 593 /* sqrt(x<0) */ 594 exc.type = DOMAIN; 595 exc.name = "sqrt"; 596 ieee_retval = setexception(3, 1.0); 597 if (lib_version == c_issue_4) 598 exc.retval = 0.0; 599 else 600 exc.retval = ieee_retval; /* quiet NaN */ 601 if (lib_version == strict_ansi) { 602 errno = EDOM; 603 } else if (!matherr(&exc)) { 604 if (lib_version == c_issue_4) { 605 (void) write(2, "sqrt: DOMAIN error\n", 19); 606 } 607 errno = EDOM; 608 } 609 break; 610 case 27: 611 /* fmod(x,0) */ 612 exc.type = DOMAIN; 613 exc.name = "fmod"; 614 if (fp_class(x) == fp_quiet) 615 ieee_retval = NaN; 616 else 617 ieee_retval = setexception(3, 1.0); 618 if (lib_version == c_issue_4) 619 exc.retval = x; 620 else 621 exc.retval = ieee_retval; 622 if (lib_version == strict_ansi) { 623 errno = EDOM; 624 } else if (!matherr(&exc)) { 625 if (lib_version == c_issue_4) { 626 (void) write(2, "fmod: DOMAIN error\n", 20); 627 } 628 errno = EDOM; 629 } 630 break; 631 case 28: 632 /* remainder(x,0) */ 633 exc.type = DOMAIN; 634 exc.name = "remainder"; 635 if (fp_class(x) == fp_quiet) 636 ieee_retval = NaN; 637 else 638 ieee_retval = setexception(3, 1.0); 639 exc.retval = NaN; 640 if (lib_version == strict_ansi) { 641 errno = EDOM; 642 } else if (!matherr(&exc)) { 643 if (lib_version == c_issue_4) { 644 (void) write(2, "remainder: DOMAIN error\n", 645 24); 646 } 647 errno = EDOM; 648 } 649 break; 650 case 29: 651 /* acosh(x<1) */ 652 exc.type = DOMAIN; 653 exc.name = "acosh"; 654 ieee_retval = setexception(3, 1.0); 655 exc.retval = NaN; 656 if (lib_version == strict_ansi) { 657 errno = EDOM; 658 } else if (!matherr(&exc)) { 659 if (lib_version == c_issue_4) { 660 (void) write(2, "acosh: DOMAIN error\n", 20); 661 } 662 errno = EDOM; 663 } 664 break; 665 case 30: 666 /* atanh(|x|>1) */ 667 exc.type = DOMAIN; 668 exc.name = "atanh"; 669 ieee_retval = setexception(3, 1.0); 670 exc.retval = NaN; 671 if (lib_version == strict_ansi) { 672 errno = EDOM; 673 } else if (!matherr(&exc)) { 674 if (lib_version == c_issue_4) { 675 (void) write(2, "atanh: DOMAIN error\n", 20); 676 } 677 errno = EDOM; 678 } 679 break; 680 case 31: 681 /* atanh(|x|=1) */ 682 exc.type = SING; 683 exc.name = "atanh"; 684 ieee_retval = setexception(0, x); 685 exc.retval = ieee_retval; 686 if (lib_version == strict_ansi) { 687 errno = ERANGE; 688 } else if (!matherr(&exc)) { 689 if (lib_version == c_issue_4) { 690 (void) write(2, "atanh: SING error\n", 18); 691 errno = EDOM; 692 } else { 693 errno = ERANGE; 694 } 695 } 696 break; 697 case 32: 698 /* scalb overflow; SVID also returns +-HUGE_VAL */ 699 exc.type = OVERFLOW; 700 exc.name = "scalb"; 701 ieee_retval = setexception(2, x); 702 exc.retval = x > 0.0 ? HUGE_VAL : -HUGE_VAL; 703 if (lib_version == strict_ansi) 704 errno = ERANGE; 705 else if (!matherr(&exc)) 706 errno = ERANGE; 707 break; 708 case 33: 709 /* scalb underflow */ 710 exc.type = UNDERFLOW; 711 exc.name = "scalb"; 712 ieee_retval = setexception(1, x); 713 exc.retval = ieee_retval; /* +-0.0 */ 714 if (lib_version == strict_ansi) 715 errno = ERANGE; 716 else if (!matherr(&exc)) 717 errno = ERANGE; 718 break; 719 case 34: 720 /* j0(|x|>X_TLOSS) */ 721 exc.type = TLOSS; 722 exc.name = "j0"; 723 exc.retval = 0.0; 724 ieee_retval = y; 725 if (lib_version == strict_ansi) { 726 errno = ERANGE; 727 } else if (!matherr(&exc)) { 728 if (lib_version == c_issue_4) { 729 (void) write(2, exc.name, 2); 730 (void) write(2, ": TLOSS error\n", 14); 731 } 732 errno = ERANGE; 733 } 734 break; 735 case 35: 736 /* y0(x>X_TLOSS) */ 737 exc.type = TLOSS; 738 exc.name = "y0"; 739 exc.retval = 0.0; 740 ieee_retval = y; 741 if (lib_version == strict_ansi) { 742 errno = ERANGE; 743 } else if (!matherr(&exc)) { 744 if (lib_version == c_issue_4) { 745 (void) write(2, exc.name, 2); 746 (void) write(2, ": TLOSS error\n", 14); 747 } 748 errno = ERANGE; 749 } 750 break; 751 case 36: 752 /* j1(|x|>X_TLOSS) */ 753 exc.type = TLOSS; 754 exc.name = "j1"; 755 exc.retval = 0.0; 756 ieee_retval = y; 757 if (lib_version == strict_ansi) { 758 errno = ERANGE; 759 } else if (!matherr(&exc)) { 760 if (lib_version == c_issue_4) { 761 (void) write(2, exc.name, 2); 762 (void) write(2, ": TLOSS error\n", 14); 763 } 764 errno = ERANGE; 765 } 766 break; 767 case 37: 768 /* y1(x>X_TLOSS) */ 769 exc.type = TLOSS; 770 exc.name = "y1"; 771 exc.retval = 0.0; 772 ieee_retval = y; 773 if (lib_version == strict_ansi) { 774 errno = ERANGE; 775 } else if (!matherr(&exc)) { 776 if (lib_version == c_issue_4) { 777 (void) write(2, exc.name, 2); 778 (void) write(2, ": TLOSS error\n", 14); 779 } 780 errno = ERANGE; 781 } 782 break; 783 case 38: 784 /* jn(|x|>X_TLOSS) */ 785 /* incorrect ieee value: ieee should never be here */ 786 exc.type = TLOSS; 787 exc.name = "jn"; 788 exc.retval = 0.0; 789 ieee_retval = 0.0; /* shall not be used */ 790 if (lib_version == strict_ansi) { 791 errno = ERANGE; 792 } else if (!matherr(&exc)) { 793 if (lib_version == c_issue_4) { 794 (void) write(2, exc.name, 2); 795 (void) write(2, ": TLOSS error\n", 14); 796 } 797 errno = ERANGE; 798 } 799 break; 800 case 39: 801 /* yn(x>X_TLOSS) */ 802 /* incorrect ieee value: ieee should never be here */ 803 exc.type = TLOSS; 804 exc.name = "yn"; 805 exc.retval = 0.0; 806 ieee_retval = 0.0; /* shall not be used */ 807 if (lib_version == strict_ansi) { 808 errno = ERANGE; 809 } else if (!matherr(&exc)) { 810 if (lib_version == c_issue_4) { 811 (void) write(2, exc.name, 2); 812 (void) write(2, ": TLOSS error\n", 14); 813 } 814 errno = ERANGE; 815 } 816 break; 817 case 40: 818 /* gamma(finite) overflow */ 819 exc.type = OVERFLOW; 820 exc.name = "gamma"; 821 ieee_retval = setexception(2, 1.0); 822 if (lib_version == c_issue_4) 823 exc.retval = HUGE; 824 else 825 exc.retval = HUGE_VAL; 826 if (lib_version == strict_ansi) 827 errno = ERANGE; 828 else if (!matherr(&exc)) 829 errno = ERANGE; 830 break; 831 case 41: 832 /* gamma(-integer) or gamma(0) */ 833 exc.type = SING; 834 exc.name = "gamma"; 835 ieee_retval = setexception(0, 1.0); 836 if (lib_version == c_issue_4) 837 exc.retval = HUGE; 838 else 839 exc.retval = HUGE_VAL; 840 if (lib_version == strict_ansi) { 841 errno = EDOM; 842 } else if (!matherr(&exc)) { 843 if (lib_version == c_issue_4) { 844 (void) write(2, "gamma: SING error\n", 18); 845 } 846 errno = EDOM; 847 } 848 break; 849 case 42: 850 /* pow(NaN,0.0) */ 851 /* error if lib_version == c_issue_4 or ansi_1 */ 852 exc.type = DOMAIN; 853 exc.name = "pow"; 854 exc.retval = x; 855 ieee_retval = 1.0; 856 if (lib_version == strict_ansi) { 857 exc.retval = 1.0; 858 } else if (!matherr(&exc)) { 859 if ((lib_version == c_issue_4) || (lib_version == ansi_1)) 860 errno = EDOM; 861 } 862 break; 863 case 43: 864 /* log1p(-1) */ 865 exc.type = SING; 866 exc.name = "log1p"; 867 ieee_retval = setexception(0, -1.0); 868 if (lib_version == c_issue_4) 869 exc.retval = -HUGE; 870 else 871 exc.retval = -HUGE_VAL; 872 if (lib_version == strict_ansi) { 873 errno = ERANGE; 874 } else if (!matherr(&exc)) { 875 if (lib_version == c_issue_4) { 876 (void) write(2, "log1p: SING error\n", 18); 877 errno = EDOM; 878 } else { 879 errno = ERANGE; 880 } 881 } 882 break; 883 case 44: 884 /* log1p(x<-1) */ 885 exc.type = DOMAIN; 886 exc.name = "log1p"; 887 ieee_retval = setexception(3, 1.0); 888 exc.retval = ieee_retval; 889 if (lib_version == strict_ansi) { 890 errno = EDOM; 891 } else if (!matherr(&exc)) { 892 if (lib_version == c_issue_4) { 893 (void) write(2, "log1p: DOMAIN error\n", 20); 894 } 895 errno = EDOM; 896 } 897 break; 898 case 45: 899 /* logb(0) */ 900 exc.type = DOMAIN; 901 exc.name = "logb"; 902 ieee_retval = setexception(0, -1.0); 903 exc.retval = -HUGE_VAL; 904 if (lib_version == strict_ansi) 905 errno = EDOM; 906 else if (!matherr(&exc)) 907 errno = EDOM; 908 break; 909 case 46: 910 /* nextafter overflow */ 911 exc.type = OVERFLOW; 912 exc.name = "nextafter"; 913 /* 914 * The value as returned by setexception is +/-DBL_MAX in 915 * round-to-{zero,-/+Inf} mode respectively, which is not 916 * usable. 917 */ 918 (void) setexception(2, x); 919 ieee_retval = x > 0 ? Inf : -Inf; 920 exc.retval = x > 0 ? HUGE_VAL : -HUGE_VAL; 921 if (lib_version == strict_ansi) 922 errno = ERANGE; 923 else if (!matherr(&exc)) 924 errno = ERANGE; 925 break; 926 case 47: 927 /* scalb(x,inf) */ 928 iy = ((int *)&y)[HIWORD]; 929 if (lib_version == c_issue_4) 930 /* SVID3: ERANGE in all cases */ 931 errno = ERANGE; 932 else if ((x == 0.0 && iy > 0) || (!finite(x) && iy < 0)) 933 /* EDOM for scalb(0,+inf) or scalb(inf,-inf) */ 934 errno = EDOM; 935 exc.retval = ieee_retval = ((iy < 0)? x / -y : x * y); 936 break; 937 } 938 switch (lib_version) { 939 case c_issue_4: 940 case ansi_1: 941 case strict_ansi: 942 return (exc.retval); 943 /* NOTREACHED */ 944 default: 945 return (ieee_retval); 946 } 947 /* NOTREACHED */ 948 } 949 950 static double 951 setexception(int n, double x) { 952 /* 953 * n = 954 * 0 division by zero 955 * 1 underflow 956 * 2 overflow 957 * 3 invalid 958 */ 959 volatile double one = 1.0, zero = 0.0, retv; 960 961 switch (n) { 962 case 0: /* division by zero */ 963 retv = copysign(one / zero, x); 964 break; 965 case 1: /* underflow */ 966 retv = DBL_MIN * copysign(DBL_MIN, x); 967 break; 968 case 2: /* overflow */ 969 retv = DBL_MAX * copysign(DBL_MAX, x); 970 break; 971 case 3: /* invalid */ 972 retv = zero * Inf; /* for Cheetah */ 973 break; 974 } 975 return (retv); 976 } 977