pow.go 2.6 KB

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