feMul static method

void feMul(
  1. FieldElement h,
  2. FieldElement f,
  3. FieldElement g
)

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;
}