Implemented fatanh,cosh,etox,etoxm1,lognp1,tanh, and twotox

but not ftentox, because this hits a clang bug. Clang 3.5
(and earlier?) wants to optimize pow(10.0, x) to
__exp10(x), but __exp10() doesn't exist in the 10.8 SDK,
so the linker fails. There's probably some simple workaround...
This commit is contained in:
Peter Rutenbar 2014-11-09 15:31:48 -05:00
parent 7fa1e15257
commit c8e7ba594c
1 changed files with 201 additions and 25 deletions

View File

@ -792,18 +792,16 @@ float128 _from_native(double n)
#define _native_cos(a) cos(a)
#define _native_acos(a) acos(a)
#define _native_cosh(a) cosh(a)
#define _native_acosh(a) acosh(a)
#define _native_sin(a) sin(a)
#define _native_asin(a) asin(a)
#define _native_sinh(a) sinh(a)
#define _native_asinh(a) asinh(a)
#define _native_tan(a) tan(a)
#define _native_atan(a) atan(a)
#define _native_tanh(a) tanh(a)
#define _native_atanh(a) atanh(a)
#define _native_pow(a, b) pow((a), (b))
#define _native_exp(a) exp(a)
#define _native_expm1(a) exp((a) - 1.0) /* or expm1() */
#define _native_expm1(a) (exp(a) - 1.0) /* or expm1() */
#define _native_log10(a) log10(a)
#define _native_log2(a) (log(a) / log(2.0)) /* or log2() */
#define _native_log(a) log(a)
@ -832,10 +830,6 @@ static float128 _hack_cosh (float128 x) {
return _from_native(_native_cosh(_to_native(x)));
}
static float128 _hack_acosh (float128 x) {
return _from_native(_native_acosh(_to_native(x)));
}
static float128 _hack_sin (float128 x) {
return _from_native(_native_sin(_to_native(x)));
}
@ -848,10 +842,6 @@ static float128 _hack_sinh (float128 x) {
return _from_native(_native_sinh(_to_native(x)));
}
static float128 _hack_asinh (float128 x) {
return _from_native(_native_asinh(_to_native(x)));
}
static float128 _hack_tan (float128 x) {
return _from_native(_native_tan(_to_native(x)));
}
@ -1192,6 +1182,11 @@ const float128 _one128 = {
.low = 0
};
const float128 _zero128 = {
.high = 0,
.low = 0
};
static void inst_fmath_fabs ()
{
fpu_get_state_ptr();
@ -1314,7 +1309,34 @@ static void inst_fmath_fatanh ()
{
fpu_get_state_ptr();
assert(!"fmath: fatanh not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
const _Bool source_sign = _float128_is_neg(fpu->source);
/* Take the absolute value of source */
float128 tmp = fpu->source;
tmp.high <<= 1;
tmp.high >>= 1;
/* If source is 0, return source */
if (source_zero) {
fpu->result = fpu->source;
return;
}
/* If |source| == 1.0, set dz, return +-inf */
else if (float128_eq(tmp, _one128)) {
es_dz = 1;
fpu->result = _assemble_float128(source_sign, 0x7fff, 0, 0);
return;
}
/* If |source| > 1.0, set operr, return nan */
else if (!float128_le(tmp, _one128)) {
es_operr = 1;
fpu->result = _nan128;
return ;
}
fpu->result = _hack_atanh(fpu->source);
}
static void inst_fmath_fcmp ()
@ -1365,7 +1387,21 @@ static void inst_fmath_fcosh ()
{
fpu_get_state_ptr();
assert(!"fmath: fcosh not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
/* If source is zero, result is +1.0 */
if (source_zero) {
fpu->result = _one128;
return;
}
/* If source is +/- inf, result is +inf */
else if (source_inf) {
fpu->result = _assemble_float128(0, 0x7fff, 0, 0);
return;
}
fpu->result = _hack_cosh(fpu->source);
}
static void inst_fmath_fdiv ()
@ -1399,14 +1435,56 @@ static void inst_fmath_fetox ()
{
fpu_get_state_ptr();
assert(!"fmath: fetox not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
const _Bool source_sign = _float128_is_neg(fpu->source);
/* If source is zero, result is +1.0 */
if (source_zero) {
fpu->result = _one128;
return ;
}
/* if source is -inf, result is +0.0 */
else if (source_inf && source_sign) {
fpu->result = _zero128;
return ;
}
/* if source is +inf, result is +inf */
else if (source_inf) {
fpu->result = fpu->source;
return ;
}
fpu->result = _hack_etox(fpu->source);
}
static void inst_fmath_fetoxm1 ()
{
fpu_get_state_ptr();
assert(!"fmath: fetoxm1 not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
const _Bool source_sign = _float128_is_neg(fpu->source);
const float128 negone = _assemble_float128(1, 0x3fff, 0, 0);
/* If source is zero, result is source */
if (source_zero) {
fpu->result = fpu->source;
return ;
}
/* if source is -inf, result is +0.0 */
else if (source_inf && source_sign) {
fpu->result = negone;
return ;
}
/* if source is +inf, result is +inf */
else if (source_inf) {
fpu->result = fpu->source;
return ;
}
fpu->result = _hack_etoxm1(fpu->source);
}
static void inst_fmath_fgetexp ()
@ -1533,6 +1611,42 @@ static void inst_fmath_flog2 ()
fpu->result = _hack_log2(fpu->source);
}
static void inst_fmath_flognp1 ()
{
fpu_get_state_ptr();
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
const _Bool source_sign = _float128_is_neg(fpu->source);
const float128 negone = _assemble_float128(1, 0x3fff, 0, 0);
/* If source is zero, result is source */
if (source_zero) {
fpu->result = fpu->source;
return;
}
/* If source is -1.0, set dz, result is -inf */
else if (float128_eq(negone, fpu->source)) {
es_dz = 1;
fpu->result = _assemble_float128(1, 0x7fff, 0, 0);
return;
}
/* If source < -1.0, set operr, result is nan */
else if (float128_lt(fpu->source, negone)) {
es_operr = 1;
fpu->result = _nan128;
return;
}
/* If source is +inf, result is +inf. */
else if (source_inf) {
fpu->result = fpu->source;
return;
}
fpu->result = _hack_lognp1(fpu->source);
}
static void inst_fmath_flogn ()
{
fpu_get_state_ptr();
@ -1562,13 +1676,6 @@ static void inst_fmath_flogn ()
fpu->result = _hack_logn(fpu->source);
}
static void inst_fmath_flognp1 ()
{
fpu_get_state_ptr();
assert(!"fmath: flognp1 not implemented");
}
static void inst_fmath_fmove ()
{
fpu_get_state_ptr();
@ -1854,7 +1961,16 @@ static void inst_fmath_fsinh ()
{
fpu_get_state_ptr();
assert(!"fmath: fsinh not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
/* If source is zero or inf, return source */
if (source_zero || source_inf) {
fpu->result = fpu->source;
return;
}
fpu->result = _hack_sinh(fpu->source);
}
static void inst_fmath_fsqrt ()
@ -1929,13 +2045,53 @@ static void inst_fmath_ftanh ()
{
fpu_get_state_ptr();
assert(!"fmath: ftanh not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
const _Bool source_sign = _float128_is_neg(fpu->source);
/* If source is zero, result is source */
if (source_zero) {
fpu->result = fpu->source;
return;
}
/* If source is +/- inf, result is +/- 1.0 */
else if (source_inf) {
fpu->result = _assemble_float128(source_sign, 0x3fff, 0, 0);
return;
}
fpu->result = _hack_tanh(fpu->source);
}
static void inst_fmath_ftentox ()
{
fpu_get_state_ptr();
// _hack_ftentox() is broken on clang 3.5 on osx 10.10
// (tries to optimize pow(10.0, x) to __exp10(x), and __exp10
// isn't implemented in the 10.8 SDK)
// const _Bool source_zero = _float128_is_zero(fpu->source);
// const _Bool source_inf = _float128_is_infinity(fpu->source);
// const _Bool source_sign = _float128_is_neg(fpu->source);
//
// /* If source is zero, result is +1.0 */
// if (source_zero) {
// fpu->result = _one128;
// return ;
// }
// /* if source is -inf, result is +0.0 */
// else if (source_inf && source_sign) {
// fpu->result = _zero128;
// return ;
// }
// /* if source is +inf, result is +inf */
// else if (source_inf) {
// fpu->result = fpu->source;
// return ;
// }
//
// fpu->result = _hack_tentox(fpu->source);
//
assert(!"fmath: ftentox not implemented");
}
@ -1954,7 +2110,27 @@ static void inst_fmath_ftwotox ()
{
fpu_get_state_ptr();
assert(!"fmath: ftwotox not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
const _Bool source_sign = _float128_is_neg(fpu->source);
/* If source is zero, result is +1.0 */
if (source_zero) {
fpu->result = _one128;
return ;
}
/* if source is -inf, result is +0.0 */
else if (source_inf && source_sign) {
fpu->result = _zero128;
return ;
}
/* if source is +inf, result is +inf */
else if (source_inf) {
fpu->result = fpu->source;
return ;
}
fpu->result = _hack_twotox(fpu->source);
}
typedef void (fmath_impl_t)(void);