Home | History | Annotate | Download | only in raw
      1 package org.bouncycastle.math.raw;
      2 
      3 import java.math.BigInteger;
      4 
      5 import org.bouncycastle.util.Pack;
      6 
      7 public 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 void copy64(long[] x, long[] z)
    242     {
    243         z[0] = x[0];
    244         z[1] = x[1];
    245         z[2] = x[2];
    246         z[3] = x[3];
    247     }
    248 
    249     public static int[] create()
    250     {
    251         return new int[8];
    252     }
    253 
    254     public static long[] create64()
    255     {
    256         return new long[4];
    257     }
    258 
    259     public static int[] createExt()
    260     {
    261         return new int[16];
    262     }
    263 
    264     public static long[] createExt64()
    265     {
    266         return new long[8];
    267     }
    268 
    269     public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
    270     {
    271         boolean pos = gte(x, xOff, y, yOff);
    272         if (pos)
    273         {
    274             sub(x, xOff, y, yOff, z, zOff);
    275         }
    276         else
    277         {
    278             sub(y, yOff, x, xOff, z, zOff);
    279         }
    280         return pos;
    281     }
    282 
    283     public static boolean eq(int[] x, int[] y)
    284     {
    285         for (int i = 7; i >= 0; --i)
    286         {
    287             if (x[i] != y[i])
    288             {
    289                 return false;
    290             }
    291         }
    292         return true;
    293     }
    294 
    295     public static boolean eq64(long[] x, long[] y)
    296     {
    297         for (int i = 3; i >= 0; --i)
    298         {
    299             if (x[i] != y[i])
    300             {
    301                 return false;
    302             }
    303         }
    304         return true;
    305     }
    306 
    307     public static int[] fromBigInteger(BigInteger x)
    308     {
    309         if (x.signum() < 0 || x.bitLength() > 256)
    310         {
    311             throw new IllegalArgumentException();
    312         }
    313 
    314         int[] z = create();
    315         int i = 0;
    316         while (x.signum() != 0)
    317         {
    318             z[i++] = x.intValue();
    319             x = x.shiftRight(32);
    320         }
    321         return z;
    322     }
    323 
    324     public static long[] fromBigInteger64(BigInteger x)
    325     {
    326         if (x.signum() < 0 || x.bitLength() > 256)
    327         {
    328             throw new IllegalArgumentException();
    329         }
    330 
    331         long[] z = create64();
    332         int i = 0;
    333         while (x.signum() != 0)
    334         {
    335             z[i++] = x.longValue();
    336             x = x.shiftRight(64);
    337         }
    338         return z;
    339     }
    340 
    341     public static int getBit(int[] x, int bit)
    342     {
    343         if (bit == 0)
    344         {
    345             return x[0] & 1;
    346         }
    347         if ((bit & 255) != bit)
    348         {
    349             return 0;
    350         }
    351         int w = bit >>> 5;
    352         int b = bit & 31;
    353         return (x[w] >>> b) & 1;
    354     }
    355 
    356     public static boolean gte(int[] x, int[] y)
    357     {
    358         for (int i = 7; i >= 0; --i)
    359         {
    360             int x_i = x[i] ^ Integer.MIN_VALUE;
    361             int y_i = y[i] ^ Integer.MIN_VALUE;
    362             if (x_i < y_i)
    363                 return false;
    364             if (x_i > y_i)
    365                 return true;
    366         }
    367         return true;
    368     }
    369 
    370     public static boolean gte(int[] x, int xOff, int[] y, int yOff)
    371     {
    372         for (int i = 7; i >= 0; --i)
    373         {
    374             int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
    375             int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
    376             if (x_i < y_i)
    377                 return false;
    378             if (x_i > y_i)
    379                 return true;
    380         }
    381         return true;
    382     }
    383 
    384     public static boolean isOne(int[] x)
    385     {
    386         if (x[0] != 1)
    387         {
    388             return false;
    389         }
    390         for (int i = 1; i < 8; ++i)
    391         {
    392             if (x[i] != 0)
    393             {
    394                 return false;
    395             }
    396         }
    397         return true;
    398     }
    399 
    400     public static boolean isOne64(long[] x)
    401     {
    402         if (x[0] != 1L)
    403         {
    404             return false;
    405         }
    406         for (int i = 1; i < 4; ++i)
    407         {
    408             if (x[i] != 0L)
    409             {
    410                 return false;
    411             }
    412         }
    413         return true;
    414     }
    415 
    416     public static boolean isZero(int[] x)
    417     {
    418         for (int i = 0; i < 8; ++i)
    419         {
    420             if (x[i] != 0)
    421             {
    422                 return false;
    423             }
    424         }
    425         return true;
    426     }
    427 
    428     public static boolean isZero64(long[] x)
    429     {
    430         for (int i = 0; i < 4; ++i)
    431         {
    432             if (x[i] != 0L)
    433             {
    434                 return false;
    435             }
    436         }
    437         return true;
    438     }
    439 
    440     public static void mul(int[] x, int[] y, int[] zz)
    441     {
    442         long y_0 = y[0] & M;
    443         long y_1 = y[1] & M;
    444         long y_2 = y[2] & M;
    445         long y_3 = y[3] & M;
    446         long y_4 = y[4] & M;
    447         long y_5 = y[5] & M;
    448         long y_6 = y[6] & M;
    449         long y_7 = y[7] & M;
    450 
    451         {
    452             long c = 0, x_0 = x[0] & M;
    453             c += x_0 * y_0;
    454             zz[0] = (int)c;
    455             c >>>= 32;
    456             c += x_0 * y_1;
    457             zz[1] = (int)c;
    458             c >>>= 32;
    459             c += x_0 * y_2;
    460             zz[2] = (int)c;
    461             c >>>= 32;
    462             c += x_0 * y_3;
    463             zz[3] = (int)c;
    464             c >>>= 32;
    465             c += x_0 * y_4;
    466             zz[4] = (int)c;
    467             c >>>= 32;
    468             c += x_0 * y_5;
    469             zz[5] = (int)c;
    470             c >>>= 32;
    471             c += x_0 * y_6;
    472             zz[6] = (int)c;
    473             c >>>= 32;
    474             c += x_0 * y_7;
    475             zz[7] = (int)c;
    476             c >>>= 32;
    477             zz[8] = (int)c;
    478         }
    479 
    480         for (int i = 1; i < 8; ++i)
    481         {
    482             long c = 0, x_i = x[i] & M;
    483             c += x_i * y_0 + (zz[i + 0] & M);
    484             zz[i + 0] = (int)c;
    485             c >>>= 32;
    486             c += x_i * y_1 + (zz[i + 1] & M);
    487             zz[i + 1] = (int)c;
    488             c >>>= 32;
    489             c += x_i * y_2 + (zz[i + 2] & M);
    490             zz[i + 2] = (int)c;
    491             c >>>= 32;
    492             c += x_i * y_3 + (zz[i + 3] & M);
    493             zz[i + 3] = (int)c;
    494             c >>>= 32;
    495             c += x_i * y_4 + (zz[i + 4] & M);
    496             zz[i + 4] = (int)c;
    497             c >>>= 32;
    498             c += x_i * y_5 + (zz[i + 5] & M);
    499             zz[i + 5] = (int)c;
    500             c >>>= 32;
    501             c += x_i * y_6 + (zz[i + 6] & M);
    502             zz[i + 6] = (int)c;
    503             c >>>= 32;
    504             c += x_i * y_7 + (zz[i + 7] & M);
    505             zz[i + 7] = (int)c;
    506             c >>>= 32;
    507             zz[i + 8] = (int)c;
    508         }
    509     }
    510 
    511     public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
    512     {
    513         long y_0 = y[yOff + 0] & M;
    514         long y_1 = y[yOff + 1] & M;
    515         long y_2 = y[yOff + 2] & M;
    516         long y_3 = y[yOff + 3] & M;
    517         long y_4 = y[yOff + 4] & M;
    518         long y_5 = y[yOff + 5] & M;
    519         long y_6 = y[yOff + 6] & M;
    520         long y_7 = y[yOff + 7] & M;
    521 
    522         {
    523             long c = 0, x_0 = x[xOff + 0] & M;
    524             c += x_0 * y_0;
    525             zz[zzOff + 0] = (int)c;
    526             c >>>= 32;
    527             c += x_0 * y_1;
    528             zz[zzOff + 1] = (int)c;
    529             c >>>= 32;
    530             c += x_0 * y_2;
    531             zz[zzOff + 2] = (int)c;
    532             c >>>= 32;
    533             c += x_0 * y_3;
    534             zz[zzOff + 3] = (int)c;
    535             c >>>= 32;
    536             c += x_0 * y_4;
    537             zz[zzOff + 4] = (int)c;
    538             c >>>= 32;
    539             c += x_0 * y_5;
    540             zz[zzOff + 5] = (int)c;
    541             c >>>= 32;
    542             c += x_0 * y_6;
    543             zz[zzOff + 6] = (int)c;
    544             c >>>= 32;
    545             c += x_0 * y_7;
    546             zz[zzOff + 7] = (int)c;
    547             c >>>= 32;
    548             zz[zzOff + 8] = (int)c;
    549         }
    550 
    551         for (int i = 1; i < 8; ++i)
    552         {
    553             ++zzOff;
    554             long c = 0, x_i = x[xOff + i] & M;
    555             c += x_i * y_0 + (zz[zzOff + 0] & M);
    556             zz[zzOff + 0] = (int)c;
    557             c >>>= 32;
    558             c += x_i * y_1 + (zz[zzOff + 1] & M);
    559             zz[zzOff + 1] = (int)c;
    560             c >>>= 32;
    561             c += x_i * y_2 + (zz[zzOff + 2] & M);
    562             zz[zzOff + 2] = (int)c;
    563             c >>>= 32;
    564             c += x_i * y_3 + (zz[zzOff + 3] & M);
    565             zz[zzOff + 3] = (int)c;
    566             c >>>= 32;
    567             c += x_i * y_4 + (zz[zzOff + 4] & M);
    568             zz[zzOff + 4] = (int)c;
    569             c >>>= 32;
    570             c += x_i * y_5 + (zz[zzOff + 5] & M);
    571             zz[zzOff + 5] = (int)c;
    572             c >>>= 32;
    573             c += x_i * y_6 + (zz[zzOff + 6] & M);
    574             zz[zzOff + 6] = (int)c;
    575             c >>>= 32;
    576             c += x_i * y_7 + (zz[zzOff + 7] & M);
    577             zz[zzOff + 7] = (int)c;
    578             c >>>= 32;
    579             zz[zzOff + 8] = (int)c;
    580         }
    581     }
    582 
    583     public static int mulAddTo(int[] x, int[] y, int[] zz)
    584     {
    585         long y_0 = y[0] & M;
    586         long y_1 = y[1] & M;
    587         long y_2 = y[2] & M;
    588         long y_3 = y[3] & M;
    589         long y_4 = y[4] & M;
    590         long y_5 = y[5] & M;
    591         long y_6 = y[6] & M;
    592         long y_7 = y[7] & M;
    593 
    594         long zc = 0;
    595         for (int i = 0; i < 8; ++i)
    596         {
    597             long c = 0, x_i = x[i] & M;
    598             c += x_i * y_0 + (zz[i + 0] & M);
    599             zz[i + 0] = (int)c;
    600             c >>>= 32;
    601             c += x_i * y_1 + (zz[i + 1] & M);
    602             zz[i + 1] = (int)c;
    603             c >>>= 32;
    604             c += x_i * y_2 + (zz[i + 2] & M);
    605             zz[i + 2] = (int)c;
    606             c >>>= 32;
    607             c += x_i * y_3 + (zz[i + 3] & M);
    608             zz[i + 3] = (int)c;
    609             c >>>= 32;
    610             c += x_i * y_4 + (zz[i + 4] & M);
    611             zz[i + 4] = (int)c;
    612             c >>>= 32;
    613             c += x_i * y_5 + (zz[i + 5] & M);
    614             zz[i + 5] = (int)c;
    615             c >>>= 32;
    616             c += x_i * y_6 + (zz[i + 6] & M);
    617             zz[i + 6] = (int)c;
    618             c >>>= 32;
    619             c += x_i * y_7 + (zz[i + 7] & M);
    620             zz[i + 7] = (int)c;
    621             c >>>= 32;
    622             c += zc + (zz[i + 8] & M);
    623             zz[i + 8] = (int)c;
    624             zc = c >>> 32;
    625         }
    626         return (int)zc;
    627     }
    628 
    629     public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
    630     {
    631         long y_0 = y[yOff + 0] & M;
    632         long y_1 = y[yOff + 1] & M;
    633         long y_2 = y[yOff + 2] & M;
    634         long y_3 = y[yOff + 3] & M;
    635         long y_4 = y[yOff + 4] & M;
    636         long y_5 = y[yOff + 5] & M;
    637         long y_6 = y[yOff + 6] & M;
    638         long y_7 = y[yOff + 7] & M;
    639 
    640         long zc = 0;
    641         for (int i = 0; i < 8; ++i)
    642         {
    643             long c = 0, x_i = x[xOff + i] & M;
    644             c += x_i * y_0 + (zz[zzOff + 0] & M);
    645             zz[zzOff + 0] = (int)c;
    646             c >>>= 32;
    647             c += x_i * y_1 + (zz[zzOff + 1] & M);
    648             zz[zzOff + 1] = (int)c;
    649             c >>>= 32;
    650             c += x_i * y_2 + (zz[zzOff + 2] & M);
    651             zz[zzOff + 2] = (int)c;
    652             c >>>= 32;
    653             c += x_i * y_3 + (zz[zzOff + 3] & M);
    654             zz[zzOff + 3] = (int)c;
    655             c >>>= 32;
    656             c += x_i * y_4 + (zz[zzOff + 4] & M);
    657             zz[zzOff + 4] = (int)c;
    658             c >>>= 32;
    659             c += x_i * y_5 + (zz[zzOff + 5] & M);
    660             zz[zzOff + 5] = (int)c;
    661             c >>>= 32;
    662             c += x_i * y_6 + (zz[zzOff + 6] & M);
    663             zz[zzOff + 6] = (int)c;
    664             c >>>= 32;
    665             c += x_i * y_7 + (zz[zzOff + 7] & M);
    666             zz[zzOff + 7] = (int)c;
    667             c >>>= 32;
    668             c += zc + (zz[zzOff + 8] & M);
    669             zz[zzOff + 8] = (int)c;
    670             zc = c >>> 32;
    671             ++zzOff;
    672         }
    673         return (int)zc;
    674     }
    675 
    676     public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
    677     {
    678         // assert w >>> 31 == 0;
    679 
    680         long c = 0, wVal = w & M;
    681         long x0 = x[xOff + 0] & M;
    682         c += wVal * x0 + (y[yOff + 0] & M);
    683         z[zOff + 0] = (int)c;
    684         c >>>= 32;
    685         long x1 = x[xOff + 1] & M;
    686         c += wVal * x1 + x0 + (y[yOff + 1] & M);
    687         z[zOff + 1] = (int)c;
    688         c >>>= 32;
    689         long x2 = x[xOff + 2] & M;
    690         c += wVal * x2 + x1 + (y[yOff + 2] & M);
    691         z[zOff + 2] = (int)c;
    692         c >>>= 32;
    693         long x3 = x[xOff + 3] & M;
    694         c += wVal * x3 + x2 + (y[yOff + 3] & M);
    695         z[zOff + 3] = (int)c;
    696         c >>>= 32;
    697         long x4 = x[xOff + 4] & M;
    698         c += wVal * x4 + x3 + (y[yOff + 4] & M);
    699         z[zOff + 4] = (int)c;
    700         c >>>= 32;
    701         long x5 = x[xOff + 5] & M;
    702         c += wVal * x5 + x4 + (y[yOff + 5] & M);
    703         z[zOff + 5] = (int)c;
    704         c >>>= 32;
    705         long x6 = x[xOff + 6] & M;
    706         c += wVal * x6 + x5 + (y[yOff + 6] & M);
    707         z[zOff + 6] = (int)c;
    708         c >>>= 32;
    709         long x7 = x[xOff + 7] & M;
    710         c += wVal * x7 + x6 + (y[yOff + 7] & M);
    711         z[zOff + 7] = (int)c;
    712         c >>>= 32;
    713         c += x7;
    714         return c;
    715     }
    716 
    717     public static int mulByWord(int x, int[] z)
    718     {
    719         long c = 0, xVal = x & M;
    720         c += xVal * (z[0] & M);
    721         z[0] = (int)c;
    722         c >>>= 32;
    723         c += xVal * (z[1] & M);
    724         z[1] = (int)c;
    725         c >>>= 32;
    726         c += xVal * (z[2] & M);
    727         z[2] = (int)c;
    728         c >>>= 32;
    729         c += xVal * (z[3] & M);
    730         z[3] = (int)c;
    731         c >>>= 32;
    732         c += xVal * (z[4] & M);
    733         z[4] = (int)c;
    734         c >>>= 32;
    735         c += xVal * (z[5] & M);
    736         z[5] = (int)c;
    737         c >>>= 32;
    738         c += xVal * (z[6] & M);
    739         z[6] = (int)c;
    740         c >>>= 32;
    741         c += xVal * (z[7] & M);
    742         z[7] = (int)c;
    743         c >>>= 32;
    744         return (int)c;
    745     }
    746 
    747     public static int mulByWordAddTo(int x, int[] y, int[] z)
    748     {
    749         long c = 0, xVal = x & M;
    750         c += xVal * (z[0] & M) + (y[0] & M);
    751         z[0] = (int)c;
    752         c >>>= 32;
    753         c += xVal * (z[1] & M) + (y[1] & M);
    754         z[1] = (int)c;
    755         c >>>= 32;
    756         c += xVal * (z[2] & M) + (y[2] & M);
    757         z[2] = (int)c;
    758         c >>>= 32;
    759         c += xVal * (z[3] & M) + (y[3] & M);
    760         z[3] = (int)c;
    761         c >>>= 32;
    762         c += xVal * (z[4] & M) + (y[4] & M);
    763         z[4] = (int)c;
    764         c >>>= 32;
    765         c += xVal * (z[5] & M) + (y[5] & M);
    766         z[5] = (int)c;
    767         c >>>= 32;
    768         c += xVal * (z[6] & M) + (y[6] & M);
    769         z[6] = (int)c;
    770         c >>>= 32;
    771         c += xVal * (z[7] & M) + (y[7] & M);
    772         z[7] = (int)c;
    773         c >>>= 32;
    774         return (int)c;
    775     }
    776 
    777     public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff)
    778     {
    779         long c = 0, xVal = x & M;
    780         c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M);
    781         z[zOff + 0] = (int)c;
    782         c >>>= 32;
    783         c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M);
    784         z[zOff + 1] = (int)c;
    785         c >>>= 32;
    786         c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M);
    787         z[zOff + 2] = (int)c;
    788         c >>>= 32;
    789         c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M);
    790         z[zOff + 3] = (int)c;
    791         c >>>= 32;
    792         c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M);
    793         z[zOff + 4] = (int)c;
    794         c >>>= 32;
    795         c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M);
    796         z[zOff + 5] = (int)c;
    797         c >>>= 32;
    798         c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M);
    799         z[zOff + 6] = (int)c;
    800         c >>>= 32;
    801         c += xVal * (y[yOff + 7] & M) + (z[zOff + 7] & M);
    802         z[zOff + 7] = (int)c;
    803         c >>>= 32;
    804         return (int)c;
    805     }
    806 
    807     public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
    808     {
    809         // assert x >>> 31 == 0;
    810         // assert zOff <= 4;
    811 
    812         long c = 0, xVal = x & M;
    813         long y00 = y & M;
    814         c += xVal * y00 + (z[zOff + 0] & M);
    815         z[zOff + 0] = (int)c;
    816         c >>>= 32;
    817         long y01 = y >>> 32;
    818         c += xVal * y01 + y00 + (z[zOff + 1] & M);
    819         z[zOff + 1] = (int)c;
    820         c >>>= 32;
    821         c += y01 + (z[zOff + 2] & M);
    822         z[zOff + 2] = (int)c;
    823         c >>>= 32;
    824         c += (z[zOff + 3] & M);
    825         z[zOff + 3] = (int)c;
    826         c >>>= 32;
    827         return c == 0 ? 0 : Nat.incAt(8, z, zOff, 4);
    828     }
    829 
    830     public static int mul33WordAdd(int x, int y, int[] z, int zOff)
    831     {
    832         // assert x >>> 31 == 0;
    833         // assert zOff <= 5;
    834 
    835         long c = 0, xVal = x & M, yVal = y & M;
    836         c += yVal * xVal + (z[zOff + 0] & M);
    837         z[zOff + 0] = (int)c;
    838         c >>>= 32;
    839         c += yVal + (z[zOff + 1] & M);
    840         z[zOff + 1] = (int)c;
    841         c >>>= 32;
    842         c += (z[zOff + 2] & M);
    843         z[zOff + 2] = (int)c;
    844         c >>>= 32;
    845         return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
    846     }
    847 
    848     public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
    849     {
    850         // assert zOff <= 5;
    851         long c = 0, xVal = x & M;
    852         c += xVal * (y & M) + (z[zOff + 0] & M);
    853         z[zOff + 0] = (int)c;
    854         c >>>= 32;
    855         c += xVal * (y >>> 32) + (z[zOff + 1] & M);
    856         z[zOff + 1] = (int)c;
    857         c >>>= 32;
    858         c += (z[zOff + 2] & M);
    859         z[zOff + 2] = (int)c;
    860         c >>>= 32;
    861         return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
    862     }
    863 
    864     public static int mulWord(int x, int[] y, int[] z, int zOff)
    865     {
    866         long c = 0, xVal = x & M;
    867         int i = 0;
    868         do
    869         {
    870             c += xVal * (y[i] & M);
    871             z[zOff + i] = (int)c;
    872             c >>>= 32;
    873         }
    874         while (++i < 8);
    875         return (int)c;
    876     }
    877 
    878     public static void square(int[] x, int[] zz)
    879     {
    880         long x_0 = x[0] & M;
    881         long zz_1;
    882 
    883         int c = 0, w;
    884         {
    885             int i = 7, j = 16;
    886             do
    887             {
    888                 long xVal = (x[i--] & M);
    889                 long p = xVal * xVal;
    890                 zz[--j] = (c << 31) | (int)(p >>> 33);
    891                 zz[--j] = (int)(p >>> 1);
    892                 c = (int)p;
    893             }
    894             while (i > 0);
    895 
    896             {
    897                 long p = x_0 * x_0;
    898                 zz_1 = ((c << 31) & M) | (p >>> 33);
    899                 zz[0] = (int)p;
    900                 c = (int)(p >>> 32) & 1;
    901             }
    902         }
    903 
    904         long x_1 = x[1] & M;
    905         long zz_2 = zz[2] & M;
    906 
    907         {
    908             zz_1 += x_1 * x_0;
    909             w = (int)zz_1;
    910             zz[1] = (w << 1) | c;
    911             c = w >>> 31;
    912             zz_2 += zz_1 >>> 32;
    913         }
    914 
    915         long x_2 = x[2] & M;
    916         long zz_3 = zz[3] & M;
    917         long zz_4 = zz[4] & M;
    918         {
    919             zz_2 += x_2 * x_0;
    920             w = (int)zz_2;
    921             zz[2] = (w << 1) | c;
    922             c = w >>> 31;
    923             zz_3 += (zz_2 >>> 32) + x_2 * x_1;
    924             zz_4 += zz_3 >>> 32;
    925             zz_3 &= M;
    926         }
    927 
    928         long x_3 = x[3] & M;
    929         long zz_5 = (zz[5] & M) + (zz_4 >>> 32); zz_4 &= M;
    930         long zz_6 = (zz[6] & M) + (zz_5 >>> 32); zz_5 &= M;
    931         {
    932             zz_3 += x_3 * x_0;
    933             w = (int)zz_3;
    934             zz[3] = (w << 1) | c;
    935             c = w >>> 31;
    936             zz_4 += (zz_3 >>> 32) + x_3 * x_1;
    937             zz_5 += (zz_4 >>> 32) + x_3 * x_2;
    938             zz_4 &= M;
    939             zz_6 += zz_5 >>> 32;
    940             zz_5 &= M;
    941         }
    942 
    943         long x_4 = x[4] & M;
    944         long zz_7 = (zz[7] & M) + (zz_6 >>> 32); zz_6 &= M;
    945         long zz_8 = (zz[8] & M) + (zz_7 >>> 32); zz_7 &= M;
    946         {
    947             zz_4 += x_4 * x_0;
    948             w = (int)zz_4;
    949             zz[4] = (w << 1) | c;
    950             c = w >>> 31;
    951             zz_5 += (zz_4 >>> 32) + x_4 * x_1;
    952             zz_6 += (zz_5 >>> 32) + x_4 * x_2;
    953             zz_5 &= M;
    954             zz_7 += (zz_6 >>> 32) + x_4 * x_3;
    955             zz_6 &= M;
    956             zz_8 += zz_7 >>> 32;
    957             zz_7 &= M;
    958         }
    959 
    960         long x_5 = x[5] & M;
    961         long zz_9 = (zz[9] & M) + (zz_8 >>> 32); zz_8 &= M;
    962         long zz_10 = (zz[10] & M) + (zz_9 >>> 32); zz_9 &= M;
    963         {
    964             zz_5 += x_5 * x_0;
    965             w = (int)zz_5;
    966             zz[5] = (w << 1) | c;
    967             c = w >>> 31;
    968             zz_6 += (zz_5 >>> 32) + x_5 * x_1;
    969             zz_7 += (zz_6 >>> 32) + x_5 * x_2;
    970             zz_6 &= M;
    971             zz_8 += (zz_7 >>> 32) + x_5 * x_3;
    972             zz_7 &= M;
    973             zz_9 += (zz_8 >>> 32) + x_5 * x_4;
    974             zz_8 &= M;
    975             zz_10 += zz_9 >>> 32;
    976             zz_9 &= M;
    977         }
    978 
    979         long x_6 = x[6] & M;
    980         long zz_11 = (zz[11] & M) + (zz_10 >>> 32); zz_10 &= M;
    981         long zz_12 = (zz[12] & M) + (zz_11 >>> 32); zz_11 &= M;
    982         {
    983             zz_6 += x_6 * x_0;
    984             w = (int)zz_6;
    985             zz[6] = (w << 1) | c;
    986             c = w >>> 31;
    987             zz_7 += (zz_6 >>> 32) + x_6 * x_1;
    988             zz_8 += (zz_7 >>> 32) + x_6 * x_2;
    989             zz_7 &= M;
    990             zz_9 += (zz_8 >>> 32) + x_6 * x_3;
    991             zz_8 &= M;
    992             zz_10 += (zz_9 >>> 32) + x_6 * x_4;
    993             zz_9 &= M;
    994             zz_11 += (zz_10 >>> 32) + x_6 * x_5;
    995             zz_10 &= M;
    996             zz_12 += zz_11 >>> 32;
    997             zz_11 &= M;
    998         }
    999 
   1000         long x_7 = x[7] & M;
   1001         long zz_13 = (zz[13] & M) + (zz_12 >>> 32); zz_12 &= M;
   1002         long zz_14 = (zz[14] & M) + (zz_13 >>> 32); zz_13 &= M;
   1003         {
   1004             zz_7 += x_7 * x_0;
   1005             w = (int)zz_7;
   1006             zz[7] = (w << 1) | c;
   1007             c = w >>> 31;
   1008             zz_8 += (zz_7 >>> 32) + x_7 * x_1;
   1009             zz_9 += (zz_8 >>> 32) + x_7 * x_2;
   1010             zz_10 += (zz_9 >>> 32) + x_7 * x_3;
   1011             zz_11 += (zz_10 >>> 32) + x_7 * x_4;
   1012             zz_12 += (zz_11 >>> 32) + x_7 * x_5;
   1013             zz_13 += (zz_12 >>> 32) + x_7 * x_6;
   1014             zz_14 += zz_13 >>> 32;
   1015         }
   1016 
   1017         w = (int)zz_8;
   1018         zz[8] = (w << 1) | c;
   1019         c = w >>> 31;
   1020         w = (int)zz_9;
   1021         zz[9] = (w << 1) | c;
   1022         c = w >>> 31;
   1023         w = (int)zz_10;
   1024         zz[10] = (w << 1) | c;
   1025         c = w >>> 31;
   1026         w = (int)zz_11;
   1027         zz[11] = (w << 1) | c;
   1028         c = w >>> 31;
   1029         w = (int)zz_12;
   1030         zz[12] = (w << 1) | c;
   1031         c = w >>> 31;
   1032         w = (int)zz_13;
   1033         zz[13] = (w << 1) | c;
   1034         c = w >>> 31;
   1035         w = (int)zz_14;
   1036         zz[14] = (w << 1) | c;
   1037         c = w >>> 31;
   1038         w = zz[15] + (int)(zz_14 >>> 32);
   1039         zz[15] = (w << 1) | c;
   1040     }
   1041 
   1042     public static void square(int[] x, int xOff, int[] zz, int zzOff)
   1043     {
   1044         long x_0 = x[xOff + 0] & M;
   1045         long zz_1;
   1046 
   1047         int c = 0, w;
   1048         {
   1049             int i = 7, j = 16;
   1050             do
   1051             {
   1052                 long xVal = (x[xOff + i--] & M);
   1053                 long p = xVal * xVal;
   1054                 zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
   1055                 zz[zzOff + --j] = (int)(p >>> 1);
   1056                 c = (int)p;
   1057             }
   1058             while (i > 0);
   1059 
   1060             {
   1061                 long p = x_0 * x_0;
   1062                 zz_1 = ((c << 31) & M) | (p >>> 33);
   1063                 zz[zzOff + 0] = (int)p;
   1064                 c = (int)(p >>> 32) & 1;
   1065             }
   1066         }
   1067 
   1068         long x_1 = x[xOff + 1] & M;
   1069         long zz_2 = zz[zzOff + 2] & M;
   1070 
   1071         {
   1072             zz_1 += x_1 * x_0;
   1073             w = (int)zz_1;
   1074             zz[zzOff + 1] = (w << 1) | c;
   1075             c = w >>> 31;
   1076             zz_2 += zz_1 >>> 32;
   1077         }
   1078 
   1079         long x_2 = x[xOff + 2] & M;
   1080         long zz_3 = zz[zzOff + 3] & M;
   1081         long zz_4 = zz[zzOff + 4] & M;
   1082         {
   1083             zz_2 += x_2 * x_0;
   1084             w = (int)zz_2;
   1085             zz[zzOff + 2] = (w << 1) | c;
   1086             c = w >>> 31;
   1087             zz_3 += (zz_2 >>> 32) + x_2 * x_1;
   1088             zz_4 += zz_3 >>> 32;
   1089             zz_3 &= M;
   1090         }
   1091 
   1092         long x_3 = x[xOff + 3] & M;
   1093         long zz_5 = (zz[zzOff + 5] & M) + (zz_4 >>> 32); zz_4 &= M;
   1094         long zz_6 = (zz[zzOff + 6] & M) + (zz_5 >>> 32); zz_5 &= M;
   1095         {
   1096             zz_3 += x_3 * x_0;
   1097             w = (int)zz_3;
   1098             zz[zzOff + 3] = (w << 1) | c;
   1099             c = w >>> 31;
   1100             zz_4 += (zz_3 >>> 32) + x_3 * x_1;
   1101             zz_5 += (zz_4 >>> 32) + x_3 * x_2;
   1102             zz_4 &= M;
   1103             zz_6 += zz_5 >>> 32;
   1104             zz_5 &= M;
   1105         }
   1106 
   1107         long x_4 = x[xOff + 4] & M;
   1108         long zz_7 = (zz[zzOff + 7] & M) + (zz_6 >>> 32); zz_6 &= M;
   1109         long zz_8 = (zz[zzOff + 8] & M) + (zz_7 >>> 32); zz_7 &= M;
   1110         {
   1111             zz_4 += x_4 * x_0;
   1112             w = (int)zz_4;
   1113             zz[zzOff + 4] = (w << 1) | c;
   1114             c = w >>> 31;
   1115             zz_5 += (zz_4 >>> 32) + x_4 * x_1;
   1116             zz_6 += (zz_5 >>> 32) + x_4 * x_2;
   1117             zz_5 &= M;
   1118             zz_7 += (zz_6 >>> 32) + x_4 * x_3;
   1119             zz_6 &= M;
   1120             zz_8 += zz_7 >>> 32;
   1121             zz_7 &= M;
   1122         }
   1123 
   1124         long x_5 = x[xOff + 5] & M;
   1125         long zz_9 = (zz[zzOff + 9] & M) + (zz_8 >>> 32); zz_8 &= M;
   1126         long zz_10 = (zz[zzOff + 10] & M) + (zz_9 >>> 32); zz_9 &= M;
   1127         {
   1128             zz_5 += x_5 * x_0;
   1129             w = (int)zz_5;
   1130             zz[zzOff + 5] = (w << 1) | c;
   1131             c = w >>> 31;
   1132             zz_6 += (zz_5 >>> 32) + x_5 * x_1;
   1133             zz_7 += (zz_6 >>> 32) + x_5 * x_2;
   1134             zz_6 &= M;
   1135             zz_8 += (zz_7 >>> 32) + x_5 * x_3;
   1136             zz_7 &= M;
   1137             zz_9 += (zz_8 >>> 32) + x_5 * x_4;
   1138             zz_8 &= M;
   1139             zz_10 += zz_9 >>> 32;
   1140             zz_9 &= M;
   1141         }
   1142 
   1143         long x_6 = x[xOff + 6] & M;
   1144         long zz_11 = (zz[zzOff + 11] & M) + (zz_10 >>> 32); zz_10 &= M;
   1145         long zz_12 = (zz[zzOff + 12] & M) + (zz_11 >>> 32); zz_11 &= M;
   1146         {
   1147             zz_6 += x_6 * x_0;
   1148             w = (int)zz_6;
   1149             zz[zzOff + 6] = (w << 1) | c;
   1150             c = w >>> 31;
   1151             zz_7 += (zz_6 >>> 32) + x_6 * x_1;
   1152             zz_8 += (zz_7 >>> 32) + x_6 * x_2;
   1153             zz_7 &= M;
   1154             zz_9 += (zz_8 >>> 32) + x_6 * x_3;
   1155             zz_8 &= M;
   1156             zz_10 += (zz_9 >>> 32) + x_6 * x_4;
   1157             zz_9 &= M;
   1158             zz_11 += (zz_10 >>> 32) + x_6 * x_5;
   1159             zz_10 &= M;
   1160             zz_12 += zz_11 >>> 32;
   1161             zz_11 &= M;
   1162         }
   1163 
   1164         long x_7 = x[xOff + 7] & M;
   1165         long zz_13 = (zz[zzOff + 13] & M) + (zz_12 >>> 32); zz_12 &= M;
   1166         long zz_14 = (zz[zzOff + 14] & M) + (zz_13 >>> 32); zz_13 &= M;
   1167         {
   1168             zz_7 += x_7 * x_0;
   1169             w = (int)zz_7;
   1170             zz[zzOff + 7] = (w << 1) | c;
   1171             c = w >>> 31;
   1172             zz_8 += (zz_7 >>> 32) + x_7 * x_1;
   1173             zz_9 += (zz_8 >>> 32) + x_7 * x_2;
   1174             zz_10 += (zz_9 >>> 32) + x_7 * x_3;
   1175             zz_11 += (zz_10 >>> 32) + x_7 * x_4;
   1176             zz_12 += (zz_11 >>> 32) + x_7 * x_5;
   1177             zz_13 += (zz_12 >>> 32) + x_7 * x_6;
   1178             zz_14 += zz_13 >>> 32;
   1179         }
   1180 
   1181         w = (int)zz_8;
   1182         zz[zzOff + 8] = (w << 1) | c;
   1183         c = w >>> 31;
   1184         w = (int)zz_9;
   1185         zz[zzOff + 9] = (w << 1) | c;
   1186         c = w >>> 31;
   1187         w = (int)zz_10;
   1188         zz[zzOff + 10] = (w << 1) | c;
   1189         c = w >>> 31;
   1190         w = (int)zz_11;
   1191         zz[zzOff + 11] = (w << 1) | c;
   1192         c = w >>> 31;
   1193         w = (int)zz_12;
   1194         zz[zzOff + 12] = (w << 1) | c;
   1195         c = w >>> 31;
   1196         w = (int)zz_13;
   1197         zz[zzOff + 13] = (w << 1) | c;
   1198         c = w >>> 31;
   1199         w = (int)zz_14;
   1200         zz[zzOff + 14] = (w << 1) | c;
   1201         c = w >>> 31;
   1202         w = zz[zzOff + 15] + (int)(zz_14 >>> 32);
   1203         zz[zzOff + 15] = (w << 1) | c;
   1204     }
   1205 
   1206     public static int sub(int[] x, int[] y, int[] z)
   1207     {
   1208         long c = 0;
   1209         c += (x[0] & M) - (y[0] & M);
   1210         z[0] = (int)c;
   1211         c >>= 32;
   1212         c += (x[1] & M) - (y[1] & M);
   1213         z[1] = (int)c;
   1214         c >>= 32;
   1215         c += (x[2] & M) - (y[2] & M);
   1216         z[2] = (int)c;
   1217         c >>= 32;
   1218         c += (x[3] & M) - (y[3] & M);
   1219         z[3] = (int)c;
   1220         c >>= 32;
   1221         c += (x[4] & M) - (y[4] & M);
   1222         z[4] = (int)c;
   1223         c >>= 32;
   1224         c += (x[5] & M) - (y[5] & M);
   1225         z[5] = (int)c;
   1226         c >>= 32;
   1227         c += (x[6] & M) - (y[6] & M);
   1228         z[6] = (int)c;
   1229         c >>= 32;
   1230         c += (x[7] & M) - (y[7] & M);
   1231         z[7] = (int)c;
   1232         c >>= 32;
   1233         return (int)c;
   1234     }
   1235 
   1236     public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
   1237     {
   1238         long c = 0;
   1239         c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
   1240         z[zOff + 0] = (int)c;
   1241         c >>= 32;
   1242         c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
   1243         z[zOff + 1] = (int)c;
   1244         c >>= 32;
   1245         c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
   1246         z[zOff + 2] = (int)c;
   1247         c >>= 32;
   1248         c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
   1249         z[zOff + 3] = (int)c;
   1250         c >>= 32;
   1251         c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
   1252         z[zOff + 4] = (int)c;
   1253         c >>= 32;
   1254         c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
   1255         z[zOff + 5] = (int)c;
   1256         c >>= 32;
   1257         c += (x[xOff + 6] & M) - (y[yOff + 6] & M);
   1258         z[zOff + 6] = (int)c;
   1259         c >>= 32;
   1260         c += (x[xOff + 7] & M) - (y[yOff + 7] & M);
   1261         z[zOff + 7] = (int)c;
   1262         c >>= 32;
   1263         return (int)c;
   1264     }
   1265 
   1266     public static int subBothFrom(int[] x, int[] y, int[] z)
   1267     {
   1268         long c = 0;
   1269         c += (z[0] & M) - (x[0] & M) - (y[0] & M);
   1270         z[0] = (int)c;
   1271         c >>= 32;
   1272         c += (z[1] & M) - (x[1] & M) - (y[1] & M);
   1273         z[1] = (int)c;
   1274         c >>= 32;
   1275         c += (z[2] & M) - (x[2] & M) - (y[2] & M);
   1276         z[2] = (int)c;
   1277         c >>= 32;
   1278         c += (z[3] & M) - (x[3] & M) - (y[3] & M);
   1279         z[3] = (int)c;
   1280         c >>= 32;
   1281         c += (z[4] & M) - (x[4] & M) - (y[4] & M);
   1282         z[4] = (int)c;
   1283         c >>= 32;
   1284         c += (z[5] & M) - (x[5] & M) - (y[5] & M);
   1285         z[5] = (int)c;
   1286         c >>= 32;
   1287         c += (z[6] & M) - (x[6] & M) - (y[6] & M);
   1288         z[6] = (int)c;
   1289         c >>= 32;
   1290         c += (z[7] & M) - (x[7] & M) - (y[7] & M);
   1291         z[7] = (int)c;
   1292         c >>= 32;
   1293         return (int)c;
   1294     }
   1295 
   1296     public static int subFrom(int[] x, int[] z)
   1297     {
   1298         long c = 0;
   1299         c += (z[0] & M) - (x[0] & M);
   1300         z[0] = (int)c;
   1301         c >>= 32;
   1302         c += (z[1] & M) - (x[1] & M);
   1303         z[1] = (int)c;
   1304         c >>= 32;
   1305         c += (z[2] & M) - (x[2] & M);
   1306         z[2] = (int)c;
   1307         c >>= 32;
   1308         c += (z[3] & M) - (x[3] & M);
   1309         z[3] = (int)c;
   1310         c >>= 32;
   1311         c += (z[4] & M) - (x[4] & M);
   1312         z[4] = (int)c;
   1313         c >>= 32;
   1314         c += (z[5] & M) - (x[5] & M);
   1315         z[5] = (int)c;
   1316         c >>= 32;
   1317         c += (z[6] & M) - (x[6] & M);
   1318         z[6] = (int)c;
   1319         c >>= 32;
   1320         c += (z[7] & M) - (x[7] & M);
   1321         z[7] = (int)c;
   1322         c >>= 32;
   1323         return (int)c;
   1324     }
   1325 
   1326     public static int subFrom(int[] x, int xOff, int[] z, int zOff)
   1327     {
   1328         long c = 0;
   1329         c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
   1330         z[zOff + 0] = (int)c;
   1331         c >>= 32;
   1332         c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
   1333         z[zOff + 1] = (int)c;
   1334         c >>= 32;
   1335         c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
   1336         z[zOff + 2] = (int)c;
   1337         c >>= 32;
   1338         c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
   1339         z[zOff + 3] = (int)c;
   1340         c >>= 32;
   1341         c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
   1342         z[zOff + 4] = (int)c;
   1343         c >>= 32;
   1344         c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
   1345         z[zOff + 5] = (int)c;
   1346         c >>= 32;
   1347         c += (z[zOff + 6] & M) - (x[xOff + 6] & M);
   1348         z[zOff + 6] = (int)c;
   1349         c >>= 32;
   1350         c += (z[zOff + 7] & M) - (x[xOff + 7] & M);
   1351         z[zOff + 7] = (int)c;
   1352         c >>= 32;
   1353         return (int)c;
   1354     }
   1355 
   1356     public static BigInteger toBigInteger(int[] x)
   1357     {
   1358         byte[] bs = new byte[32];
   1359         for (int i = 0; i < 8; ++i)
   1360         {
   1361             int x_i = x[i];
   1362             if (x_i != 0)
   1363             {
   1364                 Pack.intToBigEndian(x_i, bs, (7 - i) << 2);
   1365             }
   1366         }
   1367         return new BigInteger(1, bs);
   1368     }
   1369 
   1370     public static BigInteger toBigInteger64(long[] x)
   1371     {
   1372         byte[] bs = new byte[32];
   1373         for (int i = 0; i < 4; ++i)
   1374         {
   1375             long x_i = x[i];
   1376             if (x_i != 0L)
   1377             {
   1378                 Pack.longToBigEndian(x_i, bs, (3 - i) << 3);
   1379             }
   1380         }
   1381         return new BigInteger(1, bs);
   1382     }
   1383 
   1384     public static void zero(int[] z)
   1385     {
   1386         z[0] = 0;
   1387         z[1] = 0;
   1388         z[2] = 0;
   1389         z[3] = 0;
   1390         z[4] = 0;
   1391         z[5] = 0;
   1392         z[6] = 0;
   1393         z[7] = 0;
   1394     }
   1395 }
   1396