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.
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.
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]
22 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
30 #include "xpg6.h" /* __xpg6 */
32 #include <float.h> /* DBL_MAX, DBL_MIN */
33 #include <unistd.h> /* write */
37 #define fp_class fpclass
38 #define fp_quiet FP_QNAN
42 #include <sys/isa_defs.h>
46 * Report libm exception error according to System V Interface Definition
62 * 14-- lgamma(finite) overflow
63 * 15-- lgamma(-integer)
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
81 * 33-- scalb underflow
82 * 34-- j0(|x|>X_TLOSS)
84 * 36-- j1(|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
94 * 46-- nextafter overflow
99 static double setexception(int, double);
105 #ifdef _LITTLE_ENDIAN
106 { 0xffffffff, 0x7fffffff },
107 { 0x54442d18, 0x400921fb },
109 { 0x7fffffff, 0xffffffff },
110 { 0x400921fb, 0x54442d18 },
117 #define __HI(x) ((unsigned *)&x)[HIWORD]
118 #define __LO(x) ((unsigned *)&x)[LOWORD]
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
;
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
);
142 ieee_retval
= setexception(3, 1.0);
144 if (lib_version
== strict_ansi
) {
146 } else if (!matherr(&exc
)) {
147 if (lib_version
== c_issue_4
) {
148 (void) write(2, "acos: DOMAIN error\n", 19);
158 ieee_retval
= setexception(3, 1.0);
159 if (lib_version
== strict_ansi
) {
161 } else if (!matherr(&exc
)) {
162 if (lib_version
== c_issue_4
) {
163 (void) write(2, "asin: DOMAIN error\n", 19);
174 ieee_retval
= copysign(1.0, x
) == 1.0 ? y
:
175 copysign(PI_RZ
+ DBL_MIN
, y
);
177 if (lib_version
== strict_ansi
) {
179 } else if (!matherr(&exc
)) {
180 if (lib_version
== c_issue_4
) {
181 (void) write(2, "atan2: DOMAIN error\n", 20);
187 /* hypot(finite,finite) overflow */
191 if (lib_version
== c_issue_4
)
194 exc
.retval
= HUGE_VAL
;
195 if (lib_version
== strict_ansi
)
197 else if (!matherr(&exc
))
201 /* cosh(finite) overflow */
204 ieee_retval
= setexception(2, 1.0);
205 if (lib_version
== c_issue_4
)
208 exc
.retval
= HUGE_VAL
;
209 if (lib_version
== strict_ansi
)
211 else if (!matherr(&exc
))
215 /* exp(finite) overflow */
218 ieee_retval
= setexception(2, 1.0);
219 if (lib_version
== c_issue_4
)
222 exc
.retval
= HUGE_VAL
;
223 if (lib_version
== strict_ansi
)
225 else if (!matherr(&exc
))
229 /* exp(finite) underflow */
230 exc
.type
= UNDERFLOW
;
232 ieee_retval
= setexception(1, 1.0);
234 if (lib_version
== strict_ansi
)
236 else if (!matherr(&exc
))
241 exc
.type
= DOMAIN
; /* should be SING for IEEE */
243 ieee_retval
= setexception(0, -1.0);
244 if (lib_version
== c_issue_4
)
247 exc
.retval
= -HUGE_VAL
;
248 if (lib_version
== strict_ansi
) {
250 } else if (!matherr(&exc
)) {
251 if (lib_version
== c_issue_4
) {
252 (void) write(2, "y0: DOMAIN error\n", 17);
261 ieee_retval
= setexception(3, 1.0);
262 if (lib_version
== c_issue_4
)
265 exc
.retval
= -HUGE_VAL
;
266 if (lib_version
== strict_ansi
) {
268 } else if (!matherr(&exc
)) {
269 if (lib_version
== c_issue_4
) {
270 (void) write(2, "y0: DOMAIN error\n", 17);
277 exc
.type
= DOMAIN
; /* should be SING for IEEE */
279 ieee_retval
= setexception(0, -1.0);
280 if (lib_version
== c_issue_4
)
283 exc
.retval
= -HUGE_VAL
;
284 if (lib_version
== strict_ansi
) {
286 } else if (!matherr(&exc
)) {
287 if (lib_version
== c_issue_4
) {
288 (void) write(2, "y1: DOMAIN error\n", 17);
297 ieee_retval
= setexception(3, 1.0);
298 if (lib_version
== c_issue_4
)
301 exc
.retval
= -HUGE_VAL
;
302 if (lib_version
== strict_ansi
) {
304 } else if (!matherr(&exc
)) {
305 if (lib_version
== c_issue_4
) {
306 (void) write(2, "y1: DOMAIN error\n", 17);
313 exc
.type
= DOMAIN
; /* should be SING for IEEE */
315 ieee_retval
= setexception(0, -1.0);
316 if (lib_version
== c_issue_4
)
319 exc
.retval
= -HUGE_VAL
;
320 if (lib_version
== strict_ansi
) {
322 } else if (!matherr(&exc
)) {
323 if (lib_version
== c_issue_4
) {
324 (void) write(2, "yn: DOMAIN error\n", 17);
333 ieee_retval
= setexception(3, 1.0);
334 if (lib_version
== c_issue_4
)
337 exc
.retval
= -HUGE_VAL
;
338 if (lib_version
== strict_ansi
) {
340 } else if (!matherr(&exc
)) {
341 if (lib_version
== c_issue_4
) {
342 (void) write(2, "yn: DOMAIN error\n", 17);
348 /* lgamma(finite) overflow */
351 ieee_retval
= setexception(2, 1.0);
352 if (lib_version
== c_issue_4
)
355 exc
.retval
= HUGE_VAL
;
356 if (lib_version
== strict_ansi
)
358 else if (!matherr(&exc
))
362 /* lgamma(-integer) or lgamma(0) */
365 ieee_retval
= setexception(0, 1.0);
366 if (lib_version
== c_issue_4
)
369 exc
.retval
= HUGE_VAL
;
370 if (lib_version
== strict_ansi
) {
372 } else if (!matherr(&exc
)) {
373 if (lib_version
== c_issue_4
) {
374 (void) write(2, "lgamma: SING error\n", 19);
383 ieee_retval
= setexception(0, -1.0);
384 if (lib_version
== c_issue_4
)
387 exc
.retval
= -HUGE_VAL
;
388 if (lib_version
== strict_ansi
) {
390 } else if (!matherr(&exc
)) {
391 if (lib_version
== c_issue_4
) {
392 (void) write(2, "log: SING error\n", 16);
403 ieee_retval
= setexception(3, 1.0);
404 if (lib_version
== c_issue_4
)
407 exc
.retval
= -HUGE_VAL
;
408 if (lib_version
== strict_ansi
) {
410 } else if (!matherr(&exc
)) {
411 if (lib_version
== c_issue_4
) {
412 (void) write(2, "log: DOMAIN error\n", 18);
421 ieee_retval
= setexception(0, -1.0);
422 if (lib_version
== c_issue_4
)
425 exc
.retval
= -HUGE_VAL
;
426 if (lib_version
== strict_ansi
) {
428 } else if (!matherr(&exc
)) {
429 if (lib_version
== c_issue_4
) {
430 (void) write(2, "log10: SING error\n", 18);
441 ieee_retval
= setexception(3, 1.0);
442 if (lib_version
== c_issue_4
)
445 exc
.retval
= -HUGE_VAL
;
446 if (lib_version
== strict_ansi
) {
448 } else if (!matherr(&exc
)) {
449 if (lib_version
== c_issue_4
) {
450 (void) write(2, "log10: DOMAIN error\n", 20);
457 /* error only if lib_version == c_issue_4 */
462 if (lib_version
!= c_issue_4
) {
464 } else if (!matherr(&exc
)) {
465 (void) write(2, "pow(0,0): DOMAIN error\n", 23);
470 /* pow(x,y) overflow */
473 exc
.retval
= (lib_version
== c_issue_4
)? HUGE
: HUGE_VAL
;
478 if (t
!= w
+ w
) { /* y is odd */
479 exc
.retval
= -exc
.retval
;
483 ieee_retval
= setexception(2, exc
.retval
);
484 if (lib_version
== strict_ansi
)
486 else if (!matherr(&exc
))
490 /* pow(x,y) underflow */
491 exc
.type
= UNDERFLOW
;
498 if (t
!= w
+ w
) /* y is odd */
499 exc
.retval
= -exc
.retval
;
502 ieee_retval
= setexception(1, exc
.retval
);
503 if (lib_version
== strict_ansi
)
505 else if (!matherr(&exc
))
512 ieee_retval
= setexception(0, 1.0);
514 int ahy
, k
, j
, yisint
, ly
, hx
;
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
524 ahy
= __HI(y
)&0x7fffffff;
528 if (ahy
>= 0x43400000) {
529 yisint
= 2; /* even integer y */
530 } else if (ahy
>= 0x3ff00000) {
531 k
= (ahy
>> 20) - 0x3ff; /* exponent */
534 if ((j
<< (52 - k
)) == ly
)
535 yisint
= 2 - (j
& 1);
536 } else if (ly
== 0) {
538 if ((j
<< (20 - k
)) == ahy
)
539 yisint
= 2 - (j
& 1);
542 if (hx
< 0 && yisint
== 1)
543 ieee_retval
= -ieee_retval
;
545 if (lib_version
== c_issue_4
)
548 exc
.retval
= -HUGE_VAL
;
549 if (lib_version
== strict_ansi
) {
551 } else if (!matherr(&exc
)) {
552 if (lib_version
== c_issue_4
) {
553 (void) write(2, "pow(0,neg): DOMAIN error\n",
560 /* neg**non-integral */
563 ieee_retval
= setexception(3, 1.0);
564 if (lib_version
== c_issue_4
)
567 exc
.retval
= ieee_retval
; /* X/Open allow NaN */
568 if (lib_version
== strict_ansi
) {
570 } else if (!matherr(&exc
)) {
571 if (lib_version
== c_issue_4
) {
573 "neg**non-integral: DOMAIN error\n", 32);
579 /* sinh(finite) overflow */
582 ieee_retval
= copysign(Inf
, x
);
583 if (lib_version
== c_issue_4
)
584 exc
.retval
= x
> 0.0 ? HUGE
: -HUGE
;
586 exc
.retval
= x
> 0.0 ? HUGE_VAL
: -HUGE_VAL
;
587 if (lib_version
== strict_ansi
)
589 else if (!matherr(&exc
))
596 ieee_retval
= setexception(3, 1.0);
597 if (lib_version
== c_issue_4
)
600 exc
.retval
= ieee_retval
; /* quiet NaN */
601 if (lib_version
== strict_ansi
) {
603 } else if (!matherr(&exc
)) {
604 if (lib_version
== c_issue_4
) {
605 (void) write(2, "sqrt: DOMAIN error\n", 19);
614 if (fp_class(x
) == fp_quiet
)
617 ieee_retval
= setexception(3, 1.0);
618 if (lib_version
== c_issue_4
)
621 exc
.retval
= ieee_retval
;
622 if (lib_version
== strict_ansi
) {
624 } else if (!matherr(&exc
)) {
625 if (lib_version
== c_issue_4
) {
626 (void) write(2, "fmod: DOMAIN error\n", 20);
634 exc
.name
= "remainder";
635 if (fp_class(x
) == fp_quiet
)
638 ieee_retval
= setexception(3, 1.0);
640 if (lib_version
== strict_ansi
) {
642 } else if (!matherr(&exc
)) {
643 if (lib_version
== c_issue_4
) {
644 (void) write(2, "remainder: DOMAIN error\n",
654 ieee_retval
= setexception(3, 1.0);
656 if (lib_version
== strict_ansi
) {
658 } else if (!matherr(&exc
)) {
659 if (lib_version
== c_issue_4
) {
660 (void) write(2, "acosh: DOMAIN error\n", 20);
669 ieee_retval
= setexception(3, 1.0);
671 if (lib_version
== strict_ansi
) {
673 } else if (!matherr(&exc
)) {
674 if (lib_version
== c_issue_4
) {
675 (void) write(2, "atanh: DOMAIN error\n", 20);
684 ieee_retval
= setexception(0, x
);
685 exc
.retval
= ieee_retval
;
686 if (lib_version
== strict_ansi
) {
688 } else if (!matherr(&exc
)) {
689 if (lib_version
== c_issue_4
) {
690 (void) write(2, "atanh: SING error\n", 18);
698 /* scalb overflow; SVID also returns +-HUGE_VAL */
701 ieee_retval
= setexception(2, x
);
702 exc
.retval
= x
> 0.0 ? HUGE_VAL
: -HUGE_VAL
;
703 if (lib_version
== strict_ansi
)
705 else if (!matherr(&exc
))
709 /* scalb underflow */
710 exc
.type
= UNDERFLOW
;
712 ieee_retval
= setexception(1, x
);
713 exc
.retval
= ieee_retval
; /* +-0.0 */
714 if (lib_version
== strict_ansi
)
716 else if (!matherr(&exc
))
720 /* j0(|x|>X_TLOSS) */
725 if (lib_version
== strict_ansi
) {
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);
741 if (lib_version
== strict_ansi
) {
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);
752 /* j1(|x|>X_TLOSS) */
757 if (lib_version
== strict_ansi
) {
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);
773 if (lib_version
== strict_ansi
) {
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);
784 /* jn(|x|>X_TLOSS) */
785 /* incorrect ieee value: ieee should never be here */
789 ieee_retval
= 0.0; /* shall not be used */
790 if (lib_version
== strict_ansi
) {
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);
802 /* incorrect ieee value: ieee should never be here */
806 ieee_retval
= 0.0; /* shall not be used */
807 if (lib_version
== strict_ansi
) {
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);
818 /* gamma(finite) overflow */
821 ieee_retval
= setexception(2, 1.0);
822 if (lib_version
== c_issue_4
)
825 exc
.retval
= HUGE_VAL
;
826 if (lib_version
== strict_ansi
)
828 else if (!matherr(&exc
))
832 /* gamma(-integer) or gamma(0) */
835 ieee_retval
= setexception(0, 1.0);
836 if (lib_version
== c_issue_4
)
839 exc
.retval
= HUGE_VAL
;
840 if (lib_version
== strict_ansi
) {
842 } else if (!matherr(&exc
)) {
843 if (lib_version
== c_issue_4
) {
844 (void) write(2, "gamma: SING error\n", 18);
851 /* error if lib_version == c_issue_4 or ansi_1 */
856 if (lib_version
== strict_ansi
) {
858 } else if (!matherr(&exc
)) {
859 if ((lib_version
== c_issue_4
) || (lib_version
== ansi_1
))
867 ieee_retval
= setexception(0, -1.0);
868 if (lib_version
== c_issue_4
)
871 exc
.retval
= -HUGE_VAL
;
872 if (lib_version
== strict_ansi
) {
874 } else if (!matherr(&exc
)) {
875 if (lib_version
== c_issue_4
) {
876 (void) write(2, "log1p: SING error\n", 18);
887 ieee_retval
= setexception(3, 1.0);
888 exc
.retval
= ieee_retval
;
889 if (lib_version
== strict_ansi
) {
891 } else if (!matherr(&exc
)) {
892 if (lib_version
== c_issue_4
) {
893 (void) write(2, "log1p: DOMAIN error\n", 20);
902 ieee_retval
= setexception(0, -1.0);
903 exc
.retval
= -HUGE_VAL
;
904 if (lib_version
== strict_ansi
)
906 else if (!matherr(&exc
))
910 /* nextafter overflow */
912 exc
.name
= "nextafter";
914 * The value as returned by setexception is +/-DBL_MAX in
915 * round-to-{zero,-/+Inf} mode respectively, which is not
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
)
923 else if (!matherr(&exc
))
928 iy
= ((int *)&y
)[HIWORD
];
929 if (lib_version
== c_issue_4
)
930 /* SVID3: ERANGE in all cases */
932 else if ((x
== 0.0 && iy
> 0) || (!finite(x
) && iy
< 0))
933 /* EDOM for scalb(0,+inf) or scalb(inf,-inf) */
935 exc
.retval
= ieee_retval
= ((iy
< 0)? x
/ -y
: x
* y
);
938 switch (lib_version
) {
945 return (ieee_retval
);
951 setexception(int n
, double x
) {
959 volatile double one
= 1.0, zero
= 0.0, retv
;
962 case 0: /* division by zero */
963 retv
= copysign(one
/ zero
, x
);
965 case 1: /* underflow */
966 retv
= DBL_MIN
* copysign(DBL_MIN
, x
);
968 case 2: /* overflow */
969 retv
= DBL_MAX
* copysign(DBL_MAX
, x
);
971 case 3: /* invalid */
972 retv
= zero
* Inf
; /* for Cheetah */