secp256k1FeNormalizesToZeroVar static method

int secp256k1FeNormalizesToZeroVar(
  1. Secp256k1Fe r
)

Implementation

static int secp256k1FeNormalizesToZeroVar(Secp256k1Fe r) {
  BigInt t0, t1, t2, t3, t4;
  BigInt z0, z1;
  BigInt x;

  t0 = r[0];
  t4 = r[4];

  /// Reduce t4 at the start so there will be at most a single carry from the first pass
  x = (t4 >> 48).toUnsigned64;

  /// The first pass ensures the magnitude is 1, ...
  t0 = (t0 + x * Secp256k1Const.mask33).toUnsigned64;

  /// z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P
  z0 = (t0 & Secp256k1Const.mask52).toUnsigned64;
  z1 = (z0 ^ 0x1000003D0.toBigInt).toUnsigned64;

  /// Fast return path should catch the majority of cases
  if ((z0 != BigInt.zero) & (z1 != Secp256k1Const.mask52)) {
    return 0;
  }

  t1 = r[1];
  t2 = r[2];
  t3 = r[3];

  t4 = (t4 & Secp256k1Const.mask48).toUnsigned64;

  t1 = (t1 + (t0 >> 52)).toUnsigned64;
  t2 = (t2 + (t1 >> 52)).toUnsigned64;
  t1 = (t1 & Secp256k1Const.mask52).toUnsigned64;
  z0 = (z0 | t1).toUnsigned64;
  z1 = (z1 & t1).toUnsigned64;
  t3 = (t3 + (t2 >> 52)).toUnsigned64;
  t2 = (t2 & Secp256k1Const.mask52).toUnsigned64;
  z0 = (z0 | t2).toUnsigned64;
  z1 = (z1 & t2).toUnsigned64;
  t4 = (t4 + (t3 >> 52)).toUnsigned64;
  t3 = (t3 & Secp256k1Const.mask52).toUnsigned64;
  z0 = (z0 | t3).toUnsigned64;
  z1 = (z1 & t3).toUnsigned64;
  z0 = (z0 | t4).toUnsigned64;
  z1 = (z1 & (t4 ^ Secp256k1Const.high4Mask52)).toUnsigned64;

  /// ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element)
  _cond(t4 >> 49 == BigInt.zero, "secp256k1FeNormalizesToZeroVar");
  final n = ((z0 == BigInt.zero) | (z1 == Secp256k1Const.mask52));
  return n.toInt;
}