#include "libm.h"
#include "xpg6.h"
#include <stdio.h>
#include <float.h>
#include <unistd.h>
#if defined(__x86)
#include <ieeefp.h>
#undef fp_class
#define fp_class fpclass
#define fp_quiet FP_QNAN
#endif
#include <errno.h>
#undef fflush
#include <sys/isa_defs.h>
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;
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:
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:
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:
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 (lib_version != libm_ieee && !matherr(&exc)) {
if (lib_version == c_issue_4) {
(void) write(2, "atan2: DOMAIN error\n", 20);
}
errno = EDOM;
}
break;
case 4:
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:
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:
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:
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:
exc.type = DOMAIN;
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:
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:
exc.type = DOMAIN;
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:
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:
exc.type = DOMAIN;
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:
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:
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:
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:
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:
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:
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:
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:
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:
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) {
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:
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)
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:
exc.type = DOMAIN;
exc.name = "pow";
ieee_retval = setexception(0, 1.0);
{
int ahy, k, j, yisint, ly, hx;
hx = __HI(x);
ahy = __HI(y)&0x7fffffff;
ly = __LO(y);
yisint = 0;
if (ahy >= 0x43400000) {
yisint = 2;
} else if (ahy >= 0x3ff00000) {
k = (ahy >> 20) - 0x3ff;
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:
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;
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:
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:
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;
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:
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:
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:
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:
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:
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:
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:
exc.type = UNDERFLOW;
exc.name = "scalb";
ieee_retval = setexception(1, x);
exc.retval = ieee_retval;
if (lib_version == strict_ansi)
errno = ERANGE;
else if (!matherr(&exc))
errno = ERANGE;
break;
case 34:
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:
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:
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:
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:
exc.type = TLOSS;
exc.name = "jn";
exc.retval = 0.0;
ieee_retval = 0.0;
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:
exc.type = TLOSS;
exc.name = "yn";
exc.retval = 0.0;
ieee_retval = 0.0;
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:
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:
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:
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:
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:
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:
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:
exc.type = OVERFLOW;
exc.name = "nextafter";
(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:
iy = ((int *)&y)[HIWORD];
if (lib_version == c_issue_4)
errno = ERANGE;
else if ((x == 0.0 && iy > 0) || (!finite(x) && iy < 0))
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);
default:
return (ieee_retval);
}
}
static double
setexception(int n, double x)
{
volatile double one = 1.0, zero = 0.0, retv;
switch (n) {
case 0:
retv = copysign(one / zero, x);
break;
case 1:
retv = DBL_MIN * copysign(DBL_MIN, x);
break;
case 2:
retv = DBL_MAX * copysign(DBL_MAX, x);
break;
case 3:
retv = zero * Inf;
break;
}
return (retv);
}