Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}