Source file
src/math/big/sqrt.go
1
2
3
4
5 package big
6
7 import (
8 "math"
9 "sync"
10 )
11
12 var threeOnce struct {
13 sync.Once
14 v *Float
15 }
16
17 func three() *Float {
18 threeOnce.Do(func() {
19 threeOnce.v = NewFloat(3.0)
20 })
21 return threeOnce.v
22 }
23
24
25
26
27
28
29
30
31
32
33 func (z *Float) Sqrt(x *Float) *Float {
34 if debugFloat {
35 x.validate()
36 }
37
38 if z.prec == 0 {
39 z.prec = x.prec
40 }
41
42 if x.Sign() == -1 {
43
44 panic(ErrNaN{"square root of negative operand"})
45 }
46
47
48 if x.form != finite {
49 z.acc = Exact
50 z.form = x.form
51 z.neg = x.neg
52 return z
53 }
54
55
56
57
58 prec := z.prec
59 b := x.MantExp(z)
60 z.prec = prec
61
62
63
64
65
66 switch b % 2 {
67 case 0:
68
69 case 1:
70 z.exp++
71 case -1:
72 z.exp--
73 }
74
75
76
77
78 z.sqrtInverse(z)
79
80
81 return z.SetMantExp(z, b/2)
82 }
83
84
85
86
87
88
89 func (z *Float) sqrtInverse(x *Float) {
90
91
92
93
94
95
96 u := newFloat(z.prec)
97 v := newFloat(z.prec)
98 three := three()
99 ng := func(t *Float) *Float {
100 u.prec = t.prec
101 v.prec = t.prec
102 u.Mul(t, t)
103 u.Mul(x, u)
104 v.Sub(three, u)
105 u.Mul(t, v)
106 u.exp--
107 return t.Set(u)
108 }
109
110 xf, _ := x.Float64()
111 sqi := newFloat(z.prec)
112 sqi.SetFloat64(1 / math.Sqrt(xf))
113 for prec := z.prec + 32; sqi.prec < prec; {
114 sqi.prec *= 2
115 sqi = ng(sqi)
116 }
117
118
119
120 z.Mul(x, sqi)
121 }
122
123
124
125 func newFloat(prec2 uint32) *Float {
126 z := new(Float)
127
128 z.mant = z.mant.make(int(prec2/_W) * 2)
129 return z
130 }
131
View as plain text