exp.go 2.5 KB

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