X-Git-Url: http://nsz.repo.hu/git/?p=libm;a=blobdiff_plain;f=src%2Fmath%2F__expf.c;h=192838f7ebfb852b5fb71c34741d5f899516c95a;hp=fa4fcdcabc1db910cd9fc6ac8656dc7c58e6acb8;hb=25215b63b9aa93089a9a05d1cffc3784109228c6;hpb=7e71d459b4104aae67ad092172be295cc221e284 diff --git a/src/math/__expf.c b/src/math/__expf.c index fa4fcdc..192838f 100644 --- a/src/math/__expf.c +++ b/src/math/__expf.c @@ -27,53 +27,25 @@ #include "libm.h" -static const uint32_t k = 235; /* constant for reduction */ -static const float kln2 = 162.88958740F; /* k * ln2 */ - /* - * See __exp.c for details. - * - * Input: ln(FLT_MAX) <= x < ln(2 * FLT_MAX / FLT_MIN_DENORM) ~= 192.7 - * Output: 2**127 <= y < 2**128 + * We use exp(x) = exp(x - kln2) * 2**k, + * k is carefully chosen to minimize |exp(kln2) - 2**k| */ -static float __frexp_expf(float x, int *expt) -{ - float exp_x; - uint32_t hx; - - exp_x = expf(x - kln2); - GET_FLOAT_WORD(hx, exp_x); - *expt = (hx >> 23) - (0x7f + 127) + k; - SET_FLOAT_WORD(exp_x, (hx & 0x7fffff) | ((0x7f + 127) << 23)); - return exp_x; -} - -float __ldexp_expf(float x, int expt) -{ - float exp_x, scale; - int ex_expt; - - exp_x = __frexp_expf(x, &ex_expt); - expt += ex_expt; - SET_FLOAT_WORD(scale, (0x7f + expt) << 23); - return exp_x * scale; -} +static const uint32_t k = 235; +static const float kln2 = 162.88958740f; -float complex __ldexp_cexpf(float complex z, int expt) +/* expf(x)/2 when x is huge */ +float __expo2f(float x) { - float x, y, exp_x, scale1, scale2; - int ex_expt, half_expt; - - x = crealf(z); - y = cimagf(z); - exp_x = __frexp_expf(x, &ex_expt); - expt += ex_expt; - - half_expt = expt / 2; - SET_FLOAT_WORD(scale1, (0x7f + half_expt) << 23); - half_expt = expt - half_expt; - SET_FLOAT_WORD(scale2, (0x7f + half_expt) << 23); - - return (cpackf(cosf(y) * exp_x * scale1 * scale2, - sinf(y) * exp_x * scale1 * scale2)); + float scale; + int n; + + /* + * efficient scalbnf(y, k-1): + * 2**(k-1) cannot be represented + * so we use that k-1 is even and scale in two steps + */ + n = (k - 1)/2; + SET_FLOAT_WORD(scale, (0x7f + n) << 23); + return expf(x - kln2) * scale * scale; }