/**
* Point multiplication method 2P = R where
* s = (3xP2 + a)/(2yP) mod p
* xR = s2 - 2xP mod p
* yR = -yP + s(xP - xR) mod p
*
* @param PointInterface $point
* @param CurveParameterInterface
* @return PointInterface
*/
public static function pointDouble(PointInterface $point, CurveParameterInterface $parameters = null)
{
if ($point->isInfinity()) {
return $point;
}
if (null === $parameters) {
$parameters = new Secp256k1();
}
$p = $parameters->pHex();
$a = $parameters->aHex();
$s = 0;
$R = array('x' => 0, 'y' => 0);
// Critical math section
try {
$m = Math::add(Math::mul(3, Math::mul($point->getX(), $point->getX())), $a);
$o = Math::mul(2, $point->getY());
$n = Math::invertm($o, $p);
$n2 = Math::mod($o, $p);
$st = Math::mul($m, $n);
$st2 = Math::mul($m, $n2);
$s = Math::mod($st, $p);
$s2 = Math::mod($st2, $p);
$xmul = Math::mul(2, $point->getX());
$smul = Math::mul($s, $s);
$xsub = Math::sub($smul, $xmul);
$xmod = Math::mod($xsub, $p);
$R['x'] = $xmod;
$ysub = Math::sub($point->getX(), $R['x']);
$ymul = Math::mul($s, $ysub);
$ysub2 = Math::sub(0, $point->getY());
$yadd = Math::add($ysub2, $ymul);
$R['y'] = Math::mod($yadd, $p);
} catch (\Exception $e) {
throw new \Exception('Error in Util::pointDouble(): ' . $e->getMessage());
}
return new Point($R['x'], $R['y']);
}