pow.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package math32
  2. import "math"
  3. func isOddInt(x float32) bool {
  4. xi, xf := Modf(x)
  5. return xf == 0 && int32(xi)&1 == 1
  6. }
  7. // Special cases taken from FreeBSD's /usr/src/lib/msun/src/e_pow.c
  8. // updated by IEEE Std. 754-2008 "Section 9.2.1 Special values".
  9. // Pow returns x**y, the base-x exponential of y.
  10. //
  11. // Special cases are (in order):
  12. // Pow(x, ±0) = 1 for any x
  13. // Pow(1, y) = 1 for any y
  14. // Pow(x, 1) = x for any x
  15. // Pow(NaN, y) = NaN
  16. // Pow(x, NaN) = NaN
  17. // Pow(±0, y) = ±Inf for y an odd integer < 0
  18. // Pow(±0, -Inf) = +Inf
  19. // Pow(±0, +Inf) = +0
  20. // Pow(±0, y) = +Inf for finite y < 0 and not an odd integer
  21. // Pow(±0, y) = ±0 for y an odd integer > 0
  22. // Pow(±0, y) = +0 for finite y > 0 and not an odd integer
  23. // Pow(-1, ±Inf) = 1
  24. // Pow(x, +Inf) = +Inf for |x| > 1
  25. // Pow(x, -Inf) = +0 for |x| > 1
  26. // Pow(x, +Inf) = +0 for |x| < 1
  27. // Pow(x, -Inf) = +Inf for |x| < 1
  28. // Pow(+Inf, y) = +Inf for y > 0
  29. // Pow(+Inf, y) = +0 for y < 0
  30. // Pow(-Inf, y) = Pow(-0, -y)
  31. // Pow(x, y) = NaN for finite x < 0 and finite non-integer y
  32. func Pow(x, y float32) float32 {
  33. switch {
  34. case y == 0 || x == 1:
  35. return 1
  36. case y == 1:
  37. return x
  38. case y == 0.5:
  39. return Sqrt(x)
  40. case y == -0.5:
  41. return 1 / Sqrt(x)
  42. case IsNaN(x) || IsNaN(y):
  43. return NaN()
  44. case x == 0:
  45. switch {
  46. case y < 0:
  47. if isOddInt(y) {
  48. return Copysign(Inf(1), x)
  49. }
  50. return Inf(1)
  51. case y > 0:
  52. if isOddInt(y) {
  53. return x
  54. }
  55. return 0
  56. }
  57. case IsInf(y, 0):
  58. switch {
  59. case x == -1:
  60. return 1
  61. case (Abs(x) < 1) == IsInf(y, 1):
  62. return 0
  63. default:
  64. return Inf(1)
  65. }
  66. case IsInf(x, 0):
  67. if IsInf(x, -1) {
  68. return Pow(1/x, -y) // Pow(-0, -y)
  69. }
  70. switch {
  71. case y < 0:
  72. return 0
  73. case y > 0:
  74. return Inf(1)
  75. }
  76. }
  77. absy := y
  78. flip := false
  79. if absy < 0 {
  80. absy = -absy
  81. flip = true
  82. }
  83. yi, yf := Modf(absy)
  84. if yf != 0 && x < 0 {
  85. return NaN()
  86. }
  87. if yi >= 1<<31 {
  88. return Exp(y * Log(x))
  89. }
  90. // ans = a1 * 2**ae (= 1 for now).
  91. a1 := float32(1.0)
  92. ae := 0
  93. // ans *= x**yf
  94. if yf != 0 {
  95. if yf > 0.5 {
  96. yf--
  97. yi++
  98. }
  99. a1 = Exp(yf * Log(x))
  100. }
  101. // ans *= x**yi
  102. // by multiplying in successive squarings
  103. // of x according to bits of yi.
  104. // accumulate powers of two into exp.
  105. x1, xe := Frexp(x)
  106. for i := int32(yi); i != 0; i >>= 1 {
  107. if i&1 == 1 {
  108. a1 *= x1
  109. ae += xe
  110. }
  111. x1 *= x1
  112. xe <<= 1
  113. if x1 < .5 {
  114. x1 += x1
  115. xe--
  116. }
  117. }
  118. // ans = a1*2**ae
  119. // if flip { ans = 1 / ans }
  120. // but in the opposite order
  121. if flip {
  122. a1 = 1 / a1
  123. ae = -ae
  124. }
  125. return Ldexp(a1, ae)
  126. }
  127. func Pow10(e int) float32 {
  128. return float32(math.Pow10(e))
  129. }