secp256k1Modinv64Divsteps62Var static method

BigInt secp256k1Modinv64Divsteps62Var(
  1. BigInt eta,
  2. BigInt f0,
  3. BigInt g0,
  4. Secp256k1ModinvTrans t,
)

Implementation

static BigInt secp256k1Modinv64Divsteps62Var(
    BigInt eta, BigInt f0, BigInt g0, Secp256k1ModinvTrans t) {
  /// Transformation matrix; see comments in secp256k1_modinv64_divsteps_62.
  BigInt u = BigInt.one, v = BigInt.zero, q = BigInt.zero, r = BigInt.one;
  BigInt f = f0, g = g0, m;
  int w;
  int i = 62, limit, zeros;

  for (;;) {
    /// Use a sentinel bit to count zeros only up to i.
    zeros = secp256k1CtzVar((g | (maxU64 << i)).toUnsigned64);

    /// Perform zeros divsteps at once; they all just divide g by two.
    g = (g >> zeros).toUnsigned64;
    u = (u << zeros).toUnsigned64;
    v = (v << zeros).toUnsigned64;
    eta = (eta - zeros.toBigInt).toSigned64;
    i = (i - zeros).toSigned32;

    /// We're done once we've done 62 divsteps.
    if (i == 0) break;
    _cond((f & BigInt.one) == BigInt.one, "secp256k1Modinv64Divsteps62Var");
    _cond((g & BigInt.one) == BigInt.one, "secp256k1Modinv64Divsteps62Var");
    _cond((u * f0 + v * g0).toUnsigned64 == (f << (62 - i)).toUnsigned64,
        "secp256k1Modinv64Divsteps62Var");
    _cond((q * f0 + r * g0).toUnsigned64 == (g << (62 - i)).toUnsigned64,
        "secp256k1Modinv64Divsteps62Var");

    /// Bounds on eta that follow from the bounds on iteration count (max 12*62 divsteps).
    _cond(eta >= -745.toBigInt && eta <= 745.toBigInt,
        "secp256k1Modinv64Divsteps62Var");

    /// If eta is negative, negate it and replace f,g with g,-f.
    if (eta.isNegative) {
      BigInt tmp;
      eta = -eta;
      tmp = f;
      f = g;
      g = (-tmp).toUnsigned64;
      tmp = u;
      u = q;
      q = (-tmp).toUnsigned64;
      tmp = v;
      v = r;
      r = (-tmp).toUnsigned64;
      limit = (eta.toSignedInt32 + 1) > i ? i : (eta.toSignedInt32 + 1);
      // VERIFY_CHECK(limit > 0 && limit <= 62);
      /// m is a mask for the bottom min(limit, 6) bits.
      m = ((maxU64 >> (64 - limit)) & 63.toBigInt).toUnsigned64;

      w = ((f * g * (f * f - BigInt.two)) & m).toUnSignedInt32;
    } else {
      limit = (eta.toSignedInt32 + 1) > i ? i : (eta.toSignedInt32 + 1);
      _cond(limit > 0 && limit <= 62, "secp256k1Modinv64Divsteps62Var");

      /// m is a mask for the bottom min(limit, 4) bits.
      m = ((maxU64 >> (64 - limit)) & 15.toBigInt).toUnsigned64;

      w = (f + (((f + BigInt.one) & 4.toBigInt) << 1)).toUnSignedInt32;
      w = (((-w).toBigInt * g) & m).toUnSignedInt32;
    }
    g = (g + (f * w.toBigInt)).toUnsigned64;
    q = (q + (u * w.toBigInt)).toUnsigned64;
    r = (r + (v * w.toBigInt)).toUnsigned64;
    _cond((g & m) == BigInt.zero, "secp256k1Modinv64Divsteps62Var");
  }

  /// Return data in t and return value.
  // t.u = u.toSigned64;
  // t.v = v.toSigned64;
  // t.q = q.toSigned64;
  // t.r = r.toSigned64;
  t.set(u, v, q, r);

  _cond(secp256k1Modinv64DetCheckPow2(t, 62, 0).toBool,
      "secp256k1Modinv64Divsteps62Var");

  return eta;
}