mod.gno
14.52 Kb · 608 lines
1package uint256
2
3import (
4 "math/bits"
5)
6
7// Reciprocal computes the 320-bit reciprocal estimate used by Barrett reduction.
8//
9// The implementation is specialized for a four-word modulus with m[3] non-zero
10// (2^192 <= m < 2^256). For a modulus whose most-significant word is zero it
11// returns an all-zero estimate instead of running the refinement steps.
12//
13// Parameters:
14// - m: Four-word unsigned modulus; its most-significant word selects the supported range.
15//
16// Returns:
17// - mu: Five little-endian uint64 words containing the reciprocal estimate for m.
18func Reciprocal(m *Uint) (mu [5]uint64) {
19 if m[3] == 0 {
20 return mu
21 }
22
23 s := bits.LeadingZeros64(m[3]) // Replace with leadingZeros(m) for general case
24 p := 255 - s // floor(log_2(m)), m>0
25
26 // 0 or a power of 2?
27
28 // Check if at least one bit is set in m[2], m[1] or m[0],
29 // or at least two bits in m[3]
30
31 if m[0]|m[1]|m[2]|(m[3]&(m[3]-1)) == 0 {
32
33 mu[4] = 18446744073709551615 >> uint(p&63)
34 mu[3] = 18446744073709551615
35 mu[2] = 18446744073709551615
36 mu[1] = 18446744073709551615
37 mu[0] = 18446744073709551615
38
39 return mu
40 }
41
42 // Maximise division precision by left-aligning divisor
43
44 var (
45 y Uint // left-aligned copy of m
46 r0 uint32 // estimate of 2^31/y
47 )
48
49 y.Lsh(m, uint(s)) // 1/2 < y < 1
50
51 // Extract most significant 32 bits
52
53 yh := uint32(y[3] >> 32)
54
55 if yh == 0x80000000 { // Avoid overflow in division
56 r0 = 0xffffffff
57 } else {
58 r0, _ = bits.Div32(0x80000000, 0, yh)
59 }
60
61 // First iteration: 32 -> 64
62
63 t1 := uint64(r0) // 2^31/y
64 t1 *= t1 // 2^62/y^2
65 t1, _ = bits.Mul64(t1, y[3]) // 2^62/y^2 * 2^64/y / 2^64 = 2^62/y
66
67 r1 := uint64(r0) << 32 // 2^63/y
68 r1 -= t1 // 2^63/y - 2^62/y = 2^62/y
69 r1 *= 2 // 2^63/y
70
71 if (r1 | (y[3] << 1)) == 0 {
72 r1 = 18446744073709551615
73 }
74
75 // Second iteration: 64 -> 128
76
77 // square: 2^126/y^2
78 a2h, a2l := bits.Mul64(r1, r1)
79
80 // multiply by y: e2h:e2l:b2h = 2^126/y^2 * 2^128/y / 2^128 = 2^126/y
81 b2h, _ := bits.Mul64(a2l, y[2])
82 c2h, c2l := bits.Mul64(a2l, y[3])
83 d2h, d2l := bits.Mul64(a2h, y[2])
84 e2h, e2l := bits.Mul64(a2h, y[3])
85
86 b2h, c := bits.Add64(b2h, c2l, 0)
87 e2l, c = bits.Add64(e2l, c2h, c)
88 e2h, _ = bits.Add64(e2h, 0, c)
89
90 _, c = bits.Add64(b2h, d2l, 0)
91 e2l, c = bits.Add64(e2l, d2h, c)
92 e2h, _ = bits.Add64(e2h, 0, c)
93
94 // subtract: t2h:t2l = 2^127/y - 2^126/y = 2^126/y
95 t2l, b := bits.Sub64(0, e2l, 0)
96 t2h, _ := bits.Sub64(r1, e2h, b)
97
98 // double: r2h:r2l = 2^127/y
99 r2l, c := bits.Add64(t2l, t2l, 0)
100 r2h, _ := bits.Add64(t2h, t2h, c)
101
102 if (r2h | r2l | (y[3] << 1)) == 0 {
103 r2h = 18446744073709551615
104 r2l = 18446744073709551615
105 }
106
107 // Third iteration: 128 -> 192
108
109 // square r2 (keep 256 bits): 2^190/y^2
110 a3h, a3l := bits.Mul64(r2l, r2l)
111 b3h, b3l := bits.Mul64(r2l, r2h)
112 c3h, c3l := bits.Mul64(r2h, r2h)
113
114 a3h, c = bits.Add64(a3h, b3l, 0)
115 c3l, c = bits.Add64(c3l, b3h, c)
116 c3h, _ = bits.Add64(c3h, 0, c)
117
118 a3h, c = bits.Add64(a3h, b3l, 0)
119 c3l, c = bits.Add64(c3l, b3h, c)
120 c3h, _ = bits.Add64(c3h, 0, c)
121
122 // multiply by y: q = 2^190/y^2 * 2^192/y / 2^192 = 2^190/y
123
124 x0 := a3l
125 x1 := a3h
126 x2 := c3l
127 x3 := c3h
128
129 var q0, q1, q2, q3, q4, t0 uint64
130
131 q0, _ = bits.Mul64(x2, y[0])
132 q1, t0 = bits.Mul64(x3, y[0])
133 q0, c = bits.Add64(q0, t0, 0)
134 q1, _ = bits.Add64(q1, 0, c)
135
136 t1, _ = bits.Mul64(x1, y[1])
137 q0, c = bits.Add64(q0, t1, 0)
138 q2, t0 = bits.Mul64(x3, y[1])
139 q1, c = bits.Add64(q1, t0, c)
140 q2, _ = bits.Add64(q2, 0, c)
141
142 t1, t0 = bits.Mul64(x2, y[1])
143 q0, c = bits.Add64(q0, t0, 0)
144 q1, c = bits.Add64(q1, t1, c)
145 q2, _ = bits.Add64(q2, 0, c)
146
147 t1, t0 = bits.Mul64(x1, y[2])
148 q0, c = bits.Add64(q0, t0, 0)
149 q1, c = bits.Add64(q1, t1, c)
150 q3, t0 = bits.Mul64(x3, y[2])
151 q2, c = bits.Add64(q2, t0, c)
152 q3, _ = bits.Add64(q3, 0, c)
153
154 t1, _ = bits.Mul64(x0, y[2])
155 q0, c = bits.Add64(q0, t1, 0)
156 t1, t0 = bits.Mul64(x2, y[2])
157 q1, c = bits.Add64(q1, t0, c)
158 q2, c = bits.Add64(q2, t1, c)
159 q3, _ = bits.Add64(q3, 0, c)
160
161 t1, t0 = bits.Mul64(x1, y[3])
162 q1, c = bits.Add64(q1, t0, 0)
163 q2, c = bits.Add64(q2, t1, c)
164 q4, t0 = bits.Mul64(x3, y[3])
165 q3, c = bits.Add64(q3, t0, c)
166 q4, _ = bits.Add64(q4, 0, c)
167
168 t1, t0 = bits.Mul64(x0, y[3])
169 q0, c = bits.Add64(q0, t0, 0)
170 q1, c = bits.Add64(q1, t1, c)
171 t1, t0 = bits.Mul64(x2, y[3])
172 q2, c = bits.Add64(q2, t0, c)
173 q3, c = bits.Add64(q3, t1, c)
174 q4, _ = bits.Add64(q4, 0, c)
175
176 // subtract: t3 = 2^191/y - 2^190/y = 2^190/y
177 _, b = bits.Sub64(0, q0, 0)
178 _, b = bits.Sub64(0, q1, b)
179 t3l, b := bits.Sub64(0, q2, b)
180 t3m, b := bits.Sub64(r2l, q3, b)
181 t3h, _ := bits.Sub64(r2h, q4, b)
182
183 // double: r3 = 2^191/y
184 r3l, c := bits.Add64(t3l, t3l, 0)
185 r3m, c := bits.Add64(t3m, t3m, c)
186 r3h, _ := bits.Add64(t3h, t3h, c)
187
188 // Fourth iteration: 192 -> 320
189
190 // square r3
191
192 a4h, a4l := bits.Mul64(r3l, r3l)
193 b4h, b4l := bits.Mul64(r3l, r3m)
194 c4h, c4l := bits.Mul64(r3l, r3h)
195 d4h, d4l := bits.Mul64(r3m, r3m)
196 e4h, e4l := bits.Mul64(r3m, r3h)
197 f4h, f4l := bits.Mul64(r3h, r3h)
198
199 b4h, c = bits.Add64(b4h, c4l, 0)
200 e4l, c = bits.Add64(e4l, c4h, c)
201 e4h, _ = bits.Add64(e4h, 0, c)
202
203 a4h, c = bits.Add64(a4h, b4l, 0)
204 d4l, c = bits.Add64(d4l, b4h, c)
205 d4h, c = bits.Add64(d4h, e4l, c)
206 f4l, c = bits.Add64(f4l, e4h, c)
207 f4h, _ = bits.Add64(f4h, 0, c)
208
209 a4h, c = bits.Add64(a4h, b4l, 0)
210 d4l, c = bits.Add64(d4l, b4h, c)
211 d4h, c = bits.Add64(d4h, e4l, c)
212 f4l, c = bits.Add64(f4l, e4h, c)
213 f4h, _ = bits.Add64(f4h, 0, c)
214
215 // multiply by y
216
217 x1, x0 = bits.Mul64(d4h, y[0])
218 x3, x2 = bits.Mul64(f4h, y[0])
219 t1, t0 = bits.Mul64(f4l, y[0])
220 x1, c = bits.Add64(x1, t0, 0)
221 x2, c = bits.Add64(x2, t1, c)
222 x3, _ = bits.Add64(x3, 0, c)
223
224 t1, t0 = bits.Mul64(d4h, y[1])
225 x1, c = bits.Add64(x1, t0, 0)
226 x2, c = bits.Add64(x2, t1, c)
227 x4, t0 := bits.Mul64(f4h, y[1])
228 x3, c = bits.Add64(x3, t0, c)
229 x4, _ = bits.Add64(x4, 0, c)
230 t1, t0 = bits.Mul64(d4l, y[1])
231 x0, c = bits.Add64(x0, t0, 0)
232 x1, c = bits.Add64(x1, t1, c)
233 t1, t0 = bits.Mul64(f4l, y[1])
234 x2, c = bits.Add64(x2, t0, c)
235 x3, c = bits.Add64(x3, t1, c)
236 x4, _ = bits.Add64(x4, 0, c)
237
238 t1, t0 = bits.Mul64(a4h, y[2])
239 x0, c = bits.Add64(x0, t0, 0)
240 x1, c = bits.Add64(x1, t1, c)
241 t1, t0 = bits.Mul64(d4h, y[2])
242 x2, c = bits.Add64(x2, t0, c)
243 x3, c = bits.Add64(x3, t1, c)
244 x5, t0 := bits.Mul64(f4h, y[2])
245 x4, c = bits.Add64(x4, t0, c)
246 x5, _ = bits.Add64(x5, 0, c)
247 t1, t0 = bits.Mul64(d4l, y[2])
248 x1, c = bits.Add64(x1, t0, 0)
249 x2, c = bits.Add64(x2, t1, c)
250 t1, t0 = bits.Mul64(f4l, y[2])
251 x3, c = bits.Add64(x3, t0, c)
252 x4, c = bits.Add64(x4, t1, c)
253 x5, _ = bits.Add64(x5, 0, c)
254
255 t1, t0 = bits.Mul64(a4h, y[3])
256 x1, c = bits.Add64(x1, t0, 0)
257 x2, c = bits.Add64(x2, t1, c)
258 t1, t0 = bits.Mul64(d4h, y[3])
259 x3, c = bits.Add64(x3, t0, c)
260 x4, c = bits.Add64(x4, t1, c)
261 x6, t0 := bits.Mul64(f4h, y[3])
262 x5, c = bits.Add64(x5, t0, c)
263 x6, _ = bits.Add64(x6, 0, c)
264 t1, t0 = bits.Mul64(a4l, y[3])
265 x0, c = bits.Add64(x0, t0, 0)
266 x1, c = bits.Add64(x1, t1, c)
267 t1, t0 = bits.Mul64(d4l, y[3])
268 x2, c = bits.Add64(x2, t0, c)
269 x3, c = bits.Add64(x3, t1, c)
270 t1, t0 = bits.Mul64(f4l, y[3])
271 x4, c = bits.Add64(x4, t0, c)
272 x5, c = bits.Add64(x5, t1, c)
273 x6, _ = bits.Add64(x6, 0, c)
274
275 // subtract
276 _, b = bits.Sub64(0, x0, 0)
277 _, b = bits.Sub64(0, x1, b)
278 r4l, b := bits.Sub64(0, x2, b)
279 r4k, b := bits.Sub64(0, x3, b)
280 r4j, b := bits.Sub64(r3l, x4, b)
281 r4i, b := bits.Sub64(r3m, x5, b)
282 r4h, _ := bits.Sub64(r3h, x6, b)
283
284 // Multiply candidate for 1/4y by y, with full precision
285
286 x0 = r4l
287 x1 = r4k
288 x2 = r4j
289 x3 = r4i
290 x4 = r4h
291
292 q1, q0 = bits.Mul64(x0, y[0])
293 q3, q2 = bits.Mul64(x2, y[0])
294 q5, q4 := bits.Mul64(x4, y[0])
295
296 t1, t0 = bits.Mul64(x1, y[0])
297 q1, c = bits.Add64(q1, t0, 0)
298 q2, c = bits.Add64(q2, t1, c)
299 t1, t0 = bits.Mul64(x3, y[0])
300 q3, c = bits.Add64(q3, t0, c)
301 q4, c = bits.Add64(q4, t1, c)
302 q5, _ = bits.Add64(q5, 0, c)
303
304 t1, t0 = bits.Mul64(x0, y[1])
305 q1, c = bits.Add64(q1, t0, 0)
306 q2, c = bits.Add64(q2, t1, c)
307 t1, t0 = bits.Mul64(x2, y[1])
308 q3, c = bits.Add64(q3, t0, c)
309 q4, c = bits.Add64(q4, t1, c)
310 q6, t0 := bits.Mul64(x4, y[1])
311 q5, c = bits.Add64(q5, t0, c)
312 q6, _ = bits.Add64(q6, 0, c)
313
314 t1, t0 = bits.Mul64(x1, y[1])
315 q2, c = bits.Add64(q2, t0, 0)
316 q3, c = bits.Add64(q3, t1, c)
317 t1, t0 = bits.Mul64(x3, y[1])
318 q4, c = bits.Add64(q4, t0, c)
319 q5, c = bits.Add64(q5, t1, c)
320 q6, _ = bits.Add64(q6, 0, c)
321
322 t1, t0 = bits.Mul64(x0, y[2])
323 q2, c = bits.Add64(q2, t0, 0)
324 q3, c = bits.Add64(q3, t1, c)
325 t1, t0 = bits.Mul64(x2, y[2])
326 q4, c = bits.Add64(q4, t0, c)
327 q5, c = bits.Add64(q5, t1, c)
328 q7, t0 := bits.Mul64(x4, y[2])
329 q6, c = bits.Add64(q6, t0, c)
330 q7, _ = bits.Add64(q7, 0, c)
331
332 t1, t0 = bits.Mul64(x1, y[2])
333 q3, c = bits.Add64(q3, t0, 0)
334 q4, c = bits.Add64(q4, t1, c)
335 t1, t0 = bits.Mul64(x3, y[2])
336 q5, c = bits.Add64(q5, t0, c)
337 q6, c = bits.Add64(q6, t1, c)
338 q7, _ = bits.Add64(q7, 0, c)
339
340 t1, t0 = bits.Mul64(x0, y[3])
341 q3, c = bits.Add64(q3, t0, 0)
342 q4, c = bits.Add64(q4, t1, c)
343 t1, t0 = bits.Mul64(x2, y[3])
344 q5, c = bits.Add64(q5, t0, c)
345 q6, c = bits.Add64(q6, t1, c)
346 q8, t0 := bits.Mul64(x4, y[3])
347 q7, c = bits.Add64(q7, t0, c)
348 q8, _ = bits.Add64(q8, 0, c)
349
350 t1, t0 = bits.Mul64(x1, y[3])
351 q4, c = bits.Add64(q4, t0, 0)
352 q5, c = bits.Add64(q5, t1, c)
353 t1, t0 = bits.Mul64(x3, y[3])
354 q6, c = bits.Add64(q6, t0, c)
355 q7, c = bits.Add64(q7, t1, c)
356 q8, _ = bits.Add64(q8, 0, c)
357
358 // Final adjustment
359
360 // subtract q from 1/4
361 _, b = bits.Sub64(0, q0, 0)
362 _, b = bits.Sub64(0, q1, b)
363 _, b = bits.Sub64(0, q2, b)
364 _, b = bits.Sub64(0, q3, b)
365 _, b = bits.Sub64(0, q4, b)
366 _, b = bits.Sub64(0, q5, b)
367 _, b = bits.Sub64(0, q6, b)
368 _, b = bits.Sub64(0, q7, b)
369 _, b = bits.Sub64(uint64(1)<<62, q8, b)
370
371 // decrement the result
372 x0, t := bits.Sub64(r4l, 1, 0)
373 x1, t = bits.Sub64(r4k, 0, t)
374 x2, t = bits.Sub64(r4j, 0, t)
375 x3, t = bits.Sub64(r4i, 0, t)
376 x4, _ = bits.Sub64(r4h, 0, t)
377
378 // commit the decrement if the subtraction underflowed (reciprocal was too large)
379 if b != 0 {
380 r4h, r4i, r4j, r4k, r4l = x4, x3, x2, x1, x0
381 }
382
383 // Shift to correct bit alignment, truncating excess bits
384
385 p = (p & 63) - 1
386
387 x0, c = bits.Add64(r4l, r4l, 0)
388 x1, c = bits.Add64(r4k, r4k, c)
389 x2, c = bits.Add64(r4j, r4j, c)
390 x3, c = bits.Add64(r4i, r4i, c)
391 x4, _ = bits.Add64(r4h, r4h, c)
392
393 if p < 0 {
394 r4h, r4i, r4j, r4k, r4l = x4, x3, x2, x1, x0
395 p = 0 // avoid negative shift below
396 }
397
398 {
399 r := uint(p) // right shift
400 l := uint(64 - r) // left shift
401
402 x0 = (r4l >> r) | (r4k << l)
403 x1 = (r4k >> r) | (r4j << l)
404 x2 = (r4j >> r) | (r4i << l)
405 x3 = (r4i >> r) | (r4h << l)
406 x4 = (r4h >> r)
407 }
408
409 if p > 0 {
410 r4h, r4i, r4j, r4k, r4l = x4, x3, x2, x1, x0
411 }
412
413 mu[0] = r4l
414 mu[1] = r4k
415 mu[2] = r4j
416 mu[3] = r4i
417 mu[4] = r4h
418
419 return mu
420}
421
422// reduce4 computes the least non-negative residue of x modulo m
423//
424// requires a four-word modulus (m[3] > 1) and its inverse (mu)
425func reduce4(x [8]uint64, m *Uint, mu [5]uint64) (z Uint) {
426 // NB: Most variable names in the comments match the pseudocode for
427 // Barrett reduction in the Handbook of Applied Cryptography.
428
429 // q1 = x/2^192
430
431 x0 := x[3]
432 x1 := x[4]
433 x2 := x[5]
434 x3 := x[6]
435 x4 := x[7]
436
437 // q2 = q1 * mu; q3 = q2 / 2^320
438
439 var q0, q1, q2, q3, q4, q5, t0, t1, c uint64
440
441 q0, _ = bits.Mul64(x3, mu[0])
442 q1, t0 = bits.Mul64(x4, mu[0])
443 q0, c = bits.Add64(q0, t0, 0)
444 q1, _ = bits.Add64(q1, 0, c)
445
446 t1, _ = bits.Mul64(x2, mu[1])
447 q0, c = bits.Add64(q0, t1, 0)
448 q2, t0 = bits.Mul64(x4, mu[1])
449 q1, c = bits.Add64(q1, t0, c)
450 q2, _ = bits.Add64(q2, 0, c)
451
452 t1, t0 = bits.Mul64(x3, mu[1])
453 q0, c = bits.Add64(q0, t0, 0)
454 q1, c = bits.Add64(q1, t1, c)
455 q2, _ = bits.Add64(q2, 0, c)
456
457 t1, t0 = bits.Mul64(x2, mu[2])
458 q0, c = bits.Add64(q0, t0, 0)
459 q1, c = bits.Add64(q1, t1, c)
460 q3, t0 = bits.Mul64(x4, mu[2])
461 q2, c = bits.Add64(q2, t0, c)
462 q3, _ = bits.Add64(q3, 0, c)
463
464 t1, _ = bits.Mul64(x1, mu[2])
465 q0, c = bits.Add64(q0, t1, 0)
466 t1, t0 = bits.Mul64(x3, mu[2])
467 q1, c = bits.Add64(q1, t0, c)
468 q2, c = bits.Add64(q2, t1, c)
469 q3, _ = bits.Add64(q3, 0, c)
470
471 t1, _ = bits.Mul64(x0, mu[3])
472 q0, c = bits.Add64(q0, t1, 0)
473 t1, t0 = bits.Mul64(x2, mu[3])
474 q1, c = bits.Add64(q1, t0, c)
475 q2, c = bits.Add64(q2, t1, c)
476 q4, t0 = bits.Mul64(x4, mu[3])
477 q3, c = bits.Add64(q3, t0, c)
478 q4, _ = bits.Add64(q4, 0, c)
479
480 t1, t0 = bits.Mul64(x1, mu[3])
481 q0, c = bits.Add64(q0, t0, 0)
482 q1, c = bits.Add64(q1, t1, c)
483 t1, t0 = bits.Mul64(x3, mu[3])
484 q2, c = bits.Add64(q2, t0, c)
485 q3, c = bits.Add64(q3, t1, c)
486 q4, _ = bits.Add64(q4, 0, c)
487
488 t1, t0 = bits.Mul64(x0, mu[4])
489 _, c = bits.Add64(q0, t0, 0)
490 q1, c = bits.Add64(q1, t1, c)
491 t1, t0 = bits.Mul64(x2, mu[4])
492 q2, c = bits.Add64(q2, t0, c)
493 q3, c = bits.Add64(q3, t1, c)
494 q5, t0 = bits.Mul64(x4, mu[4])
495 q4, c = bits.Add64(q4, t0, c)
496 q5, _ = bits.Add64(q5, 0, c)
497
498 t1, t0 = bits.Mul64(x1, mu[4])
499 q1, c = bits.Add64(q1, t0, 0)
500 q2, c = bits.Add64(q2, t1, c)
501 t1, t0 = bits.Mul64(x3, mu[4])
502 q3, c = bits.Add64(q3, t0, c)
503 q4, c = bits.Add64(q4, t1, c)
504 q5, _ = bits.Add64(q5, 0, c)
505
506 // Drop the fractional part of q3
507
508 q0 = q1
509 q1 = q2
510 q2 = q3
511 q3 = q4
512 q4 = q5
513
514 // r1 = x mod 2^320
515
516 x0 = x[0]
517 x1 = x[1]
518 x2 = x[2]
519 x3 = x[3]
520 x4 = x[4]
521
522 // r2 = q3 * m mod 2^320
523
524 var r0, r1, r2, r3, r4 uint64
525
526 r4, r3 = bits.Mul64(q0, m[3])
527 _, t0 = bits.Mul64(q1, m[3])
528 r4, _ = bits.Add64(r4, t0, 0)
529
530 t1, r2 = bits.Mul64(q0, m[2])
531 r3, c = bits.Add64(r3, t1, 0)
532 _, t0 = bits.Mul64(q2, m[2])
533 r4, _ = bits.Add64(r4, t0, c)
534
535 t1, t0 = bits.Mul64(q1, m[2])
536 r3, c = bits.Add64(r3, t0, 0)
537 r4, _ = bits.Add64(r4, t1, c)
538
539 t1, r1 = bits.Mul64(q0, m[1])
540 r2, c = bits.Add64(r2, t1, 0)
541 t1, t0 = bits.Mul64(q2, m[1])
542 r3, c = bits.Add64(r3, t0, c)
543 r4, _ = bits.Add64(r4, t1, c)
544
545 t1, t0 = bits.Mul64(q1, m[1])
546 r2, c = bits.Add64(r2, t0, 0)
547 r3, c = bits.Add64(r3, t1, c)
548 _, t0 = bits.Mul64(q3, m[1])
549 r4, _ = bits.Add64(r4, t0, c)
550
551 t1, r0 = bits.Mul64(q0, m[0])
552 r1, c = bits.Add64(r1, t1, 0)
553 t1, t0 = bits.Mul64(q2, m[0])
554 r2, c = bits.Add64(r2, t0, c)
555 r3, c = bits.Add64(r3, t1, c)
556 _, t0 = bits.Mul64(q4, m[0])
557 r4, _ = bits.Add64(r4, t0, c)
558
559 t1, t0 = bits.Mul64(q1, m[0])
560 r1, c = bits.Add64(r1, t0, 0)
561 r2, c = bits.Add64(r2, t1, c)
562 t1, t0 = bits.Mul64(q3, m[0])
563 r3, c = bits.Add64(r3, t0, c)
564 r4, _ = bits.Add64(r4, t1, c)
565
566 // r = r1 - r2
567
568 var b uint64
569
570 r0, b = bits.Sub64(x0, r0, 0)
571 r1, b = bits.Sub64(x1, r1, b)
572 r2, b = bits.Sub64(x2, r2, b)
573 r3, b = bits.Sub64(x3, r3, b)
574 r4, b = bits.Sub64(x4, r4, b)
575
576 // if r<0 then r+=m
577
578 if b != 0 {
579 r0, c = bits.Add64(r0, m[0], 0)
580 r1, c = bits.Add64(r1, m[1], c)
581 r2, c = bits.Add64(r2, m[2], c)
582 r3, c = bits.Add64(r3, m[3], c)
583 r4, _ = bits.Add64(r4, 0, c)
584 }
585
586 // while (r>=m) r-=m
587
588 for {
589 // q = r - m
590 q0, b = bits.Sub64(r0, m[0], 0)
591 q1, b = bits.Sub64(r1, m[1], b)
592 q2, b = bits.Sub64(r2, m[2], b)
593 q3, b = bits.Sub64(r3, m[3], b)
594 q4, b = bits.Sub64(r4, 0, b)
595
596 // if borrow break
597 if b != 0 {
598 break
599 }
600
601 // r = q
602 r4, r3, r2, r1, r0 = q4, q3, q2, q1, q0
603 }
604
605 z[3], z[2], z[1], z[0] = r3, r2, r1, r0
606
607 return z
608}