Source file
src/math/big/arith.go
1
2
3
4
5
6
7
8
9
10
11 package big
12
13 import (
14 "math/bits"
15 _ "unsafe"
16 )
17
18
19 type Word uint
20
21 const (
22 _S = _W / 8
23
24 _W = bits.UintSize
25 _B = 1 << _W
26 _M = _B - 1
27 )
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 func mulWW(x, y Word) (z1, z0 Word) {
44 hi, lo := bits.Mul(uint(x), uint(y))
45 return Word(hi), Word(lo)
46 }
47
48
49 func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
50 hi, lo := bits.Mul(uint(x), uint(y))
51 var cc uint
52 lo, cc = bits.Add(lo, uint(c), 0)
53 return Word(hi + cc), Word(lo)
54 }
55
56
57
58 func nlz(x Word) uint {
59 return uint(bits.LeadingZeros(uint(x)))
60 }
61
62
63 func addVV_g(z, x, y []Word) (c Word) {
64 if len(x) != len(z) || len(y) != len(z) {
65 panic("addVV len")
66 }
67
68 for i := range z {
69 zi, cc := bits.Add(uint(x[i]), uint(y[i]), uint(c))
70 z[i] = Word(zi)
71 c = Word(cc)
72 }
73 return
74 }
75
76
77 func subVV_g(z, x, y []Word) (c Word) {
78 if len(x) != len(z) || len(y) != len(z) {
79 panic("subVV len")
80 }
81
82 for i := range z {
83 zi, cc := bits.Sub(uint(x[i]), uint(y[i]), uint(c))
84 z[i] = Word(zi)
85 c = Word(cc)
86 }
87 return
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 func addVW(z, x []Word, y Word) (c Word) {
104 if len(x) != len(z) {
105 panic("addVW len")
106 }
107
108 if len(z) == 0 {
109 return y
110 }
111 zi, cc := bits.Add(uint(x[0]), uint(y), 0)
112 z[0] = Word(zi)
113 if cc == 0 {
114 if &z[0] != &x[0] {
115 copy(z[1:], x[1:])
116 }
117 return 0
118 }
119 for i := 1; i < len(z); i++ {
120 xi := x[i]
121 if xi != ^Word(0) {
122 z[i] = xi + 1
123 if &z[0] != &x[0] {
124 copy(z[i+1:], x[i+1:])
125 }
126 return 0
127 }
128 z[i] = 0
129 }
130 return 1
131 }
132
133
134 func addVW_ref(z, x []Word, y Word) (c Word) {
135 c = y
136 for i := range z {
137 zi, cc := bits.Add(uint(x[i]), uint(c), 0)
138 z[i] = Word(zi)
139 c = Word(cc)
140 }
141 return
142 }
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 func subVW(z, x []Word, y Word) (c Word) {
158 if len(x) != len(z) {
159 panic("subVW len")
160 }
161
162 if len(z) == 0 {
163 return y
164 }
165 zi, cc := bits.Sub(uint(x[0]), uint(y), 0)
166 z[0] = Word(zi)
167 if cc == 0 {
168 if &z[0] != &x[0] {
169 copy(z[1:], x[1:])
170 }
171 return 0
172 }
173 for i := 1; i < len(z); i++ {
174 xi := x[i]
175 if xi != 0 {
176 z[i] = xi - 1
177 if &z[0] != &x[0] {
178 copy(z[i+1:], x[i+1:])
179 }
180 return 0
181 }
182 z[i] = ^Word(0)
183 }
184 return 1
185 }
186
187
188 func subVW_ref(z, x []Word, y Word) (c Word) {
189 c = y
190 for i := range z {
191 zi, cc := bits.Sub(uint(x[i]), uint(c), 0)
192 z[i] = Word(zi)
193 c = Word(cc)
194 }
195 return c
196 }
197
198 func lshVU_g(z, x []Word, s uint) (c Word) {
199 if len(x) != len(z) {
200 panic("lshVU len")
201 }
202
203 if s == 0 {
204 copy(z, x)
205 return
206 }
207 if len(z) == 0 {
208 return
209 }
210 s &= _W - 1
211 ŝ := _W - s
212 ŝ &= _W - 1
213 c = x[len(z)-1] >> ŝ
214 for i := len(z) - 1; i > 0; i-- {
215 z[i] = x[i]<<s | x[i-1]>>ŝ
216 }
217 z[0] = x[0] << s
218 return
219 }
220
221 func rshVU_g(z, x []Word, s uint) (c Word) {
222 if len(x) != len(z) {
223 panic("rshVU len")
224 }
225
226 if s == 0 {
227 copy(z, x)
228 return
229 }
230 if len(z) == 0 {
231 return
232 }
233 s &= _W - 1
234 ŝ := _W - s
235 ŝ &= _W - 1
236 c = x[0] << ŝ
237 for i := 1; i < len(z); i++ {
238 z[i-1] = x[i-1]>>s | x[i]<<ŝ
239 }
240 z[len(z)-1] = x[len(z)-1] >> s
241 return
242 }
243
244 func mulAddVWW_g(z, x []Word, y, r Word) (c Word) {
245 if len(x) != len(z) {
246 panic("mulAddVWW len")
247 }
248 c = r
249 for i := range z {
250 c, z[i] = mulAddWWW_g(x[i], y, c)
251 }
252 return
253 }
254
255 func addMulVVWW_g(z, x, y []Word, m, a Word) (c Word) {
256 if len(x) != len(z) || len(y) != len(z) {
257 panic("rshVU len")
258 }
259
260 c = a
261 for i := range z {
262 z1, z0 := mulAddWWW_g(y[i], m, x[i])
263 lo, cc := bits.Add(uint(z0), uint(c), 0)
264 c, z[i] = Word(cc), Word(lo)
265 c += z1
266 }
267 return
268 }
269
270
271
272
273 func divWW(x1, x0, y, m Word) (q, r Word) {
274 s := nlz(y)
275 if s != 0 {
276 x1 = x1<<s | x0>>(_W-s)
277 x0 <<= s
278 y <<= s
279 }
280 d := uint(y)
281
282
283
284
285
286
287
288
289
290
291
292
293 t1, t0 := bits.Mul(uint(m), uint(x1))
294 _, c := bits.Add(t0, uint(x0), 0)
295 t1, _ = bits.Add(t1, uint(x1), c)
296
297
298 qq := t1
299
300 dq1, dq0 := bits.Mul(d, qq)
301 r0, b := bits.Sub(uint(x0), dq0, 0)
302 r1, _ := bits.Sub(uint(x1), dq1, b)
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320 if r1 != 0 {
321 qq++
322 r0 -= d
323 }
324
325 if r0 >= d {
326 qq++
327 r0 -= d
328 }
329 return Word(qq), Word(r0 >> s)
330 }
331
332
333 func reciprocalWord(d1 Word) Word {
334 u := uint(d1 << nlz(d1))
335 x1 := ^u
336 x0 := uint(_M)
337 rec, _ := bits.Div(x1, x0, u)
338 return Word(rec)
339 }
340
View as plain text