glibc/sysdeps/ieee754/k_standard.c
Joseph Myers 4f3647e46e Prefer new libm function wrappers for !LIBM_SVID_COMPAT.
The initial obsoletion of SVID libm error handling left the old
wrappers and __kernel_standard still being used for new ports and
static linking, just with macro definitions of _LIB_VERSION and
matherr that meant symbols with those names were never actually used
and the code for different error handling variants could be optimized
out.

This patch cleans things up further by eliminating the
__kernel_standard use for new ports and static linking.  Now, the old
wrappers no longer generate any code in the !LIBM_SVID_COMPAT case,
while the new errno-only wrappers that were added for float128 support
are now also used for float, double and long double in that case.

The changes are generally straightforward.  The w_scalb*_compat
wrappers continue to be used (scalb is obsolescent in the sense of not
being supported for float128, but is present in supported standards -
the 2001 edition of POSIX and earlier XSI versions - so remains
supported for static linking and new ports, as do the float and long
double variants that are existing GNU extensions).  Those wrappers
would only call __kernel_standard in the _LIB_VERSION == _SVID_ case.
Since we would like to be able to compile most of glibc without
optimization, relying on a static function whose only use is under an
if (0) condition being optimized away to avoid an undefined
__kernel_standard reference may not be a good idea.  Thus, the
relevant code in the scalb wrappers has LIBM_SVID_COMPAT conditionals
added to guarantee it's not built at all in the case where
__kernel_standard does not exist.

Just as i386 has its own w_sqrt_compat.c, so w_sqrt.c is also added.
ia64 gets dummy w_*.c to prevent those files being built where they
would conflict with the ia64 libm, as with its existing w_*_compat.c.

Conditions disabling code for !LIBM_SVID_COMPAT are needed in both the
math/ wrappers and in the long double wrappers in ldbl-opt (to avoid
them setting up aliases and symbol versions for undefined symbols).  I
hope that future cleanups to how libm function aliases and symbol
versioning are done will eliminate the need for most of the ldbl-opt
wrappers.

Tested for x86_64 and x86, and with build-many-glibcs.py.

	* sysdeps/generic/math-type-macros-double.h: Include
	<math-svid-compat.h>.
	(__USE_WRAPPER_TEMPLATE): Define to !LIBM_SVID_COMPAT.
	* sysdeps/generic/math-type-macros-float.h: Include
	<math-svid-compat.h>.
	(__USE_WRAPPER_TEMPLATE): Define to !LIBM_SVID_COMPAT.
	* sysdeps/generic/math-type-macros-ldouble.h: Include
	<math-svid-compat.h>.
	(__USE_WRAPPER_TEMPLATE): Define to !LIBM_SVID_COMPAT.
	* math/lgamma-compat.h (BUILD_LGAMMA): Include LIBM_SVID_COMPAT
	condition.
	* math/w_acos_compat.c: Condition contents on [LIBM_SVID_COMPAT].
	* math/w_acosf_compat.c: Likewise.
	* math/w_acosh_compat.c: Likewise.
	* math/w_acoshf_compat.c: Likewise.
	* math/w_acoshl_compat.c: Likewise.
	* math/w_acosl_compat.c: Likewise.
	* math/w_asin_compat.c: Likewise.
	* math/w_asinf_compat.c: Likewise.
	* math/w_asinl_compat.c: Likewise.
	* math/w_atan2_compat.c: Likewise.
	* math/w_atan2f_compat.c: Likewise.
	* math/w_atan2l_compat.c: Likewise.
	* math/w_atanh_compat.c: Likewise.
	* math/w_atanhf_compat.c: Likewise.
	* math/w_atanhl_compat.c: Likewise.
	* math/w_cosh_compat.c: Likewise.
	* math/w_coshf_compat.c: Likewise.
	* math/w_coshl_compat.c: Likewise.
	* math/w_exp10_compat.c: Likewise.
	* math/w_exp10f_compat.c: Likewise.
	* math/w_exp10l_compat.c: Likewise.
	* math/w_exp2_compat.c: Likewise.
	* math/w_exp2f_compat.c: Likewise.
	* math/w_exp2l_compat.c: Likewise.
	* math/w_fmod_compat.c: Likewise.
	* math/w_fmodf_compat.c: Likewise.
	* math/w_fmodl_compat.c: Likewise.
	* math/w_hypot_compat.c: Likewise.
	* math/w_hypotf_compat.c: Likewise.
	* math/w_hypotl_compat.c: Likewise.
	* math/w_j0_compat.c: Likewise.
	* math/w_j0f_compat.c: Likewise.
	* math/w_j0l_compat.c: Likewise.
	* math/w_j1_compat.c: Likewise.
	* math/w_j1f_compat.c: Likewise.
	* math/w_j1l_compat.c: Likewise.
	* math/w_jn_compat.c: Likewise.
	* math/w_jnf_compat.c: Likewise.
	* math/w_jnl_compat.c: Likewise.
	* math/w_lgamma_r_compat.c: Likewise.
	* math/w_lgammaf_r_compat.c: Likewise.
	* math/w_lgammal_r_compat.c: Likewise.
	* math/w_log10_compat.c: Likewise.
	* math/w_log10f_compat.c: Likewise.
	* math/w_log10l_compat.c: Likewise.
	* math/w_log2_compat.c: Likewise.
	* math/w_log2f_compat.c: Likewise.
	* math/w_log2l_compat.c: Likewise.
	* math/w_log_compat.c: Likewise.
	* math/w_logf_compat.c: Likewise.
	* math/w_logl_compat.c: Likewise.
	* math/w_pow_compat.c: Likewise.
	* math/w_powf_compat.c: Likewise.
	* math/w_powl_compat.c: Likewise.
	* math/w_remainder_compat.c: Likewise.
	* math/w_remainderf_compat.c: Likewise.
	* math/w_remainderl_compat.c: Likewise.
	* math/w_sinh_compat.c: Likewise.
	* math/w_sinhf_compat.c: Likewise.
	* math/w_sinhl_compat.c: Likewise.
	* math/w_sqrt_compat.c: Likewise.
	* math/w_sqrtf_compat.c: Likewise.
	* math/w_sqrtl_compat.c: Likewise.
	* math/w_tgamma_compat.c: Likewise.
	* math/w_tgammaf_compat.c: Likewise.
	* math/w_tgammal_compat.c: Likewise.
	* math/w_scalb_compat.c (sysv_scalb): Condition definition on
	[LIBM_SVID_COMPAT].
	(__scalb): Condition call to sysv_scalb on [LIBM_SVID_COMPAT].
	* math/w_scalbf_compat.c (sysv_scalbf): Condition definition on
	[LIBM_SVID_COMPAT].
	(__scalbf): Condition call to sysv_scalbf on [LIBM_SVID_COMPAT].
	* math/w_scalbl_compat.c (sysv_scalbl): Condition definition on
	[LIBM_SVID_COMPAT].
	(__scalbl): Condition call to sysv_scalbl on [LIBM_SVID_COMPAT].
	* sysdeps/i386/fpu/w_sqrt.c: New file.
	* sysdeps/ia64/fpu/w_acos.c: Likewise.
	* sysdeps/ia64/fpu/w_acosf.c: Likewise.
	* sysdeps/ia64/fpu/w_acosh.c: Likewise.
	* sysdeps/ia64/fpu/w_acoshf.c: Likewise.
	* sysdeps/ia64/fpu/w_acoshl.c: Likewise.
	* sysdeps/ia64/fpu/w_acosl.c: Likewise.
	* sysdeps/ia64/fpu/w_asin.c: Likewise.
	* sysdeps/ia64/fpu/w_asinf.c: Likewise.
	* sysdeps/ia64/fpu/w_asinl.c: Likewise.
	* sysdeps/ia64/fpu/w_atan2.c: Likewise.
	* sysdeps/ia64/fpu/w_atan2f.c: Likewise.
	* sysdeps/ia64/fpu/w_atan2l.c: Likewise.
	* sysdeps/ia64/fpu/w_atanh.c: Likewise.
	* sysdeps/ia64/fpu/w_atanhf.c: Likewise.
	* sysdeps/ia64/fpu/w_atanhl.c: Likewise.
	* sysdeps/ia64/fpu/w_cosh.c: Likewise.
	* sysdeps/ia64/fpu/w_coshf.c: Likewise.
	* sysdeps/ia64/fpu/w_coshl.c: Likewise.
	* sysdeps/ia64/fpu/w_exp.c: Likewise.
	* sysdeps/ia64/fpu/w_exp10.c: Likewise.
	* sysdeps/ia64/fpu/w_exp10f.c: Likewise.
	* sysdeps/ia64/fpu/w_exp10l.c: Likewise.
	* sysdeps/ia64/fpu/w_exp2.c: Likewise.
	* sysdeps/ia64/fpu/w_exp2f.c: Likewise.
	* sysdeps/ia64/fpu/w_exp2l.c: Likewise.
	* sysdeps/ia64/fpu/w_expf.c: Likewise.
	* sysdeps/ia64/fpu/w_expl.c: Likewise.
	* sysdeps/ia64/fpu/w_fmod.c: Likewise.
	* sysdeps/ia64/fpu/w_fmodf.c: Likewise.
	* sysdeps/ia64/fpu/w_fmodl.c: Likewise.
	* sysdeps/ia64/fpu/w_hypot.c: Likewise.
	* sysdeps/ia64/fpu/w_hypotf.c: Likewise.
	* sysdeps/ia64/fpu/w_hypotl.c: Likewise.
	* sysdeps/ia64/fpu/w_lgamma_r.c: Likewise.
	* sysdeps/ia64/fpu/w_lgammaf_r.c: Likewise.
	* sysdeps/ia64/fpu/w_lgammal_r.c: Likewise.
	* sysdeps/ia64/fpu/w_log.c: Likewise.
	* sysdeps/ia64/fpu/w_log10.c: Likewise.
	* sysdeps/ia64/fpu/w_log10f.c: Likewise.
	* sysdeps/ia64/fpu/w_log10l.c: Likewise.
	* sysdeps/ia64/fpu/w_log2.c: Likewise.
	* sysdeps/ia64/fpu/w_log2f.c: Likewise.
	* sysdeps/ia64/fpu/w_log2l.c: Likewise.
	* sysdeps/ia64/fpu/w_logf.c: Likewise.
	* sysdeps/ia64/fpu/w_logl.c: Likewise.
	* sysdeps/ia64/fpu/w_pow.c: Likewise.
	* sysdeps/ia64/fpu/w_powf.c: Likewise.
	* sysdeps/ia64/fpu/w_powl.c: Likewise.
	* sysdeps/ia64/fpu/w_remainder.c: Likewise.
	* sysdeps/ia64/fpu/w_remainderf.c: Likewise.
	* sysdeps/ia64/fpu/w_remainderl.c: Likewise.
	* sysdeps/ia64/fpu/w_sinh.c: Likewise.
	* sysdeps/ia64/fpu/w_sinhf.c: Likewise.
	* sysdeps/ia64/fpu/w_sinhl.c: Likewise.
	* sysdeps/ia64/fpu/w_sqrt.c: Likewise.
	* sysdeps/ia64/fpu/w_sqrtf.c: Likewise.
	* sysdeps/ia64/fpu/w_sqrtl.c: Likewise.
	* sysdeps/ia64/fpu/w_tgamma.c: Likewise.
	* sysdeps/ia64/fpu/w_tgammaf.c: Likewise.
	* sysdeps/ia64/fpu/w_tgammal.c: Likewise.
	* sysdeps/ieee754/dbl-64/w_exp_compat.c: Condition contents on
	[LIBM_SVID_COMPAT].
	* sysdeps/ieee754/flt-32/w_expf_compat.c: Likewise.
	* sysdeps/ieee754/k_standard.c: Likewise.
	* sysdeps/ieee754/k_standardf.c: Likewise.
	* sysdeps/ieee754/k_standardl.c: Likewise.
	* sysdeps/ieee754/ldbl-128/w_expl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-128ibm/w_expl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-96/w_expl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-64-128/w_expl_compat.c: Condition
	long_double_symbol call on [LIBM_SVID_COMPAT].
	* sysdeps/ieee754/ldbl-opt/w_acoshl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_acosl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_asinl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_atan2l_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_atanhl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_coshl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_fmodl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_hypotl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_j0l_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_j1l_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_jnl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_lgammal_r_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_log10l_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_log2l_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_logl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_powl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_remainderl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_sinhl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_sqrtl_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_tgammal_compat.c: Likewise.
	* sysdeps/ieee754/ldbl-opt/w_exp10l_compat.c: Condition
	long_double_symbol and compat_symbol calls on [LIBM_SVID_COMPAT].
2017-09-05 23:35:55 +00:00

951 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 <math-svid-compat.h>
#include <errno.h>
#include <assert.h>
#if LIBM_SVID_COMPAT
# 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 ### */
default:
__builtin_unreachable ();
}
return exc.retval;
}
#endif