Math package for float32 / compex64 types https://godoc.org/pkg/math/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

exp.go 2.4KB

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