secp256k1FeMul static method

void secp256k1FeMul(
  1. Secp256k1Fe r,
  2. Secp256k1Fe a,
  3. Secp256k1Fe b
)

Implementation

static void secp256k1FeMul(Secp256k1Fe r, Secp256k1Fe a, Secp256k1Fe b) {
  void verifyBits(BigInt x, int n) => _verifyBits(x, n, "secp256k1FeMul");
  void verifyBits128(Secp256k1Uint128 x, int n) =>
      _verifyBits128(x, n, "secp256k1FeMul");
  _cond(r != b, "secp256k1FeMul");
  _cond(a != b, "secp256k1FeMul");
  Secp256k1Uint128 c = Secp256k1Uint128(), d = Secp256k1Uint128();
  BigInt t3, t4, tx, u0;
  BigInt a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
  BigInt M = Secp256k1Const.mask52, R = Secp256k1Const.bit33Mask;
  verifyBits(a[0], 56);
  verifyBits(a[1], 56);
  verifyBits(a[2], 56);
  verifyBits(a[3], 56);
  verifyBits(a[4], 52);
  verifyBits(b[0], 56);
  verifyBits(b[1], 56);
  verifyBits(b[2], 56);
  verifyBits(b[3], 56);
  verifyBits(b[4], 52);
  _cond(r != b, "secp256k1FeMul");
  _cond(a != b, "secp256k1FeMul");

  secp256k1U128Mul(d, a0, b[3]);
  secp256k1U128AccumMul(d, a1, b[2]);
  secp256k1U128AccumMul(d, a2, b[1]);
  secp256k1U128AccumMul(d, a3, b[0]);
  verifyBits128(d, 114);

  /// [d 0 0 0] = [p3 0 0 0]
  secp256k1U128Mul(c, a4, b[4]);
  verifyBits128(c, 112);
  // /// [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0]
  secp256k1U128AccumMul(d, R, secp256k1U128ToU64(c));
  secp256k1U128Rshift(c, 64);
  verifyBits128(d, 115);
  verifyBits128(c, 48);

  /// [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0]
  t3 = (secp256k1U128ToU64(d) & M).toUnsigned64;
  secp256k1U128Rshift(d, 52);
  verifyBits(t3, 52);
  verifyBits128(d, 63);

  /// [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0]

  secp256k1U128AccumMul(d, a0, b[4]);
  secp256k1U128AccumMul(d, a1, b[3]);
  secp256k1U128AccumMul(d, a2, b[2]);
  secp256k1U128AccumMul(d, a3, b[1]);
  secp256k1U128AccumMul(d, a4, b[0]);
  verifyBits128(d, 115);

  /// [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0]
  secp256k1U128AccumMul(d, R << 12, secp256k1U128ToU64(c));
  verifyBits128(d, 116);

  /// [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0]
  t4 = (secp256k1U128ToU64(d) & M).toUnsigned64;
  secp256k1U128Rshift(d, 52);
  verifyBits(t4, 52);
  verifyBits128(d, 64);

  /// [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0]
  tx = (t4 >> 48).toUnsigned64;
  t4 = (t4 & (M >> 4)).toUnsigned64;
  verifyBits(tx, 4);
  verifyBits(t4, 48);

  /// [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0]

  secp256k1U128Mul(c, a0, b[0]);
  verifyBits128(c, 112);

  /// [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0]
  secp256k1U128AccumMul(d, a1, b[4]);
  secp256k1U128AccumMul(d, a2, b[3]);
  secp256k1U128AccumMul(d, a3, b[2]);
  secp256k1U128AccumMul(d, a4, b[1]);
  verifyBits128(d, 114);

  /// [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0]
  u0 = (secp256k1U128ToU64(d) & M).toUnsigned64;
  secp256k1U128Rshift(d, 52);
  verifyBits(u0, 52);
  verifyBits128(d, 62);

  /// [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0]
  /// [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0]
  u0 = ((u0 << 4) | tx).toUnsigned64;
  verifyBits(u0, 56);

  /// [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0]
  secp256k1U128AccumMul(c, u0, R >> 4);
  verifyBits128(c, 113);

  /// [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0]
  r[0] = secp256k1U128ToU64(c) & M;
  secp256k1U128Rshift(c, 52);
  verifyBits(r[0], 52);
  verifyBits128(c, 61);

  /// [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0]

  secp256k1U128AccumMul(c, a0, b[1]);
  secp256k1U128AccumMul(c, a1, b[0]);
  verifyBits128(c, 114);

  /// [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0]
  secp256k1U128AccumMul(d, a2, b[4]);
  secp256k1U128AccumMul(d, a3, b[3]);
  secp256k1U128AccumMul(d, a4, b[2]);
  verifyBits128(d, 114);

  /// [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0]
  secp256k1U128AccumMul(c, secp256k1U128ToU64(d) & M, R);
  secp256k1U128Rshift(d, 52);
  verifyBits128(c, 115);
  verifyBits128(d, 62);

  /// [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0]
  r[1] = secp256k1U128ToU64(c) & M;
  secp256k1U128Rshift(c, 52);
  verifyBits(r[1], 52);
  verifyBits128(c, 63);

  /// [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0]

  secp256k1U128AccumMul(c, a0, b[2]);
  secp256k1U128AccumMul(c, a1, b[1]);
  secp256k1U128AccumMul(c, a2, b[0]);
  verifyBits128(c, 114);

  /// [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0]
  secp256k1U128AccumMul(d, a3, b[4]);
  secp256k1U128AccumMul(d, a4, b[3]);
  verifyBits128(d, 114);

  /// [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]
  secp256k1U128AccumMul(c, R, secp256k1U128ToU64(d));
  secp256k1U128Rshift(d, 64);
  verifyBits128(c, 115);
  verifyBits128(d, 50);

  /// [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]

  r[2] = secp256k1U128ToU64(c) & M;
  secp256k1U128Rshift(c, 52);
  verifyBits(r[2], 52);
  verifyBits128(c, 63);

  /// [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]
  secp256k1U128AccumMul(c, R << 12, secp256k1U128ToU64(d));
  secp256k1U128AccumU64(c, t3);
  verifyBits128(c, 100);

  /// [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]
  r[3] = secp256k1U128ToU64(c) & M;
  secp256k1U128Rshift(c, 52);
  verifyBits(r[3], 52);
  verifyBits128(c, 48);

  /// [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]
  r[4] = secp256k1U128ToU64(c) + t4;
  verifyBits(r[4], 49);

  /// [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]
}