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