x = $x; $this->y = $y; $this->order = $order; $this->infinity = $infinity; } public static function create(GMP $x, GMP $y, ?GMP $order = null): self { return new self($x, $y, null === $order ? gmp_init(0, 10) : $order); } 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; } public static function cswap(self $a, self $b, int $cond): void { 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): void { $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): void { $size = max(mb_strlen(gmp_strval($sa, 2), '8bit'), mb_strlen(gmp_strval($sb, 2), '8bit')); $mask = (string) (1 - $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); } }