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 func (z *Float) sqrtInverse(x *Float) {
88
89
90
91
92
93
94 u := newFloat(z.prec)
95 v := newFloat(z.prec)
96 three := three()
97 ng := func(t *Float) *Float {
98 u.prec = t.prec
99 v.prec = t.prec
100 u.Mul(t, t)
101 u.Mul(x, u)
102 v.Sub(three, u)
103 u.Mul(t, v)
104 u.exp--
105 return t.Set(u)
106 }
107
108 xf, _ := x.Float64()
109 sqi := newFloat(z.prec)
110 sqi.SetFloat64(1 / math.Sqrt(xf))
111 for prec := z.prec + 32; sqi.prec < prec; {
112 sqi.prec *= 2
113 sqi = ng(sqi)
114 }
115
116
117
118 z.Mul(x, sqi)
119 }
120
121
122
123 func newFloat(prec2 uint32) *Float {
124 z := new(Float)
125
126 z.mant = z.mant.make(int(prec2/_W) * 2)
127 return z
128 }
129
View as plain text