1package org.bouncycastle.math.raw;
2
3import java.math.BigInteger;
4
5import org.bouncycastle.util.Pack;
6
7public abstract class Nat256
8{
9    private static final long M = 0xFFFFFFFFL;
10
11    public static int add(int[] x, int[] y, int[] z)
12    {
13        long c = 0;
14        c += (x[0] & M) + (y[0] & M);
15        z[0] = (int)c;
16        c >>>= 32;
17        c += (x[1] & M) + (y[1] & M);
18        z[1] = (int)c;
19        c >>>= 32;
20        c += (x[2] & M) + (y[2] & M);
21        z[2] = (int)c;
22        c >>>= 32;
23        c += (x[3] & M) + (y[3] & M);
24        z[3] = (int)c;
25        c >>>= 32;
26        c += (x[4] & M) + (y[4] & M);
27        z[4] = (int)c;
28        c >>>= 32;
29        c += (x[5] & M) + (y[5] & M);
30        z[5] = (int)c;
31        c >>>= 32;
32        c += (x[6] & M) + (y[6] & M);
33        z[6] = (int)c;
34        c >>>= 32;
35        c += (x[7] & M) + (y[7] & M);
36        z[7] = (int)c;
37        c >>>= 32;
38        return (int)c;
39    }
40
41    public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
42    {
43        long c = 0;
44        c += (x[xOff + 0] & M) + (y[yOff + 0] & M);
45        z[zOff + 0] = (int)c;
46        c >>>= 32;
47        c += (x[xOff + 1] & M) + (y[yOff + 1] & M);
48        z[zOff + 1] = (int)c;
49        c >>>= 32;
50        c += (x[xOff + 2] & M) + (y[yOff + 2] & M);
51        z[zOff + 2] = (int)c;
52        c >>>= 32;
53        c += (x[xOff + 3] & M) + (y[yOff + 3] & M);
54        z[zOff + 3] = (int)c;
55        c >>>= 32;
56        c += (x[xOff + 4] & M) + (y[yOff + 4] & M);
57        z[zOff + 4] = (int)c;
58        c >>>= 32;
59        c += (x[xOff + 5] & M) + (y[yOff + 5] & M);
60        z[zOff + 5] = (int)c;
61        c >>>= 32;
62        c += (x[xOff + 6] & M) + (y[yOff + 6] & M);
63        z[zOff + 6] = (int)c;
64        c >>>= 32;
65        c += (x[xOff + 7] & M) + (y[yOff + 7] & M);
66        z[zOff + 7] = (int)c;
67        c >>>= 32;
68        return (int)c;
69    }
70
71    public static int addBothTo(int[] x, int[] y, int[] z)
72    {
73        long c = 0;
74        c += (x[0] & M) + (y[0] & M) + (z[0] & M);
75        z[0] = (int)c;
76        c >>>= 32;
77        c += (x[1] & M) + (y[1] & M) + (z[1] & M);
78        z[1] = (int)c;
79        c >>>= 32;
80        c += (x[2] & M) + (y[2] & M) + (z[2] & M);
81        z[2] = (int)c;
82        c >>>= 32;
83        c += (x[3] & M) + (y[3] & M) + (z[3] & M);
84        z[3] = (int)c;
85        c >>>= 32;
86        c += (x[4] & M) + (y[4] & M) + (z[4] & M);
87        z[4] = (int)c;
88        c >>>= 32;
89        c += (x[5] & M) + (y[5] & M) + (z[5] & M);
90        z[5] = (int)c;
91        c >>>= 32;
92        c += (x[6] & M) + (y[6] & M) + (z[6] & M);
93        z[6] = (int)c;
94        c >>>= 32;
95        c += (x[7] & M) + (y[7] & M) + (z[7] & M);
96        z[7] = (int)c;
97        c >>>= 32;
98        return (int)c;
99    }
100
101    public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
102    {
103        long c = 0;
104        c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M);
105        z[zOff + 0] = (int)c;
106        c >>>= 32;
107        c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M);
108        z[zOff + 1] = (int)c;
109        c >>>= 32;
110        c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M);
111        z[zOff + 2] = (int)c;
112        c >>>= 32;
113        c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M);
114        z[zOff + 3] = (int)c;
115        c >>>= 32;
116        c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M);
117        z[zOff + 4] = (int)c;
118        c >>>= 32;
119        c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M);
120        z[zOff + 5] = (int)c;
121        c >>>= 32;
122        c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M);
123        z[zOff + 6] = (int)c;
124        c >>>= 32;
125        c += (x[xOff + 7] & M) + (y[yOff + 7] & M) + (z[zOff + 7] & M);
126        z[zOff + 7] = (int)c;
127        c >>>= 32;
128        return (int)c;
129    }
130
131    public static int addTo(int[] x, int[] z)
132    {
133        long c = 0;
134        c += (x[0] & M) + (z[0] & M);
135        z[0] = (int)c;
136        c >>>= 32;
137        c += (x[1] & M) + (z[1] & M);
138        z[1] = (int)c;
139        c >>>= 32;
140        c += (x[2] & M) + (z[2] & M);
141        z[2] = (int)c;
142        c >>>= 32;
143        c += (x[3] & M) + (z[3] & M);
144        z[3] = (int)c;
145        c >>>= 32;
146        c += (x[4] & M) + (z[4] & M);
147        z[4] = (int)c;
148        c >>>= 32;
149        c += (x[5] & M) + (z[5] & M);
150        z[5] = (int)c;
151        c >>>= 32;
152        c += (x[6] & M) + (z[6] & M);
153        z[6] = (int)c;
154        c >>>= 32;
155        c += (x[7] & M) + (z[7] & M);
156        z[7] = (int)c;
157        c >>>= 32;
158        return (int)c;
159    }
160
161    public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
162    {
163        long c = cIn & M;
164        c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
165        z[zOff + 0] = (int)c;
166        c >>>= 32;
167        c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
168        z[zOff + 1] = (int)c;
169        c >>>= 32;
170        c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
171        z[zOff + 2] = (int)c;
172        c >>>= 32;
173        c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
174        z[zOff + 3] = (int)c;
175        c >>>= 32;
176        c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
177        z[zOff + 4] = (int)c;
178        c >>>= 32;
179        c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
180        z[zOff + 5] = (int)c;
181        c >>>= 32;
182        c += (x[xOff + 6] & M) + (z[zOff + 6] & M);
183        z[zOff + 6] = (int)c;
184        c >>>= 32;
185        c += (x[xOff + 7] & M) + (z[zOff + 7] & M);
186        z[zOff + 7] = (int)c;
187        c >>>= 32;
188        return (int)c;
189    }
190
191    public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
192    {
193        long c = 0;
194        c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
195        u[uOff + 0] = (int)c;
196        v[vOff + 0] = (int)c;
197        c >>>= 32;
198        c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
199        u[uOff + 1] = (int)c;
200        v[vOff + 1] = (int)c;
201        c >>>= 32;
202        c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
203        u[uOff + 2] = (int)c;
204        v[vOff + 2] = (int)c;
205        c >>>= 32;
206        c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
207        u[uOff + 3] = (int)c;
208        v[vOff + 3] = (int)c;
209        c >>>= 32;
210        c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
211        u[uOff + 4] = (int)c;
212        v[vOff + 4] = (int)c;
213        c >>>= 32;
214        c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
215        u[uOff + 5] = (int)c;
216        v[vOff + 5] = (int)c;
217        c >>>= 32;
218        c += (u[uOff + 6] & M) + (v[vOff + 6] & M);
219        u[uOff + 6] = (int)c;
220        v[vOff + 6] = (int)c;
221        c >>>= 32;
222        c += (u[uOff + 7] & M) + (v[vOff + 7] & M);
223        u[uOff + 7] = (int)c;
224        v[vOff + 7] = (int)c;
225        c >>>= 32;
226        return (int)c;
227    }
228
229    public static void copy(int[] x, int[] z)
230    {
231        z[0] = x[0];
232        z[1] = x[1];
233        z[2] = x[2];
234        z[3] = x[3];
235        z[4] = x[4];
236        z[5] = x[5];
237        z[6] = x[6];
238        z[7] = x[7];
239    }
240
241    public static int[] create()
242    {
243        return new int[8];
244    }
245
246    public static int[] createExt()
247    {
248        return new int[16];
249    }
250
251    public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
252    {
253        boolean pos = gte(x, xOff, y, yOff);
254        if (pos)
255        {
256            sub(x, xOff, y, yOff, z, zOff);
257        }
258        else
259        {
260            sub(y, yOff, x, xOff, z, zOff);
261        }
262        return pos;
263    }
264
265    public static boolean eq(int[] x, int[] y)
266    {
267        for (int i = 7; i >= 0; --i)
268        {
269            if (x[i] != y[i])
270            {
271                return false;
272            }
273        }
274        return true;
275    }
276
277    public static int[] fromBigInteger(BigInteger x)
278    {
279        if (x.signum() < 0 || x.bitLength() > 256)
280        {
281            throw new IllegalArgumentException();
282        }
283
284        int[] z = create();
285        int i = 0;
286        while (x.signum() != 0)
287        {
288            z[i++] = x.intValue();
289            x = x.shiftRight(32);
290        }
291        return z;
292    }
293
294    public static int getBit(int[] x, int bit)
295    {
296        if (bit == 0)
297        {
298            return x[0] & 1;
299        }
300        if ((bit & 255) != bit)
301        {
302            return 0;
303        }
304        int w = bit >>> 5;
305        int b = bit & 31;
306        return (x[w] >>> b) & 1;
307    }
308
309    public static boolean gte(int[] x, int[] y)
310    {
311        for (int i = 7; i >= 0; --i)
312        {
313            int x_i = x[i] ^ Integer.MIN_VALUE;
314            int y_i = y[i] ^ Integer.MIN_VALUE;
315            if (x_i < y_i)
316                return false;
317            if (x_i > y_i)
318                return true;
319        }
320        return true;
321    }
322
323    public static boolean gte(int[] x, int xOff, int[] y, int yOff)
324    {
325        for (int i = 7; i >= 0; --i)
326        {
327            int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
328            int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
329            if (x_i < y_i)
330                return false;
331            if (x_i > y_i)
332                return true;
333        }
334        return true;
335    }
336
337    public static boolean isOne(int[] x)
338    {
339        if (x[0] != 1)
340        {
341            return false;
342        }
343        for (int i = 1; i < 8; ++i)
344        {
345            if (x[i] != 0)
346            {
347                return false;
348            }
349        }
350        return true;
351    }
352
353    public static boolean isZero(int[] x)
354    {
355        for (int i = 0; i < 8; ++i)
356        {
357            if (x[i] != 0)
358            {
359                return false;
360            }
361        }
362        return true;
363    }
364
365    public static void mul(int[] x, int[] y, int[] zz)
366    {
367        long y_0 = y[0] & M;
368        long y_1 = y[1] & M;
369        long y_2 = y[2] & M;
370        long y_3 = y[3] & M;
371        long y_4 = y[4] & M;
372        long y_5 = y[5] & M;
373        long y_6 = y[6] & M;
374        long y_7 = y[7] & M;
375
376        {
377            long c = 0, x_0 = x[0] & M;
378            c += x_0 * y_0;
379            zz[0] = (int)c;
380            c >>>= 32;
381            c += x_0 * y_1;
382            zz[1] = (int)c;
383            c >>>= 32;
384            c += x_0 * y_2;
385            zz[2] = (int)c;
386            c >>>= 32;
387            c += x_0 * y_3;
388            zz[3] = (int)c;
389            c >>>= 32;
390            c += x_0 * y_4;
391            zz[4] = (int)c;
392            c >>>= 32;
393            c += x_0 * y_5;
394            zz[5] = (int)c;
395            c >>>= 32;
396            c += x_0 * y_6;
397            zz[6] = (int)c;
398            c >>>= 32;
399            c += x_0 * y_7;
400            zz[7] = (int)c;
401            c >>>= 32;
402            zz[8] = (int)c;
403        }
404
405        for (int i = 1; i < 8; ++i)
406        {
407            long c = 0, x_i = x[i] & M;
408            c += x_i * y_0 + (zz[i + 0] & M);
409            zz[i + 0] = (int)c;
410            c >>>= 32;
411            c += x_i * y_1 + (zz[i + 1] & M);
412            zz[i + 1] = (int)c;
413            c >>>= 32;
414            c += x_i * y_2 + (zz[i + 2] & M);
415            zz[i + 2] = (int)c;
416            c >>>= 32;
417            c += x_i * y_3 + (zz[i + 3] & M);
418            zz[i + 3] = (int)c;
419            c >>>= 32;
420            c += x_i * y_4 + (zz[i + 4] & M);
421            zz[i + 4] = (int)c;
422            c >>>= 32;
423            c += x_i * y_5 + (zz[i + 5] & M);
424            zz[i + 5] = (int)c;
425            c >>>= 32;
426            c += x_i * y_6 + (zz[i + 6] & M);
427            zz[i + 6] = (int)c;
428            c >>>= 32;
429            c += x_i * y_7 + (zz[i + 7] & M);
430            zz[i + 7] = (int)c;
431            c >>>= 32;
432            zz[i + 8] = (int)c;
433        }
434    }
435
436    public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
437    {
438        long y_0 = y[yOff + 0] & M;
439        long y_1 = y[yOff + 1] & M;
440        long y_2 = y[yOff + 2] & M;
441        long y_3 = y[yOff + 3] & M;
442        long y_4 = y[yOff + 4] & M;
443        long y_5 = y[yOff + 5] & M;
444        long y_6 = y[yOff + 6] & M;
445        long y_7 = y[yOff + 7] & M;
446
447        {
448            long c = 0, x_0 = x[xOff + 0] & M;
449            c += x_0 * y_0;
450            zz[zzOff + 0] = (int)c;
451            c >>>= 32;
452            c += x_0 * y_1;
453            zz[zzOff + 1] = (int)c;
454            c >>>= 32;
455            c += x_0 * y_2;
456            zz[zzOff + 2] = (int)c;
457            c >>>= 32;
458            c += x_0 * y_3;
459            zz[zzOff + 3] = (int)c;
460            c >>>= 32;
461            c += x_0 * y_4;
462            zz[zzOff + 4] = (int)c;
463            c >>>= 32;
464            c += x_0 * y_5;
465            zz[zzOff + 5] = (int)c;
466            c >>>= 32;
467            c += x_0 * y_6;
468            zz[zzOff + 6] = (int)c;
469            c >>>= 32;
470            c += x_0 * y_7;
471            zz[zzOff + 7] = (int)c;
472            c >>>= 32;
473            zz[zzOff + 8] = (int)c;
474        }
475
476        for (int i = 1; i < 8; ++i)
477        {
478            ++zzOff;
479            long c = 0, x_i = x[xOff + i] & M;
480            c += x_i * y_0 + (zz[zzOff + 0] & M);
481            zz[zzOff + 0] = (int)c;
482            c >>>= 32;
483            c += x_i * y_1 + (zz[zzOff + 1] & M);
484            zz[zzOff + 1] = (int)c;
485            c >>>= 32;
486            c += x_i * y_2 + (zz[zzOff + 2] & M);
487            zz[zzOff + 2] = (int)c;
488            c >>>= 32;
489            c += x_i * y_3 + (zz[zzOff + 3] & M);
490            zz[zzOff + 3] = (int)c;
491            c >>>= 32;
492            c += x_i * y_4 + (zz[zzOff + 4] & M);
493            zz[zzOff + 4] = (int)c;
494            c >>>= 32;
495            c += x_i * y_5 + (zz[zzOff + 5] & M);
496            zz[zzOff + 5] = (int)c;
497            c >>>= 32;
498            c += x_i * y_6 + (zz[zzOff + 6] & M);
499            zz[zzOff + 6] = (int)c;
500            c >>>= 32;
501            c += x_i * y_7 + (zz[zzOff + 7] & M);
502            zz[zzOff + 7] = (int)c;
503            c >>>= 32;
504            zz[zzOff + 8] = (int)c;
505        }
506    }
507
508    public static int mulAddTo(int[] x, int[] y, int[] zz)
509    {
510        long y_0 = y[0] & M;
511        long y_1 = y[1] & M;
512        long y_2 = y[2] & M;
513        long y_3 = y[3] & M;
514        long y_4 = y[4] & M;
515        long y_5 = y[5] & M;
516        long y_6 = y[6] & M;
517        long y_7 = y[7] & M;
518
519        long zc = 0;
520        for (int i = 0; i < 8; ++i)
521        {
522            long c = 0, x_i = x[i] & M;
523            c += x_i * y_0 + (zz[i + 0] & M);
524            zz[i + 0] = (int)c;
525            c >>>= 32;
526            c += x_i * y_1 + (zz[i + 1] & M);
527            zz[i + 1] = (int)c;
528            c >>>= 32;
529            c += x_i * y_2 + (zz[i + 2] & M);
530            zz[i + 2] = (int)c;
531            c >>>= 32;
532            c += x_i * y_3 + (zz[i + 3] & M);
533            zz[i + 3] = (int)c;
534            c >>>= 32;
535            c += x_i * y_4 + (zz[i + 4] & M);
536            zz[i + 4] = (int)c;
537            c >>>= 32;
538            c += x_i * y_5 + (zz[i + 5] & M);
539            zz[i + 5] = (int)c;
540            c >>>= 32;
541            c += x_i * y_6 + (zz[i + 6] & M);
542            zz[i + 6] = (int)c;
543            c >>>= 32;
544            c += x_i * y_7 + (zz[i + 7] & M);
545            zz[i + 7] = (int)c;
546            c >>>= 32;
547            c += zc + (zz[i + 8] & M);
548            zz[i + 8] = (int)c;
549            zc = c >>> 32;
550        }
551        return (int)zc;
552    }
553
554    public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
555    {
556        long y_0 = y[yOff + 0] & M;
557        long y_1 = y[yOff + 1] & M;
558        long y_2 = y[yOff + 2] & M;
559        long y_3 = y[yOff + 3] & M;
560        long y_4 = y[yOff + 4] & M;
561        long y_5 = y[yOff + 5] & M;
562        long y_6 = y[yOff + 6] & M;
563        long y_7 = y[yOff + 7] & M;
564
565        long zc = 0;
566        for (int i = 0; i < 8; ++i)
567        {
568            long c = 0, x_i = x[xOff + i] & M;
569            c += x_i * y_0 + (zz[zzOff + 0] & M);
570            zz[zzOff + 0] = (int)c;
571            c >>>= 32;
572            c += x_i * y_1 + (zz[zzOff + 1] & M);
573            zz[zzOff + 1] = (int)c;
574            c >>>= 32;
575            c += x_i * y_2 + (zz[zzOff + 2] & M);
576            zz[zzOff + 2] = (int)c;
577            c >>>= 32;
578            c += x_i * y_3 + (zz[zzOff + 3] & M);
579            zz[zzOff + 3] = (int)c;
580            c >>>= 32;
581            c += x_i * y_4 + (zz[zzOff + 4] & M);
582            zz[zzOff + 4] = (int)c;
583            c >>>= 32;
584            c += x_i * y_5 + (zz[zzOff + 5] & M);
585            zz[zzOff + 5] = (int)c;
586            c >>>= 32;
587            c += x_i * y_6 + (zz[zzOff + 6] & M);
588            zz[zzOff + 6] = (int)c;
589            c >>>= 32;
590            c += x_i * y_7 + (zz[zzOff + 7] & M);
591            zz[zzOff + 7] = (int)c;
592            c >>>= 32;
593            c += zc + (zz[zzOff + 8] & M);
594            zz[zzOff + 8] = (int)c;
595            zc = c >>> 32;
596            ++zzOff;
597        }
598        return (int)zc;
599    }
600
601    public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
602    {
603        // assert w >>> 31 == 0;
604
605        long c = 0, wVal = w & M;
606        long x0 = x[xOff + 0] & M;
607        c += wVal * x0 + (y[yOff + 0] & M);
608        z[zOff + 0] = (int)c;
609        c >>>= 32;
610        long x1 = x[xOff + 1] & M;
611        c += wVal * x1 + x0 + (y[yOff + 1] & M);
612        z[zOff + 1] = (int)c;
613        c >>>= 32;
614        long x2 = x[xOff + 2] & M;
615        c += wVal * x2 + x1 + (y[yOff + 2] & M);
616        z[zOff + 2] = (int)c;
617        c >>>= 32;
618        long x3 = x[xOff + 3] & M;
619        c += wVal * x3 + x2 + (y[yOff + 3] & M);
620        z[zOff + 3] = (int)c;
621        c >>>= 32;
622        long x4 = x[xOff + 4] & M;
623        c += wVal * x4 + x3 + (y[yOff + 4] & M);
624        z[zOff + 4] = (int)c;
625        c >>>= 32;
626        long x5 = x[xOff + 5] & M;
627        c += wVal * x5 + x4 + (y[yOff + 5] & M);
628        z[zOff + 5] = (int)c;
629        c >>>= 32;
630        long x6 = x[xOff + 6] & M;
631        c += wVal * x6 + x5 + (y[yOff + 6] & M);
632        z[zOff + 6] = (int)c;
633        c >>>= 32;
634        long x7 = x[xOff + 7] & M;
635        c += wVal * x7 + x6 + (y[yOff + 7] & M);
636        z[zOff + 7] = (int)c;
637        c >>>= 32;
638        c += x7;
639        return c;
640    }
641
642    public static int mulByWord(int x, int[] z)
643    {
644        long c = 0, xVal = x & M;
645        c += xVal * (z[0] & M);
646        z[0] = (int)c;
647        c >>>= 32;
648        c += xVal * (z[1] & M);
649        z[1] = (int)c;
650        c >>>= 32;
651        c += xVal * (z[2] & M);
652        z[2] = (int)c;
653        c >>>= 32;
654        c += xVal * (z[3] & M);
655        z[3] = (int)c;
656        c >>>= 32;
657        c += xVal * (z[4] & M);
658        z[4] = (int)c;
659        c >>>= 32;
660        c += xVal * (z[5] & M);
661        z[5] = (int)c;
662        c >>>= 32;
663        c += xVal * (z[6] & M);
664        z[6] = (int)c;
665        c >>>= 32;
666        c += xVal * (z[7] & M);
667        z[7] = (int)c;
668        c >>>= 32;
669        return (int)c;
670    }
671
672    public static int mulByWordAddTo(int x, int[] y, int[] z)
673    {
674        long c = 0, xVal = x & M;
675        c += xVal * (z[0] & M) + (y[0] & M);
676        z[0] = (int)c;
677        c >>>= 32;
678        c += xVal * (z[1] & M) + (y[1] & M);
679        z[1] = (int)c;
680        c >>>= 32;
681        c += xVal * (z[2] & M) + (y[2] & M);
682        z[2] = (int)c;
683        c >>>= 32;
684        c += xVal * (z[3] & M) + (y[3] & M);
685        z[3] = (int)c;
686        c >>>= 32;
687        c += xVal * (z[4] & M) + (y[4] & M);
688        z[4] = (int)c;
689        c >>>= 32;
690        c += xVal * (z[5] & M) + (y[5] & M);
691        z[5] = (int)c;
692        c >>>= 32;
693        c += xVal * (z[6] & M) + (y[6] & M);
694        z[6] = (int)c;
695        c >>>= 32;
696        c += xVal * (z[7] & M) + (y[7] & M);
697        z[7] = (int)c;
698        c >>>= 32;
699        return (int)c;
700    }
701
702    public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff)
703    {
704        long c = 0, xVal = x & M;
705        c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M);
706        z[zOff + 0] = (int)c;
707        c >>>= 32;
708        c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M);
709        z[zOff + 1] = (int)c;
710        c >>>= 32;
711        c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M);
712        z[zOff + 2] = (int)c;
713        c >>>= 32;
714        c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M);
715        z[zOff + 3] = (int)c;
716        c >>>= 32;
717        c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M);
718        z[zOff + 4] = (int)c;
719        c >>>= 32;
720        c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M);
721        z[zOff + 5] = (int)c;
722        c >>>= 32;
723        c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M);
724        z[zOff + 6] = (int)c;
725        c >>>= 32;
726        c += xVal * (y[yOff + 7] & M) + (z[zOff + 7] & M);
727        z[zOff + 7] = (int)c;
728        c >>>= 32;
729        return (int)c;
730    }
731
732    public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
733    {
734        // assert x >>> 31 == 0;
735        // assert zOff <= 4;
736
737        long c = 0, xVal = x & M;
738        long y00 = y & M;
739        c += xVal * y00 + (z[zOff + 0] & M);
740        z[zOff + 0] = (int)c;
741        c >>>= 32;
742        long y01 = y >>> 32;
743        c += xVal * y01 + y00 + (z[zOff + 1] & M);
744        z[zOff + 1] = (int)c;
745        c >>>= 32;
746        c += y01 + (z[zOff + 2] & M);
747        z[zOff + 2] = (int)c;
748        c >>>= 32;
749        c += (z[zOff + 3] & M);
750        z[zOff + 3] = (int)c;
751        c >>>= 32;
752        return c == 0 ? 0 : Nat.incAt(8, z, zOff, 4);
753    }
754
755    public static int mul33WordAdd(int x, int y, int[] z, int zOff)
756    {
757        // assert x >>> 31 == 0;
758        // assert zOff <= 5;
759
760        long c = 0, xVal = x & M, yVal = y & M;
761        c += yVal * xVal + (z[zOff + 0] & M);
762        z[zOff + 0] = (int)c;
763        c >>>= 32;
764        c += yVal + (z[zOff + 1] & M);
765        z[zOff + 1] = (int)c;
766        c >>>= 32;
767        c += (z[zOff + 2] & M);
768        z[zOff + 2] = (int)c;
769        c >>>= 32;
770        return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
771    }
772
773    public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
774    {
775        // assert zOff <= 5;
776        long c = 0, xVal = x & M;
777        c += xVal * (y & M) + (z[zOff + 0] & M);
778        z[zOff + 0] = (int)c;
779        c >>>= 32;
780        c += xVal * (y >>> 32) + (z[zOff + 1] & M);
781        z[zOff + 1] = (int)c;
782        c >>>= 32;
783        c += (z[zOff + 2] & M);
784        z[zOff + 2] = (int)c;
785        c >>>= 32;
786        return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
787    }
788
789    public static int mulWord(int x, int[] y, int[] z, int zOff)
790    {
791        long c = 0, xVal = x & M;
792        int i = 0;
793        do
794        {
795            c += xVal * (y[i] & M);
796            z[zOff + i] = (int)c;
797            c >>>= 32;
798        }
799        while (++i < 8);
800        return (int)c;
801    }
802
803    public static void square(int[] x, int[] zz)
804    {
805        long x_0 = x[0] & M;
806        long zz_1;
807
808        int c = 0, w;
809        {
810            int i = 7, j = 16;
811            do
812            {
813                long xVal = (x[i--] & M);
814                long p = xVal * xVal;
815                zz[--j] = (c << 31) | (int)(p >>> 33);
816                zz[--j] = (int)(p >>> 1);
817                c = (int)p;
818            }
819            while (i > 0);
820
821            {
822                long p = x_0 * x_0;
823                zz_1 = ((c << 31) & M) | (p >>> 33);
824                zz[0] = (int)p;
825                c = (int)(p >>> 32) & 1;
826            }
827        }
828
829        long x_1 = x[1] & M;
830        long zz_2 = zz[2] & M;
831
832        {
833            zz_1 += x_1 * x_0;
834            w = (int)zz_1;
835            zz[1] = (w << 1) | c;
836            c = w >>> 31;
837            zz_2 += zz_1 >>> 32;
838        }
839
840        long x_2 = x[2] & M;
841        long zz_3 = zz[3] & M;
842        long zz_4 = zz[4] & M;
843        {
844            zz_2 += x_2 * x_0;
845            w = (int)zz_2;
846            zz[2] = (w << 1) | c;
847            c = w >>> 31;
848            zz_3 += (zz_2 >>> 32) + x_2 * x_1;
849            zz_4 += zz_3 >>> 32;
850            zz_3 &= M;
851        }
852
853        long x_3 = x[3] & M;
854        long zz_5 = zz[5] & M;
855        long zz_6 = zz[6] & M;
856        {
857            zz_3 += x_3 * x_0;
858            w = (int)zz_3;
859            zz[3] = (w << 1) | c;
860            c = w >>> 31;
861            zz_4 += (zz_3 >>> 32) + x_3 * x_1;
862            zz_5 += (zz_4 >>> 32) + x_3 * x_2;
863            zz_4 &= M;
864            zz_6 += zz_5 >>> 32;
865            zz_5 &= M;
866        }
867
868        long x_4 = x[4] & M;
869        long zz_7 = zz[7] & M;
870        long zz_8 = zz[8] & M;
871        {
872            zz_4 += x_4 * x_0;
873            w = (int)zz_4;
874            zz[4] = (w << 1) | c;
875            c = w >>> 31;
876            zz_5 += (zz_4 >>> 32) + x_4 * x_1;
877            zz_6 += (zz_5 >>> 32) + x_4 * x_2;
878            zz_5 &= M;
879            zz_7 += (zz_6 >>> 32) + x_4 * x_3;
880            zz_6 &= M;
881            zz_8 += zz_7 >>> 32;
882            zz_7 &= M;
883        }
884
885        long x_5 = x[5] & M;
886        long zz_9 = zz[9] & M;
887        long zz_10 = zz[10] & M;
888        {
889            zz_5 += x_5 * x_0;
890            w = (int)zz_5;
891            zz[5] = (w << 1) | c;
892            c = w >>> 31;
893            zz_6 += (zz_5 >>> 32) + x_5 * x_1;
894            zz_7 += (zz_6 >>> 32) + x_5 * x_2;
895            zz_6 &= M;
896            zz_8 += (zz_7 >>> 32) + x_5 * x_3;
897            zz_7 &= M;
898            zz_9 += (zz_8 >>> 32) + x_5 * x_4;
899            zz_8 &= M;
900            zz_10 += zz_9 >>> 32;
901            zz_9 &= M;
902        }
903
904        long x_6 = x[6] & M;
905        long zz_11 = zz[11] & M;
906        long zz_12 = zz[12] & M;
907        {
908            zz_6 += x_6 * x_0;
909            w = (int)zz_6;
910            zz[6] = (w << 1) | c;
911            c = w >>> 31;
912            zz_7 += (zz_6 >>> 32) + x_6 * x_1;
913            zz_8 += (zz_7 >>> 32) + x_6 * x_2;
914            zz_7 &= M;
915            zz_9 += (zz_8 >>> 32) + x_6 * x_3;
916            zz_8 &= M;
917            zz_10 += (zz_9 >>> 32) + x_6 * x_4;
918            zz_9 &= M;
919            zz_11 += (zz_10 >>> 32) + x_6 * x_5;
920            zz_10 &= M;
921            zz_12 += zz_11 >>> 32;
922            zz_11 &= M;
923        }
924
925        long x_7 = x[7] & M;
926        long zz_13 = zz[13] & M;
927        long zz_14 = zz[14] & M;
928        {
929            zz_7 += x_7 * x_0;
930            w = (int)zz_7;
931            zz[7] = (w << 1) | c;
932            c = w >>> 31;
933            zz_8 += (zz_7 >>> 32) + x_7 * x_1;
934            zz_9 += (zz_8 >>> 32) + x_7 * x_2;
935            zz_10 += (zz_9 >>> 32) + x_7 * x_3;
936            zz_11 += (zz_10 >>> 32) + x_7 * x_4;
937            zz_12 += (zz_11 >>> 32) + x_7 * x_5;
938            zz_13 += (zz_12 >>> 32) + x_7 * x_6;
939            zz_14 += zz_13 >>> 32;
940        }
941
942        w = (int)zz_8;
943        zz[8] = (w << 1) | c;
944        c = w >>> 31;
945        w = (int)zz_9;
946        zz[9] = (w << 1) | c;
947        c = w >>> 31;
948        w = (int)zz_10;
949        zz[10] = (w << 1) | c;
950        c = w >>> 31;
951        w = (int)zz_11;
952        zz[11] = (w << 1) | c;
953        c = w >>> 31;
954        w = (int)zz_12;
955        zz[12] = (w << 1) | c;
956        c = w >>> 31;
957        w = (int)zz_13;
958        zz[13] = (w << 1) | c;
959        c = w >>> 31;
960        w = (int)zz_14;
961        zz[14] = (w << 1) | c;
962        c = w >>> 31;
963        w = zz[15] + (int)(zz_14 >> 32);
964        zz[15] = (w << 1) | c;
965    }
966
967    public static void square(int[] x, int xOff, int[] zz, int zzOff)
968    {
969        long x_0 = x[xOff + 0] & M;
970        long zz_1;
971
972        int c = 0, w;
973        {
974            int i = 7, j = 16;
975            do
976            {
977                long xVal = (x[xOff + i--] & M);
978                long p = xVal * xVal;
979                zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
980                zz[zzOff + --j] = (int)(p >>> 1);
981                c = (int)p;
982            }
983            while (i > 0);
984
985            {
986                long p = x_0 * x_0;
987                zz_1 = ((c << 31) & M) | (p >>> 33);
988                zz[zzOff + 0] = (int)p;
989                c = (int)(p >>> 32) & 1;
990            }
991        }
992
993        long x_1 = x[xOff + 1] & M;
994        long zz_2 = zz[zzOff + 2] & M;
995
996        {
997            zz_1 += x_1 * x_0;
998            w = (int)zz_1;
999            zz[zzOff + 1] = (w << 1) | c;
1000            c = w >>> 31;
1001            zz_2 += zz_1 >>> 32;
1002        }
1003
1004        long x_2 = x[xOff + 2] & M;
1005        long zz_3 = zz[zzOff + 3] & M;
1006        long zz_4 = zz[zzOff + 4] & M;
1007        {
1008            zz_2 += x_2 * x_0;
1009            w = (int)zz_2;
1010            zz[zzOff + 2] = (w << 1) | c;
1011            c = w >>> 31;
1012            zz_3 += (zz_2 >>> 32) + x_2 * x_1;
1013            zz_4 += zz_3 >>> 32;
1014            zz_3 &= M;
1015        }
1016
1017        long x_3 = x[xOff + 3] & M;
1018        long zz_5 = zz[zzOff + 5] & M;
1019        long zz_6 = zz[zzOff + 6] & M;
1020        {
1021            zz_3 += x_3 * x_0;
1022            w = (int)zz_3;
1023            zz[zzOff + 3] = (w << 1) | c;
1024            c = w >>> 31;
1025            zz_4 += (zz_3 >>> 32) + x_3 * x_1;
1026            zz_5 += (zz_4 >>> 32) + x_3 * x_2;
1027            zz_4 &= M;
1028            zz_6 += zz_5 >>> 32;
1029            zz_5 &= M;
1030        }
1031
1032        long x_4 = x[xOff + 4] & M;
1033        long zz_7 = zz[zzOff + 7] & M;
1034        long zz_8 = zz[zzOff + 8] & M;
1035        {
1036            zz_4 += x_4 * x_0;
1037            w = (int)zz_4;
1038            zz[zzOff + 4] = (w << 1) | c;
1039            c = w >>> 31;
1040            zz_5 += (zz_4 >>> 32) + x_4 * x_1;
1041            zz_6 += (zz_5 >>> 32) + x_4 * x_2;
1042            zz_5 &= M;
1043            zz_7 += (zz_6 >>> 32) + x_4 * x_3;
1044            zz_6 &= M;
1045            zz_8 += zz_7 >>> 32;
1046            zz_7 &= M;
1047        }
1048
1049        long x_5 = x[xOff + 5] & M;
1050        long zz_9 = zz[zzOff + 9] & M;
1051        long zz_10 = zz[zzOff + 10] & M;
1052        {
1053            zz_5 += x_5 * x_0;
1054            w = (int)zz_5;
1055            zz[zzOff + 5] = (w << 1) | c;
1056            c = w >>> 31;
1057            zz_6 += (zz_5 >>> 32) + x_5 * x_1;
1058            zz_7 += (zz_6 >>> 32) + x_5 * x_2;
1059            zz_6 &= M;
1060            zz_8 += (zz_7 >>> 32) + x_5 * x_3;
1061            zz_7 &= M;
1062            zz_9 += (zz_8 >>> 32) + x_5 * x_4;
1063            zz_8 &= M;
1064            zz_10 += zz_9 >>> 32;
1065            zz_9 &= M;
1066        }
1067
1068        long x_6 = x[xOff + 6] & M;
1069        long zz_11 = zz[zzOff + 11] & M;
1070        long zz_12 = zz[zzOff + 12] & M;
1071        {
1072            zz_6 += x_6 * x_0;
1073            w = (int)zz_6;
1074            zz[zzOff + 6] = (w << 1) | c;
1075            c = w >>> 31;
1076            zz_7 += (zz_6 >>> 32) + x_6 * x_1;
1077            zz_8 += (zz_7 >>> 32) + x_6 * x_2;
1078            zz_7 &= M;
1079            zz_9 += (zz_8 >>> 32) + x_6 * x_3;
1080            zz_8 &= M;
1081            zz_10 += (zz_9 >>> 32) + x_6 * x_4;
1082            zz_9 &= M;
1083            zz_11 += (zz_10 >>> 32) + x_6 * x_5;
1084            zz_10 &= M;
1085            zz_12 += zz_11 >>> 32;
1086            zz_11 &= M;
1087        }
1088
1089        long x_7 = x[xOff + 7] & M;
1090        long zz_13 = zz[zzOff + 13] & M;
1091        long zz_14 = zz[zzOff + 14] & M;
1092        {
1093            zz_7 += x_7 * x_0;
1094            w = (int)zz_7;
1095            zz[zzOff + 7] = (w << 1) | c;
1096            c = w >>> 31;
1097            zz_8 += (zz_7 >>> 32) + x_7 * x_1;
1098            zz_9 += (zz_8 >>> 32) + x_7 * x_2;
1099            zz_10 += (zz_9 >>> 32) + x_7 * x_3;
1100            zz_11 += (zz_10 >>> 32) + x_7 * x_4;
1101            zz_12 += (zz_11 >>> 32) + x_7 * x_5;
1102            zz_13 += (zz_12 >>> 32) + x_7 * x_6;
1103            zz_14 += zz_13 >>> 32;
1104        }
1105
1106        w = (int)zz_8;
1107        zz[zzOff + 8] = (w << 1) | c;
1108        c = w >>> 31;
1109        w = (int)zz_9;
1110        zz[zzOff + 9] = (w << 1) | c;
1111        c = w >>> 31;
1112        w = (int)zz_10;
1113        zz[zzOff + 10] = (w << 1) | c;
1114        c = w >>> 31;
1115        w = (int)zz_11;
1116        zz[zzOff + 11] = (w << 1) | c;
1117        c = w >>> 31;
1118        w = (int)zz_12;
1119        zz[zzOff + 12] = (w << 1) | c;
1120        c = w >>> 31;
1121        w = (int)zz_13;
1122        zz[zzOff + 13] = (w << 1) | c;
1123        c = w >>> 31;
1124        w = (int)zz_14;
1125        zz[zzOff + 14] = (w << 1) | c;
1126        c = w >>> 31;
1127        w = zz[zzOff + 15] + (int)(zz_14 >> 32);
1128        zz[zzOff + 15] = (w << 1) | c;
1129    }
1130
1131    public static int sub(int[] x, int[] y, int[] z)
1132    {
1133        long c = 0;
1134        c += (x[0] & M) - (y[0] & M);
1135        z[0] = (int)c;
1136        c >>= 32;
1137        c += (x[1] & M) - (y[1] & M);
1138        z[1] = (int)c;
1139        c >>= 32;
1140        c += (x[2] & M) - (y[2] & M);
1141        z[2] = (int)c;
1142        c >>= 32;
1143        c += (x[3] & M) - (y[3] & M);
1144        z[3] = (int)c;
1145        c >>= 32;
1146        c += (x[4] & M) - (y[4] & M);
1147        z[4] = (int)c;
1148        c >>= 32;
1149        c += (x[5] & M) - (y[5] & M);
1150        z[5] = (int)c;
1151        c >>= 32;
1152        c += (x[6] & M) - (y[6] & M);
1153        z[6] = (int)c;
1154        c >>= 32;
1155        c += (x[7] & M) - (y[7] & M);
1156        z[7] = (int)c;
1157        c >>= 32;
1158        return (int)c;
1159    }
1160
1161    public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
1162    {
1163        long c = 0;
1164        c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
1165        z[zOff + 0] = (int)c;
1166        c >>= 32;
1167        c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
1168        z[zOff + 1] = (int)c;
1169        c >>= 32;
1170        c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
1171        z[zOff + 2] = (int)c;
1172        c >>= 32;
1173        c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
1174        z[zOff + 3] = (int)c;
1175        c >>= 32;
1176        c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
1177        z[zOff + 4] = (int)c;
1178        c >>= 32;
1179        c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
1180        z[zOff + 5] = (int)c;
1181        c >>= 32;
1182        c += (x[xOff + 6] & M) - (y[yOff + 6] & M);
1183        z[zOff + 6] = (int)c;
1184        c >>= 32;
1185        c += (x[xOff + 7] & M) - (y[yOff + 7] & M);
1186        z[zOff + 7] = (int)c;
1187        c >>= 32;
1188        return (int)c;
1189    }
1190
1191    public static int subBothFrom(int[] x, int[] y, int[] z)
1192    {
1193        long c = 0;
1194        c += (z[0] & M) - (x[0] & M) - (y[0] & M);
1195        z[0] = (int)c;
1196        c >>= 32;
1197        c += (z[1] & M) - (x[1] & M) - (y[1] & M);
1198        z[1] = (int)c;
1199        c >>= 32;
1200        c += (z[2] & M) - (x[2] & M) - (y[2] & M);
1201        z[2] = (int)c;
1202        c >>= 32;
1203        c += (z[3] & M) - (x[3] & M) - (y[3] & M);
1204        z[3] = (int)c;
1205        c >>= 32;
1206        c += (z[4] & M) - (x[4] & M) - (y[4] & M);
1207        z[4] = (int)c;
1208        c >>= 32;
1209        c += (z[5] & M) - (x[5] & M) - (y[5] & M);
1210        z[5] = (int)c;
1211        c >>= 32;
1212        c += (z[6] & M) - (x[6] & M) - (y[6] & M);
1213        z[6] = (int)c;
1214        c >>= 32;
1215        c += (z[7] & M) - (x[7] & M) - (y[7] & M);
1216        z[7] = (int)c;
1217        c >>= 32;
1218        return (int)c;
1219    }
1220
1221    public static int subFrom(int[] x, int[] z)
1222    {
1223        long c = 0;
1224        c += (z[0] & M) - (x[0] & M);
1225        z[0] = (int)c;
1226        c >>= 32;
1227        c += (z[1] & M) - (x[1] & M);
1228        z[1] = (int)c;
1229        c >>= 32;
1230        c += (z[2] & M) - (x[2] & M);
1231        z[2] = (int)c;
1232        c >>= 32;
1233        c += (z[3] & M) - (x[3] & M);
1234        z[3] = (int)c;
1235        c >>= 32;
1236        c += (z[4] & M) - (x[4] & M);
1237        z[4] = (int)c;
1238        c >>= 32;
1239        c += (z[5] & M) - (x[5] & M);
1240        z[5] = (int)c;
1241        c >>= 32;
1242        c += (z[6] & M) - (x[6] & M);
1243        z[6] = (int)c;
1244        c >>= 32;
1245        c += (z[7] & M) - (x[7] & M);
1246        z[7] = (int)c;
1247        c >>= 32;
1248        return (int)c;
1249    }
1250
1251    public static int subFrom(int[] x, int xOff, int[] z, int zOff)
1252    {
1253        long c = 0;
1254        c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
1255        z[zOff + 0] = (int)c;
1256        c >>= 32;
1257        c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
1258        z[zOff + 1] = (int)c;
1259        c >>= 32;
1260        c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
1261        z[zOff + 2] = (int)c;
1262        c >>= 32;
1263        c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
1264        z[zOff + 3] = (int)c;
1265        c >>= 32;
1266        c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
1267        z[zOff + 4] = (int)c;
1268        c >>= 32;
1269        c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
1270        z[zOff + 5] = (int)c;
1271        c >>= 32;
1272        c += (z[zOff + 6] & M) - (x[xOff + 6] & M);
1273        z[zOff + 6] = (int)c;
1274        c >>= 32;
1275        c += (z[zOff + 7] & M) - (x[xOff + 7] & M);
1276        z[zOff + 7] = (int)c;
1277        c >>= 32;
1278        return (int)c;
1279    }
1280
1281    public static BigInteger toBigInteger(int[] x)
1282    {
1283        byte[] bs = new byte[32];
1284        for (int i = 0; i < 8; ++i)
1285        {
1286            int x_i = x[i];
1287            if (x_i != 0)
1288            {
1289                Pack.intToBigEndian(x_i, bs, (7 - i) << 2);
1290            }
1291        }
1292        return new BigInteger(1, bs);
1293    }
1294
1295    public static void zero(int[] z)
1296    {
1297        z[0] = 0;
1298        z[1] = 0;
1299        z[2] = 0;
1300        z[3] = 0;
1301        z[4] = 0;
1302        z[5] = 0;
1303        z[6] = 0;
1304        z[7] = 0;
1305    }
1306}
1307