x = $x; $this->y = $y; $this->order = $order; $this->infinity = $infinity; } /** * @return Point */ public static function create(\GMP $x, \GMP $y, ?\GMP $order = null): self { return new self($x, $y, null === $order ? \gmp_init(0, 10) : $order); } /** * @return Point */ public static function infinity(): self { $zero = \gmp_init(0, 10); return new self($zero, $zero, $zero, true); } public function isInfinity(): bool { return $this->infinity; } public function getOrder(): \GMP { return $this->order; } public function getX(): \GMP { return $this->x; } public function getY(): \GMP { return $this->y; } /** * @param Point $a * @param Point $b */ public static function cswap(self $a, self $b, int $cond) { self::cswapGMP($a->x, $b->x, $cond); self::cswapGMP($a->y, $b->y, $cond); self::cswapGMP($a->order, $b->order, $cond); self::cswapBoolean($a->infinity, $b->infinity, $cond); } private static function cswapBoolean(bool &$a, bool &$b, int $cond) { $sa = \gmp_init((int) ($a), 10); $sb = \gmp_init((int) ($b), 10); self::cswapGMP($sa, $sb, $cond); $a = (bool) \gmp_strval($sa, 10); $b = (bool) \gmp_strval($sb, 10); } private static function cswapGMP(\GMP &$sa, \GMP &$sb, int $cond) { $size = \max(\mb_strlen(\gmp_strval($sa, 2), '8bit'), \mb_strlen(\gmp_strval($sb, 2), '8bit')); $mask = (string) (1 - (int) ($cond)); $mask = \str_pad('', $size, $mask, STR_PAD_LEFT); $mask = \gmp_init($mask, 2); $taA = Math::bitwiseAnd($sa, $mask); $taB = Math::bitwiseAnd($sb, $mask); $sa = Math::bitwiseXor(Math::bitwiseXor($sa, $sb), $taB); $sb = Math::bitwiseXor(Math::bitwiseXor($sa, $sb), $taA); $sa = Math::bitwiseXor(Math::bitwiseXor($sa, $sb), $taB); } }