153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giropackage org.bouncycastle.math.ec.custom.sec;
253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport java.math.BigInteger;
453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.math.raw.Nat;
653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.math.raw.Nat224;
753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giropublic class SecP224R1Field
953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro{
1053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    private static final long M = 0xFFFFFFFFL;
1153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
1253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    // 2^224 - 2^96 + 1
1353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    static final int[] P = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
1453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
1553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        0xFFFFFFFF, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
1653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0x00000000,
1753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001 };
1853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    private static final int P6 = 0xFFFFFFFF;
1953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    private static final int PExt13 = 0xFFFFFFFF;
2053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
2153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void add(int[] x, int[] y, int[] z)
2253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
2353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int c = Nat224.add(x, y, z);
2453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
2553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
2653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            addPInvTo(z);
2753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
2853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
2953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
3053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void addExt(int[] xx, int[] yy, int[] zz)
3153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
3253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int c = Nat.add(14, xx, yy, zz);
3353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
3453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
3553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
3653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
3753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                Nat.incAt(14, zz, PExtInv.length);
3853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
3953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
4053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
4153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
4253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void addOne(int[] x, int[] z)
4353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
4453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int c = Nat.inc(7, x, z);
4553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
4653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
4753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            addPInvTo(z);
4853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
4953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
5053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
5153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static int[] fromBigInteger(BigInteger x)
5253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
5353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int[] z = Nat224.fromBigInteger(x);
5453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (z[6] == P6 && Nat224.gte(z, P))
5553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
5653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Nat224.subFrom(P, z);
5753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
5853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        return z;
5953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
6053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
6153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void half(int[] x, int[] z)
6253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
6353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if ((x[0] & 1) == 0)
6453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
6553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Nat.shiftDownBit(7, x, 0, z);
6653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
6753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        else
6853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
6953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            int c = Nat224.add(x, P, z);
7053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Nat.shiftDownBit(7, z, c);
7153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
7253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
7353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
7453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void multiply(int[] x, int[] y, int[] z)
7553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
7653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int[] tt = Nat224.createExt();
7753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Nat224.mul(x, y, tt);
7853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        reduce(tt, z);
7953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
8053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
8153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
8253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
8353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int c = Nat224.mulAddTo(x, y, zz);
8453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
8553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
8653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
8753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
8853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                Nat.incAt(14, zz, PExtInv.length);
8953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
9053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
9153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
9253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
9353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void negate(int[] x, int[] z)
9453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
9553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (Nat224.isZero(x))
9653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
9753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Nat224.zero(z);
9853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
9953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        else
10053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
10153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Nat224.sub(P, x, z);
10253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
10353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
10453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
10553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void reduce(int[] xx, int[] z)
10653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
10753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long xx10 = xx[10] & M, xx11 = xx[11] & M, xx12 = xx[12] & M, xx13 = xx[13] & M;
10853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
10953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        final long n = 1;
11053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
11153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long t0 = (xx[7] & M) + xx11 - n;
11253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long t1 = (xx[8] & M) + xx12;
11353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long t2 = (xx[9] & M) + xx13;
11453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
11553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long cc = 0;
11653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc += (xx[0] & M) - t0;
11753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long z0 = cc & M;
11853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc >>= 32;
11953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc += (xx[1] & M) - t1;
12053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[1] = (int)cc;
12153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc >>= 32;
12253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc += (xx[2] & M) - t2;
12353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[2] = (int)cc;
12453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc >>= 32;
12553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc += (xx[3] & M) + t0 - xx10;
12653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long z3 = cc & M;
12753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc >>= 32;
12853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc += (xx[4] & M) + t1 - xx11;
12953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[4] = (int)cc;
13053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc >>= 32;
13153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc += (xx[5] & M) + t2 - xx12;
13253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[5] = (int)cc;
13353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc >>= 32;
13453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc += (xx[6] & M) + xx10 - xx13;
13553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[6] = (int)cc;
13653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc >>= 32;
13753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc += n;
13853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
13953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro//        assert cc >= 0;
14053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
14153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z3 += cc;
14253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
14353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z0 -= cc;
14453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[0] = (int)z0;
14553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc = z0 >> 32;
14653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (cc != 0)
14753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
14853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            cc += (z[1] & M);
14953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            z[1] = (int)cc;
15053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            cc >>= 32;
15153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            cc += (z[2] & M);
15253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            z[2] = (int)cc;
15353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            z3 += cc >> 32;
15453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
15553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[3] = (int)z3;
15653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        cc = z3 >> 32;
15753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
15853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro//        assert cc == 0 || cc == 1;
15953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
16053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if ((cc != 0 && Nat.incAt(7, z, 4) != 0)
16153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            || (z[6] == P6 && Nat224.gte(z, P)))
16253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
16353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            addPInvTo(z);
16453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
16553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
16653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
16753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void reduce32(int x, int[] z)
16853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
16953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long cc = 0;
17053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
17153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (x != 0)
17253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
17353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            long xx07 = x & M;
174bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro
17553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            cc += (z[0] & M) - xx07;
17653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            z[0] = (int)cc;
17753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            cc >>= 32;
17853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            if (cc != 0)
17953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
18053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                cc += (z[1] & M);
18153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                z[1] = (int)cc;
18253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                cc >>= 32;
18353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                cc += (z[2] & M);
18453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                z[2] = (int)cc;
18553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                cc >>= 32;
18653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
18753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            cc += (z[3] & M) + xx07;
18853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            z[3] = (int)cc;
18953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            cc >>= 32;
19053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
19153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro//            assert cc == 0 || cc == 1;
19253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
19353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
19453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if ((cc != 0 && Nat.incAt(7, z, 4) != 0)
19553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            || (z[6] == P6 && Nat224.gte(z, P)))
19653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
19753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            addPInvTo(z);
19853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
19953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
20053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
20153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void square(int[] x, int[] z)
20253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
20353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int[] tt = Nat224.createExt();
20453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Nat224.square(x, tt);
20553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        reduce(tt, z);
20653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
20753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
20853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void squareN(int[] x, int n, int[] z)
20953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
21053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro//        assert n > 0;
21153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
21253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int[] tt = Nat224.createExt();
21353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Nat224.square(x, tt);
21453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        reduce(tt, z);
21553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
21653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        while (--n > 0)
21753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
21853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Nat224.square(z, tt);
21953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            reduce(tt, z);
22053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
22153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
22253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
22353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void subtract(int[] x, int[] y, int[] z)
22453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
22553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int c = Nat224.sub(x, y, z);
22653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0)
22753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
22853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            subPInvFrom(z);
22953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
23053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
23153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
23253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void subtractExt(int[] xx, int[] yy, int[] zz)
23353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
23453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int c = Nat.sub(14, xx, yy, zz);
23553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0)
23653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
23753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
23853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            {
23953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro                Nat.decAt(14, zz, PExtInv.length);
24053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            }
24153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
24253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
24353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
24453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public static void twice(int[] x, int[] z)
24553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
24653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        int c = Nat.shiftUpBit(7, x, 0, z);
24753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
24853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
24953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            addPInvTo(z);
25053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
25153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
25253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
25353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    private static void addPInvTo(int[] z)
25453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
25553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long c = (z[0] & M) - 1;
25653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[0] = (int)c;
25753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        c >>= 32;
25853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0)
25953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
26053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            c += (z[1] & M);
26153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            z[1] = (int)c;
26253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            c >>= 32;
26353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            c += (z[2] & M);
26453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            z[2] = (int)c;
26553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            c >>= 32;
26653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
26753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        c += (z[3] & M) + 1;
26853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[3] = (int)c;
26953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        c >>= 32;
27053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0)
27153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
27253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Nat.incAt(7, z, 4);
27353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
27453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
27553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
27653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    private static void subPInvFrom(int[] z)
27753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
27853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        long c = (z[0] & M) + 1;
27953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[0] = (int)c;
28053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        c >>= 32;
28153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0)
28253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
28353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            c += (z[1] & M);
28453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            z[1] = (int)c;
28553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            c >>= 32;
28653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            c += (z[2] & M);
28753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            z[2] = (int)c;
28853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            c >>= 32;
28953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
29053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        c += (z[3] & M) - 1;
29153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        z[3] = (int)c;
29253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        c >>= 32;
29353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        if (c != 0)
29453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
29553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Nat.decAt(7, z, 4);
29653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
29753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
29853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro}
299