feMul static method
Implementation
static void feMul(FieldElement h, FieldElement f, FieldElement g) {
final int f0 = f.h[0];
final int f1 = f.h[1];
final int f2 = f.h[2];
final int f3 = f.h[3];
final int f4 = f.h[4];
final int f5 = f.h[5];
final int f6 = f.h[6];
final int f7 = f.h[7];
final int f8 = f.h[8];
final int f9 = f.h[9];
final int g0 = g.h[0];
final int g1 = g.h[1];
final int g2 = g.h[2];
final int g3 = g.h[3];
final int g4 = g.h[4];
final int g5 = g.h[5];
final int g6 = g.h[6];
final int g7 = g.h[7];
final int g8 = g.h[8];
final int g9 = g.h[9];
final int g1_19 = (19 * g1).toInt32; /* 1.959375*2^29 */
final int g2_19 = (19 * g2).toInt32; /* 1.959375*2^30; still ok */
final int g3_19 = (19 * g3).toInt32;
final int g4_19 = (19 * g4).toInt32;
final int g5_19 = (19 * g5).toInt32;
final int g6_19 = (19 * g6).toInt32;
final int g7_19 = (19 * g7).toInt32;
final int g8_19 = (19 * g8).toInt32;
final int g9_19 = (19 * g9).toInt32;
final int f1_2 = (2 * f1).toInt32;
final int f3_2 = (2 * f3).toInt32;
final int f5_2 = (2 * f5).toInt32;
final int f7_2 = (2 * f7).toInt32;
final int f9_2 = (2 * f9).toInt32;
final BigInt f0g0 = f0.toBig * g0.toBig;
final BigInt f0g1 = f0.toBig * g1.toBig;
final BigInt f0g2 = f0.toBig * g2.toBig;
final BigInt f0g3 = f0.toBig * g3.toBig;
final BigInt f0g4 = f0.toBig * g4.toBig;
final BigInt f0g5 = f0.toBig * g5.toBig;
final BigInt f0g6 = f0.toBig * g6.toBig;
final BigInt f0g7 = f0.toBig * g7.toBig;
final BigInt f0g8 = f0.toBig * g8.toBig;
final BigInt f0g9 = f0.toBig * g9.toBig;
final BigInt f1g0 = f1.toBig * g0.toBig;
final BigInt f1g1_2 = f1_2.toBig * g1.toBig;
final BigInt f1g2 = f1.toBig * g2.toBig;
final BigInt f1g3_2 = f1_2.toBig * g3.toBig;
final BigInt f1g4 = f1.toBig * g4.toBig;
final BigInt f1g5_2 = f1_2.toBig * g5.toBig;
final BigInt f1g6 = f1.toBig * g6.toBig;
final BigInt f1g7_2 = f1_2.toBig * g7.toBig;
final BigInt f1g8 = f1.toBig * g8.toBig;
final BigInt f1g9_38 = f1_2.toBig * g9_19.toBig;
final BigInt f2g0 = f2.toBig * g0.toBig;
final BigInt f2g1 = f2.toBig * g1.toBig;
final BigInt f2g2 = f2.toBig * g2.toBig;
final BigInt f2g3 = f2.toBig * g3.toBig;
final BigInt f2g4 = f2.toBig * g4.toBig;
final BigInt f2g5 = f2.toBig * g5.toBig;
final BigInt f2g6 = f2.toBig * g6.toBig;
final BigInt f2g7 = f2.toBig * g7.toBig;
final BigInt f2g8_19 = f2.toBig * g8_19.toBig;
final BigInt f2g9_19 = f2.toBig * g9_19.toBig;
final BigInt f3g0 = f3.toBig * g0.toBig;
final BigInt f3g1_2 = f3_2.toBig * g1.toBig;
final BigInt f3g2 = f3.toBig * g2.toBig;
final BigInt f3g3_2 = f3_2.toBig * g3.toBig;
final BigInt f3g4 = f3.toBig * g4.toBig;
final BigInt f3g5_2 = f3_2.toBig * g5.toBig;
final BigInt f3g6 = f3.toBig * g6.toBig;
final BigInt f3g7_38 = f3_2.toBig * g7_19.toBig;
final BigInt f3g8_19 = f3.toBig * g8_19.toBig;
final BigInt f3g9_38 = f3_2.toBig * g9_19.toBig;
final BigInt f4g0 = f4.toBig * g0.toBig;
final BigInt f4g1 = f4.toBig * g1.toBig;
final BigInt f4g2 = f4.toBig * g2.toBig;
final BigInt f4g3 = f4.toBig * g3.toBig;
final BigInt f4g4 = f4.toBig * g4.toBig;
final BigInt f4g5 = f4.toBig * g5.toBig;
final BigInt f4g6_19 = f4.toBig * g6_19.toBig;
final BigInt f4g7_19 = f4.toBig * g7_19.toBig;
final BigInt f4g8_19 = f4.toBig * g8_19.toBig;
final BigInt f4g9_19 = f4.toBig * g9_19.toBig;
final BigInt f5g0 = f5.toBig * g0.toBig;
final BigInt f5g1_2 = f5_2.toBig * g1.toBig;
final BigInt f5g2 = f5.toBig * g2.toBig;
final BigInt f5g3_2 = f5_2.toBig * g3.toBig;
final BigInt f5g4 = f5.toBig * g4.toBig;
final BigInt f5g5_38 = f5_2.toBig * g5_19.toBig;
final BigInt f5g6_19 = f5.toBig * g6_19.toBig;
final BigInt f5g7_38 = f5_2.toBig * g7_19.toBig;
final BigInt f5g8_19 = f5.toBig * g8_19.toBig;
final BigInt f5g9_38 = f5_2.toBig * g9_19.toBig;
final BigInt f6g0 = f6.toBig * g0.toBig;
final BigInt f6g1 = f6.toBig * g1.toBig;
final BigInt f6g2 = f6.toBig * g2.toBig;
final BigInt f6g3 = f6.toBig * g3.toBig;
final BigInt f6g4_19 = f6.toBig * g4_19.toBig;
final BigInt f6g5_19 = f6.toBig * g5_19.toBig;
final BigInt f6g6_19 = f6.toBig * g6_19.toBig;
final BigInt f6g7_19 = f6.toBig * g7_19.toBig;
final BigInt f6g8_19 = f6.toBig * g8_19.toBig;
final BigInt f6g9_19 = f6.toBig * g9_19.toBig;
final BigInt f7g0 = f7.toBig * g0.toBig;
final BigInt f7g1_2 = f7_2.toBig * g1.toBig;
final BigInt f7g2 = f7.toBig * g2.toBig;
final BigInt f7g3_38 = f7_2.toBig * g3_19.toBig;
final BigInt f7g4_19 = f7.toBig * g4_19.toBig;
final BigInt f7g5_38 = f7_2.toBig * g5_19.toBig;
final BigInt f7g6_19 = f7.toBig * g6_19.toBig;
final BigInt f7g7_38 = f7_2.toBig * g7_19.toBig;
final BigInt f7g8_19 = f7.toBig * g8_19.toBig;
final BigInt f7g9_38 = f7_2.toBig * g9_19.toBig;
final BigInt f8g0 = f8.toBig * g0.toBig;
final BigInt f8g1 = f8.toBig * g1.toBig;
final BigInt f8g2_19 = f8.toBig * g2_19.toBig;
final BigInt f8g3_19 = f8.toBig * g3_19.toBig;
final BigInt f8g4_19 = f8.toBig * g4_19.toBig;
final BigInt f8g5_19 = f8.toBig * g5_19.toBig;
final BigInt f8g6_19 = f8.toBig * g6_19.toBig;
final BigInt f8g7_19 = f8.toBig * g7_19.toBig;
final BigInt f8g8_19 = f8.toBig * g8_19.toBig;
final BigInt f8g9_19 = f8.toBig * g9_19.toBig;
final BigInt f9g0 = f9.toBig * g0.toBig;
final BigInt f9g1_38 = f9_2.toBig * g1_19.toBig;
final BigInt f9g2_19 = f9.toBig * g2_19.toBig;
final BigInt f9g3_38 = f9_2.toBig * g3_19.toBig;
final BigInt f9g4_19 = f9.toBig * g4_19.toBig;
final BigInt f9g5_38 = f9_2.toBig * g5_19.toBig;
final BigInt f9g6_19 = f9.toBig * g6_19.toBig;
final BigInt f9g7_38 = f9_2.toBig * g7_19.toBig;
final BigInt f9g8_19 = f9.toBig * g8_19.toBig;
final BigInt f9g9_38 = f9_2.toBig * g9_19.toBig;
BigInt h0 = f0g0 +
f1g9_38 +
f2g8_19 +
f3g7_38 +
f4g6_19 +
f5g5_38 +
f6g4_19 +
f7g3_38 +
f8g2_19 +
f9g1_38;
BigInt h1 = f0g1 +
f1g0 +
f2g9_19 +
f3g8_19 +
f4g7_19 +
f5g6_19 +
f6g5_19 +
f7g4_19 +
f8g3_19 +
f9g2_19;
BigInt h2 = f0g2 +
f1g1_2 +
f2g0 +
f3g9_38 +
f4g8_19 +
f5g7_38 +
f6g6_19 +
f7g5_38 +
f8g4_19 +
f9g3_38;
BigInt h3 = f0g3 +
f1g2 +
f2g1 +
f3g0 +
f4g9_19 +
f5g8_19 +
f6g7_19 +
f7g6_19 +
f8g5_19 +
f9g4_19;
BigInt h4 = f0g4 +
f1g3_2 +
f2g2 +
f3g1_2 +
f4g0 +
f5g9_38 +
f6g8_19 +
f7g7_38 +
f8g6_19 +
f9g5_38;
BigInt h5 = f0g5 +
f1g4 +
f2g3 +
f3g2 +
f4g1 +
f5g0 +
f6g9_19 +
f7g8_19 +
f8g7_19 +
f9g6_19;
BigInt h6 = f0g6 +
f1g5_2 +
f2g4 +
f3g3_2 +
f4g2 +
f5g1_2 +
f6g0 +
f7g9_38 +
f8g8_19 +
f9g7_38;
BigInt h7 = f0g7 +
f1g6 +
f2g5 +
f3g4 +
f4g3 +
f5g2 +
f6g1 +
f7g0 +
f8g9_19 +
f9g8_19;
BigInt h8 = f0g8 +
f1g7_2 +
f2g6 +
f3g5_2 +
f4g4 +
f5g3_2 +
f6g2 +
f7g1_2 +
f8g0 +
f9g9_38;
BigInt h9 =
f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0;
BigInt carry0;
BigInt carry1;
BigInt carry2;
BigInt carry3;
BigInt carry4;
BigInt carry5;
BigInt carry6;
BigInt carry7;
BigInt carry8;
BigInt carry9;
/*
|h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
|h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9
*/
carry0 = (h0 + _bitMaskFor25) >> 26;
h1 += carry0;
h0 -= carry0 << 26;
carry4 = (h4 + _bitMaskFor25) >> 26;
h5 += carry4;
h4 -= carry4 << 26;
/* |h0| <= 2^25 */
/* |h4| <= 2^25 */
/* |h1| <= 1.71*2^59 */
/* |h5| <= 1.71*2^59 */
carry1 = (h1 + _bitMaskFor24) >> 25;
h2 += carry1;
h1 -= carry1 << 25;
carry5 = (h5 + _bitMaskFor24) >> 25;
h6 += carry5;
h5 -= carry5 << 25;
/* |h1| <= 2^24; from now on fits into int32 */
/* |h5| <= 2^24; from now on fits into int32 */
/* |h2| <= 1.41*2^60 */
/* |h6| <= 1.41*2^60 */
carry2 = (h2 + _bitMaskFor25) >> 26;
h3 += carry2;
h2 -= carry2 << 26;
carry6 = (h6 + _bitMaskFor25) >> 26;
h7 += carry6;
h6 -= carry6 << 26;
/* |h2| <= 2^25; from now on fits into int32 unchanged */
/* |h6| <= 2^25; from now on fits into int32 unchanged */
/* |h3| <= 1.71*2^59 */
/* |h7| <= 1.71*2^59 */
carry3 = (h3 + _bitMaskFor24) >> 25;
h4 += carry3;
h3 -= carry3 << 25;
carry7 = (h7 + _bitMaskFor24) >> 25;
h8 += carry7;
h7 -= carry7 << 25;
/* |h3| <= 2^24; from now on fits into int32 unchanged */
/* |h7| <= 2^24; from now on fits into int32 unchanged */
/* |h4| <= 1.72*2^34 */
/* |h8| <= 1.41*2^60 */
carry4 = (h4 + _bitMaskFor25) >> 26;
h5 += carry4;
h4 -= carry4 << 26;
carry8 = (h8 + _bitMaskFor25) >> 26;
h9 += carry8;
h8 -= carry8 << 26;
/* |h4| <= 2^25; from now on fits into int32 unchanged */
/* |h8| <= 2^25; from now on fits into int32 unchanged */
/* |h5| <= 1.01*2^24 */
/* |h9| <= 1.71*2^59 */
carry9 = (h9 + _bitMaskFor24) >> 25;
h0 += carry9 * BigInt.from(19);
h9 -= carry9 << 25;
/* |h9| <= 2^24; from now on fits into int32 unchanged */
/* |h0| <= 1.1*2^39 */
carry0 = (h0 + _bitMaskFor25) >> 26;
h1 += carry0;
h0 -= carry0 << 26;
/* |h0| <= 2^25; from now on fits into int32 unchanged */
/* |h1| <= 1.01*2^24 */
h.h[0] = h0.toInt32;
h.h[1] = h1.toInt32;
h.h[2] = h2.toInt32;
h.h[3] = h3.toInt32;
h.h[4] = h4.toInt32;
h.h[5] = h5.toInt32;
h.h[6] = h6.toInt32;
h.h[7] = h7.toInt32;
h.h[8] = h8.toInt32;
h.h[9] = h9.toInt32;
}