Source file
src/math/big/arith.go
1
2
3
4
5
6
7
8
9 package big
10
11 import "math/bits"
12
13
14 type Word uint
15
16 const (
17 _S = _W / 8
18
19 _W = bits.UintSize
20 _B = 1 << _W
21 _M = _B - 1
22
23 _W2 = _W / 2
24 _B2 = 1 << _W2
25 _M2 = _B2 - 1
26 )
27
28
29
30
31
32
33
34 func addWW_g(x, y, c Word) (z1, z0 Word) {
35 yc := y + c
36 z0 = x + yc
37 if z0 < x || yc < y {
38 z1 = 1
39 }
40 return
41 }
42
43
44 func subWW_g(x, y, c Word) (z1, z0 Word) {
45 yc := y + c
46 z0 = x - yc
47 if z0 > x || yc < y {
48 z1 = 1
49 }
50 return
51 }
52
53
54
55 func mulWW_g(x, y Word) (z1, z0 Word) {
56 x0 := x & _M2
57 x1 := x >> _W2
58 y0 := y & _M2
59 y1 := y >> _W2
60 w0 := x0 * y0
61 t := x1*y0 + w0>>_W2
62 w1 := t & _M2
63 w2 := t >> _W2
64 w1 += x0 * y1
65 z1 = x1*y1 + w2 + w1>>_W2
66 z0 = x * y
67 return
68 }
69
70
71 func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
72 z1, zz0 := mulWW_g(x, y)
73 if z0 = zz0 + c; z0 < zz0 {
74 z1++
75 }
76 return
77 }
78
79
80
81 func nlz(x Word) uint {
82 return uint(bits.LeadingZeros(uint(x)))
83 }
84
85
86
87 func divWW_g(u1, u0, v Word) (q, r Word) {
88 if u1 >= v {
89 return 1<<_W - 1, 1<<_W - 1
90 }
91
92 s := nlz(v)
93 v <<= s
94
95 vn1 := v >> _W2
96 vn0 := v & _M2
97 un32 := u1<<s | u0>>(_W-s)
98 un10 := u0 << s
99 un1 := un10 >> _W2
100 un0 := un10 & _M2
101 q1 := un32 / vn1
102 rhat := un32 - q1*vn1
103
104 for q1 >= _B2 || q1*vn0 > _B2*rhat+un1 {
105 q1--
106 rhat += vn1
107 if rhat >= _B2 {
108 break
109 }
110 }
111
112 un21 := un32*_B2 + un1 - q1*v
113 q0 := un21 / vn1
114 rhat = un21 - q0*vn1
115
116 for q0 >= _B2 || q0*vn0 > _B2*rhat+un0 {
117 q0--
118 rhat += vn1
119 if rhat >= _B2 {
120 break
121 }
122 }
123
124 return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s
125 }
126
127
128
129 const use_addWW_g = false
130
131
132 func addVV_g(z, x, y []Word) (c Word) {
133 if use_addWW_g {
134 for i := range z {
135 c, z[i] = addWW_g(x[i], y[i], c)
136 }
137 return
138 }
139
140 for i, xi := range x[:len(z)] {
141 yi := y[i]
142 zi := xi + yi + c
143 z[i] = zi
144
145 c = (xi&yi | (xi|yi)&^zi) >> (_W - 1)
146 }
147 return
148 }
149
150
151 func subVV_g(z, x, y []Word) (c Word) {
152 if use_addWW_g {
153 for i := range z {
154 c, z[i] = subWW_g(x[i], y[i], c)
155 }
156 return
157 }
158
159 for i, xi := range x[:len(z)] {
160 yi := y[i]
161 zi := xi - yi - c
162 z[i] = zi
163
164 c = (yi&^xi | (yi|^xi)&zi) >> (_W - 1)
165 }
166 return
167 }
168
169
170 func addVW_g(z, x []Word, y Word) (c Word) {
171 if use_addWW_g {
172 c = y
173 for i := range z {
174 c, z[i] = addWW_g(x[i], c, 0)
175 }
176 return
177 }
178
179 c = y
180 for i, xi := range x[:len(z)] {
181 zi := xi + c
182 z[i] = zi
183 c = xi &^ zi >> (_W - 1)
184 }
185 return
186 }
187
188 func subVW_g(z, x []Word, y Word) (c Word) {
189 if use_addWW_g {
190 c = y
191 for i := range z {
192 c, z[i] = subWW_g(x[i], c, 0)
193 }
194 return
195 }
196
197 c = y
198 for i, xi := range x[:len(z)] {
199 zi := xi - c
200 z[i] = zi
201 c = (zi &^ xi) >> (_W - 1)
202 }
203 return
204 }
205
206 func shlVU_g(z, x []Word, s uint) (c Word) {
207 if n := len(z); n > 0 {
208 ŝ := _W - s
209 w1 := x[n-1]
210 c = w1 >> ŝ
211 for i := n - 1; i > 0; i-- {
212 w := w1
213 w1 = x[i-1]
214 z[i] = w<<s | w1>>ŝ
215 }
216 z[0] = w1 << s
217 }
218 return
219 }
220
221 func shrVU_g(z, x []Word, s uint) (c Word) {
222 if n := len(z); n > 0 {
223 ŝ := _W - s
224 w1 := x[0]
225 c = w1 << ŝ
226 for i := 0; i < n-1; i++ {
227 w := w1
228 w1 = x[i+1]
229 z[i] = w>>s | w1<<ŝ
230 }
231 z[n-1] = w1 >> s
232 }
233 return
234 }
235
236 func mulAddVWW_g(z, x []Word, y, r Word) (c Word) {
237 c = r
238 for i := range z {
239 c, z[i] = mulAddWWW_g(x[i], y, c)
240 }
241 return
242 }
243
244
245 func addMulVVW_g(z, x []Word, y Word) (c Word) {
246 for i := range z {
247 z1, z0 := mulAddWWW_g(x[i], y, z[i])
248 c, z[i] = addWW_g(z0, c, 0)
249 c += z1
250 }
251 return
252 }
253
254 func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) {
255 r = xn
256 for i := len(z) - 1; i >= 0; i-- {
257 z[i], r = divWW_g(r, x[i], y)
258 }
259 return
260 }
261
View as plain text