sqrt.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright 2017 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 big
  5. import (
  6. "math"
  7. "sync"
  8. )
  9. var threeOnce struct {
  10. sync.Once
  11. v *Float
  12. }
  13. func three() *Float {
  14. threeOnce.Do(func() {
  15. threeOnce.v = NewFloat(3.0)
  16. })
  17. return threeOnce.v
  18. }
  19. // Sqrt sets z to the rounded square root of x, and returns it.
  20. //
  21. // If z's precision is 0, it is changed to x's precision before the
  22. // operation. Rounding is performed according to z's precision and
  23. // rounding mode, but z's accuracy is not computed. Specifically, the
  24. // result of z.Acc() is undefined.
  25. //
  26. // The function panics if z < 0. The value of z is undefined in that
  27. // case.
  28. func (z *Float) Sqrt(x *Float) *Float {
  29. if debugFloat {
  30. x.validate()
  31. }
  32. if z.prec == 0 {
  33. z.prec = x.prec
  34. }
  35. if x.Sign() == -1 {
  36. // following IEEE754-2008 (section 7.2)
  37. panic(ErrNaN{"square root of negative operand"})
  38. }
  39. // handle ±0 and +∞
  40. if x.form != finite {
  41. z.acc = Exact
  42. z.form = x.form
  43. z.neg = x.neg // IEEE754-2008 requires √±0 = ±0
  44. return z
  45. }
  46. // MantExp sets the argument's precision to the receiver's, and
  47. // when z.prec > x.prec this will lower z.prec. Restore it after
  48. // the MantExp call.
  49. prec := z.prec
  50. b := x.MantExp(z)
  51. z.prec = prec
  52. // Compute √(z·2**b) as
  53. // √( z)·2**(½b) if b is even
  54. // √(2z)·2**(⌊½b⌋) if b > 0 is odd
  55. // √(½z)·2**(⌈½b⌉) if b < 0 is odd
  56. switch b % 2 {
  57. case 0:
  58. // nothing to do
  59. case 1:
  60. z.exp++
  61. case -1:
  62. z.exp--
  63. }
  64. // 0.25 <= z < 2.0
  65. // Solving 1/x² - z = 0 avoids Quo calls and is faster, especially
  66. // for high precisions.
  67. z.sqrtInverse(z)
  68. // re-attach halved exponent
  69. return z.SetMantExp(z, b/2)
  70. }
  71. // Compute √x (to z.prec precision) by solving
  72. // 1/t² - x = 0
  73. // for t (using Newton's method), and then inverting.
  74. func (z *Float) sqrtInverse(x *Float) {
  75. // let
  76. // f(t) = 1/t² - x
  77. // then
  78. // g(t) = f(t)/f'(t) = -½t(1 - xt²)
  79. // and the next guess is given by
  80. // t2 = t - g(t) = ½t(3 - xt²)
  81. u := newFloat(z.prec)
  82. v := newFloat(z.prec)
  83. three := three()
  84. ng := func(t *Float) *Float {
  85. u.prec = t.prec
  86. v.prec = t.prec
  87. u.Mul(t, t) // u = t²
  88. u.Mul(x, u) // = xt²
  89. v.Sub(three, u) // v = 3 - xt²
  90. u.Mul(t, v) // u = t(3 - xt²)
  91. u.exp-- // = ½t(3 - xt²)
  92. return t.Set(u)
  93. }
  94. xf, _ := x.Float64()
  95. sqi := newFloat(z.prec)
  96. sqi.SetFloat64(1 / math.Sqrt(xf))
  97. for prec := z.prec + 32; sqi.prec < prec; {
  98. sqi.prec *= 2
  99. sqi = ng(sqi)
  100. }
  101. // sqi = 1/√x
  102. // x/√x = √x
  103. z.Mul(x, sqi)
  104. }
  105. // newFloat returns a new *Float with space for twice the given
  106. // precision.
  107. func newFloat(prec2 uint32) *Float {
  108. z := new(Float)
  109. // nat.make ensures the slice length is > 0
  110. z.mant = z.mant.make(int(prec2/_W) * 2)
  111. return z
  112. }