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