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