/*
* 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
* 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 <stdio.h>
#include <float.h> /* DBL_MAX, DBL_MIN */
#include <unistd.h> /* write */
#if defined(__x86)
#include <ieeefp.h>
#endif
#include <errno.h>
#include <sys/isa_defs.h>
/* 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)
* 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
double
double t, w, ieee_retval = 0;
int iy;
/* force libm_ieee behavior in SUSv3 mode */
if ((__xpg6 & _C99SUSv3_math_errexcept) != 0)
if (lib_version == c_issue_4) {
}
switch (type) {
case 1:
/* acos(|x|>1) */
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 2:
/* asin(|x|>1) */
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 3:
/* atan2(+-0,+-0) */
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 4:
/* hypot(finite,finite) overflow */
ieee_retval = Inf;
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi)
break;
case 5:
/* cosh(finite) overflow */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi)
break;
case 6:
/* exp(finite) overflow */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi)
break;
case 7:
/* exp(finite) underflow */
if (lib_version == strict_ansi)
break;
case 8:
/* y0(0) = -inf */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 9:
/* y0(x<0) = NaN */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 10:
/* y1(0) = -inf */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 11:
/* y1(x<0) = NaN */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 12:
/* yn(n,0) = -inf */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 13:
/* yn(x<0) = NaN */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 14:
/* lgamma(finite) overflow */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi)
break;
case 15:
/* lgamma(-integer) or lgamma(0) */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 16:
/* log(0) */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
} else {
}
}
break;
case 17:
/* log(x<0) */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 18:
/* log10(0) */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
} else {
}
}
break;
case 19:
/* log10(x<0) */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 20:
/* pow(0.0,0.0) */
/* error only if lib_version == c_issue_4 */
ieee_retval = 1.0;
if (lib_version != c_issue_4) {
}
break;
case 21:
/* pow(x,y) overflow */
if (signbit(x)) {
t = rint(y);
if (t == y) {
w = rint(0.5 * y);
if (t != w + w) { /* y is odd */
}
}
}
if (lib_version == strict_ansi)
break;
case 22:
/* pow(x,y) underflow */
if (signbit(x)) {
t = rint(y);
if (t == y) {
w = rint(0.5 * y);
if (t != w + w) /* y is odd */
}
}
if (lib_version == strict_ansi)
break;
case 23:
/* (+-0)**neg */
{
/* 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 */
yisint = 0;
if (ahy >= 0x43400000) {
} else if (ahy >= 0x3ff00000) {
if (k > 20) {
j = ly >> (52 - k);
if ((j << (52 - k)) == ly)
} else if (ly == 0) {
j = ahy >> (20 - k);
if ((j << (20 - k)) == ahy)
}
}
}
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
25);
}
}
break;
case 24:
/* neg**non-integral */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
(void) write(2,
"neg**non-integral: DOMAIN error\n", 32);
}
}
break;
case 25:
/* sinh(finite) overflow */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi)
break;
case 26:
/* sqrt(x<0) */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 27:
/* fmod(x,0) */
ieee_retval = NaN;
else
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 28:
/* remainder(x,0) */
ieee_retval = NaN;
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
24);
}
}
break;
case 29:
/* acosh(x<1) */
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 30:
/* atanh(|x|>1) */
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 31:
/* atanh(|x|=1) */
ieee_retval = setexception(0, x);
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
} else {
}
}
break;
case 32:
/* scalb overflow; SVID also returns +-HUGE_VAL */
if (lib_version == strict_ansi)
break;
case 33:
/* scalb underflow */
if (lib_version == strict_ansi)
break;
case 34:
/* j0(|x|>X_TLOSS) */
ieee_retval = y;
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 35:
/* y0(x>X_TLOSS) */
ieee_retval = y;
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 36:
/* j1(|x|>X_TLOSS) */
ieee_retval = y;
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 37:
/* y1(x>X_TLOSS) */
ieee_retval = y;
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 38:
/* jn(|x|>X_TLOSS) */
/* incorrect ieee value: ieee should never be here */
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 39:
/* yn(x>X_TLOSS) */
/* incorrect ieee value: ieee should never be here */
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 40:
/* gamma(finite) overflow */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi)
break;
case 41:
/* gamma(-integer) or gamma(0) */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 42:
/* pow(NaN,0.0) */
/* error if lib_version == c_issue_4 or ansi_1 */
ieee_retval = 1.0;
if (lib_version == strict_ansi) {
}
break;
case 43:
/* log1p(-1) */
if (lib_version == c_issue_4)
else
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
} else {
}
}
break;
case 44:
/* log1p(x<-1) */
if (lib_version == strict_ansi) {
if (lib_version == c_issue_4) {
}
}
break;
case 45:
/* logb(0) */
if (lib_version == strict_ansi)
break;
case 46:
/* nextafter overflow */
/*
* The value as returned by setexception is +/-DBL_MAX in
* round-to-{zero,-/+Inf} mode respectively, which is not
* usable.
*/
(void) setexception(2, x);
if (lib_version == strict_ansi)
break;
case 47:
/* scalb(x,inf) */
if (lib_version == c_issue_4)
/* SVID3: ERANGE in all cases */
/* EDOM for scalb(0,+inf) or scalb(inf,-inf) */
break;
}
switch (lib_version) {
case c_issue_4:
case ansi_1:
case strict_ansi:
/* NOTREACHED */
default:
return (ieee_retval);
}
/* NOTREACHED */
}
static double
setexception(int n, double x) {
/*
* n =
* 0 division by zero
* 1 underflow
* 2 overflow
* 3 invalid
*/
switch (n) {
case 0: /* division by zero */
break;
case 1: /* underflow */
break;
case 2: /* overflow */
break;
case 3: /* invalid */
break;
}
return (retv);
}