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