math_pow.odin 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package math
  2. // pow returns x**y, the base-x exponential of y.
  3. //
  4. // Special cases are (in order):
  5. //
  6. // pow(x, ±0) = 1 for any x
  7. // pow(1, y) = 1 for any y
  8. // pow(x, 1) = x for any x
  9. // pow(NaN, y) = NaN
  10. // pow(x, NaN) = NaN
  11. // pow(±0, y) = ±Inf for y an odd integer < 0
  12. // pow(±0, -Inf) = +Inf
  13. // pow(±0, +Inf) = +0
  14. // pow(±0, y) = +Inf for finite y < 0 and not an odd integer
  15. // pow(±0, y) = ±0 for y an odd integer > 0
  16. // pow(±0, y) = +0 for finite y > 0 and not an odd integer
  17. // pow(-1, ±Inf) = 1
  18. // pow(x, +Inf) = +Inf for |x| > 1
  19. // pow(x, -Inf) = +0 for |x| > 1
  20. // pow(x, +Inf) = +0 for |x| < 1
  21. // pow(x, -Inf) = +Inf for |x| < 1
  22. // pow(+Inf, y) = +Inf for y > 0
  23. // pow(+Inf, y) = +0 for y < 0
  24. // pow(-Inf, y) = pow(-0, -y)
  25. // pow(x, y) = NaN for finite x < 0 and finite non-integer y
  26. //
  27. // Special cases taken from FreeBSD's /usr/src/lib/msun/src/e_pow.c
  28. // updated by IEEE Std. 754-2008 "Section 9.2.1 Special values".
  29. @(require_results)
  30. pow_f64 :: proc "contextless" (x, y: f64) -> f64 {
  31. is_odd_int :: proc "contextless" (x: f64) -> bool {
  32. if abs(x) >= (1<<53) {
  33. return false
  34. }
  35. i, f := modf(x)
  36. return f == 0 && (i64(i)&1 == 1)
  37. }
  38. switch {
  39. case y == 0 || x == 1:
  40. return 1.0
  41. case y == 1:
  42. return x
  43. case is_nan(x) || is_nan(y):
  44. return nan_f64()
  45. case x == 0:
  46. switch {
  47. case y < 0:
  48. if signbit(x) && is_odd_int(y) {
  49. return inf_f64(-1)
  50. }
  51. return inf_f64(1)
  52. case y > 0:
  53. if signbit(x) && is_odd_int(y) {
  54. return x
  55. }
  56. return 0.0
  57. }
  58. case is_inf(y, 0):
  59. switch {
  60. case x == -1:
  61. return 1.0
  62. case (abs(x) < 1) == is_inf(y, 1):
  63. return 0.0
  64. case:
  65. return inf_f64(1)
  66. }
  67. case is_inf(x, 0):
  68. if is_inf(x, -1) {
  69. // pow(-0, -y)
  70. return pow_f64(1.0/x, -y)
  71. }
  72. switch {
  73. case y < 0:
  74. return 0.0
  75. case y > 0:
  76. return inf_f64(1)
  77. }
  78. case y == 0.5:
  79. return sqrt_f64(x)
  80. case y == -0.5:
  81. return 1.0 / sqrt_f64(x)
  82. }
  83. yi, yf := modf(abs(y))
  84. if yf != 0 && x < 0 {
  85. return nan_f64()
  86. }
  87. if yi >= 1<<63 {
  88. // yi is a large even int that will lead to overflow (or underflow to 0)
  89. // for all x except -1 (x == 1 was handled earlier)
  90. switch {
  91. case x == -1:
  92. return 1.0
  93. case (abs(x) < 1) == (y > 0):
  94. return 0.0
  95. case:
  96. return inf_f64(1)
  97. }
  98. }
  99. // ans = a1 * 2**ae (= 1 for now).
  100. a1: f64 = 1
  101. ae: int = 0
  102. // ans *= x**yf
  103. if yf != 0 {
  104. if yf > 0.5 {
  105. yf -= 1
  106. yi += 1
  107. }
  108. a1 = exp(yf * ln(x))
  109. }
  110. // ans *= x**yi
  111. // by multiplying in successive squarings
  112. // of x according to bits of yi.
  113. // accumulate powers of two into exp.
  114. x1, xe := frexp(x)
  115. for i := i64(yi); i != 0; i >>= 1 {
  116. if xe < -1<<12 || 1<<12 < xe {
  117. // catch xe before it overflows the left shift below
  118. // Since i !=0 it has at least one bit still set, so ae will accumulate xe
  119. // on at least one more iteration, ae += xe is a lower bound on ae
  120. // the lower bound on ae exceeds the size of a f64 exp
  121. // so the final call to ldexp will produce under/overflow (0/Inf)
  122. ae += xe
  123. break
  124. }
  125. if i&1 == 1 {
  126. a1 *= x1
  127. ae += xe
  128. }
  129. x1 *= x1
  130. xe <<= 1
  131. if x1 < .5 {
  132. x1 += x1
  133. xe -= 1
  134. }
  135. }
  136. // ans = a1*2**ae
  137. // if y < 0 { ans = 1 / ans }
  138. // but in the opposite order
  139. if y < 0 {
  140. a1 = 1 / a1
  141. ae = -ae
  142. }
  143. return ldexp(a1, ae)
  144. }
  145. @(require_results) pow_f16 :: proc "contextless" (x, power: f16) -> f16 { return f16(pow_f64(f64(x), f64(power))) }
  146. @(require_results) pow_f32 :: proc "contextless" (x, power: f32) -> f32 { return f32(pow_f64(f64(x), f64(power))) }
  147. exp_f64 :: proc "contextless" (x: f64) -> f64 {
  148. LN2_HI :: 6.93147180369123816490e-01
  149. LN2_LO :: 1.90821492927058770002e-10
  150. LOG2_E :: 1.44269504088896338700e+00
  151. OVERFLOW :: 7.09782712893383973096e+02
  152. UNDERFLOW :: -7.45133219101941108420e+02
  153. NEAR_ZERO :: 1.0 / (1 << 28) // 2**-28
  154. // special cases
  155. switch {
  156. case is_nan(x) || is_inf(x, 1):
  157. return x
  158. case is_inf(x, -1):
  159. return 0
  160. case x > OVERFLOW:
  161. return inf_f64(1)
  162. case x < UNDERFLOW:
  163. return 0
  164. case -NEAR_ZERO < x && x < NEAR_ZERO:
  165. return 1 + x
  166. }
  167. // reduce; computed as r = hi - lo for extra precision.
  168. k: int
  169. switch {
  170. case x < 0:
  171. k = int(LOG2_E*x - 0.5)
  172. case x > 0:
  173. k = int(LOG2_E*x + 0.5)
  174. }
  175. hi := x - f64(k)*LN2_HI
  176. lo := f64(k) * LN2_LO
  177. P1 :: 0h3FC5555555555555 // 1.66666666666666657415e-01
  178. P2 :: 0hBF66C16C16BEBD93 // -2.77777777770155933842e-03
  179. P3 :: 0h3F11566AAF25DE2C // 6.61375632143793436117e-05
  180. P4 :: 0hBEBBBD41C5D26BF1 // -1.65339022054652515390e-06
  181. P5 :: 0h3E66376972BEA4D0 // 4.13813679705723846039e-08
  182. r := hi - lo
  183. t := r * r
  184. c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
  185. y := 1 - ((lo - (r*c)/(2-c)) - hi)
  186. return ldexp(y, k)
  187. }
  188. @(require_results) exp_f16 :: proc "contextless" (x: f16) -> f16 { return f16(exp_f64(f64(x))) }
  189. @(require_results) exp_f32 :: proc "contextless" (x: f32) -> f32 { return f32(exp_f64(f64(x))) }