1package org.bouncycastle.math.raw;
2
3import java.math.BigInteger;
4
5import org.bouncycastle.util.Pack;
6
7public abstract class Nat192
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        return (int)c;
33    }
34
35    public static int addBothTo(int[] x, int[] y, int[] z)
36    {
37        long c = 0;
38        c += (x[0] & M) + (y[0] & M) + (z[0] & M);
39        z[0] = (int)c;
40        c >>>= 32;
41        c += (x[1] & M) + (y[1] & M) + (z[1] & M);
42        z[1] = (int)c;
43        c >>>= 32;
44        c += (x[2] & M) + (y[2] & M) + (z[2] & M);
45        z[2] = (int)c;
46        c >>>= 32;
47        c += (x[3] & M) + (y[3] & M) + (z[3] & M);
48        z[3] = (int)c;
49        c >>>= 32;
50        c += (x[4] & M) + (y[4] & M) + (z[4] & M);
51        z[4] = (int)c;
52        c >>>= 32;
53        c += (x[5] & M) + (y[5] & M) + (z[5] & M);
54        z[5] = (int)c;
55        c >>>= 32;
56        return (int)c;
57    }
58
59    public static int addTo(int[] x, int[] z)
60    {
61        long c = 0;
62        c += (x[0] & M) + (z[0] & M);
63        z[0] = (int)c;
64        c >>>= 32;
65        c += (x[1] & M) + (z[1] & M);
66        z[1] = (int)c;
67        c >>>= 32;
68        c += (x[2] & M) + (z[2] & M);
69        z[2] = (int)c;
70        c >>>= 32;
71        c += (x[3] & M) + (z[3] & M);
72        z[3] = (int)c;
73        c >>>= 32;
74        c += (x[4] & M) + (z[4] & M);
75        z[4] = (int)c;
76        c >>>= 32;
77        c += (x[5] & M) + (z[5] & M);
78        z[5] = (int)c;
79        c >>>= 32;
80        return (int)c;
81    }
82
83    public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
84    {
85        long c = cIn & M;
86        c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
87        z[zOff + 0] = (int)c;
88        c >>>= 32;
89        c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
90        z[zOff + 1] = (int)c;
91        c >>>= 32;
92        c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
93        z[zOff + 2] = (int)c;
94        c >>>= 32;
95        c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
96        z[zOff + 3] = (int)c;
97        c >>>= 32;
98        c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
99        z[zOff + 4] = (int)c;
100        c >>>= 32;
101        c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
102        z[zOff + 5] = (int)c;
103        c >>>= 32;
104        return (int)c;
105    }
106
107    public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
108    {
109        long c = 0;
110        c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
111        u[uOff + 0] = (int)c;
112        v[vOff + 0] = (int)c;
113        c >>>= 32;
114        c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
115        u[uOff + 1] = (int)c;
116        v[vOff + 1] = (int)c;
117        c >>>= 32;
118        c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
119        u[uOff + 2] = (int)c;
120        v[vOff + 2] = (int)c;
121        c >>>= 32;
122        c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
123        u[uOff + 3] = (int)c;
124        v[vOff + 3] = (int)c;
125        c >>>= 32;
126        c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
127        u[uOff + 4] = (int)c;
128        v[vOff + 4] = (int)c;
129        c >>>= 32;
130        c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
131        u[uOff + 5] = (int)c;
132        v[vOff + 5] = (int)c;
133        c >>>= 32;
134        return (int)c;
135    }
136
137    public static void copy(int[] x, int[] z)
138    {
139        z[0] = x[0];
140        z[1] = x[1];
141        z[2] = x[2];
142        z[3] = x[3];
143        z[4] = x[4];
144        z[5] = x[5];
145    }
146
147    public static int[] create()
148    {
149        return new int[6];
150    }
151
152    public static int[] createExt()
153    {
154        return new int[12];
155    }
156
157    public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
158    {
159        boolean pos = gte(x, xOff, y, yOff);
160        if (pos)
161        {
162            sub(x, xOff, y, yOff, z, zOff);
163        }
164        else
165        {
166            sub(y, yOff, x, xOff, z, zOff);
167        }
168        return pos;
169    }
170
171    public static boolean eq(int[] x, int[] y)
172    {
173        for (int i = 5; i >= 0; --i)
174        {
175            if (x[i] != y[i])
176            {
177                return false;
178            }
179        }
180        return true;
181    }
182
183    public static int[] fromBigInteger(BigInteger x)
184    {
185        if (x.signum() < 0 || x.bitLength() > 192)
186        {
187            throw new IllegalArgumentException();
188        }
189
190        int[] z = create();
191        int i = 0;
192        while (x.signum() != 0)
193        {
194            z[i++] = x.intValue();
195            x = x.shiftRight(32);
196        }
197        return z;
198    }
199
200    public static int getBit(int[] x, int bit)
201    {
202        if (bit == 0)
203        {
204            return x[0] & 1;
205        }
206        int w = bit >> 5;
207        if (w < 0 || w >= 6)
208        {
209            return 0;
210        }
211        int b = bit & 31;
212        return (x[w] >>> b) & 1;
213    }
214
215    public static boolean gte(int[] x, int[] y)
216    {
217        for (int i = 5; i >= 0; --i)
218        {
219            int x_i = x[i] ^ Integer.MIN_VALUE;
220            int y_i = y[i] ^ Integer.MIN_VALUE;
221            if (x_i < y_i)
222                return false;
223            if (x_i > y_i)
224                return true;
225        }
226        return true;
227    }
228
229    public static boolean gte(int[] x, int xOff, int[] y, int yOff)
230    {
231        for (int i = 5; i >= 0; --i)
232        {
233            int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
234            int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
235            if (x_i < y_i)
236                return false;
237            if (x_i > y_i)
238                return true;
239        }
240        return true;
241    }
242
243    public static boolean isOne(int[] x)
244    {
245        if (x[0] != 1)
246        {
247            return false;
248        }
249        for (int i = 1; i < 6; ++i)
250        {
251            if (x[i] != 0)
252            {
253                return false;
254            }
255        }
256        return true;
257    }
258
259    public static boolean isZero(int[] x)
260    {
261        for (int i = 0; i < 6; ++i)
262        {
263            if (x[i] != 0)
264            {
265                return false;
266            }
267        }
268        return true;
269    }
270
271    public static void mul(int[] x, int[] y, int[] zz)
272    {
273        long y_0 = y[0] & M;
274        long y_1 = y[1] & M;
275        long y_2 = y[2] & M;
276        long y_3 = y[3] & M;
277        long y_4 = y[4] & M;
278        long y_5 = y[5] & M;
279
280        {
281            long c = 0, x_0 = x[0] & M;
282            c += x_0 * y_0;
283            zz[0] = (int)c;
284            c >>>= 32;
285            c += x_0 * y_1;
286            zz[1] = (int)c;
287            c >>>= 32;
288            c += x_0 * y_2;
289            zz[2] = (int)c;
290            c >>>= 32;
291            c += x_0 * y_3;
292            zz[3] = (int)c;
293            c >>>= 32;
294            c += x_0 * y_4;
295            zz[4] = (int)c;
296            c >>>= 32;
297            c += x_0 * y_5;
298            zz[5] = (int)c;
299            c >>>= 32;
300            zz[6] = (int)c;
301        }
302
303        for (int i = 1; i < 6; ++i)
304        {
305            long c = 0, x_i = x[i] & M;
306            c += x_i * y_0 + (zz[i + 0] & M);
307            zz[i + 0] = (int)c;
308            c >>>= 32;
309            c += x_i * y_1 + (zz[i + 1] & M);
310            zz[i + 1] = (int)c;
311            c >>>= 32;
312            c += x_i * y_2 + (zz[i + 2] & M);
313            zz[i + 2] = (int)c;
314            c >>>= 32;
315            c += x_i * y_3 + (zz[i + 3] & M);
316            zz[i + 3] = (int)c;
317            c >>>= 32;
318            c += x_i * y_4 + (zz[i + 4] & M);
319            zz[i + 4] = (int)c;
320            c >>>= 32;
321            c += x_i * y_5 + (zz[i + 5] & M);
322            zz[i + 5] = (int)c;
323            c >>>= 32;
324            zz[i + 6] = (int)c;
325        }
326    }
327
328    public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
329    {
330        long y_0 = y[yOff + 0] & M;
331        long y_1 = y[yOff + 1] & M;
332        long y_2 = y[yOff + 2] & M;
333        long y_3 = y[yOff + 3] & M;
334        long y_4 = y[yOff + 4] & M;
335        long y_5 = y[yOff + 5] & M;
336
337        {
338            long c = 0, x_0 = x[xOff + 0] & M;
339            c += x_0 * y_0;
340            zz[zzOff + 0] = (int)c;
341            c >>>= 32;
342            c += x_0 * y_1;
343            zz[zzOff + 1] = (int)c;
344            c >>>= 32;
345            c += x_0 * y_2;
346            zz[zzOff + 2] = (int)c;
347            c >>>= 32;
348            c += x_0 * y_3;
349            zz[zzOff + 3] = (int)c;
350            c >>>= 32;
351            c += x_0 * y_4;
352            zz[zzOff + 4] = (int)c;
353            c >>>= 32;
354            c += x_0 * y_5;
355            zz[zzOff + 5] = (int)c;
356            c >>>= 32;
357            zz[zzOff + 6] = (int)c;
358        }
359
360        for (int i = 1; i < 6; ++i)
361        {
362            ++zzOff;
363            long c = 0, x_i = x[xOff + i] & M;
364            c += x_i * y_0 + (zz[zzOff + 0] & M);
365            zz[zzOff + 0] = (int)c;
366            c >>>= 32;
367            c += x_i * y_1 + (zz[zzOff + 1] & M);
368            zz[zzOff + 1] = (int)c;
369            c >>>= 32;
370            c += x_i * y_2 + (zz[zzOff + 2] & M);
371            zz[zzOff + 2] = (int)c;
372            c >>>= 32;
373            c += x_i * y_3 + (zz[zzOff + 3] & M);
374            zz[zzOff + 3] = (int)c;
375            c >>>= 32;
376            c += x_i * y_4 + (zz[zzOff + 4] & M);
377            zz[zzOff + 4] = (int)c;
378            c >>>= 32;
379            c += x_i * y_5 + (zz[zzOff + 5] & M);
380            zz[zzOff + 5] = (int)c;
381            c >>>= 32;
382            zz[zzOff + 6] = (int)c;
383        }
384    }
385
386    public static int mulAddTo(int[] x, int[] y, int[] zz)
387    {
388        long y_0 = y[0] & M;
389        long y_1 = y[1] & M;
390        long y_2 = y[2] & M;
391        long y_3 = y[3] & M;
392        long y_4 = y[4] & M;
393        long y_5 = y[5] & M;
394
395        long zc = 0;
396        for (int i = 0; i < 6; ++i)
397        {
398            long c = 0, x_i = x[i] & M;
399            c += x_i * y_0 + (zz[i + 0] & M);
400            zz[i + 0] = (int)c;
401            c >>>= 32;
402            c += x_i * y_1 + (zz[i + 1] & M);
403            zz[i + 1] = (int)c;
404            c >>>= 32;
405            c += x_i * y_2 + (zz[i + 2] & M);
406            zz[i + 2] = (int)c;
407            c >>>= 32;
408            c += x_i * y_3 + (zz[i + 3] & M);
409            zz[i + 3] = (int)c;
410            c >>>= 32;
411            c += x_i * y_4 + (zz[i + 4] & M);
412            zz[i + 4] = (int)c;
413            c >>>= 32;
414            c += x_i * y_5 + (zz[i + 5] & M);
415            zz[i + 5] = (int)c;
416            c >>>= 32;
417            c += zc + (zz[i + 6] & M);
418            zz[i + 6] = (int)c;
419            zc = c >>> 32;
420        }
421        return (int)zc;
422    }
423
424    public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
425    {
426        long y_0 = y[yOff + 0] & M;
427        long y_1 = y[yOff + 1] & M;
428        long y_2 = y[yOff + 2] & M;
429        long y_3 = y[yOff + 3] & M;
430        long y_4 = y[yOff + 4] & M;
431        long y_5 = y[yOff + 5] & M;
432
433        long zc = 0;
434        for (int i = 0; i < 6; ++i)
435        {
436            long c = 0, x_i = x[xOff + i] & M;
437            c += x_i * y_0 + (zz[zzOff + 0] & M);
438            zz[zzOff + 0] = (int)c;
439            c >>>= 32;
440            c += x_i * y_1 + (zz[zzOff + 1] & M);
441            zz[zzOff + 1] = (int)c;
442            c >>>= 32;
443            c += x_i * y_2 + (zz[zzOff + 2] & M);
444            zz[zzOff + 2] = (int)c;
445            c >>>= 32;
446            c += x_i * y_3 + (zz[zzOff + 3] & M);
447            zz[zzOff + 3] = (int)c;
448            c >>>= 32;
449            c += x_i * y_4 + (zz[zzOff + 4] & M);
450            zz[zzOff + 4] = (int)c;
451            c >>>= 32;
452            c += x_i * y_5 + (zz[zzOff + 5] & M);
453            zz[zzOff + 5] = (int)c;
454            c >>>= 32;
455            c += zc + (zz[zzOff + 6] & M);
456            zz[zzOff + 6] = (int)c;
457            zc = c >>> 32;
458            ++zzOff;
459        }
460        return (int)zc;
461    }
462
463    public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
464    {
465        // assert w >>> 31 == 0;
466
467        long c = 0, wVal = w & M;
468        long x0 = x[xOff + 0] & M;
469        c += wVal * x0 + (y[yOff + 0] & M);
470        z[zOff + 0] = (int)c;
471        c >>>= 32;
472        long x1 = x[xOff + 1] & M;
473        c += wVal * x1 + x0 + (y[yOff + 1] & M);
474        z[zOff + 1] = (int)c;
475        c >>>= 32;
476        long x2 = x[xOff + 2] & M;
477        c += wVal * x2 + x1 + (y[yOff + 2] & M);
478        z[zOff + 2] = (int)c;
479        c >>>= 32;
480        long x3 = x[xOff + 3] & M;
481        c += wVal * x3 + x2 + (y[yOff + 3] & M);
482        z[zOff + 3] = (int)c;
483        c >>>= 32;
484        long x4 = x[xOff + 4] & M;
485        c += wVal * x4 + x3 + (y[yOff + 4] & M);
486        z[zOff + 4] = (int)c;
487        c >>>= 32;
488        long x5 = x[xOff + 5] & M;
489        c += wVal * x5 + x4 + (y[yOff + 5] & M);
490        z[zOff + 5] = (int)c;
491        c >>>= 32;
492        c += x5;
493        return c;
494    }
495
496    public static int mulWordAddExt(int x, int[] yy, int yyOff, int[] zz, int zzOff)
497    {
498        // assert yyOff <= 6;
499        // assert zzOff <= 6;
500        long c = 0, xVal = x & M;
501        c += xVal * (yy[yyOff + 0] & M) + (zz[zzOff + 0] & M);
502        zz[zzOff + 0] = (int)c;
503        c >>>= 32;
504        c += xVal * (yy[yyOff + 1] & M) + (zz[zzOff + 1] & M);
505        zz[zzOff + 1] = (int)c;
506        c >>>= 32;
507        c += xVal * (yy[yyOff + 2] & M) + (zz[zzOff + 2] & M);
508        zz[zzOff + 2] = (int)c;
509        c >>>= 32;
510        c += xVal * (yy[yyOff + 3] & M) + (zz[zzOff + 3] & M);
511        zz[zzOff + 3] = (int)c;
512        c >>>= 32;
513        c += xVal * (yy[yyOff + 4] & M) + (zz[zzOff + 4] & M);
514        zz[zzOff + 4] = (int)c;
515        c >>>= 32;
516        c += xVal * (yy[yyOff + 5] & M) + (zz[zzOff + 5] & M);
517        zz[zzOff + 5] = (int)c;
518        c >>>= 32;
519        return (int)c;
520    }
521
522    public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
523    {
524        // assert x >>> 31 == 0;
525        // assert zOff <= 2;
526
527        long c = 0, xVal = x & M;
528        long y00 = y & M;
529        c += xVal * y00 + (z[zOff + 0] & M);
530        z[zOff + 0] = (int)c;
531        c >>>= 32;
532        long y01 = y >>> 32;
533        c += xVal * y01 + y00 + (z[zOff + 1] & M);
534        z[zOff + 1] = (int)c;
535        c >>>= 32;
536        c += y01 + (z[zOff + 2] & M);
537        z[zOff + 2] = (int)c;
538        c >>>= 32;
539        c += (z[zOff + 3] & M);
540        z[zOff + 3] = (int)c;
541        c >>>= 32;
542        return c == 0 ? 0 : Nat.incAt(6, z, zOff, 4);
543    }
544
545    public static int mul33WordAdd(int x, int y, int[] z, int zOff)
546    {
547        // assert x >>> 31 == 0;
548        // assert zOff <= 3;
549
550        long c = 0, xVal = x & M, yVal = y & M;
551        c += yVal * xVal + (z[zOff + 0] & M);
552        z[zOff + 0] = (int)c;
553        c >>>= 32;
554        c += yVal + (z[zOff + 1] & M);
555        z[zOff + 1] = (int)c;
556        c >>>= 32;
557        c += (z[zOff + 2] & M);
558        z[zOff + 2] = (int)c;
559        c >>>= 32;
560        return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3);
561    }
562
563    public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
564    {
565        // assert zOff <= 3;
566        long c = 0, xVal = x & M;
567        c += xVal * (y & M) + (z[zOff + 0] & M);
568        z[zOff + 0] = (int)c;
569        c >>>= 32;
570        c += xVal * (y >>> 32) + (z[zOff + 1] & M);
571        z[zOff + 1] = (int)c;
572        c >>>= 32;
573        c += (z[zOff + 2] & M);
574        z[zOff + 2] = (int)c;
575        c >>>= 32;
576        return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3);
577    }
578
579    public static int mulWord(int x, int[] y, int[] z, int zOff)
580    {
581        long c = 0, xVal = x & M;
582        int i = 0;
583        do
584        {
585            c += xVal * (y[i] & M);
586            z[zOff + i] = (int)c;
587            c >>>= 32;
588        }
589        while (++i < 6);
590        return (int)c;
591    }
592
593    public static void square(int[] x, int[] zz)
594    {
595        long x_0 = x[0] & M;
596        long zz_1;
597
598        int c = 0, w;
599        {
600            int i = 5, j = 12;
601            do
602            {
603                long xVal = (x[i--] & M);
604                long p = xVal * xVal;
605                zz[--j] = (c << 31) | (int)(p >>> 33);
606                zz[--j] = (int)(p >>> 1);
607                c = (int)p;
608            }
609            while (i > 0);
610
611            {
612                long p = x_0 * x_0;
613                zz_1 = ((c << 31) & M) | (p >>> 33);
614                zz[0] = (int)p;
615                c = (int)(p >>> 32) & 1;
616            }
617        }
618
619        long x_1 = x[1] & M;
620        long zz_2 = zz[2] & M;
621
622        {
623            zz_1 += x_1 * x_0;
624            w = (int)zz_1;
625            zz[1] = (w << 1) | c;
626            c = w >>> 31;
627            zz_2 += zz_1 >>> 32;
628        }
629
630        long x_2 = x[2] & M;
631        long zz_3 = zz[3] & M;
632        long zz_4 = zz[4] & M;
633        {
634            zz_2 += x_2 * x_0;
635            w = (int)zz_2;
636            zz[2] = (w << 1) | c;
637            c = w >>> 31;
638            zz_3 += (zz_2 >>> 32) + x_2 * x_1;
639            zz_4 += zz_3 >>> 32;
640            zz_3 &= M;
641        }
642
643        long x_3 = x[3] & M;
644        long zz_5 = zz[5] & M;
645        long zz_6 = zz[6] & M;
646        {
647            zz_3 += x_3 * x_0;
648            w = (int)zz_3;
649            zz[3] = (w << 1) | c;
650            c = w >>> 31;
651            zz_4 += (zz_3 >>> 32) + x_3 * x_1;
652            zz_5 += (zz_4 >>> 32) + x_3 * x_2;
653            zz_4 &= M;
654            zz_6 += zz_5 >>> 32;
655            zz_5 &= M;
656        }
657
658        long x_4 = x[4] & M;
659        long zz_7 = zz[7] & M;
660        long zz_8 = zz[8] & M;
661        {
662            zz_4 += x_4 * x_0;
663            w = (int)zz_4;
664            zz[4] = (w << 1) | c;
665            c = w >>> 31;
666            zz_5 += (zz_4 >>> 32) + x_4 * x_1;
667            zz_6 += (zz_5 >>> 32) + x_4 * x_2;
668            zz_5 &= M;
669            zz_7 += (zz_6 >>> 32) + x_4 * x_3;
670            zz_6 &= M;
671            zz_8 += zz_7 >>> 32;
672            zz_7 &= M;
673        }
674
675        long x_5 = x[5] & M;
676        long zz_9 = zz[9] & M;
677        long zz_10 = zz[10] & M;
678        {
679            zz_5 += x_5 * x_0;
680            w = (int)zz_5;
681            zz[5] = (w << 1) | c;
682            c = w >>> 31;
683            zz_6 += (zz_5 >>> 32) + x_5 * x_1;
684            zz_7 += (zz_6 >>> 32) + x_5 * x_2;
685            zz_8 += (zz_7 >>> 32) + x_5 * x_3;
686            zz_9 += (zz_8 >>> 32) + x_5 * x_4;
687            zz_10 += zz_9 >>> 32;
688        }
689
690        w = (int)zz_6;
691        zz[6] = (w << 1) | c;
692        c = w >>> 31;
693        w = (int)zz_7;
694        zz[7] = (w << 1) | c;
695        c = w >>> 31;
696        w = (int)zz_8;
697        zz[8] = (w << 1) | c;
698        c = w >>> 31;
699        w = (int)zz_9;
700        zz[9] = (w << 1) | c;
701        c = w >>> 31;
702        w = (int)zz_10;
703        zz[10] = (w << 1) | c;
704        c = w >>> 31;
705        w = zz[11] + (int)(zz_10 >> 32);
706        zz[11] = (w << 1) | c;
707    }
708
709    public static void square(int[] x, int xOff, int[] zz, int zzOff)
710    {
711        long x_0 = x[xOff + 0] & M;
712        long zz_1;
713
714        int c = 0, w;
715        {
716            int i = 5, j = 12;
717            do
718            {
719                long xVal = (x[xOff + i--] & M);
720                long p = xVal * xVal;
721                zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
722                zz[zzOff + --j] = (int)(p >>> 1);
723                c = (int)p;
724            }
725            while (i > 0);
726
727            {
728                long p = x_0 * x_0;
729                zz_1 = ((c << 31) & M) | (p >>> 33);
730                zz[zzOff + 0] = (int)p;
731                c = (int)(p >>> 32) & 1;
732            }
733        }
734
735        long x_1 = x[xOff + 1] & M;
736        long zz_2 = zz[zzOff + 2] & M;
737
738        {
739            zz_1 += x_1 * x_0;
740            w = (int)zz_1;
741            zz[zzOff + 1] = (w << 1) | c;
742            c = w >>> 31;
743            zz_2 += zz_1 >>> 32;
744        }
745
746        long x_2 = x[xOff + 2] & M;
747        long zz_3 = zz[zzOff + 3] & M;
748        long zz_4 = zz[zzOff + 4] & M;
749        {
750            zz_2 += x_2 * x_0;
751            w = (int)zz_2;
752            zz[zzOff + 2] = (w << 1) | c;
753            c = w >>> 31;
754            zz_3 += (zz_2 >>> 32) + x_2 * x_1;
755            zz_4 += zz_3 >>> 32;
756            zz_3 &= M;
757        }
758
759        long x_3 = x[xOff + 3] & M;
760        long zz_5 = zz[zzOff + 5] & M;
761        long zz_6 = zz[zzOff + 6] & M;
762        {
763            zz_3 += x_3 * x_0;
764            w = (int)zz_3;
765            zz[zzOff + 3] = (w << 1) | c;
766            c = w >>> 31;
767            zz_4 += (zz_3 >>> 32) + x_3 * x_1;
768            zz_5 += (zz_4 >>> 32) + x_3 * x_2;
769            zz_4 &= M;
770            zz_6 += zz_5 >>> 32;
771            zz_5 &= M;
772        }
773
774        long x_4 = x[xOff + 4] & M;
775        long zz_7 = zz[zzOff + 7] & M;
776        long zz_8 = zz[zzOff + 8] & M;
777        {
778            zz_4 += x_4 * x_0;
779            w = (int)zz_4;
780            zz[zzOff + 4] = (w << 1) | c;
781            c = w >>> 31;
782            zz_5 += (zz_4 >>> 32) + x_4 * x_1;
783            zz_6 += (zz_5 >>> 32) + x_4 * x_2;
784            zz_5 &= M;
785            zz_7 += (zz_6 >>> 32) + x_4 * x_3;
786            zz_6 &= M;
787            zz_8 += zz_7 >>> 32;
788            zz_7 &= M;
789        }
790
791        long x_5 = x[xOff + 5] & M;
792        long zz_9 = zz[zzOff + 9] & M;
793        long zz_10 = zz[zzOff + 10] & M;
794        {
795            zz_5 += x_5 * x_0;
796            w = (int)zz_5;
797            zz[zzOff + 5] = (w << 1) | c;
798            c = w >>> 31;
799            zz_6 += (zz_5 >>> 32) + x_5 * x_1;
800            zz_7 += (zz_6 >>> 32) + x_5 * x_2;
801            zz_8 += (zz_7 >>> 32) + x_5 * x_3;
802            zz_9 += (zz_8 >>> 32) + x_5 * x_4;
803            zz_10 += zz_9 >>> 32;
804        }
805
806        w = (int)zz_6;
807        zz[zzOff + 6] = (w << 1) | c;
808        c = w >>> 31;
809        w = (int)zz_7;
810        zz[zzOff + 7] = (w << 1) | c;
811        c = w >>> 31;
812        w = (int)zz_8;
813        zz[zzOff + 8] = (w << 1) | c;
814        c = w >>> 31;
815        w = (int)zz_9;
816        zz[zzOff + 9] = (w << 1) | c;
817        c = w >>> 31;
818        w = (int)zz_10;
819        zz[zzOff + 10] = (w << 1) | c;
820        c = w >>> 31;
821        w = zz[zzOff + 11] + (int)(zz_10 >> 32);
822        zz[zzOff + 11] = (w << 1) | c;
823    }
824
825    public static int sub(int[] x, int[] y, int[] z)
826    {
827        long c = 0;
828        c += (x[0] & M) - (y[0] & M);
829        z[0] = (int)c;
830        c >>= 32;
831        c += (x[1] & M) - (y[1] & M);
832        z[1] = (int)c;
833        c >>= 32;
834        c += (x[2] & M) - (y[2] & M);
835        z[2] = (int)c;
836        c >>= 32;
837        c += (x[3] & M) - (y[3] & M);
838        z[3] = (int)c;
839        c >>= 32;
840        c += (x[4] & M) - (y[4] & M);
841        z[4] = (int)c;
842        c >>= 32;
843        c += (x[5] & M) - (y[5] & M);
844        z[5] = (int)c;
845        c >>= 32;
846        return (int)c;
847    }
848
849    public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
850    {
851        long c = 0;
852        c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
853        z[zOff + 0] = (int)c;
854        c >>= 32;
855        c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
856        z[zOff + 1] = (int)c;
857        c >>= 32;
858        c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
859        z[zOff + 2] = (int)c;
860        c >>= 32;
861        c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
862        z[zOff + 3] = (int)c;
863        c >>= 32;
864        c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
865        z[zOff + 4] = (int)c;
866        c >>= 32;
867        c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
868        z[zOff + 5] = (int)c;
869        c >>= 32;
870        return (int)c;
871    }
872
873    public static int subBothFrom(int[] x, int[] y, int[] z)
874    {
875        long c = 0;
876        c += (z[0] & M) - (x[0] & M) - (y[0] & M);
877        z[0] = (int)c;
878        c >>= 32;
879        c += (z[1] & M) - (x[1] & M) - (y[1] & M);
880        z[1] = (int)c;
881        c >>= 32;
882        c += (z[2] & M) - (x[2] & M) - (y[2] & M);
883        z[2] = (int)c;
884        c >>= 32;
885        c += (z[3] & M) - (x[3] & M) - (y[3] & M);
886        z[3] = (int)c;
887        c >>= 32;
888        c += (z[4] & M) - (x[4] & M) - (y[4] & M);
889        z[4] = (int)c;
890        c >>= 32;
891        c += (z[5] & M) - (x[5] & M) - (y[5] & M);
892        z[5] = (int)c;
893        c >>= 32;
894        return (int)c;
895    }
896
897    public static int subFrom(int[] x, int[] z)
898    {
899        long c = 0;
900        c += (z[0] & M) - (x[0] & M);
901        z[0] = (int)c;
902        c >>= 32;
903        c += (z[1] & M) - (x[1] & M);
904        z[1] = (int)c;
905        c >>= 32;
906        c += (z[2] & M) - (x[2] & M);
907        z[2] = (int)c;
908        c >>= 32;
909        c += (z[3] & M) - (x[3] & M);
910        z[3] = (int)c;
911        c >>= 32;
912        c += (z[4] & M) - (x[4] & M);
913        z[4] = (int)c;
914        c >>= 32;
915        c += (z[5] & M) - (x[5] & M);
916        z[5] = (int)c;
917        c >>= 32;
918        return (int)c;
919    }
920
921    public static int subFrom(int[] x, int xOff, int[] z, int zOff)
922    {
923        long c = 0;
924        c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
925        z[zOff + 0] = (int)c;
926        c >>= 32;
927        c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
928        z[zOff + 1] = (int)c;
929        c >>= 32;
930        c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
931        z[zOff + 2] = (int)c;
932        c >>= 32;
933        c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
934        z[zOff + 3] = (int)c;
935        c >>= 32;
936        c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
937        z[zOff + 4] = (int)c;
938        c >>= 32;
939        c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
940        z[zOff + 5] = (int)c;
941        c >>= 32;
942        return (int)c;
943    }
944
945    public static BigInteger toBigInteger(int[] x)
946    {
947        byte[] bs = new byte[24];
948        for (int i = 0; i < 6; ++i)
949        {
950            int x_i = x[i];
951            if (x_i != 0)
952            {
953                Pack.intToBigEndian(x_i, bs, (5 - i) << 2);
954            }
955        }
956        return new BigInteger(1, bs);
957    }
958
959    public static void zero(int[] z)
960    {
961        z[0] = 0;
962        z[1] = 0;
963        z[2] = 0;
964        z[3] = 0;
965        z[4] = 0;
966        z[5] = 0;
967    }
968}
969