/* origin: FreeBSD /usr/src/lib/msun/src/e_exp.c *//** ====================================================* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.** Permission to use, copy, modify, and distribute this* software is freely granted, provided that this notice* is preserved.* ====================================================*//* exp(x)* Returns the exponential of x.** Method* 1. Argument reduction:* Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.* Given x, find r and integer k such that** x = k*ln2 + r, |r| <= 0.5*ln2.** Here r will be represented as r = hi-lo for better* accuracy.** 2. Approximation of exp(r) by a special rational function on* the interval [0,0.34658]:* Write* R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...* We use a special Remez algorithm on [0,0.34658] to generate* a polynomial of degree 5 to approximate R. The maximum error* of this polynomial approximation is bounded by 2**-59. In* other words,* R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5* (where z=r*r, and the values of P1 to P5 are listed below)* and* | 5 | -59* | 2.0+P1*z+...+P5*z - R(z) | <= 2* | |* The computation of exp(r) thus becomes* 2*r* exp(r) = 1 + ----------* R(r) - r* r*c(r)* = 1 + r + ----------- (for better accuracy)* 2 - c(r)* where* 2 4 10* c(r) = r - (P1*r + P2*r + ... + P5*r ).** 3. Scale back to obtain exp(x):* From step 1, we have* exp(x) = 2^k * exp(r)** Special cases:* exp(INF) is INF, exp(NaN) is NaN;* exp(-INF) is 0, and* for finite argument, only exp(0)=1 is exact.** Accuracy:* according to an error analysis, the error is always less than* 1 ulp (unit in the last place).** Misc. info.* For IEEE double* if x > 709.782712893383973096 then exp(x) overflows* if x < -745.133219101941108420 then exp(x) underflows*/#include "libm.h"static const doublehalf[2] = {0.5,-0.5},ln2hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ln2lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */double exp(double x){double_t hi, lo, c, xx, y;int k, sign;uint32_t hx;GET_HIGH_WORD(hx, x);sign = hx>>31;hx &= 0x7fffffff; /* high word of |x| *//* special cases */if (hx >= 0x4086232b) { /* if |x| >= 708.39... */if (isnan(x))return x;if (x > 709.782712893383973096) {/* overflow if x!=inf */x *= 0x1p1023;return x;}if (x < -708.39641853226410622) {/* underflow if x!=-inf */FORCE_EVAL((float)(-0x1p-149/x));if (x < -745.13321910194110842)return 0;}}/* argument reduction */if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */if (hx >= 0x3ff0a2b2) /* if |x| >= 1.5 ln2 */k = (int)(invln2*x + half[sign]);elsek = 1 - sign - sign;hi = x - k*ln2hi; /* k*ln2hi is exact here */lo = k*ln2lo;x = hi - lo;} else if (hx > 0x3e300000) { /* if |x| > 2**-28 */k = 0;hi = x;lo = 0;} else {/* inexact if x!=0 */FORCE_EVAL(0x1p1023 + x);return 1 + x;}/* x is now in primary range */xx = x*x;c = x - xx*(P1+xx*(P2+xx*(P3+xx*(P4+xx*P5))));y = 1 + (x*c/(2-c) - lo + hi);if (k == 0)return y;return scalbn(y, k);}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。