static JacobianEcPoint addJacobianPoints(
      JacobianEcPoint p1, JacobianEcPoint p2, BigInteger a, BigInteger modulus) {
    // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-2007-bl
    // and https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
    if (p1.isInfinity()) {
      return p2;
    }
    if (p2.isInfinity()) {
      return p1;
    }
    BigInteger z1z1 = p1.z.multiply(p1.z).mod(modulus);
    BigInteger z2z2 = p2.z.multiply(p2.z).mod(modulus);
    BigInteger u1 = p1.x.multiply(z2z2).mod(modulus);
    BigInteger u2 = p2.x.multiply(z1z1).mod(modulus);
    BigInteger s1 = p1.y.multiply(p2.z).mod(modulus).multiply(z2z2).mod(modulus);
    BigInteger s2 = p2.y.multiply(p1.z).mod(modulus).multiply(z1z1).mod(modulus);
    if (u1.equals(u2)) {
      if (!s1.equals(s2)) {
        return JacobianEcPoint.INFINITY;
      } else {
        return doubleJacobianPoint(p1, a, modulus);
      }
    }
    BigInteger h = u2.subtract(u1).mod(modulus);
    BigInteger i = h.multiply(FOUR).multiply(h).mod(modulus);
    BigInteger j = h.multiply(i).mod(modulus);
    BigInteger r = s2.subtract(s1).multiply(TWO).mod(modulus);
    BigInteger v = u1.multiply(i).mod(modulus);
    BigInteger x3 = r.multiply(r).mod(modulus).subtract(j).subtract(v.multiply(TWO)).mod(modulus);
    BigInteger y3 = r.multiply(v.subtract(x3)).subtract(s1.multiply(TWO).multiply(j)).mod(modulus);
    BigInteger z12 = p1.z.add(p2.z);
    BigInteger z3 =
        z12.multiply(z12).mod(modulus).subtract(z1z1).subtract(z2z2).multiply(h).mod(modulus);
    return new JacobianEcPoint(x3, y3, z3);
  }
Jacobian representation of elliptic curve points.

<p>The point (X, Y) is represented by a triple (x, y, z), where X = x/z^2 and Y = y/z^3.
java_src/src/main/java/com/google/crypto/tink/internal/EllipticCurvesUtil.java