diff options
Diffstat (limited to 'sysdeps/ieee754/flt-32/e_jnf.c')
-rw-r--r-- | sysdeps/ieee754/flt-32/e_jnf.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/sysdeps/ieee754/flt-32/e_jnf.c b/sysdeps/ieee754/flt-32/e_jnf.c index 5984d94a3c..44a3761adb 100644 --- a/sysdeps/ieee754/flt-32/e_jnf.c +++ b/sysdeps/ieee754/flt-32/e_jnf.c @@ -14,6 +14,7 @@ */ #include <errno.h> +#include <float.h> #include <math.h> #include <math_private.h> @@ -26,6 +27,8 @@ static const float zero = 0.0000000000e+00; float __ieee754_jnf(int n, float x) { + float ret; + { int32_t i,hx,ix, sgn; float a, b, temp, di; float z, w; @@ -46,8 +49,9 @@ __ieee754_jnf(int n, float x) if(n==1) return(__ieee754_j1f(x)); sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ x = fabsf(x); + SET_RESTORE_ROUNDF (FE_TONEAREST); if(__builtin_expect(ix==0||ix>=0x7f800000, 0)) /* if x is 0 or inf */ - b = zero; + return sgn == 1 ? -zero : zero; else if((float)n<=x) { /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ a = __ieee754_j0f(x); @@ -162,13 +166,23 @@ __ieee754_jnf(int n, float x) b = (t * w / a); } } - if(sgn==1) return -b; else return b; + if(sgn==1) ret = -b; else ret = b; + } + if (ret == 0) + ret = __copysignf (FLT_MIN, ret) * FLT_MIN; + else if (fabsf (ret) < FLT_MIN) { + float force_underflow = ret * ret; + math_force_eval (force_underflow); + } + return ret; } strong_alias (__ieee754_jnf, __jnf_finite) float __ieee754_ynf(int n, float x) { + float ret; + { int32_t i,hx,ix; u_int32_t ib; int32_t sign; @@ -187,7 +201,11 @@ __ieee754_ynf(int n, float x) sign = 1 - ((n&1)<<1); } if(n==0) return(__ieee754_y0f(x)); - if(n==1) return(sign*__ieee754_y1f(x)); + SET_RESTORE_ROUNDF (FE_TONEAREST); + if(n==1) { + ret = sign*__ieee754_y1f(x); + goto out; + } if(__builtin_expect(ix==0x7f800000, 0)) return zero; a = __ieee754_y0f(x); @@ -201,8 +219,13 @@ __ieee754_ynf(int n, float x) a = temp; } /* If B is +-Inf, set up errno accordingly. */ - if (! __finitef (b)) + if (! isfinite (b)) __set_errno (ERANGE); - if(sign>0) return b; else return -b; + if(sign>0) ret = b; else ret = -b; + } + out: + if (isinf (ret)) + ret = __copysignf (FLT_MAX, ret) * FLT_MAX; + return ret; } strong_alias (__ieee754_ynf, __ynf_finite) |