72d839a42f
The dbl-64 implementation of __ieee754_pow returns a NaN for pow (qNaN, 0) when it should return 1. Normally this is covered up by the wrappers ending up calling __kernel_standard which fixes up the result for this case, but for -lieee the wrappers are bypassed and the bad result gets through as a return value. Now, the wrappers fixing this are dealing with variant error handling that wants a result of NaN for pow (qNaN, 0), and only ever call __kernel_standard for this case if NaN resulted from __ieee754_pow. This leads to a question of whether the dbl-64 code might be deliberately returning NaN in order to use those code paths. However, I can find no sign that this is deliberate. If it were deliberate one would expect other implementations to do the same, and would expect the return of NaN to be very old, but it appears it came in by accident when the present e_pow.c implementation replaced an fdlibm implementation in 2001. So it appears to be unintended that this path through the pow wrapper could be used at all. So this patch fixes the implementation to return 1 in this case as expected. This is consistent with all the other implementations. The relevant path through the wrappers is now unreachable, so is removed (which is the main motivation of this patch: to avoid that path becoming accidentally reachable when implementing TS 18661-1 semantics that pow (sNaN, 0) should return qNaN with "invalid" raised). Another path that would require __ieee754_pow (0, 0) to return 0 is also unreachable (as all implementations return 1, in accordance with C99 semantics), so is removed as well. Note: we don't have anything set up to test -lieee, which in any case is obsolescent (at some point we should remove the ability for new programs to access _LIB_VERSION or define matherr and have it called by glibc). So testing will be implicit through sNaN tests added when making sNaN inputs work correctly for pow functions. Tested for x86_64 and x86. [BZ #20919] * sysdeps/ieee754/dbl-64/e_pow.c (__ieee754_pow): Do not return NaN first argument when raised to power 0. * math/w_pow.c (__pow): Do not check for NaN or zero results from raising to power zero. * math/w_powf.c (__powf): Likewise. * math/w_powl.c (__powl): Likewise. * sysdeps/ieee754/k_standard.c (__kernel_standard): Do not handle pow (0, 0) or pow (NaN, 0).
944 lines
20 KiB
C
944 lines
20 KiB
C
/* @(#)k_standard.c 5.1 93/09/24 */
|
|
/*
|
|
* ====================================================
|
|
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
|
* Permission to use, copy, modify, and distribute this
|
|
* software is freely granted, provided that this notice
|
|
* is preserved.
|
|
* ====================================================
|
|
*/
|
|
|
|
#if defined(LIBM_SCCS) && !defined(lint)
|
|
static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $";
|
|
#endif
|
|
|
|
#include <math.h>
|
|
#include <math_private.h>
|
|
#include <errno.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#ifndef _USE_WRITE
|
|
#include <stdio.h> /* fputs(), stderr */
|
|
#define WRITE2(u,v) fputs(u, stderr)
|
|
#else /* !defined(_USE_WRITE) */
|
|
#include <unistd.h> /* write */
|
|
#define WRITE2(u,v) write(2, u, v)
|
|
#undef fflush
|
|
#endif /* !defined(_USE_WRITE) */
|
|
|
|
/* XXX gcc versions until now don't delay the 0.0/0.0 division until
|
|
runtime but produce NaN at compile time. This is wrong since the
|
|
exceptions are not set correctly. */
|
|
#if 0
|
|
static const double zero = 0.0; /* used as const */
|
|
#else
|
|
static double zero = 0.0; /* used as const */
|
|
#endif
|
|
|
|
/*
|
|
* Standard conformance (non-IEEE) on exception cases.
|
|
* 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)
|
|
* 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-- tgamma(finite) overflow
|
|
* 41-- tgamma(-integer)
|
|
* 43-- +0**neg
|
|
* 44-- exp2 overflow
|
|
* 45-- exp2 underflow
|
|
* 46-- exp10 overflow
|
|
* 47-- exp10 underflow
|
|
* 48-- log2(0)
|
|
* 49-- log2(x<0)
|
|
* 50-- tgamma(+-0)
|
|
*/
|
|
|
|
|
|
double
|
|
__kernel_standard(double x, double y, int type)
|
|
{
|
|
struct exception exc;
|
|
#ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */
|
|
#define HUGE_VAL inf
|
|
double inf = 0.0;
|
|
|
|
SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */
|
|
#endif
|
|
|
|
/* The SVID struct exception uses a field "char *name;". */
|
|
#define CSTR(func) ((char *) (type < 100 \
|
|
? func \
|
|
: (type < 200 ? func "f" : func "l")))
|
|
|
|
#ifdef _USE_WRITE
|
|
(void) fflush(stdout);
|
|
#endif
|
|
exc.arg1 = x;
|
|
exc.arg2 = y;
|
|
switch(type) {
|
|
case 1:
|
|
case 101:
|
|
case 201:
|
|
/* acos(|x|>1) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("acos");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = HUGE;
|
|
else
|
|
exc.retval = NAN;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if(_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("acos: DOMAIN error\n", 19);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 2:
|
|
case 102:
|
|
case 202:
|
|
/* asin(|x|>1) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("asin");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = HUGE;
|
|
else
|
|
exc.retval = NAN;
|
|
if(_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if(_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("asin: DOMAIN error\n", 19);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 3:
|
|
case 103:
|
|
case 203:
|
|
/* atan2(+-0,+-0) */
|
|
exc.arg1 = y;
|
|
exc.arg2 = x;
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("atan2");
|
|
assert (_LIB_VERSION == _SVID_);
|
|
exc.retval = HUGE;
|
|
if(_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if(_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("atan2: DOMAIN error\n", 20);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 4:
|
|
case 104:
|
|
case 204:
|
|
/* hypot(finite,finite) overflow */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("hypot");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = HUGE;
|
|
else
|
|
exc.retval = HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 5:
|
|
case 105:
|
|
case 205:
|
|
/* cosh(finite) overflow */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("cosh");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = HUGE;
|
|
else
|
|
exc.retval = HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 6:
|
|
case 106:
|
|
case 206:
|
|
/* exp(finite) overflow */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("exp");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = HUGE;
|
|
else
|
|
exc.retval = HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 7:
|
|
case 107:
|
|
case 207:
|
|
/* exp(finite) underflow */
|
|
exc.type = UNDERFLOW;
|
|
exc.name = CSTR ("exp");
|
|
exc.retval = zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 8:
|
|
case 108:
|
|
case 208:
|
|
/* y0(0) = -inf */
|
|
exc.type = DOMAIN; /* should be SING for IEEE */
|
|
exc.name = CSTR ("y0");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = -HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("y0: DOMAIN error\n", 17);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 9:
|
|
case 109:
|
|
case 209:
|
|
/* y0(x<0) = NaN */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("y0");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = NAN;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("y0: DOMAIN error\n", 17);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 10:
|
|
case 110:
|
|
case 210:
|
|
/* y1(0) = -inf */
|
|
exc.type = DOMAIN; /* should be SING for IEEE */
|
|
exc.name = CSTR ("y1");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = -HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("y1: DOMAIN error\n", 17);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 11:
|
|
case 111:
|
|
case 211:
|
|
/* y1(x<0) = NaN */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("y1");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = NAN;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("y1: DOMAIN error\n", 17);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 12:
|
|
case 112:
|
|
case 212:
|
|
/* yn(n,0) = -inf */
|
|
exc.type = DOMAIN; /* should be SING for IEEE */
|
|
exc.name = CSTR ("yn");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = ((x < 0 && ((int) x & 1) != 0)
|
|
? HUGE_VAL
|
|
: -HUGE_VAL);
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("yn: DOMAIN error\n", 17);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 13:
|
|
case 113:
|
|
case 213:
|
|
/* yn(x<0) = NaN */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("yn");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = NAN;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("yn: DOMAIN error\n", 17);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 14:
|
|
case 114:
|
|
case 214:
|
|
/* lgamma(finite) overflow */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("lgamma");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = HUGE;
|
|
else
|
|
exc.retval = HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 15:
|
|
case 115:
|
|
case 215:
|
|
/* lgamma(-integer) or lgamma(0) */
|
|
exc.type = SING;
|
|
exc.name = CSTR ("lgamma");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = HUGE;
|
|
else
|
|
exc.retval = HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("lgamma: SING error\n", 19);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 16:
|
|
case 116:
|
|
case 216:
|
|
/* log(0) */
|
|
exc.type = SING;
|
|
exc.name = CSTR ("log");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = -HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("log: SING error\n", 16);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 17:
|
|
case 117:
|
|
case 217:
|
|
/* log(x<0) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("log");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = NAN;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("log: DOMAIN error\n", 18);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 18:
|
|
case 118:
|
|
case 218:
|
|
/* log10(0) */
|
|
exc.type = SING;
|
|
exc.name = CSTR ("log10");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = -HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("log10: SING error\n", 18);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 19:
|
|
case 119:
|
|
case 219:
|
|
/* log10(x<0) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("log10");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = NAN;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("log10: DOMAIN error\n", 20);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 21:
|
|
case 121:
|
|
case 221:
|
|
/* pow(x,y) overflow */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("pow");
|
|
if (_LIB_VERSION == _SVID_) {
|
|
exc.retval = HUGE;
|
|
y *= 0.5;
|
|
if(x<zero&&__rint(y)!=y) exc.retval = -HUGE;
|
|
} else {
|
|
exc.retval = HUGE_VAL;
|
|
y *= 0.5;
|
|
if(x<zero&&__rint(y)!=y) exc.retval = -HUGE_VAL;
|
|
}
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 22:
|
|
case 122:
|
|
case 222:
|
|
/* pow(x,y) underflow */
|
|
exc.type = UNDERFLOW;
|
|
exc.name = CSTR ("pow");
|
|
exc.retval = zero;
|
|
y *= 0.5;
|
|
if (x < zero && __rint (y) != y)
|
|
exc.retval = -zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 23:
|
|
case 123:
|
|
case 223:
|
|
/* -0**neg */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("pow");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = zero;
|
|
else
|
|
exc.retval = -HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("pow(0,neg): DOMAIN error\n", 25);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 43:
|
|
case 143:
|
|
case 243:
|
|
/* +0**neg */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("pow");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = zero;
|
|
else
|
|
exc.retval = HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("pow(0,neg): DOMAIN error\n", 25);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 24:
|
|
case 124:
|
|
case 224:
|
|
/* neg**non-integral */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("pow");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = zero;
|
|
else
|
|
exc.retval = zero/zero; /* X/Open allow NaN */
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("neg**non-integral: DOMAIN error\n", 32);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 25:
|
|
case 125:
|
|
case 225:
|
|
/* sinh(finite) overflow */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("sinh");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = ( (x>zero) ? HUGE : -HUGE);
|
|
else
|
|
exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL);
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 26:
|
|
case 126:
|
|
case 226:
|
|
/* sqrt(x<0) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("sqrt");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = zero;
|
|
else
|
|
exc.retval = zero/zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("sqrt: DOMAIN error\n", 19);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 27:
|
|
case 127:
|
|
case 227:
|
|
/* fmod(x,0) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("fmod");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = x;
|
|
else
|
|
exc.retval = zero/zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("fmod: DOMAIN error\n", 20);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 28:
|
|
case 128:
|
|
case 228:
|
|
/* remainder(x,0) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("remainder");
|
|
exc.retval = zero/zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("remainder: DOMAIN error\n", 24);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 29:
|
|
case 129:
|
|
case 229:
|
|
/* acosh(x<1) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("acosh");
|
|
exc.retval = zero/zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("acosh: DOMAIN error\n", 20);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 30:
|
|
case 130:
|
|
case 230:
|
|
/* atanh(|x|>1) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("atanh");
|
|
exc.retval = zero/zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("atanh: DOMAIN error\n", 20);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 31:
|
|
case 131:
|
|
case 231:
|
|
/* atanh(|x|=1) */
|
|
exc.type = SING;
|
|
exc.name = CSTR ("atanh");
|
|
exc.retval = x/zero; /* sign(x)*inf */
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("atanh: SING error\n", 18);
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 32:
|
|
case 132:
|
|
case 232:
|
|
/* scalb overflow; SVID also returns +-HUGE_VAL */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("scalb");
|
|
exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 33:
|
|
case 133:
|
|
case 233:
|
|
/* scalb underflow */
|
|
exc.type = UNDERFLOW;
|
|
exc.name = CSTR ("scalb");
|
|
exc.retval = __copysign(zero,x);
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 34:
|
|
case 134:
|
|
case 234:
|
|
/* j0(|x|>X_TLOSS) */
|
|
exc.type = TLOSS;
|
|
exc.name = CSTR ("j0");
|
|
exc.retval = zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2(exc.name, 2);
|
|
(void) WRITE2(": TLOSS error\n", 14);
|
|
}
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 35:
|
|
case 135:
|
|
case 235:
|
|
/* y0(x>X_TLOSS) */
|
|
exc.type = TLOSS;
|
|
exc.name = CSTR ("y0");
|
|
exc.retval = zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2(exc.name, 2);
|
|
(void) WRITE2(": TLOSS error\n", 14);
|
|
}
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 36:
|
|
case 136:
|
|
case 236:
|
|
/* j1(|x|>X_TLOSS) */
|
|
exc.type = TLOSS;
|
|
exc.name = CSTR ("j1");
|
|
exc.retval = zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2(exc.name, 2);
|
|
(void) WRITE2(": TLOSS error\n", 14);
|
|
}
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 37:
|
|
case 137:
|
|
case 237:
|
|
/* y1(x>X_TLOSS) */
|
|
exc.type = TLOSS;
|
|
exc.name = CSTR ("y1");
|
|
exc.retval = zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2(exc.name, 2);
|
|
(void) WRITE2(": TLOSS error\n", 14);
|
|
}
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 38:
|
|
case 138:
|
|
case 238:
|
|
/* jn(|x|>X_TLOSS) */
|
|
exc.type = TLOSS;
|
|
exc.name = CSTR ("jn");
|
|
exc.retval = zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2(exc.name, 2);
|
|
(void) WRITE2(": TLOSS error\n", 14);
|
|
}
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 39:
|
|
case 139:
|
|
case 239:
|
|
/* yn(x>X_TLOSS) */
|
|
exc.type = TLOSS;
|
|
exc.name = CSTR ("yn");
|
|
exc.retval = zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2(exc.name, 2);
|
|
(void) WRITE2(": TLOSS error\n", 14);
|
|
}
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 40:
|
|
case 140:
|
|
case 240:
|
|
/* tgamma(finite) overflow */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("tgamma");
|
|
exc.retval = __copysign (HUGE_VAL, x);
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 41:
|
|
case 141:
|
|
case 241:
|
|
/* tgamma(-integer) */
|
|
exc.type = SING;
|
|
exc.name = CSTR ("tgamma");
|
|
exc.retval = NAN;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_) {
|
|
(void) WRITE2("tgamma: SING error\n", 18);
|
|
exc.retval = HUGE_VAL;
|
|
}
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
|
|
case 44:
|
|
case 144:
|
|
case 244:
|
|
/* exp(finite) overflow */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("exp2");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = HUGE;
|
|
else
|
|
exc.retval = HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 45:
|
|
case 145:
|
|
case 245:
|
|
/* exp(finite) underflow */
|
|
exc.type = UNDERFLOW;
|
|
exc.name = CSTR ("exp2");
|
|
exc.retval = zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
|
|
case 46:
|
|
case 146:
|
|
case 246:
|
|
/* exp(finite) overflow */
|
|
exc.type = OVERFLOW;
|
|
exc.name = CSTR ("exp10");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = HUGE;
|
|
else
|
|
exc.retval = HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 47:
|
|
case 147:
|
|
case 247:
|
|
/* exp(finite) underflow */
|
|
exc.type = UNDERFLOW;
|
|
exc.name = CSTR ("exp10");
|
|
exc.retval = zero;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
case 48:
|
|
case 148:
|
|
case 248:
|
|
/* log2(0) */
|
|
exc.type = SING;
|
|
exc.name = CSTR ("log2");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = -HUGE_VAL;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 49:
|
|
case 149:
|
|
case 249:
|
|
/* log2(x<0) */
|
|
exc.type = DOMAIN;
|
|
exc.name = CSTR ("log2");
|
|
if (_LIB_VERSION == _SVID_)
|
|
exc.retval = -HUGE;
|
|
else
|
|
exc.retval = NAN;
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (EDOM);
|
|
else if (!matherr(&exc)) {
|
|
__set_errno (EDOM);
|
|
}
|
|
break;
|
|
case 50:
|
|
case 150:
|
|
case 250:
|
|
/* tgamma(+-0) */
|
|
exc.type = SING;
|
|
exc.name = CSTR ("tgamma");
|
|
exc.retval = __copysign (HUGE_VAL, x);
|
|
if (_LIB_VERSION == _POSIX_)
|
|
__set_errno (ERANGE);
|
|
else if (!matherr(&exc)) {
|
|
if (_LIB_VERSION == _SVID_)
|
|
(void) WRITE2("tgamma: SING error\n", 18);
|
|
__set_errno (ERANGE);
|
|
}
|
|
break;
|
|
|
|
/* #### Last used is 50/150/250 ### */
|
|
}
|
|
return exc.retval;
|
|
}
|