|  | // Copyright 2017 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package big | 
|  |  | 
|  | import ( | 
|  | "math" | 
|  | "sync" | 
|  | ) | 
|  |  | 
|  | var threeOnce struct { | 
|  | sync.Once | 
|  | v *Float | 
|  | } | 
|  |  | 
|  | func three() *Float { | 
|  | threeOnce.Do(func() { | 
|  | threeOnce.v = NewFloat(3.0) | 
|  | }) | 
|  | return threeOnce.v | 
|  | } | 
|  |  | 
|  | // Sqrt sets z to the rounded square root of x, and returns it. | 
|  | // | 
|  | // If z's precision is 0, it is changed to x's precision before the | 
|  | // operation. Rounding is performed according to z's precision and | 
|  | // rounding mode, but z's accuracy is not computed. Specifically, the | 
|  | // result of z.Acc() is undefined. | 
|  | // | 
|  | // The function panics if z < 0. The value of z is undefined in that | 
|  | // case. | 
|  | func (z *Float) Sqrt(x *Float) *Float { | 
|  | if debugFloat { | 
|  | x.validate() | 
|  | } | 
|  |  | 
|  | if z.prec == 0 { | 
|  | z.prec = x.prec | 
|  | } | 
|  |  | 
|  | if x.Sign() == -1 { | 
|  | // following IEEE754-2008 (section 7.2) | 
|  | panic(ErrNaN{"square root of negative operand"}) | 
|  | } | 
|  |  | 
|  | // handle ±0 and +∞ | 
|  | if x.form != finite { | 
|  | z.acc = Exact | 
|  | z.form = x.form | 
|  | z.neg = x.neg // IEEE754-2008 requires √±0 = ±0 | 
|  | return z | 
|  | } | 
|  |  | 
|  | // MantExp sets the argument's precision to the receiver's, and | 
|  | // when z.prec > x.prec this will lower z.prec. Restore it after | 
|  | // the MantExp call. | 
|  | prec := z.prec | 
|  | b := x.MantExp(z) | 
|  | z.prec = prec | 
|  |  | 
|  | // Compute √(z·2**b) as | 
|  | //   √( z)·2**(½b)     if b is even | 
|  | //   √(2z)·2**(⌊½b⌋)   if b > 0 is odd | 
|  | //   √(½z)·2**(⌈½b⌉)   if b < 0 is odd | 
|  | switch b % 2 { | 
|  | case 0: | 
|  | // nothing to do | 
|  | case 1: | 
|  | z.exp++ | 
|  | case -1: | 
|  | z.exp-- | 
|  | } | 
|  | // 0.25 <= z < 2.0 | 
|  |  | 
|  | // Solving 1/x² - z = 0 avoids Quo calls and is faster, especially | 
|  | // for high precisions. | 
|  | z.sqrtInverse(z) | 
|  |  | 
|  | // re-attach halved exponent | 
|  | return z.SetMantExp(z, b/2) | 
|  | } | 
|  |  | 
|  | // Compute √x (to z.prec precision) by solving | 
|  | // | 
|  | //	1/t² - x = 0 | 
|  | // | 
|  | // for t (using Newton's method), and then inverting. | 
|  | func (z *Float) sqrtInverse(x *Float) { | 
|  | // let | 
|  | //   f(t) = 1/t² - x | 
|  | // then | 
|  | //   g(t) = f(t)/f'(t) = -½t(1 - xt²) | 
|  | // and the next guess is given by | 
|  | //   t2 = t - g(t) = ½t(3 - xt²) | 
|  | u := newFloat(z.prec) | 
|  | v := newFloat(z.prec) | 
|  | three := three() | 
|  | ng := func(t *Float) *Float { | 
|  | u.prec = t.prec | 
|  | v.prec = t.prec | 
|  | u.Mul(t, t)     // u = t² | 
|  | u.Mul(x, u)     //   = xt² | 
|  | v.Sub(three, u) // v = 3 - xt² | 
|  | u.Mul(t, v)     // u = t(3 - xt²) | 
|  | u.exp--         //   = ½t(3 - xt²) | 
|  | return t.Set(u) | 
|  | } | 
|  |  | 
|  | xf, _ := x.Float64() | 
|  | sqi := newFloat(z.prec) | 
|  | sqi.SetFloat64(1 / math.Sqrt(xf)) | 
|  | for prec := z.prec + 32; sqi.prec < prec; { | 
|  | sqi.prec *= 2 | 
|  | sqi = ng(sqi) | 
|  | } | 
|  | // sqi = 1/√x | 
|  |  | 
|  | // x/√x = √x | 
|  | z.Mul(x, sqi) | 
|  | } | 
|  |  | 
|  | // newFloat returns a new *Float with space for twice the given | 
|  | // precision. | 
|  | func newFloat(prec2 uint32) *Float { | 
|  | z := new(Float) | 
|  | // nat.make ensures the slice length is > 0 | 
|  | z.mant = z.mant.make(int(prec2/_W) * 2) | 
|  | return z | 
|  | } |