public static function add($p1, $p2) { if (self::cmp($p2, self::INFINITY) == 0 && $p1 instanceof Point) { return $p1; } if (self::cmp($p1, self::INFINITY) == 0 && $p2 instanceof Point) { return $p2; } if (self::cmp($p1, self::INFINITY) == 0 && self::cmp($p2, self::INFINITY) == 0) { return self::INFINITY; } if (Curve::cmp($p1->curve, $p2->curve) == 0) { if (gmp_cmp($p1->x, $p2->x) == 0) { if (gmp_mod(gmp_add($p1->y, $p2->y), $p1->curve->prime) == 0) { return self::INFINITY; } else { return self::double($p1); } } $p = $p1->curve->prime; $l = gmp_mul(gmp_sub($p2->y, $p1->y), gmp_invert(gmp_sub($p2->x, $p1->x), $p)); $x3 = gmp_mod(gmp_sub(gmp_sub(gmp_pow($l, 2), $p1->x), $p2->x), $p); $y3 = gmp_mod(gmp_sub(gmp_mul($l, gmp_sub($p1->x, $x3)), $p1->y), $p); return new Point($p1->curve, $x3, $y3); } else { throw new ErrorException('Elliptic curves do not match'); } }