secp256k1GejAddZinvVar static method

void secp256k1GejAddZinvVar(
  1. Secp256k1Gej r,
  2. Secp256k1Gej a,
  3. Secp256k1Ge b,
  4. Secp256k1Fe bzinv,
)

Implementation

static void secp256k1GejAddZinvVar(
    Secp256k1Gej r, Secp256k1Gej a, Secp256k1Ge b, Secp256k1Fe bzinv) {
  /// Operations: 9 mul, 3 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases)
  Secp256k1Fe az = Secp256k1Fe(),
      z12 = Secp256k1Fe(),
      u1 = Secp256k1Fe(),
      u2 = Secp256k1Fe(),
      s1 = Secp256k1Fe(),
      s2 = Secp256k1Fe(),
      h = Secp256k1Fe(),
      i = Secp256k1Fe(),
      h2 = Secp256k1Fe(),
      h3 = Secp256k1Fe(),
      t = Secp256k1Fe();

  if (a.infinity.toBool) {
    Secp256k1Fe bzinv2 = Secp256k1Fe(), bzinv3 = Secp256k1Fe();
    r.infinity = b.infinity;
    secp256k1FeSqr(bzinv2, bzinv);
    secp256k1FeMul(bzinv3, bzinv2, bzinv);
    secp256k1FeMul(r.x, b.x, bzinv2);
    secp256k1FeMul(r.y, b.y, bzinv3);
    secp256k1FeSetInt(r.z, 1);
    return;
  }
  if (b.infinity.toBool) {
    r.set(a);
    return;
  }

  /// We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to
  /// secp256k1's isomorphism we can multiply the Z coordinates on both sides
  ///  by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1).
  ///  This means that (rx,ry,rz) can be calculated as
  /// (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz.
  /// The variable az below holds the modified Z coordinate for a, which is used
  /// for the computation of rx and ry, but not for rz.
  ///
  secp256k1FeMul(az, a.z, bzinv);

  secp256k1FeSqr(z12, az);
  u1 = a.x.clone();
  secp256k1FeMul(u2, b.x, z12);
  s1 = a.y.clone();
  secp256k1FeMul(s2, b.y, z12);
  secp256k1FeMul(s2, s2, az);
  secp256k1FeNegate(h, u1, Secp256k1Const.secp256k1GejXMagnitudeMax);
  secp256k1FeAdd(h, u2);
  secp256k1FeNegate(i, s2, 1);
  secp256k1FeAdd(i, s1);
  if (secp256k1FeNormalizesToZeroVar(h).toBool) {
    if (secp256k1FeNormalizesToZeroVar(i).toBool) {
      secp256k1GejDoubleVar(r, a, null);
    } else {
      secp256k1GejSetInfinity(r);
    }
    return;
  }

  r.infinity = 0;
  secp256k1FeMul(r.z, a.z, h);

  secp256k1FeSqr(h2, h);
  secp256k1FeNegate(h2, h2, 1);
  secp256k1FeMul(h3, h2, h);
  secp256k1FeMul(t, u1, h2);

  secp256k1FeSqr(r.x, i);
  secp256k1FeAdd(r.x, h3);
  secp256k1FeAdd(r.x, t);
  secp256k1FeAdd(r.x, t);

  secp256k1FeAdd(t, r.x);
  secp256k1FeMul(r.y, t, i);
  secp256k1FeMul(h3, h3, s1);
  secp256k1FeAdd(r.y, h3);
}