Fpx
using Org.BouncyCastle.Crypto.Utilities;
using System;
namespace Org.BouncyCastle.Pqc.Crypto.Sike
{
internal sealed class Fpx
{
private readonly SikeEngine engine;
internal Fpx(SikeEngine engine)
{
this.engine = engine;
}
private void mp_shiftl1(ulong[] x, uint nwords)
{
for (int num = (int)(nwords - 1); num > 0; num--) {
x[num] = ((x[num] << 1) ^ (x[num - 1] >> (int)(Internal.RADIX - 1)));
}
x[0] <<= 1;
}
internal void sqr_Fp2_cycl(ulong[][] a, ulong[] one)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
fpaddPRIME(a[0], a[1], array);
fpsqr_mont(array, array);
fpsubPRIME(array, one, a[1]);
fpsqr_mont(a[0], array);
fpaddPRIME(array, array, array);
fpsubPRIME(array, one, a[0]);
}
internal void mont_n_way_inv(ulong[][][] vec, uint n, ulong[][][] output)
{
ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD);
fp2copy(vec[0], output[0]);
for (int i = 1; i < n; i++) {
fp2mul_mont(output[i - 1], vec[i], output[i]);
}
fp2copy(output[n - 1], array);
fp2inv_mont_bingcd(array);
for (int i = (int)(n - 1); i >= 1; i--) {
fp2mul_mont(output[i - 1], array, output[i]);
fp2mul_mont(array, vec[i], array);
}
fp2copy(array, output[0]);
}
internal void fpcopy(ulong[] a, long aOffset, ulong[] c)
{
for (uint num = 0; num < engine.param.NWORDS_FIELD; num++) {
c[num] = a[num + aOffset];
}
}
internal void mp2_add(ulong[][] a, ulong[][] b, ulong[][] c)
{
mp_add(a[0], b[0], c[0], engine.param.NWORDS_FIELD);
mp_add(a[1], b[1], c[1], engine.param.NWORDS_FIELD);
}
internal void fp2correction(ulong[][] a)
{
fpcorrectionPRIME(a[0]);
fpcorrectionPRIME(a[1]);
}
internal ulong mp_add(ulong[] a, ulong[] b, ulong[] c, uint nwords)
{
ulong num = 0;
for (uint num2 = 0; num2 < nwords; num2++) {
ulong num3 = a[num2] + num;
c[num2] = b[num2] + num3;
num = (is_digit_lessthan_ct(num3, num) | is_digit_lessthan_ct(c[num2], num3));
}
return num;
}
private ulong mp_add(ulong[] a, uint aOffset, ulong[] b, ulong[] c, uint cOffset, uint nwords)
{
ulong num = 0;
for (ulong num2 = 0; num2 < nwords; num2++) {
ulong num3 = a[num2 + aOffset] + num;
c[num2 + cOffset] = b[num2] + num3;
num = (is_digit_lessthan_ct(num3, num) | is_digit_lessthan_ct(c[num2 + cOffset], num3));
}
return num;
}
private ulong mp_add(ulong[] a, uint aOffset, ulong[] b, uint bOffset, ulong[] c, uint cOffset, uint nwords)
{
ulong num = 0;
for (ulong num2 = 0; num2 < nwords; num2++) {
ulong num3 = a[num2 + aOffset] + num;
c[num2 + cOffset] = b[num2 + bOffset] + num3;
num = (is_digit_lessthan_ct(num3, num) | is_digit_lessthan_ct(c[num2 + cOffset], num3));
}
return num;
}
private ulong is_digit_lessthan_ct(ulong x, ulong y)
{
return (x ^ ((x ^ y) | ((x - y) ^ y))) >> (int)(Internal.RADIX - 1);
}
private ulong is_digit_nonzero_ct(ulong x)
{
return (x | (0 - x)) >> (int)(Internal.RADIX - 1);
}
private ulong is_digit_zero_ct(ulong x)
{
return 1 ^ is_digit_nonzero_ct(x);
}
internal void fp2neg(ulong[][] a)
{
fpnegPRIME(a[0]);
fpnegPRIME(a[1]);
}
internal bool is_felm_zero(ulong[] x)
{
for (uint num = 0; num < engine.param.NWORDS_FIELD; num++) {
if (x[num] != 0)
return false;
}
return true;
}
private bool is_felm_lt(ulong[] x, ulong[] y)
{
for (int num = (int)(engine.param.NWORDS_FIELD - 1); num >= 0; num--) {
if (x[num] < y[num])
return true;
if (x[num] > y[num])
return false;
}
return false;
}
private static bool is_felm_even(ulong[] x)
{
return (x[0] & 1) == 0;
}
internal bool is_sqr_fp2(ulong[][] a, ulong[] s)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong[] array2 = new ulong[engine.param.NWORDS_FIELD];
ulong[] array3 = new ulong[engine.param.NWORDS_FIELD];
ulong[] array4 = new ulong[engine.param.NWORDS_FIELD];
fpsqr_mont(a[0], array);
fpsqr_mont(a[1], array2);
fpaddPRIME(array, array2, array3);
fpcopy(array3, 0, s);
for (uint num = 0; num < engine.param.OALICE_BITS - 2; num++) {
fpsqr_mont(s, s);
}
for (uint num = 0; num < engine.param.OBOB_EXPON; num++) {
fpsqr_mont(s, array4);
fpmul_mont(s, array4, s);
}
fpsqr_mont(s, array4);
fpcorrectionPRIME(array4);
fpcorrectionPRIME(array3);
if (!subarrayEquals(array4, array3, engine.param.NWORDS_FIELD))
return false;
return true;
}
private uint fpinv_mont_bingcd_partial(ulong[] a, ulong[] x1)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong[] array2 = new ulong[engine.param.NWORDS_FIELD];
ulong[] array3 = new ulong[engine.param.NWORDS_FIELD];
fpcopy(a, 0, array);
fpcopy(engine.param.PRIME, 0, array2);
fpzero(x1);
x1[0] = 1;
fpzero(array3);
uint num = 0;
while (!is_felm_zero(array2)) {
uint num2 = ++num / Internal.RADIX + 1;
if (num2 < engine.param.NWORDS_FIELD) {
if (is_felm_even(array2)) {
mp_shiftr1(array2);
mp_shiftl1(x1, num2);
} else if (is_felm_even(array)) {
mp_shiftr1(array);
mp_shiftl1(array3, num2);
} else if (!is_felm_lt(array2, array)) {
mp_sub(array2, array, array2, engine.param.NWORDS_FIELD);
mp_shiftr1(array2);
mp_add(x1, array3, array3, num2);
mp_shiftl1(x1, num2);
} else {
mp_sub(array, array2, array, engine.param.NWORDS_FIELD);
mp_shiftr1(array);
mp_add(x1, array3, x1, num2);
mp_shiftl1(array3, num2);
}
} else if (is_felm_even(array2)) {
mp_shiftr1(array2);
mp_shiftl1(x1, engine.param.NWORDS_FIELD);
} else if (is_felm_even(array)) {
mp_shiftr1(array);
mp_shiftl1(array3, engine.param.NWORDS_FIELD);
} else if (!is_felm_lt(array2, array)) {
mp_sub(array2, array, array2, engine.param.NWORDS_FIELD);
mp_shiftr1(array2);
mp_add(x1, array3, array3, engine.param.NWORDS_FIELD);
mp_shiftl1(x1, engine.param.NWORDS_FIELD);
} else {
mp_sub(array, array2, array, engine.param.NWORDS_FIELD);
mp_shiftr1(array);
mp_add(x1, array3, x1, engine.param.NWORDS_FIELD);
mp_shiftl1(array3, engine.param.NWORDS_FIELD);
}
}
if (is_felm_lt(engine.param.PRIME, x1))
mp_sub(x1, engine.param.PRIME, x1, engine.param.NWORDS_FIELD);
return num;
}
private void power2_setup(ulong[] x, int mark, uint nwords)
{
uint num;
for (num = 0; num < nwords; num++) {
x[num] = 0;
}
num = 0;
while (mark >= 0) {
if (mark < Internal.RADIX)
x[num] = (ulong)(1 << mark);
mark -= (int)Internal.RADIX;
num++;
}
}
private void fpinv_mont_bingcd(ulong[] a)
{
if (!is_felm_zero(a)) {
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong[] array2 = new ulong[engine.param.NWORDS_FIELD];
uint num = fpinv_mont_bingcd_partial(a, array);
if (num <= engine.param.MAXBITS_FIELD) {
fpmul_mont(array, engine.param.Montgomery_R2, array);
num += engine.param.MAXBITS_FIELD;
}
fpmul_mont(array, engine.param.Montgomery_R2, array);
power2_setup(array2, (int)(2 * engine.param.MAXBITS_FIELD - num), engine.param.NWORDS_FIELD);
fpmul_mont(array, array2, a);
}
}
internal void fp2inv_mont_bingcd(ulong[][] a)
{
ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD);
fpsqr_mont(a[0], array[0]);
fpsqr_mont(a[1], array[1]);
fpaddPRIME(array[0], array[1], array[0]);
fpinv_mont_bingcd(array[0]);
fpnegPRIME(a[1]);
fpmul_mont(a[0], array[0], a[0]);
fpmul_mont(a[1], array[0], a[1]);
}
internal void fp2div2(ulong[][] a, ulong[][] c)
{
fpdiv2_PRIME(a[0], c[0]);
fpdiv2_PRIME(a[1], c[1]);
}
private void fpdiv2_PRIME(ulong[] a, ulong[] c)
{
ulong num = 0;
ulong num2 = 0 - (a[0] & 1);
for (ulong num3 = 0; num3 < engine.param.NWORDS_FIELD; num3++) {
ulong num4 = a[num3] + num;
c[num3] = (engine.param.PRIME[num3] & num2) + num4;
num = (is_digit_lessthan_ct(num4, num) | is_digit_lessthan_ct(c[num3], num4));
}
mp_shiftr1(c);
}
private void mp_subPRIME_p2(ulong[] a, ulong[] b, ulong[] c)
{
ulong num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num3 = a[num2] - b[num2];
ulong num4 = is_digit_lessthan_ct(a[num2], b[num2]) | (num & is_digit_zero_ct(num3));
c[num2] = num3 - num;
num = num4;
}
num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num5 = c[num2] + num;
c[num2] = engine.param.PRIMEx2[num2] + num5;
num = (is_digit_lessthan_ct(num5, num) | is_digit_lessthan_ct(c[num2], num5));
}
}
private void mp_subPRIME_p4(ulong[] a, ulong[] b, ulong[] c)
{
ulong num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num3 = a[num2] - b[num2];
ulong num4 = is_digit_lessthan_ct(a[num2], b[num2]) | (num & is_digit_zero_ct(num3));
c[num2] = num3 - num;
num = num4;
}
num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num5 = c[num2] + num;
c[num2] = engine.param.PRIMEx4[num2] + num5;
num = (is_digit_lessthan_ct(num5, num) | is_digit_lessthan_ct(c[num2], num5));
}
}
private ulong digit_x_digit(ulong a, ulong b, out ulong low)
{
ulong num = 4294967295;
ulong num2 = 18446744069414584320;
ulong num3 = a & num;
ulong num4 = a >> 32;
ulong num5 = b & num;
ulong num6 = b >> 32;
ulong num7 = num3 * num5;
ulong num8 = num3 * num6;
ulong num9 = num4 * num5;
ulong num10 = num4 * num6;
low = (num7 & num);
ulong num11 = num7 >> 32;
ulong num12 = num9 & num;
ulong num13 = num8 & num;
ulong num14 = num11 + num12 + num13;
ulong num15 = num14 >> 32;
low ^= num14 << 32;
ulong num16 = num9 >> 32;
num12 = num8 >> 32;
num13 = (num10 & num);
num14 = num16 + num12 + num13 + num15;
ulong num17 = num14 & num;
num15 = (num14 & num2);
return num17 ^ ((num10 & num2) + num15);
}
private void rdc_mont(ulong[] ma, ulong[] mc)
{
ulong num = engine.param.PRIME_ZERO_WORDS;
ulong num2 = 0;
ulong num3 = 0;
ulong num4 = 0;
for (ulong num5 = 0; num5 < engine.param.NWORDS_FIELD; num5++) {
mc[num5] = 0;
}
ulong low;
ulong num8;
for (ulong num5 = 0; num5 < engine.param.NWORDS_FIELD; num5++) {
for (ulong num6 = 0; num6 < num5; num6++) {
if (num6 < num5 - engine.param.PRIME_ZERO_WORDS + 1) {
ulong num7 = digit_x_digit(mc[num6], engine.param.PRIMEp1[num5 - num6], out low);
num4 += low;
num7 += is_digit_lessthan_ct(num4, low);
num3 += num7;
num2 += is_digit_lessthan_ct(num3, num7);
}
}
num8 = ma[num5];
num4 += num8;
num8 = is_digit_lessthan_ct(num4, num8);
num3 += num8;
num8 &= is_digit_zero_ct(num3);
num2 += num8;
mc[num5] = num4;
num4 = num3;
num3 = num2;
num2 = 0;
}
for (ulong num5 = engine.param.NWORDS_FIELD; num5 < 2 * engine.param.NWORDS_FIELD - 1; num5++) {
if (num != 0)
num--;
for (ulong num6 = num5 - engine.param.NWORDS_FIELD + 1; num6 < engine.param.NWORDS_FIELD; num6++) {
if (num6 < engine.param.NWORDS_FIELD - num) {
ulong num7 = digit_x_digit(mc[num6], engine.param.PRIMEp1[num5 - num6], out low);
num4 += low;
num7 += is_digit_lessthan_ct(num4, low);
num3 += num7;
num2 += is_digit_lessthan_ct(num3, num7);
}
}
num8 = ma[num5];
num4 += num8;
num8 = is_digit_lessthan_ct(num4, num8);
num3 += num8;
num8 &= is_digit_zero_ct(num3);
num2 += num8;
mc[num5 - engine.param.NWORDS_FIELD] = num4;
num4 = num3;
num3 = num2;
num2 = 0;
}
num8 = ma[2 * engine.param.NWORDS_FIELD - 1];
num4 += num8;
num8 = is_digit_lessthan_ct(num4, num8);
mc[engine.param.NWORDS_FIELD - 1] = num4;
}
internal static bool subarrayEquals(ulong[] a, ulong[] b, uint length)
{
for (uint num = 0; num < length; num++) {
if (a[num] != b[num])
return false;
}
return true;
}
internal static bool subarrayEquals(ulong[][] a, ulong[][] b, uint length)
{
int num = b[0].Length;
for (uint num2 = 0; num2 < length; num2++) {
if (a[(long)num2 / (long)num][(long)num2 % (long)num] != b[(long)num2 / (long)num][(long)num2 % (long)num])
return false;
}
return true;
}
internal static bool subarrayEquals(ulong[][] a, ulong[][] b, uint bOffset, uint length)
{
int num = b[0].Length;
for (uint num2 = 0; num2 < length; num2++) {
if (a[(long)num2 / (long)num][(long)num2 % (long)num] != b[(long)(num2 + bOffset) / (long)num][(long)(num2 + bOffset) % (long)num])
return false;
}
return true;
}
internal static bool subarrayEquals(ulong[][] a, ulong[] b, uint bOffset, uint length)
{
int num = a[0].Length;
for (uint num2 = 0; num2 < length; num2++) {
if (a[(long)num2 / (long)num][(long)num2 % (long)num] != b[num2 + bOffset])
return false;
}
return true;
}
internal void sqrt_Fp2(ulong[][] u, ulong[][] y)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong[] array2 = new ulong[engine.param.NWORDS_FIELD];
ulong[] array3 = new ulong[engine.param.NWORDS_FIELD];
ulong[] array4 = new ulong[engine.param.NWORDS_FIELD];
fpsqr_mont(u[0], array);
fpsqr_mont(u[1], array2);
fpaddPRIME(array, array2, array);
fpcopy(array, 0, array2);
for (uint num = 0; num < engine.param.OALICE_BITS - 2; num++) {
fpsqr_mont(array2, array2);
}
for (uint num = 0; num < engine.param.OBOB_EXPON; num++) {
fpsqr_mont(array2, array);
fpmul_mont(array2, array, array2);
}
fpaddPRIME(u[0], array2, array);
fpdiv2_PRIME(array, array);
fpcopy(array, 0, array3);
fpinv_chain_mont(array3);
fpmul_mont(array, array3, array2);
fpmul_mont(array3, u[1], array3);
fpdiv2_PRIME(array3, array3);
fpsqr_mont(array2, array4);
fpcorrectionPRIME(array);
fpcorrectionPRIME(array4);
if (subarrayEquals(array, array4, engine.param.NWORDS_FIELD)) {
fpcopy(array2, 0, y[0]);
fpcopy(array3, 0, y[1]);
} else {
fpnegPRIME(array2);
fpcopy(array3, 0, y[0]);
fpcopy(array2, 0, y[1]);
}
}
internal void fp2sqr_mont(ulong[][] a, ulong[][] c)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong[] array2 = new ulong[engine.param.NWORDS_FIELD];
ulong[] array3 = new ulong[engine.param.NWORDS_FIELD];
mp_add(a[0], a[1], array, engine.param.NWORDS_FIELD);
mp_subPRIME_p4(a[0], a[1], array2);
mp_add(a[0], a[0], array3, engine.param.NWORDS_FIELD);
fpmul_mont(array, array2, c[0]);
fpmul_mont(array3, a[1], c[1]);
}
internal void fpaddPRIME(ulong[] a, ulong[] b, ulong[] c)
{
ulong num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num3 = a[num2] + num;
c[num2] = b[num2] + num3;
num = (is_digit_lessthan_ct(num3, num) | is_digit_lessthan_ct(c[num2], num3));
}
num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num4 = c[num2] - engine.param.PRIMEx2[num2];
ulong num5 = is_digit_lessthan_ct(c[num2], engine.param.PRIMEx2[num2]) | (num & is_digit_zero_ct(num4));
c[num2] = num4 - num;
num = num5;
}
ulong num6 = 0 - num;
num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num7 = c[num2] + num;
c[num2] = (engine.param.PRIMEx2[num2] & num6) + num7;
num = (is_digit_lessthan_ct(num7, num) | is_digit_lessthan_ct(c[num2], num7));
}
}
internal void cube_Fp2_cycl(ulong[][] a, ulong[] one)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
fpaddPRIME(a[0], a[0], array);
fpsqr_mont(array, array);
fpsubPRIME(array, one, array);
fpmul_mont(a[1], array, a[1]);
fpsubPRIME(array, one, array);
fpsubPRIME(array, one, array);
fpmul_mont(a[0], array, a[0]);
}
internal void fpsubPRIME(ulong[] a, ulong[] b, uint bOffset, ulong[] c)
{
ulong num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num3 = a[num2] - b[num2 + bOffset];
ulong num4 = is_digit_lessthan_ct(a[num2], b[num2 + bOffset]) | (num & is_digit_zero_ct(num3));
c[num2] = num3 - num;
num = num4;
}
ulong num5 = 0 - num;
num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num6 = c[num2] + num;
c[num2] = (engine.param.PRIMEx2[num2] & num5) + num6;
num = (is_digit_lessthan_ct(num6, num) | is_digit_lessthan_ct(c[num2], num6));
}
}
internal void fpsubPRIME(ulong[] a, uint aOffset, ulong[] b, ulong[] c)
{
ulong num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num3 = a[num2 + aOffset] - b[num2];
ulong num4 = is_digit_lessthan_ct(a[num2 + aOffset], b[num2]) | (num & is_digit_zero_ct(num3));
c[num2] = num3 - num;
num = num4;
}
ulong num5 = 0 - num;
num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num6 = c[num2] + num;
c[num2] = (engine.param.PRIMEx2[num2] & num5) + num6;
num = (is_digit_lessthan_ct(num6, num) | is_digit_lessthan_ct(c[num2], num6));
}
}
internal void fpsubPRIME(ulong[] a, ulong[] b, ulong[] c)
{
ulong num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num3 = a[num2] - b[num2];
ulong num4 = is_digit_lessthan_ct(a[num2], b[num2]) | (num & is_digit_zero_ct(num3));
c[num2] = num3 - num;
num = num4;
}
ulong num5 = 0 - num;
num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num6 = c[num2] + num;
c[num2] = (engine.param.PRIMEx2[num2] & num5) + num6;
num = (is_digit_lessthan_ct(num6, num) | is_digit_lessthan_ct(c[num2], num6));
}
}
internal void fpnegPRIME(ulong[] a)
{
ulong num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num3 = engine.param.PRIMEx2[num2] - a[num2];
ulong num4 = is_digit_lessthan_ct(engine.param.PRIMEx2[num2], a[num2]) | (num & is_digit_zero_ct(num3));
a[num2] = num3 - num;
num = num4;
}
}
internal void from_fp2mont(ulong[][] ma, ulong[][] c)
{
from_mont(ma[0], c[0]);
from_mont(ma[1], c[1]);
}
internal void fp2_encode(ulong[][] x, byte[] enc, uint encOffset)
{
ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD);
from_fp2mont(x, array);
encode_to_bytes(array[0], enc, encOffset, engine.param.FP2_ENCODED_BYTES / 2);
encode_to_bytes(array[1], enc, encOffset + engine.param.FP2_ENCODED_BYTES / 2, engine.param.FP2_ENCODED_BYTES / 2);
}
internal void fp2_decode(byte[] x, ulong[][] dec, uint xOffset)
{
decode_to_digits(x, xOffset, dec[0], engine.param.FP2_ENCODED_BYTES / 2, engine.param.NWORDS_FIELD);
decode_to_digits(x, xOffset + engine.param.FP2_ENCODED_BYTES / 2, dec[1], engine.param.FP2_ENCODED_BYTES / 2, engine.param.NWORDS_FIELD);
to_fp2mont(dec, dec);
}
internal void to_Montgomery_mod_order(ulong[] a, ulong[] mc, ulong[] order, ulong[] Montgomery_rprime, ulong[] Montgomery_Rprime)
{
Montgomery_multiply_mod_order(a, Montgomery_Rprime, mc, order, Montgomery_rprime);
}
internal void Montgomery_multiply_mod_order(ulong[] ma, ulong[] mb, ulong[] mc, ulong[] order, ulong[] Montgomery_rprime)
{
ulong num = 0;
ulong num2 = 0;
ulong[] array = new ulong[2 * engine.param.NWORDS_ORDER];
ulong[] array2 = new ulong[2 * engine.param.NWORDS_ORDER];
ulong[] array3 = new ulong[2 * engine.param.NWORDS_ORDER];
multiply(ma, mb, array, engine.param.NWORDS_ORDER);
multiply(array, Montgomery_rprime, array2, engine.param.NWORDS_ORDER);
multiply(array2, order, array3, engine.param.NWORDS_ORDER);
num = mp_add(array, array3, array3, 2 * engine.param.NWORDS_ORDER);
for (ulong num3 = 0; num3 < engine.param.NWORDS_ORDER; num3++) {
mc[num3] = array3[engine.param.NWORDS_ORDER + num3];
}
num2 = mp_sub(mc, order, mc, engine.param.NWORDS_ORDER);
ulong num4 = num - num2;
for (ulong num3 = 0; num3 < engine.param.NWORDS_ORDER; num3++) {
array3[num3] = (order[num3] & num4);
}
mp_add(mc, array3, mc, engine.param.NWORDS_ORDER);
}
internal void inv_mod_orderA(ulong[] a, ulong[] c)
{
uint num = 0;
ulong[] array = new ulong[engine.param.NWORDS_ORDER];
ulong[] array2 = new ulong[engine.param.NWORDS_ORDER];
ulong[] array3 = new ulong[2 * engine.param.NWORDS_ORDER];
ulong[] array4 = new ulong[engine.param.NWORDS_ORDER];
ulong[] array5 = new ulong[engine.param.NWORDS_ORDER];
ulong num2 = ulong.MaxValue >> (int)(engine.param.NBITS_ORDER - engine.param.OALICE_BITS);
array5[engine.param.NWORDS_ORDER - 1] = (ulong)(1 << (int)(64 - (engine.param.NBITS_ORDER - engine.param.OALICE_BITS)));
array4[0] = 1;
mp_sub(a, array4, array, engine.param.NWORDS_ORDER);
if ((a[0] & 1) == 0 || is_zero(array, engine.param.NWORDS_ORDER)) {
copy_words(a, c, engine.param.NWORDS_ORDER);
c[engine.param.NWORDS_ORDER - 1] &= num2;
} else {
mp_sub(array5, array, c, engine.param.NWORDS_ORDER);
mp_add(c, array4, c, engine.param.NWORDS_ORDER);
copy_words(array, array2, engine.param.NWORDS_ORDER);
while ((array2[0] & 1) == 0) {
num++;
mp_shiftr1(array2, engine.param.NWORDS_ORDER);
}
uint num3 = engine.param.OALICE_BITS / num;
for (uint num4 = 1; num4 < num3; num4 <<= 1) {
multiply(array, array, array3, engine.param.NWORDS_ORDER);
copy_words(array3, array, engine.param.NWORDS_ORDER);
array[engine.param.NWORDS_ORDER - 1] &= num2;
mp_add(array, array4, array2, engine.param.NWORDS_ORDER);
array2[engine.param.NWORDS_ORDER - 1] &= num2;
multiply(c, array2, array3, engine.param.NWORDS_ORDER);
copy_words(array3, c, engine.param.NWORDS_ORDER);
c[engine.param.NWORDS_ORDER - 1] &= num2;
}
}
}
internal void multiply(ulong[] a, ulong[] b, ulong[] c, uint nwords)
{
ulong num = 0;
ulong num2 = 0;
ulong num3 = 0;
ulong low;
for (ulong num4 = 0; num4 < nwords; num4++) {
for (ulong num5 = 0; num5 <= num4; num5++) {
ulong num6 = digit_x_digit(a[num5], b[num4 - num5], out low);
num3 += low;
num6 += is_digit_lessthan_ct(num3, low);
num2 += num6;
num += is_digit_lessthan_ct(num2, num6);
}
c[num4] = num3;
num3 = num2;
num2 = num;
num = 0;
}
for (ulong num4 = nwords; num4 < 2 * nwords - 1; num4++) {
for (ulong num5 = num4 - nwords + 1; num5 < nwords; num5++) {
ulong num6 = digit_x_digit(a[num5], b[num4 - num5], out low);
num3 += low;
num6 += is_digit_lessthan_ct(num3, low);
num2 += num6;
num += is_digit_lessthan_ct(num2, num6);
}
c[num4] = num3;
num3 = num2;
num2 = num;
num = 0;
}
c[2 * nwords - 1] = num3;
}
private bool is_zero_mod_order(ulong[] x)
{
for (uint num = 0; num < engine.param.NWORDS_ORDER; num++) {
if (x[num] != 0)
return false;
}
return true;
}
private bool is_even_mod_order(ulong[] x)
{
return (x[0] & 1) == 0;
}
private bool is_lt_mod_order(ulong[] x, ulong[] y)
{
for (int num = (int)(engine.param.NWORDS_ORDER - 1); num >= 0; num--) {
if (x[num] < y[num])
return true;
if (x[num] > y[num])
return false;
}
return false;
}
private bool is_zero(ulong[] a, uint nwords)
{
for (uint num = 0; num < nwords; num++) {
if (a[num] != 0)
return false;
}
return true;
}
private uint Montgomery_inversion_mod_order_bingcd_partial(ulong[] a, ulong[] x1, ulong[] order)
{
ulong[] array = new ulong[engine.param.NWORDS_ORDER];
ulong[] array2 = new ulong[engine.param.NWORDS_ORDER];
ulong[] array3 = new ulong[engine.param.NWORDS_ORDER];
copy_words(a, array, engine.param.NWORDS_ORDER);
copy_words(order, array2, engine.param.NWORDS_ORDER);
copy_words(array3, x1, engine.param.NWORDS_ORDER);
x1[0] = 1;
uint num = 0;
while (!is_zero_mod_order(array2)) {
uint num2 = ++num / Internal.RADIX + 1;
if (num2 < engine.param.NWORDS_ORDER) {
if (is_even_mod_order(array2)) {
mp_shiftr1(array2, engine.param.NWORDS_ORDER);
mp_shiftl1(x1, num2);
} else if (is_even_mod_order(array)) {
mp_shiftr1(array, engine.param.NWORDS_ORDER);
mp_shiftl1(array3, num2);
} else if (!is_lt_mod_order(array2, array)) {
mp_sub(array2, array, array2, engine.param.NWORDS_ORDER);
mp_shiftr1(array2, engine.param.NWORDS_ORDER);
mp_add(x1, array3, array3, num2);
mp_shiftl1(x1, num2);
} else {
mp_sub(array, array2, array, engine.param.NWORDS_ORDER);
mp_shiftr1(array, engine.param.NWORDS_ORDER);
mp_add(x1, array3, x1, num2);
mp_shiftl1(array3, num2);
}
} else if (is_even_mod_order(array2)) {
mp_shiftr1(array2, engine.param.NWORDS_ORDER);
mp_shiftl1(x1, engine.param.NWORDS_ORDER);
} else if (is_even_mod_order(array)) {
mp_shiftr1(array, engine.param.NWORDS_ORDER);
mp_shiftl1(array3, engine.param.NWORDS_ORDER);
} else if (!is_lt_mod_order(array2, array)) {
mp_sub(array2, array, array2, engine.param.NWORDS_ORDER);
mp_shiftr1(array2, engine.param.NWORDS_ORDER);
mp_add(x1, array3, array3, engine.param.NWORDS_ORDER);
mp_shiftl1(x1, engine.param.NWORDS_ORDER);
} else {
mp_sub(array, array2, array, engine.param.NWORDS_ORDER);
mp_shiftr1(array, engine.param.NWORDS_ORDER);
mp_add(x1, array3, x1, engine.param.NWORDS_ORDER);
mp_shiftl1(array3, engine.param.NWORDS_ORDER);
}
}
if (is_lt_mod_order(order, x1))
mp_sub(x1, order, x1, engine.param.NWORDS_ORDER);
return num;
}
internal void Montgomery_inversion_mod_order_bingcd(ulong[] a, ulong[] c, ulong[] order, ulong[] Montgomery_rprime, ulong[] Montgomery_Rprime)
{
ulong[] array = new ulong[engine.param.NWORDS_ORDER];
ulong[] array2 = new ulong[engine.param.NWORDS_ORDER];
if (is_zero(a, engine.param.NWORDS_ORDER))
copy_words(array2, c, engine.param.NWORDS_ORDER);
else {
uint num = Montgomery_inversion_mod_order_bingcd_partial(a, array, order);
if (num <= engine.param.NBITS_ORDER) {
Montgomery_multiply_mod_order(array, Montgomery_Rprime, array, order, Montgomery_rprime);
num += engine.param.NBITS_ORDER;
}
Montgomery_multiply_mod_order(array, Montgomery_Rprime, array, order, Montgomery_rprime);
power2_setup(array2, (int)(2 * engine.param.NBITS_ORDER - num), engine.param.NWORDS_ORDER);
Montgomery_multiply_mod_order(array, array2, c, order, Montgomery_rprime);
}
}
internal void from_Montgomery_mod_order(ulong[] ma, ulong[] c, ulong[] order, ulong[] Montgomery_rprime)
{
ulong[] array = new ulong[engine.param.NWORDS_ORDER];
array[0] = 1;
Montgomery_multiply_mod_order(ma, array, c, order, Montgomery_rprime);
}
internal uint mod3(ulong[] a)
{
ulong num = 0;
for (int i = 0; i < engine.param.NWORDS_ORDER; i++) {
num += a[i] >> 32;
num += (a[i] & uint.MaxValue);
}
return (uint)(num % 3);
}
internal void to_fp2mont(ulong[][] a, ulong[][] mc)
{
to_mont(a[0], mc[0]);
to_mont(a[1], mc[1]);
}
private void to_mont(ulong[] a, ulong[] mc)
{
fpmul_mont(a, engine.param.Montgomery_R2, mc);
}
internal void fpcorrectionPRIME(ulong[] a)
{
ulong num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num3 = a[num2] - engine.param.PRIME[num2];
ulong num4 = is_digit_lessthan_ct(a[num2], engine.param.PRIME[num2]) | (num & is_digit_zero_ct(num3));
a[num2] = num3 - num;
num = num4;
}
ulong num5 = 0 - num;
num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
ulong num6 = a[num2] + num;
a[num2] = (engine.param.PRIME[num2] & num5) + num6;
num = (is_digit_lessthan_ct(num6, num) | is_digit_lessthan_ct(a[num2], num6));
}
}
internal byte cmp_f2elm(ulong[][] x, ulong[][] y)
{
ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD);
ulong[][] array2 = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD);
byte b = 0;
fp2copy(x, array);
fp2copy(y, array2);
fp2correction(array);
fp2correction(array2);
for (int num = (int)(engine.param.NWORDS_FIELD - 1); num >= 0; num--) {
b = (byte)(b | (byte)((array[0][num] ^ array2[0][num]) | (array[1][num] ^ array2[1][num])));
}
return (byte)(-b >> 7);
}
internal void encode_to_bytes(ulong[] x, byte[] enc, uint encOffset, uint nbytes)
{
byte[] array = new byte[(nbytes * 4 + 7) & -8];
Pack.UInt64_To_LE(x, array, 0);
Array.Copy(array, 0, enc, encOffset, nbytes);
}
internal void decode_to_digits(byte[] x, uint xOffset, ulong[] dec, uint nbytes, uint ndigits)
{
dec[ndigits - 1] = 0;
byte[] array = new byte[(nbytes + 7) & -8];
Array.Copy(x, xOffset, array, 0, nbytes);
Pack.LE_To_UInt64(array, 0, dec);
}
internal void fp2_conj(ulong[][] v, ulong[][] r)
{
fpcopy(v[0], 0, r[0]);
fpcopy(v[1], 0, r[1]);
if (!is_felm_zero(r[1]))
fpnegPRIME(r[1]);
}
private void from_mont(ulong[] ma, ulong[] c)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
array[0] = 1;
fpmul_mont(ma, array, c);
fpcorrectionPRIME(c);
}
private void mp_shiftr1(ulong[] x)
{
for (uint num = 0; num < engine.param.NWORDS_FIELD - 1; num++) {
x[num] = ((x[num] >> 1) ^ (x[num + 1] << (int)(Internal.RADIX - 1)));
}
x[engine.param.NWORDS_FIELD - 1] >>= 1;
}
private void mp_shiftr1(ulong[] x, uint nwords)
{
for (uint num = 0; num < nwords - 1; num++) {
x[num] = ((x[num] >> 1) ^ (x[num + 1] << (int)(Internal.RADIX - 1)));
}
x[nwords - 1] >>= 1;
}
internal void fp2copy(ulong[][] a, ulong[][] c)
{
fpcopy(a[0], 0, c[0]);
fpcopy(a[1], 0, c[1]);
}
internal void fp2copy(ulong[][] a, uint aOffset, ulong[][] c)
{
fpcopy(a[aOffset], 0, c[0]);
fpcopy(a[1 + aOffset], 0, c[1]);
}
internal void fp2copy(ulong[] a, uint aOffset, ulong[][] c)
{
fpcopy(a, aOffset, c[0]);
fpcopy(a, aOffset + engine.param.NWORDS_FIELD, c[1]);
}
internal void fpzero(ulong[] a)
{
for (uint num = 0; num < engine.param.NWORDS_FIELD; num++) {
a[num] = 0;
}
}
internal void mp2_sub_p2(ulong[][] a, ulong[][] b, ulong[][] c)
{
mp_subPRIME_p2(a[0], b[0], c[0]);
mp_subPRIME_p2(a[1], b[1], c[1]);
}
internal void mp_mul(ulong[] a, ulong[] b, ulong[] c, uint nwords)
{
ulong num = 0;
ulong num2 = 0;
ulong num3 = 0;
ulong low;
for (ulong num4 = 0; num4 < nwords; num4++) {
for (ulong num5 = 0; num5 <= num4; num5++) {
ulong num6 = digit_x_digit(a[num5], b[num4 - num5], out low);
num3 += low;
num6 += is_digit_lessthan_ct(num3, low);
num2 += num6;
num += is_digit_lessthan_ct(num2, num6);
}
c[num4] = num3;
num3 = num2;
num2 = num;
num = 0;
}
for (ulong num4 = nwords; num4 < 2 * nwords - 1; num4++) {
for (ulong num5 = num4 - nwords + 1; num5 < nwords; num5++) {
ulong num6 = digit_x_digit(a[num5], b[num4 - num5], out low);
num3 += low;
num6 += is_digit_lessthan_ct(num3, low);
num2 += num6;
num += is_digit_lessthan_ct(num2, num6);
}
c[num4] = num3;
num3 = num2;
num2 = num;
num = 0;
}
c[2 * nwords - 1] = num3;
}
internal void mp_mul(ulong[] a, uint aOffset, ulong[] b, ulong[] c, uint nwords)
{
ulong num = 0;
ulong num2 = 0;
ulong num3 = 0;
ulong low;
for (ulong num4 = 0; num4 < nwords; num4++) {
for (ulong num5 = 0; num5 <= num4; num5++) {
ulong num6 = digit_x_digit(a[num5 + aOffset], b[num4 - num5], out low);
num3 += low;
num6 += is_digit_lessthan_ct(num3, low);
num2 += num6;
num += is_digit_lessthan_ct(num2, num6);
}
c[num4] = num3;
num3 = num2;
num2 = num;
num = 0;
}
for (ulong num4 = nwords; num4 < 2 * nwords - 1; num4++) {
for (ulong num5 = num4 - nwords + 1; num5 < nwords; num5++) {
ulong num6 = digit_x_digit(a[num5 + aOffset], b[num4 - num5], out low);
num3 += low;
num6 += is_digit_lessthan_ct(num3, low);
num2 += num6;
num += is_digit_lessthan_ct(num2, num6);
}
c[num4] = num3;
num3 = num2;
num2 = num;
num = 0;
}
c[2 * nwords - 1] = num3;
}
internal void fp2mul_mont(ulong[][] a, ulong[][] b, ulong[][] c)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong[] array2 = new ulong[engine.param.NWORDS_FIELD];
ulong[] array3 = new ulong[2 * engine.param.NWORDS_FIELD];
ulong[] array4 = new ulong[2 * engine.param.NWORDS_FIELD];
ulong[] array5 = new ulong[2 * engine.param.NWORDS_FIELD];
mp_add(a[0], a[1], array, engine.param.NWORDS_FIELD);
mp_add(b[0], b[1], array2, engine.param.NWORDS_FIELD);
mp_mul(a[0], b[0], array3, engine.param.NWORDS_FIELD);
mp_mul(a[1], b[1], array4, engine.param.NWORDS_FIELD);
mp_mul(array, array2, array5, engine.param.NWORDS_FIELD);
mp_dblsubfast(array3, array4, array5);
mp_subaddfast(array3, array4, array3);
rdc_mont(array5, c[1]);
rdc_mont(array3, c[0]);
}
internal void fp2mul_mont(ulong[][] a, ulong[][] b, uint bOffset, ulong[][] c)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong[] array2 = new ulong[engine.param.NWORDS_FIELD];
ulong[] array3 = new ulong[2 * engine.param.NWORDS_FIELD];
ulong[] array4 = new ulong[2 * engine.param.NWORDS_FIELD];
ulong[] array5 = new ulong[2 * engine.param.NWORDS_FIELD];
mp_add(a[0], a[1], array, engine.param.NWORDS_FIELD);
mp_add(b[bOffset], b[bOffset + 1], array2, engine.param.NWORDS_FIELD);
mp_mul(a[0], b[bOffset], array3, engine.param.NWORDS_FIELD);
mp_mul(a[1], b[bOffset + 1], array4, engine.param.NWORDS_FIELD);
mp_mul(array, array2, array5, engine.param.NWORDS_FIELD);
mp_dblsubfast(array3, array4, array5);
mp_subaddfast(array3, array4, array3);
rdc_mont(array5, c[1]);
rdc_mont(array3, c[0]);
}
internal void fp2mul_mont(ulong[][] a, ulong[] b, uint bOffset, ulong[][] c)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong[] array2 = new ulong[engine.param.NWORDS_FIELD];
ulong[] array3 = new ulong[2 * engine.param.NWORDS_FIELD];
ulong[] array4 = new ulong[2 * engine.param.NWORDS_FIELD];
ulong[] array5 = new ulong[2 * engine.param.NWORDS_FIELD];
mp_add(a[0], a[1], array, engine.param.NWORDS_FIELD);
mp_add(b, bOffset, b, bOffset + engine.param.NWORDS_FIELD, array2, 0, engine.param.NWORDS_FIELD);
mp_mul(b, bOffset, a[0], array3, engine.param.NWORDS_FIELD);
mp_mul(b, bOffset + engine.param.NWORDS_FIELD, a[1], array4, engine.param.NWORDS_FIELD);
mp_mul(array, array2, array5, engine.param.NWORDS_FIELD);
mp_dblsubfast(array3, array4, array5);
mp_subaddfast(array3, array4, array3);
rdc_mont(array5, c[1]);
rdc_mont(array3, c[0]);
}
private void mp_dblsubfast(ulong[] a, ulong[] b, ulong[] c)
{
mp_sub(c, a, c, 2 * engine.param.NWORDS_FIELD);
mp_sub(c, b, c, 2 * engine.param.NWORDS_FIELD);
}
internal ulong mp_sub(ulong[] a, ulong[] b, ulong[] c, uint nwords)
{
ulong num = 0;
for (ulong num2 = 0; num2 < nwords; num2++) {
ulong num3 = a[num2] - b[num2];
ulong num4 = is_digit_lessthan_ct(a[num2], b[num2]) | (num & is_digit_zero_ct(num3));
c[num2] = num3 - num;
num = num4;
}
return num;
}
internal bool is_orderelm_lt(ulong[] x, ulong[] y)
{
for (int num = (int)(engine.param.NWORDS_ORDER - 1); num >= 0; num--) {
if (x[num] < y[num])
return true;
if (x[num] > y[num])
return false;
}
return false;
}
private void mp_subaddfast(ulong[] a, ulong[] b, ulong[] c)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong num = 0 - mp_sub(a, b, c, 2 * engine.param.NWORDS_FIELD);
for (uint num2 = 0; num2 < engine.param.NWORDS_FIELD; num2++) {
array[num2] = (engine.param.PRIME[num2] & num);
}
mp_add(c, engine.param.NWORDS_FIELD, array, c, engine.param.NWORDS_FIELD, engine.param.NWORDS_FIELD);
}
internal void fpsqr_mont(ulong[] ma, ulong[] mc)
{
ulong[] array = new ulong[2 * engine.param.NWORDS_FIELD];
mp_mul(ma, ma, array, engine.param.NWORDS_FIELD);
rdc_mont(array, mc);
}
private void fpinv_mont(ulong[] a)
{
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
fpcopy(a, 0, array);
fpinv_chain_mont(array);
fpsqr_mont(array, array);
fpsqr_mont(array, array);
fpmul_mont(a, array, a);
}
internal void fp2inv_mont(ulong[][] a)
{
ulong[][] array = SikeUtilities.InitArray(2, engine.param.NWORDS_FIELD);
fpsqr_mont(a[0], array[0]);
fpsqr_mont(a[1], array[1]);
fpaddPRIME(array[0], array[1], array[0]);
fpinv_mont(array[0]);
fpnegPRIME(a[1]);
fpmul_mont(a[0], array[0], a[0]);
fpmul_mont(a[1], array[0], a[1]);
}
internal void mul3(byte[] a)
{
ulong[] array = new ulong[engine.param.NWORDS_ORDER];
ulong[] array2 = new ulong[engine.param.NWORDS_ORDER];
decode_to_digits(a, 0, array, engine.param.SECRETKEY_B_BYTES, engine.param.NWORDS_ORDER);
mp_add(array, array, array2, engine.param.NWORDS_ORDER);
mp_add(array, array2, array, engine.param.NWORDS_ORDER);
encode_to_bytes(array, a, 0, engine.param.SECRETKEY_B_BYTES);
}
internal byte ct_compare(byte[] a, byte[] b, uint len)
{
byte b2 = 0;
for (uint num = 0; num < len; num++) {
b2 = (byte)(b2 | (byte)(a[num] ^ b[num]));
}
return (byte)(-b2 >> 7);
}
internal void ct_cmov(byte[] r, byte[] a, uint len, byte selector)
{
for (uint num = 0; num < len; num++) {
r[num] ^= (byte)(selector & (a[num] ^ r[num]));
}
}
internal void copy_words(ulong[] a, ulong[] c, uint nwords)
{
for (uint num = 0; num < nwords; num++) {
c[num] = a[num];
}
}
internal void fp2shl(ulong[][] a, uint k, ulong[][] c)
{
fp2copy(a, c);
for (uint num = 0; num < k; num++) {
fp2add(c, c, c);
}
}
internal void copy_words(PointProj a, PointProj c)
{
for (uint num = 0; num < engine.param.NWORDS_FIELD; num++) {
c.X[0][num] = a.X[0][num];
c.X[1][num] = a.X[1][num];
c.Z[0][num] = a.Z[0][num];
c.Z[1][num] = a.Z[1][num];
}
}
internal void Montgomery_neg(ulong[] a, ulong[] order)
{
ulong num = 0;
for (ulong num2 = 0; num2 < engine.param.NWORDS_ORDER; num2++) {
ulong num3 = order[num2] - a[num2];
ulong num4 = is_digit_lessthan_ct(order[num2], a[num2]) | (num & is_digit_zero_ct(num3));
a[num2] = num3 - num;
num = num4;
}
}
internal void fp2add(ulong[][] a, ulong[][] b, ulong[][] c)
{
fpaddPRIME(a[0], b[0], c[0]);
fpaddPRIME(a[1], b[1], c[1]);
}
internal void fp2sub(ulong[][] a, ulong[][] b, ulong[][] c)
{
fpsubPRIME(a[0], b[0], c[0]);
fpsubPRIME(a[1], b[1], c[1]);
}
private void mp2_sub_p4(ulong[][] a, ulong[][] b, ulong[][] c)
{
mp_subPRIME_p4(a[0], b[0], c[0]);
mp_subPRIME_p4(a[1], b[1], c[1]);
}
internal void fpmul_mont(ulong[] ma, ulong[] mb, ulong[] mc)
{
ulong[] array = new ulong[2 * engine.param.NWORDS_FIELD];
mp_mul(ma, mb, array, engine.param.NWORDS_FIELD);
rdc_mont(array, mc);
}
internal void fpmul_mont(ulong[] ma, uint maOffset, ulong[] mb, ulong[] mc)
{
ulong[] array = new ulong[2 * engine.param.NWORDS_FIELD];
mp_mul(ma, maOffset, mb, array, engine.param.NWORDS_FIELD);
rdc_mont(array, mc);
}
private void fpinv_chain_mont(ulong[] a)
{
if (engine.param.NBITS_FIELD == 434) {
ulong[] array = new ulong[engine.param.NWORDS_FIELD];
ulong[][] array2 = SikeUtilities.InitArray(31, engine.param.NWORDS_FIELD);
fpsqr_mont(a, array);
fpmul_mont(a, array, array2[0]);
for (uint num = 0; num <= 29; num++) {
fpmul_mont(array2[num], array, array2[num + 1]);
}
fpcopy(a, 0, array);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[5], array, array);
for (uint num = 0; num < 10; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[14], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[3], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[23], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[13], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[24], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[7], array, array);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[12], array, array);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[30], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[1], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[30], array, array);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[21], array, array);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[2], array, array);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[19], array, array);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[1], array, array);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[24], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[26], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[16], array, array);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[10], array, array);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[6], array, array);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[0], array, array);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[20], array, array);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[9], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[25], array, array);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[30], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[26], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(a, array, array);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[28], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[6], array, array);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[10], array, array);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[22], array, array);
for (uint num2 = 0; num2 < 35; num2++) {
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array, array);
}
fpmul_mont(array2[30], array, array);
}
fpcopy(array, 0, a);
}
if (engine.param.NBITS_FIELD == 503) {
ulong[][] array3 = SikeUtilities.InitArray(15, engine.param.NWORDS_FIELD);
ulong[] array4 = new ulong[engine.param.NWORDS_FIELD];
fpsqr_mont(a, array4);
fpmul_mont(a, array4, array3[0]);
for (uint num = 0; num <= 13; num++) {
fpmul_mont(array3[num], array4, array3[num + 1]);
}
fpcopy(a, 0, array4);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(a, array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[8], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[6], array4, array4);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[9], array4, array4);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[0], array4, array4);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(a, array4, array4);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[6], array4, array4);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[2], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[8], array4, array4);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(a, array4, array4);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[10], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[0], array4, array4);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[10], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[10], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[5], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[2], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[6], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[3], array4, array4);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[5], array4, array4);
for (uint num = 0; num < 12; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[12], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[8], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[6], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[12], array4, array4);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[11], array4, array4);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[6], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[5], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[14], array4, array4);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[14], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[5], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[6], array4, array4);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[8], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(a, array4, array4);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[4], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[6], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[5], array4, array4);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[7], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(a, array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[0], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[11], array4, array4);
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[13], array4, array4);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[1], array4, array4);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[10], array4, array4);
for (uint num2 = 0; num2 < 49; num2++) {
for (uint num = 0; num < 5; num++) {
fpsqr_mont(array4, array4);
}
fpmul_mont(array3[14], array4, array4);
}
fpcopy(array4, 0, a);
}
if (engine.param.NBITS_FIELD == 610) {
ulong[][] array5 = SikeUtilities.InitArray(31, engine.param.NWORDS_FIELD);
ulong[] array6 = new ulong[engine.param.NWORDS_FIELD];
fpsqr_mont(a, array6);
fpmul_mont(a, array6, array5[0]);
for (uint num = 0; num <= 29; num++) {
fpmul_mont(array5[num], array6, array5[num + 1]);
}
fpcopy(a, 0, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[6], array6, array6);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[30], array6, array6);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[25], array6, array6);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[28], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[7], array6, array6);
for (uint num = 0; num < 11; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[11], array6, array6);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(a, array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[0], array6, array6);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[3], array6, array6);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[16], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[24], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[28], array6, array6);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[16], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[4], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[3], array6, array6);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[20], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[11], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[14], array6, array6);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[15], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[0], array6, array6);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[15], array6, array6);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[19], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[9], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[5], array6, array6);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[27], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[28], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[29], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[1], array6, array6);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[3], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[2], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[30], array6, array6);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[25], array6, array6);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[28], array6, array6);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[22], array6, array6);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[3], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[22], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[7], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[9], array6, array6);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[4], array6, array6);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[20], array6, array6);
for (uint num = 0; num < 11; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[10], array6, array6);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[26], array6, array6);
for (uint num = 0; num < 11; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[2], array6, array6);
for (uint num2 = 0; num2 < 50; num2++) {
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array6, array6);
}
fpmul_mont(array5[30], array6, array6);
}
fpcopy(array6, 0, a);
}
if (engine.param.NBITS_FIELD == 751) {
ulong[][] array7 = SikeUtilities.InitArray(27, engine.param.NWORDS_FIELD);
ulong[] array8 = new ulong[engine.param.NWORDS_FIELD];
fpsqr_mont(a, array8);
fpmul_mont(a, array8, array7[0]);
fpmul_mont(array7[0], array8, array7[1]);
fpmul_mont(array7[1], array8, array7[2]);
fpmul_mont(array7[2], array8, array7[3]);
fpmul_mont(array7[3], array8, array7[3]);
for (uint num = 3; num <= 8; num++) {
fpmul_mont(array7[num], array8, array7[num + 1]);
}
fpmul_mont(array7[9], array8, array7[9]);
for (uint num = 9; num <= 20; num++) {
fpmul_mont(array7[num], array8, array7[num + 1]);
}
fpmul_mont(array7[21], array8, array7[21]);
for (uint num = 21; num <= 24; num++) {
fpmul_mont(array7[num], array8, array7[num + 1]);
}
fpmul_mont(array7[25], array8, array7[25]);
fpmul_mont(array7[25], array8, array7[26]);
fpcopy(a, 0, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[20], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[24], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[11], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[8], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[2], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[23], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[2], array8, array8);
for (uint num = 0; num < 9; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[2], array8, array8);
for (uint num = 0; num < 10; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[15], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[13], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[26], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[20], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[11], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[10], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[14], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[4], array8, array8);
for (uint num = 0; num < 10; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[18], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[1], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[22], array8, array8);
for (uint num = 0; num < 10; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[6], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[24], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[9], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[18], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[17], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(a, array8, array8);
for (uint num = 0; num < 10; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[16], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[7], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[0], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[12], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[19], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[22], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[25], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[2], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[10], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[22], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[18], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[4], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[14], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[13], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[5], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[23], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[21], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[2], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[23], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[12], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[9], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[3], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[13], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[17], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[26], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[5], array8, array8);
for (uint num = 0; num < 8; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[8], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[2], array8, array8);
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[11], array8, array8);
for (uint num = 0; num < 7; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[20], array8, array8);
for (uint num2 = 0; num2 < 61; num2++) {
for (uint num = 0; num < 6; num++) {
fpsqr_mont(array8, array8);
}
fpmul_mont(array7[26], array8, array8);
}
fpcopy(array8, 0, a);
}
}
}
}