gitee.com/quant1x/num@v0.3.2/math32/exp.go (about) 1 package math32 2 3 func Exp(x float32) float32 4 5 func exp(x float32) float32 { 6 const ( 7 Ln2Hi = float32(6.9313812256e-01) 8 Ln2Lo = float32(9.0580006145e-06) 9 Log2e = float32(1.4426950216e+00) 10 11 Overflow = 7.09782712893383973096e+02 12 Underflow = -7.45133219101941108420e+02 13 NearZero = 1.0 / (1 << 28) // 2**-28 14 15 LogMax = 0x42b2d4fc // The bitmask of log(FLT_MAX), rounded down. This value is the largest input that can be passed to exp() without producing overflow. 16 LogMin = 0x42aeac50 // The bitmask of |log(REAL_FLT_MIN)|, rounding down 17 18 ) 19 // hx := Float32bits(x) & uint32(0x7fffffff) 20 21 // special cases 22 switch { 23 case IsNaN(x) || IsInf(x, 1): 24 return x 25 case IsInf(x, -1): 26 return 0 27 case x > Overflow: 28 return Inf(1) 29 case x < Underflow: 30 return 0 31 // case hx > LogMax: 32 // return Inf(1) 33 // case x < 0 && hx > LogMin: 34 return 0 35 case -NearZero < x && x < NearZero: 36 return 1 + x 37 } 38 39 // reduce; computed as r = hi - lo for extra precision. 40 var k int 41 switch { 42 case x < 0: 43 k = int(Log2e*x - 0.5) 44 case x > 0: 45 k = int(Log2e*x + 0.5) 46 } 47 hi := x - float32(k)*Ln2Hi 48 lo := float32(k) * Ln2Lo 49 50 // compute 51 return expmulti(hi, lo, k) 52 } 53 54 // Exp2 returns 2**x, the base-2 exponential of x. 55 // 56 // Special cases are the same as Exp. 57 func Exp2(x float32) float32 58 59 func exp2(x float32) float32 { 60 const ( 61 Ln2Hi = 6.9313812256e-01 62 Ln2Lo = 9.0580006145e-06 63 64 Overflow = 1.0239999999999999e+03 65 Underflow = -1.0740e+03 66 ) 67 68 // special cases 69 switch { 70 case IsNaN(x) || IsInf(x, 1): 71 return x 72 case IsInf(x, -1): 73 return 0 74 case x > Overflow: 75 return Inf(1) 76 case x < Underflow: 77 return 0 78 } 79 80 // argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2. 81 // computed as r = hi - lo for extra precision. 82 var k int 83 switch { 84 case x > 0: 85 k = int(x + 0.5) 86 case x < 0: 87 k = int(x - 0.5) 88 } 89 t := x - float32(k) 90 hi := t * Ln2Hi 91 lo := -t * Ln2Lo 92 93 // compute 94 return expmulti(hi, lo, k) 95 } 96 97 // exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2. 98 func expmulti(hi, lo float32, k int) float32 { 99 const ( 100 P1 = float32(1.6666667163e-01) /* 0x3e2aaaab */ 101 P2 = float32(-2.7777778450e-03) /* 0xbb360b61 */ 102 P3 = float32(6.6137559770e-05) /* 0x388ab355 */ 103 P4 = float32(-1.6533901999e-06) /* 0xb5ddea0e */ 104 P5 = float32(4.1381369442e-08) /* 0x3331bb4c */ 105 ) 106 107 r := hi - lo 108 t := r * r 109 c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) 110 y := 1 - ((lo - (r*c)/(2-c)) - hi) 111 // TODO(rsc): make sure Ldexp can handle boundary k 112 return Ldexp(y, k) 113 }