public static function pointAdd(PointInterface $P, PointInterface $Q)
{
if ($P->isInfinity()) {
return $Q;
}
if ($Q->isInfinity()) {
return $P;
}
if ($P->getX() == $Q->getX() && $P->getY() == $Q->getY()) {
return self::pointDouble(new Point($P->getX(), $P->getY()));
}
$p = '0x' . Secp256k1::P;
$a = '0x' . Secp256k1::A;
$s = 0;
$R = array('x' => 0, 'y' => 0, 's' => 0);
// Critical math section
try {
$m = Math::sub($P->getY(), $Q->getY());
$n = Math::sub($P->getX(), $Q->getX());
$o = Math::invertm($n, $p);
$st = Math::mul($m, $o);
$s = Math::mod($st, $p);
$R['x'] = Math::mod(Math::sub(Math::sub(Math::mul($s, $s), $P->getX()), $Q->getX()), $p);
$R['y'] = Math::mod(Math::add(Math::sub(0, $P->getY()), Math::mul($s, Math::sub($P->getX(), $R['x']))), $p);
$R['s'] = $s;
} catch (Exception $e) {
throw new \Exception('Error in Util::pointAdd(): ' . $e->getMessage());
}
return new Point($R['x'], $R['y']);
}