/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include "libm.h" #include "xpg6.h" /* __xpg6 */ #include #include /* DBL_MAX, DBL_MIN */ #include /* write */ #if defined(__x86) #include #undef fp_class #define fp_class fpclass #define fp_quiet FP_QNAN #endif #include #undef fflush #include /* INDENT OFF */ /* * Report libm exception error according to System V Interface Definition * (SVID). * Error mapping: * 1 -- acos(|x|>1) * 2 -- asin(|x|>1) * 3 -- atan2(+-0,+-0) * 4 -- hypot overflow * 5 -- cosh overflow * 6 -- exp overflow * 7 -- exp underflow * 8 -- y0(0) * 9 -- y0(-ve) * 10-- y1(0) * 11-- y1(-ve) * 12-- yn(0) * 13-- yn(-ve) * 14-- lgamma(finite) overflow * 15-- lgamma(-integer) * 16-- log(0) * 17-- log(x<0) * 18-- log10(0) * 19-- log10(x<0) * 20-- pow(0.0,0.0) * 21-- pow(x,y) overflow * 22-- pow(x,y) underflow * 23-- pow(0,negative) * 24-- pow(neg,non-integral) * 25-- sinh(finite) overflow * 26-- sqrt(negative) * 27-- fmod(x,0) * 28-- remainder(x,0) * 29-- acosh(x<1) * 30-- atanh(|x|>1) * 31-- atanh(|x|=1) * 32-- scalb overflow * 33-- scalb underflow * 34-- j0(|x|>X_TLOSS) * 35-- y0(x>X_TLOSS) * 36-- j1(|x|>X_TLOSS) * 37-- y1(x>X_TLOSS) * 38-- jn(|x|>X_TLOSS, n) * 39-- yn(x>X_TLOSS, n) * 40-- gamma(finite) overflow * 41-- gamma(-integer) * 42-- pow(NaN,0.0) return NaN for SVID/XOPEN * 43-- log1p(-1) * 44-- log1p(x<-1) * 45-- logb(0) * 46-- nextafter overflow * 47-- scalb(x,inf) */ /* INDENT ON */ static double setexception(int, double); static const union { unsigned x[2]; double d; } C[] = { #ifdef _LITTLE_ENDIAN { 0xffffffff, 0x7fffffff }, { 0x54442d18, 0x400921fb }, #else { 0x7fffffff, 0xffffffff }, { 0x400921fb, 0x54442d18 }, #endif }; #define NaN C[0].d #define PI_RZ C[1].d #define __HI(x) ((unsigned *)&x)[HIWORD] #define __LO(x) ((unsigned *)&x)[LOWORD] #undef Inf #define Inf HUGE_VAL double _SVID_libm_err(double x, double y, int type) { struct exception exc; double t, w, ieee_retval = 0; enum version lib_version = _lib_version; int iy; /* force libm_ieee behavior in SUSv3 mode */ if ((__xpg6 & _C99SUSv3_math_errexcept) != 0) lib_version = libm_ieee; if (lib_version == c_issue_4) { (void) fflush(stdout); } exc.arg1 = x; exc.arg2 = y; switch (type) { case 1: /* acos(|x|>1) */ exc.type = DOMAIN; exc.name = "acos"; ieee_retval = setexception(3, 1.0); exc.retval = 0.0; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "acos: DOMAIN error\n", 19); } errno = EDOM; } break; case 2: /* asin(|x|>1) */ exc.type = DOMAIN; exc.name = "asin"; exc.retval = 0.0; ieee_retval = setexception(3, 1.0); if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "asin: DOMAIN error\n", 19); } errno = EDOM; } break; case 3: /* atan2(+-0,+-0) */ exc.arg1 = y; exc.arg2 = x; exc.type = DOMAIN; exc.name = "atan2"; ieee_retval = copysign(1.0, x) == 1.0 ? y : copysign(PI_RZ + DBL_MIN, y); exc.retval = 0.0; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "atan2: DOMAIN error\n", 20); } errno = EDOM; } break; case 4: /* hypot(finite,finite) overflow */ exc.type = OVERFLOW; exc.name = "hypot"; ieee_retval = Inf; if (lib_version == c_issue_4) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 5: /* cosh(finite) overflow */ exc.type = OVERFLOW; exc.name = "cosh"; ieee_retval = setexception(2, 1.0); if (lib_version == c_issue_4) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 6: /* exp(finite) overflow */ exc.type = OVERFLOW; exc.name = "exp"; ieee_retval = setexception(2, 1.0); if (lib_version == c_issue_4) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 7: /* exp(finite) underflow */ exc.type = UNDERFLOW; exc.name = "exp"; ieee_retval = setexception(1, 1.0); exc.retval = 0.0; if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 8: /* y0(0) = -inf */ exc.type = DOMAIN; /* should be SING for IEEE */ exc.name = "y0"; ieee_retval = setexception(0, -1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "y0: DOMAIN error\n", 17); } errno = EDOM; } break; case 9: /* y0(x<0) = NaN */ exc.type = DOMAIN; exc.name = "y0"; ieee_retval = setexception(3, 1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "y0: DOMAIN error\n", 17); } errno = EDOM; } break; case 10: /* y1(0) = -inf */ exc.type = DOMAIN; /* should be SING for IEEE */ exc.name = "y1"; ieee_retval = setexception(0, -1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "y1: DOMAIN error\n", 17); } errno = EDOM; } break; case 11: /* y1(x<0) = NaN */ exc.type = DOMAIN; exc.name = "y1"; ieee_retval = setexception(3, 1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "y1: DOMAIN error\n", 17); } errno = EDOM; } break; case 12: /* yn(n,0) = -inf */ exc.type = DOMAIN; /* should be SING for IEEE */ exc.name = "yn"; ieee_retval = setexception(0, -1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "yn: DOMAIN error\n", 17); } errno = EDOM; } break; case 13: /* yn(x<0) = NaN */ exc.type = DOMAIN; exc.name = "yn"; ieee_retval = setexception(3, 1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "yn: DOMAIN error\n", 17); } errno = EDOM; } break; case 14: /* lgamma(finite) overflow */ exc.type = OVERFLOW; exc.name = "lgamma"; ieee_retval = setexception(2, 1.0); if (lib_version == c_issue_4) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 15: /* lgamma(-integer) or lgamma(0) */ exc.type = SING; exc.name = "lgamma"; ieee_retval = setexception(0, 1.0); if (lib_version == c_issue_4) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "lgamma: SING error\n", 19); } errno = EDOM; } break; case 16: /* log(0) */ exc.type = SING; exc.name = "log"; ieee_retval = setexception(0, -1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "log: SING error\n", 16); errno = EDOM; } else { errno = ERANGE; } } break; case 17: /* log(x<0) */ exc.type = DOMAIN; exc.name = "log"; ieee_retval = setexception(3, 1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "log: DOMAIN error\n", 18); } errno = EDOM; } break; case 18: /* log10(0) */ exc.type = SING; exc.name = "log10"; ieee_retval = setexception(0, -1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "log10: SING error\n", 18); errno = EDOM; } else { errno = ERANGE; } } break; case 19: /* log10(x<0) */ exc.type = DOMAIN; exc.name = "log10"; ieee_retval = setexception(3, 1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "log10: DOMAIN error\n", 20); } errno = EDOM; } break; case 20: /* pow(0.0,0.0) */ /* error only if lib_version == c_issue_4 */ exc.type = DOMAIN; exc.name = "pow"; exc.retval = 0.0; ieee_retval = 1.0; if (lib_version != c_issue_4) { exc.retval = 1.0; } else if (!matherr(&exc)) { (void) write(2, "pow(0,0): DOMAIN error\n", 23); errno = EDOM; } break; case 21: /* pow(x,y) overflow */ exc.type = OVERFLOW; exc.name = "pow"; exc.retval = (lib_version == c_issue_4)? HUGE : HUGE_VAL; if (signbit(x)) { t = rint(y); if (t == y) { w = rint(0.5 * y); if (t != w + w) { /* y is odd */ exc.retval = -exc.retval; } } } ieee_retval = setexception(2, exc.retval); if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 22: /* pow(x,y) underflow */ exc.type = UNDERFLOW; exc.name = "pow"; exc.retval = 0.0; if (signbit(x)) { t = rint(y); if (t == y) { w = rint(0.5 * y); if (t != w + w) /* y is odd */ exc.retval = -exc.retval; } } ieee_retval = setexception(1, exc.retval); if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 23: /* (+-0)**neg */ exc.type = DOMAIN; exc.name = "pow"; ieee_retval = setexception(0, 1.0); { int ahy, k, j, yisint, ly, hx; /* INDENT OFF */ /* * determine if y is an odd int when x = -0 * yisint = 0 ... y is not an integer * yisint = 1 ... y is an odd int * yisint = 2 ... y is an even int */ /* INDENT ON */ hx = __HI(x); ahy = __HI(y)&0x7fffffff; ly = __LO(y); yisint = 0; if (ahy >= 0x43400000) { yisint = 2; /* even integer y */ } else if (ahy >= 0x3ff00000) { k = (ahy >> 20) - 0x3ff; /* exponent */ if (k > 20) { j = ly >> (52 - k); if ((j << (52 - k)) == ly) yisint = 2 - (j & 1); } else if (ly == 0) { j = ahy >> (20 - k); if ((j << (20 - k)) == ahy) yisint = 2 - (j & 1); } } if (hx < 0 && yisint == 1) ieee_retval = -ieee_retval; } if (lib_version == c_issue_4) exc.retval = 0.0; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "pow(0,neg): DOMAIN error\n", 25); } errno = EDOM; } break; case 24: /* neg**non-integral */ exc.type = DOMAIN; exc.name = "pow"; ieee_retval = setexception(3, 1.0); if (lib_version == c_issue_4) exc.retval = 0.0; else exc.retval = ieee_retval; /* X/Open allow NaN */ if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "neg**non-integral: DOMAIN error\n", 32); } errno = EDOM; } break; case 25: /* sinh(finite) overflow */ exc.type = OVERFLOW; exc.name = "sinh"; ieee_retval = copysign(Inf, x); if (lib_version == c_issue_4) exc.retval = x > 0.0 ? HUGE : -HUGE; else exc.retval = x > 0.0 ? HUGE_VAL : -HUGE_VAL; if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 26: /* sqrt(x<0) */ exc.type = DOMAIN; exc.name = "sqrt"; ieee_retval = setexception(3, 1.0); if (lib_version == c_issue_4) exc.retval = 0.0; else exc.retval = ieee_retval; /* quiet NaN */ if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "sqrt: DOMAIN error\n", 19); } errno = EDOM; } break; case 27: /* fmod(x,0) */ exc.type = DOMAIN; exc.name = "fmod"; if (fp_class(x) == fp_quiet) ieee_retval = NaN; else ieee_retval = setexception(3, 1.0); if (lib_version == c_issue_4) exc.retval = x; else exc.retval = ieee_retval; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "fmod: DOMAIN error\n", 20); } errno = EDOM; } break; case 28: /* remainder(x,0) */ exc.type = DOMAIN; exc.name = "remainder"; if (fp_class(x) == fp_quiet) ieee_retval = NaN; else ieee_retval = setexception(3, 1.0); exc.retval = NaN; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "remainder: DOMAIN error\n", 24); } errno = EDOM; } break; case 29: /* acosh(x<1) */ exc.type = DOMAIN; exc.name = "acosh"; ieee_retval = setexception(3, 1.0); exc.retval = NaN; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "acosh: DOMAIN error\n", 20); } errno = EDOM; } break; case 30: /* atanh(|x|>1) */ exc.type = DOMAIN; exc.name = "atanh"; ieee_retval = setexception(3, 1.0); exc.retval = NaN; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "atanh: DOMAIN error\n", 20); } errno = EDOM; } break; case 31: /* atanh(|x|=1) */ exc.type = SING; exc.name = "atanh"; ieee_retval = setexception(0, x); exc.retval = ieee_retval; if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "atanh: SING error\n", 18); errno = EDOM; } else { errno = ERANGE; } } break; case 32: /* scalb overflow; SVID also returns +-HUGE_VAL */ exc.type = OVERFLOW; exc.name = "scalb"; ieee_retval = setexception(2, x); exc.retval = x > 0.0 ? HUGE_VAL : -HUGE_VAL; if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 33: /* scalb underflow */ exc.type = UNDERFLOW; exc.name = "scalb"; ieee_retval = setexception(1, x); exc.retval = ieee_retval; /* +-0.0 */ if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 34: /* j0(|x|>X_TLOSS) */ exc.type = TLOSS; exc.name = "j0"; exc.retval = 0.0; ieee_retval = y; if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, exc.name, 2); (void) write(2, ": TLOSS error\n", 14); } errno = ERANGE; } break; case 35: /* y0(x>X_TLOSS) */ exc.type = TLOSS; exc.name = "y0"; exc.retval = 0.0; ieee_retval = y; if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, exc.name, 2); (void) write(2, ": TLOSS error\n", 14); } errno = ERANGE; } break; case 36: /* j1(|x|>X_TLOSS) */ exc.type = TLOSS; exc.name = "j1"; exc.retval = 0.0; ieee_retval = y; if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, exc.name, 2); (void) write(2, ": TLOSS error\n", 14); } errno = ERANGE; } break; case 37: /* y1(x>X_TLOSS) */ exc.type = TLOSS; exc.name = "y1"; exc.retval = 0.0; ieee_retval = y; if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, exc.name, 2); (void) write(2, ": TLOSS error\n", 14); } errno = ERANGE; } break; case 38: /* jn(|x|>X_TLOSS) */ /* incorrect ieee value: ieee should never be here */ exc.type = TLOSS; exc.name = "jn"; exc.retval = 0.0; ieee_retval = 0.0; /* shall not be used */ if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, exc.name, 2); (void) write(2, ": TLOSS error\n", 14); } errno = ERANGE; } break; case 39: /* yn(x>X_TLOSS) */ /* incorrect ieee value: ieee should never be here */ exc.type = TLOSS; exc.name = "yn"; exc.retval = 0.0; ieee_retval = 0.0; /* shall not be used */ if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, exc.name, 2); (void) write(2, ": TLOSS error\n", 14); } errno = ERANGE; } break; case 40: /* gamma(finite) overflow */ exc.type = OVERFLOW; exc.name = "gamma"; ieee_retval = setexception(2, 1.0); if (lib_version == c_issue_4) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 41: /* gamma(-integer) or gamma(0) */ exc.type = SING; exc.name = "gamma"; ieee_retval = setexception(0, 1.0); if (lib_version == c_issue_4) exc.retval = HUGE; else exc.retval = HUGE_VAL; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "gamma: SING error\n", 18); } errno = EDOM; } break; case 42: /* pow(NaN,0.0) */ /* error if lib_version == c_issue_4 or ansi_1 */ exc.type = DOMAIN; exc.name = "pow"; exc.retval = x; ieee_retval = 1.0; if (lib_version == strict_ansi) { exc.retval = 1.0; } else if (!matherr(&exc)) { if ((lib_version == c_issue_4) || (lib_version == ansi_1)) errno = EDOM; } break; case 43: /* log1p(-1) */ exc.type = SING; exc.name = "log1p"; ieee_retval = setexception(0, -1.0); if (lib_version == c_issue_4) exc.retval = -HUGE; else exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) { errno = ERANGE; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "log1p: SING error\n", 18); errno = EDOM; } else { errno = ERANGE; } } break; case 44: /* log1p(x<-1) */ exc.type = DOMAIN; exc.name = "log1p"; ieee_retval = setexception(3, 1.0); exc.retval = ieee_retval; if (lib_version == strict_ansi) { errno = EDOM; } else if (!matherr(&exc)) { if (lib_version == c_issue_4) { (void) write(2, "log1p: DOMAIN error\n", 20); } errno = EDOM; } break; case 45: /* logb(0) */ exc.type = DOMAIN; exc.name = "logb"; ieee_retval = setexception(0, -1.0); exc.retval = -HUGE_VAL; if (lib_version == strict_ansi) errno = EDOM; else if (!matherr(&exc)) errno = EDOM; break; case 46: /* nextafter overflow */ exc.type = OVERFLOW; exc.name = "nextafter"; /* * The value as returned by setexception is +/-DBL_MAX in * round-to-{zero,-/+Inf} mode respectively, which is not * usable. */ (void) setexception(2, x); ieee_retval = x > 0 ? Inf : -Inf; exc.retval = x > 0 ? HUGE_VAL : -HUGE_VAL; if (lib_version == strict_ansi) errno = ERANGE; else if (!matherr(&exc)) errno = ERANGE; break; case 47: /* scalb(x,inf) */ iy = ((int *)&y)[HIWORD]; if (lib_version == c_issue_4) /* SVID3: ERANGE in all cases */ errno = ERANGE; else if ((x == 0.0 && iy > 0) || (!finite(x) && iy < 0)) /* EDOM for scalb(0,+inf) or scalb(inf,-inf) */ errno = EDOM; exc.retval = ieee_retval = ((iy < 0)? x / -y : x * y); break; } switch (lib_version) { case c_issue_4: case ansi_1: case strict_ansi: return (exc.retval); /* NOTREACHED */ default: return (ieee_retval); } /* NOTREACHED */ } static double setexception(int n, double x) { /* * n = * 0 division by zero * 1 underflow * 2 overflow * 3 invalid */ volatile double one = 1.0, zero = 0.0, retv; switch (n) { case 0: /* division by zero */ retv = copysign(one / zero, x); break; case 1: /* underflow */ retv = DBL_MIN * copysign(DBL_MIN, x); break; case 2: /* overflow */ retv = DBL_MAX * copysign(DBL_MAX, x); break; case 3: /* invalid */ retv = zero * Inf; /* for Cheetah */ break; } return (retv); }