secp256k1Modinv64 static method

void secp256k1Modinv64(
  1. Secp256k1ModinvSigned x,
  2. Secp256k1ModinvInfo modinfo
)

Implementation

static void secp256k1Modinv64(
  Secp256k1ModinvSigned x,
  Secp256k1ModinvInfo modinfo,
) {
  /// Start with d=0, e=1, f=modulus, g=x, zeta=-1.
  Secp256k1ModinvSigned d = Secp256k1ModinvSigned();
  Secp256k1ModinvSigned e = Secp256k1Const.modeInvOne.clone();
  Secp256k1ModinvSigned f = modinfo.modulus.clone();
  Secp256k1ModinvSigned g = x.clone();
  int i;
  BigInt zeta = (-1).toBigInt;

  /// Do 10 iterations of 59 divsteps each = 590 divsteps. This suffices for 256-bit inputs.
  for (i = 0; i < 10; ++i) {
    /// Compute transition matrix and new zeta after 59 divsteps.
    Secp256k1ModinvTrans t = Secp256k1ModinvTrans();
    zeta = secp256k1Modinv64Divsteps59(zeta, f[0].toU64, g[0].toU64, t);

    /// Update d,e using that transition matrix.
    secp256k1Modinv64UpdateDe62(d, e, t, modinfo);

    /// Update f,g using that transition matrix.
    _cond(
      secp256k1Modinv64MulCmp62(
            f,
            5,
            modinfo.modulus,
            Secp256k1Const.minosOne,
          ) >
          0,
      "secp256k1Modinv64",
    );
    _cond(
      secp256k1Modinv64MulCmp62(f, 5, modinfo.modulus, BigInt.one) <= 0,
      "secp256k1Modinv64",
    );
    _cond(
      secp256k1Modinv64MulCmp62(
            g,
            5,
            modinfo.modulus,
            Secp256k1Const.minosOne,
          ) >
          0,
      "secp256k1Modinv64",
    );

    /// g > -modulus
    _cond(
      secp256k1Modinv64MulCmp62(g, 5, modinfo.modulus, BigInt.one) < 0,
      "secp256k1Modinv64",
    );

    secp256k1Modinv64UpdateFg62(f, g, t);

    _cond(
      secp256k1Modinv64MulCmp62(
            f,
            5,
            modinfo.modulus,
            Secp256k1Const.minosOne,
          ) >
          0,
      "secp256k1Modinv64",
    );

    /// f > -modulus
    _cond(
      secp256k1Modinv64MulCmp62(f, 5, modinfo.modulus, BigInt.one) <= 0,
      "secp256k1Modinv64",
    );

    /// f <= modulus
    _cond(
      secp256k1Modinv64MulCmp62(
            g,
            5,
            modinfo.modulus,
            Secp256k1Const.minosOne,
          ) >
          0,
      "secp256k1Modinv64",
    );

    /// g > -modulus
    _cond(
      secp256k1Modinv64MulCmp62(g, 5, modinfo.modulus, BigInt.one) < 0,
      "secp256k1Modinv64",
    );

    /// g <  modulus
  }

  /// g == 0
  _cond(
    secp256k1Modinv64MulCmp62(
          g,
          5,
          Secp256k1Const.secp256k1Signed62One,
          BigInt.zero,
        ) ==
        0,
    "secp256k1Modinv64",
  );
  // /// |f| == 1, or (x == 0 and d == 0 and f == modulus)
  _cond(
    secp256k1Modinv64MulCmp62(
              f,
              5,
              Secp256k1Const.secp256k1Signed62One,
              Secp256k1Const.minosOne,
            ) ==
            0 ||
        secp256k1Modinv64MulCmp62(
              f,
              5,
              Secp256k1Const.secp256k1Signed62One,
              BigInt.one,
            ) ==
            0 ||
        (secp256k1Modinv64MulCmp62(
                  x,
                  5,
                  Secp256k1Const.secp256k1Signed62One,
                  BigInt.zero,
                ) ==
                0 &&
            secp256k1Modinv64MulCmp62(
                  d,
                  5,
                  Secp256k1Const.secp256k1Signed62One,
                  BigInt.zero,
                ) ==
                0 &&
            secp256k1Modinv64MulCmp62(f, 5, modinfo.modulus, BigInt.one) ==
                0),
    "secp256k1Modinv64",
  );

  /// Optionally negate d, normalize to [0,modulus), and return it.
  secp256k1Modinv64Normalize62(d, f[4], modinfo);
  x.set(d);
}