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