| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 | 
							- <?php
 
- namespace BI;
 
- if (!defined("S_MATH_BIGINTEGER_MODE")) {
 
-     if (extension_loaded("gmp")) {
 
-         define("S_MATH_BIGINTEGER_MODE", "gmp");
 
-     }
 
-     else if (extension_loaded("bcmath")) {
 
-         define("S_MATH_BIGINTEGER_MODE", "bcmath");
 
-     }
 
-     else {
 
-         if (!defined("S_MATH_BIGINTEGER_QUIET")) {
 
-             throw new \Exception("Cannot use BigInteger. Neither gmp nor bcmath module is loaded");
 
-         }
 
-     }
 
- }
 
- if (S_MATH_BIGINTEGER_MODE == "gmp") {
 
- if (!extension_loaded("gmp")) {
 
-     throw new \Exception("Extension gmp not loaded");
 
- }
 
- class BigInteger {
 
-     
 
-     public $value;
 
-     
 
-     public function __construct($value = 0, $base = 10) {
 
-         $this->value = $base === true ? $value : BigInteger::getGmp($value, $base);
 
-     }
 
-     
 
-     public static function createSafe($value = 0, $base = 10) {
 
-         try {
 
-             return new BigInteger($value, $base);
 
-         }
 
-         catch (\Exception $e) {
 
-             return false;
 
-         }
 
-     }
 
-     
 
-     public static function isGmp($var) {
 
-         if (is_resource($var)) {
 
-             return get_resource_type($var) == "GMP integer";
 
-         }
 
-         if (class_exists("GMP") && $var instanceof \GMP) {
 
-             return true;
 
-         }
 
-         return false;
 
-     }
 
-     
 
-     public static function getGmp($value = 0, $base = 10) {
 
-         if ($value instanceof BigInteger) {
 
-             return $value->value;
 
-         }
 
-         if (BigInteger::isGmp($value)) {
 
-             return $value;
 
-         }
 
-         $type = gettype($value);
 
-         if ($type == "integer") {
 
-             $gmp = gmp_init($value);
 
-             if ($gmp === false) {
 
-                 throw new \Exception("Cannot initialize");
 
-             }
 
-             return $gmp;
 
-         }
 
-         if ($type == "string") {
 
-             if ($base != 2 && $base != 10 && $base != 16 && $base != 256) {
 
-                 throw new \Exception("Unsupported BigInteger base");
 
-             }
 
-             if ($base == 256) {
 
-                 $value = bin2hex($value);
 
-                 $base = 16;
 
-             }
 
-             $level = error_reporting();
 
-             error_reporting(0);
 
-             $gmp = gmp_init($value, $base);
 
-             error_reporting($level);
 
-             if ($gmp === false) {
 
-                 throw new \Exception("Cannot initialize");
 
-             }
 
-             return $gmp;
 
-         }
 
-         throw new \Exception("Unsupported value, only string and integer are allowed, receive " . $type . ($type == "object" ? ", class: " . get_class($value) : ""));
 
-     }
 
-     
 
-     public function toDec() {
 
-         return gmp_strval($this->value, 10);
 
-     }
 
-     
 
-     public function toHex() {
 
-         $hex = gmp_strval($this->value, 16);
 
-         return strlen($hex) % 2 == 1 ? "0". $hex : $hex;
 
-     }
 
-     
 
-     public function toBytes() {
 
-         return hex2bin($this->toHex());
 
-     }
 
-     
 
-     public function toBase($base) {
 
-         if ($base < 2 || $base > 62) {
 
-             throw new \Exception("Invalid base");
 
-         }
 
-         return gmp_strval($this->value, $base);
 
-     }
 
-     
 
-     public function toBits() {
 
-         return gmp_strval($this->value, 2);
 
-     }
 
-     
 
-     public function toString($base = 10) {
 
-         if ($base == 2) {
 
-             return $this->toBits();
 
-         }
 
-         if ($base == 10) {
 
-             return $this->toDec();
 
-         }
 
-         if ($base == 16) {
 
-             return $this->toHex();
 
-         }
 
-         if ($base == 256) {
 
-             return $this->toBytes();
 
-         }
 
-         return $this->toBase($base);
 
-     }
 
-     
 
-     public function __toString() {
 
-         return $this->toString();
 
-     }
 
-     
 
-     public function toNumber() {
 
-         return gmp_intval($this->value);
 
-     }
 
-     
 
-     public function add($x) {
 
-         return new BigInteger(gmp_add($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function sub($x) {
 
-         return new BigInteger(gmp_sub($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function mul($x) {
 
-         return new BigInteger(gmp_mul($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function div($x) {
 
-         return new BigInteger(gmp_div_q($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function divR($x) {
 
-         return new BigInteger(gmp_div_r($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function divQR($x) {
 
-         $res = gmp_div_qr($this->value, BigInteger::getGmp($x));
 
-         return array(new BigInteger($res[0], true), new BigInteger($res[1], true));
 
-     }
 
-     
 
-     public function mod($x) {
 
-         return new BigInteger(gmp_mod($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function gcd($x) {
 
-         return new BigInteger(gmp_gcd($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function modInverse($x) {
 
-         $res = gmp_invert($this->value, BigInteger::getGmp($x));
 
-         return $res === false ? false : new BigInteger($res, true);
 
-     }
 
-     
 
-     public function pow($x) {
 
-         return new BigInteger(gmp_pow($this->value, (new BigInteger($x))->toNumber()), true);
 
-     }
 
-     
 
-     public function powMod($x, $n) {
 
-         return new BigInteger(gmp_powm($this->value, BigInteger::getGmp($x), BigInteger::getGmp($n)), true);
 
-     }
 
-     
 
-     public function abs() {
 
-         return new BigInteger(gmp_abs($this->value), true);
 
-     }
 
-     
 
-     public function neg() {
 
-         return new BigInteger(gmp_neg($this->value), true);
 
-     }
 
-     
 
-     public function binaryAnd($x) {
 
-         return new BigInteger(gmp_and($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function binaryOr($x) {
 
-         return new BigInteger(gmp_or($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function binaryXor($x) {
 
-         return new BigInteger(gmp_xor($this->value, BigInteger::getGmp($x)), true);
 
-     }
 
-     
 
-     public function setbit($index, $bitOn = true) {
 
-         $cpy = gmp_init(gmp_strval($this->value, 16), 16);
 
-         gmp_setbit($cpy, $index, $bitOn);
 
-         return new BigInteger($cpy, true);
 
-     }
 
-     
 
-     public function testbit($index) {
 
-         return gmp_testbit($this->value, $index);
 
-     }
 
-     
 
-     public function scan0($start) {
 
-         return gmp_scan0($this->value, $start);
 
-     }
 
-     
 
-     public function scan1($start) {
 
-         return gmp_scan1($this->value, $start);
 
-     }
 
-     
 
-     public function cmp($x) {
 
-         return gmp_cmp($this->value, BigInteger::getGmp($x));
 
-     }
 
-     
 
-     public function equals($x) {
 
-         return $this->cmp($x) === 0;
 
-     }
 
-     
 
-     public function sign() {
 
-         return gmp_sign($this->value);
 
-     }
 
- }
 
- }
 
- else if (S_MATH_BIGINTEGER_MODE == "bcmath") {
 
- if (!extension_loaded("bcmath")) {
 
-     throw new \Exception("Extension bcmath not loaded");
 
- }
 
- class BigInteger{
 
-     
 
-     public static $chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv";
 
-     public $value;
 
-     
 
-     public function __construct($value = 0, $base = 10) {
 
-         $this->value = $base === true ? $value : BigInteger::getBC($value, $base);
 
-     }
 
-     
 
-     public static function createSafe($value = 0, $base = 10) {
 
-         try {
 
-             return new BigInteger($value, $base);
 
-         }
 
-         catch (\Exception $e) {
 
-             return false;
 
-         }
 
-     }
 
-     
 
-     public static function checkBinary($str) {
 
-         $len = strlen($str);
 
-         for ($i = 0; $i < $len; $i++) {
 
-             $c = ord($str[$i]);
 
-             if (($i != 0 || $c != 45) && ($c < 48 || $c > 49)) {
 
-                 return false;
 
-             }
 
-         }
 
-         return true;
 
-     }
 
-     
 
-     public static function checkDecimal($str) {
 
-         $len = strlen($str);
 
-         for ($i = 0; $i < $len; $i++) {
 
-             $c = ord($str[$i]);
 
-             if (($i != 0 || $c != 45) && ($c < 48 || $c > 57)) {
 
-                 return false;
 
-             }
 
-         }
 
-         return true;
 
-     }
 
-     
 
-     public static function checkHex($str) {
 
-         $len = strlen($str);
 
-         for ($i = 0; $i < $len; $i++) {
 
-             $c = ord($str[$i]);
 
-             if (($i != 0 || $c != 45) && ($c < 48 || $c > 57) && ($c < 65 || $c > 70) && ($c < 97 || $c > 102)) {
 
-                 return false;
 
-             }
 
-         }
 
-         return true;
 
-     }
 
-     
 
-     public static function getBC($value = 0, $base = 10) {
 
-         if ($value instanceof BigInteger) {
 
-             return $value->value;
 
-         }
 
-         $type = gettype($value);
 
-         if ($type == "integer") {
 
-             return strval($value);
 
-         }
 
-         if ($type == "string") {
 
-             if ($base == 2) {
 
-                 $value = str_replace(" ", "", $value);
 
-                 if (!BigInteger::checkBinary($value)) {
 
-                     throw new \Exception("Invalid characters");
 
-                 }
 
-                 $minus = $value[0] == "-";
 
-                 if ($minus) {
 
-                     $value = substr($value, 1);
 
-                 }
 
-                 $len = strlen($value);
 
-                 $m = 1;
 
-                 $res = "0";
 
-                 for ($i = $len - 1; $i >= 0; $i -= 8) {
 
-                     $h = $i - 7 < 0 ? substr($value, 0, $i + 1) : substr($value, $i - 7, 8);
 
-                     $res = bcadd($res, bcmul(bindec($h), $m, 0), 0);
 
-                     $m = bcmul($m, "256", 0);
 
-                 }
 
-                 return ($minus ? "-" : "") . $res;
 
-             }
 
-             if ($base == 10) {
 
-                 $value = str_replace(" ", "", $value);
 
-                 if (!BigInteger::checkDecimal($value)) {
 
-                     throw new \Exception("Invalid characters");
 
-                 }
 
-                 return $value;
 
-             }
 
-             if ($base == 16) {
 
-                 $value = str_replace(" ", "", $value);
 
-                 if (!BigInteger::checkHex($value)) {
 
-                     throw new \Exception("Invalid characters");
 
-                 }
 
-                 $minus = $value[0] == "-";
 
-                 if ($minus) {
 
-                     $value = substr($value, 1);
 
-                 }
 
-                 $len = strlen($value);
 
-                 $m = 1;
 
-                 $res = "0";
 
-                 for ($i = $len - 1; $i >= 0; $i -= 2) {
 
-                     $h = $i == 0 ? "0" . substr($value, 0, 1) : substr($value, $i - 1, 2);
 
-                     $res = bcadd($res, bcmul(hexdec($h), $m, 0), 0);
 
-                     $m = bcmul($m, "256", 0);
 
-                 }
 
-                 return ($minus ? "-" : "") . $res;
 
-             }
 
-             if ($base == 256) {
 
-                 $len = strlen($value);
 
-                 $m = 1;
 
-                 $res = "0";
 
-                 for ($i = $len - 1; $i >= 0; $i -= 6) {
 
-                     $h = $i - 5 < 0 ? substr($value, 0, $i + 1) : substr($value, $i - 5, 6);
 
-                     $res = bcadd($res, bcmul(base_convert(bin2hex($h), 16, 10), $m, 0), 0);
 
-                     $m = bcmul($m, "281474976710656", 0);
 
-                 }
 
-                 return $res;
 
-             }
 
-             throw new \Exception("Unsupported BigInteger base");
 
-         }
 
-         throw new \Exception("Unsupported value, only string and integer are allowed, receive " . $type . ($type == "object" ? ", class: " . get_class($value) : ""));
 
-     }
 
-     
 
-     public function toDec() {
 
-         return $this->value;
 
-     }
 
-     
 
-     public function toHex() {
 
-         return bin2hex($this->toBytes());
 
-     }
 
-     
 
-     public function toBytes() {
 
-         $value = "";
 
-         $current = $this->value;
 
-         if ($current[0] == "-") {
 
-             $current = substr($current, 1);
 
-         }
 
-         while (bccomp($current, "0", 0) > 0) {
 
-             $temp = bcmod($current, "281474976710656");
 
-             $value = hex2bin(str_pad(base_convert($temp, 10, 16), 12, "0", STR_PAD_LEFT)) . $value;
 
-             $current = bcdiv($current, "281474976710656", 0);
 
-         }
 
-         return ltrim($value, chr(0));
 
-     }
 
-     
 
-     public function toBase($base) {
 
-         if ($base < 2 || $base > 62) {
 
-             throw new \Exception("Invalid base");
 
-         }
 
-         $value = '';
 
-         $current = $this->value;
 
-         $base = BigInteger::getBC($base);
 
-         
 
-         if ($current[0] == '-') {
 
-             $current = substr($current, 1);
 
-         }
 
-         
 
-         while (bccomp($current, '0', 0) > 0) {
 
-             $v = bcmod($current, $base);
 
-             $value = BigInteger::$chars[$v] . $value;
 
-             $current = bcdiv($current, $base, 0);
 
-         }
 
-         return $value;
 
-     }
 
-     
 
-     public function toBits() {
 
-         $bytes = $this->toBytes();
 
-         $res = "";
 
-         $len = strlen($bytes);
 
-         for ($i = 0; $i < $len; $i++) {
 
-             $b = decbin(ord($bytes[$i]));
 
-             $res .= strlen($b) != 8 ? str_pad($b, 8, "0", STR_PAD_LEFT) : $b;
 
-         }
 
-         $res = ltrim($res, "0");
 
-         return strlen($res) == 0 ? "0" : $res;
 
-     }
 
-     
 
-     public function toString($base = 10) {
 
-         if ($base == 2) {
 
-             return $this->toBits();
 
-         }
 
-         if ($base == 10) {
 
-             return $this->toDec();
 
-         }
 
-         if ($base == 16) {
 
-             return $this->toHex();
 
-         }
 
-         if ($base == 256) {
 
-             return $this->toBytes();
 
-         }
 
-         return $this->toBase($base);
 
-     }
 
-     
 
-     public function __toString() {
 
-         return $this->toString();
 
-     }
 
-     
 
-     public function toNumber() {
 
-         return intval($this->value);
 
-     }
 
-     
 
-     public function add($x) {
 
-         return new BigInteger(bcadd($this->value, BigInteger::getBC($x), 0), true);
 
-     }
 
-     
 
-     public function sub($x) {
 
-         return new BigInteger(bcsub($this->value, BigInteger::getBC($x), 0), true);
 
-     }
 
-     
 
-     public function mul($x) {
 
-         return new BigInteger(bcmul($this->value, BigInteger::getBC($x), 0), true);
 
-     }
 
-     
 
-     public function div($x) {
 
-         return new BigInteger(bcdiv($this->value, BigInteger::getBC($x), 0), true);
 
-     }
 
-     
 
-     public function divR($x) {
 
-         return new BigInteger(bcmod($this->value, BigInteger::getBC($x)), true);
 
-     }
 
-     
 
-     public function divQR($x) {
 
-         return array(
 
-             $this->div($x),
 
-             $this->divR($x)
 
-         );
 
-     }
 
-     
 
-     public function mod($x) {
 
-         $xv = BigInteger::getBC($x);
 
-         $mod = bcmod($this->value, $xv);
 
-         if ($mod[0] == "-") {
 
-             $mod = bcadd($mod, $xv[0] == "-" ? substr($xv, 1) : $xv, 0);
 
-         }
 
-         return new BigInteger($mod, true);
 
-     }
 
-     
 
-     public function extendedGcd($n) {
 
-         $u = $this->value;
 
-         $v = (new BigInteger($n))->abs()->value;
 
-         
 
-         $a = "1";
 
-         $b = "0";
 
-         $c = "0";
 
-         $d = "1";
 
-         
 
-         while (bccomp($v, "0", 0) != 0) {
 
-             $q = bcdiv($u, $v, 0);
 
-             
 
-             $temp = $u;
 
-             $u = $v;
 
-             $v = bcsub($temp, bcmul($v, $q, 0), 0);
 
-             
 
-             $temp = $a;
 
-             $a = $c;
 
-             $c = bcsub($temp, bcmul($a, $q, 0), 0);
 
-             
 
-             $temp = $b;
 
-             $b = $d;
 
-             $d = bcsub($temp, bcmul($b, $q, 0), 0);
 
-         }
 
-         
 
-         return array(
 
-             "gcd" => new BigInteger($u, true),
 
-             "x" => new BigInteger($a, true),
 
-             "y" => new BigInteger($b, true)
 
-         );
 
-     }
 
-     
 
-     public function gcd($x) {
 
-         return $this->extendedGcd($x)["gcd"];
 
-     }
 
-     
 
-     public function modInverse($n) {
 
-         $n = (new BigInteger($n))->abs();
 
-         
 
-         if ($this->sign() < 0) {
 
-             $temp = $this->abs();
 
-             $temp = $temp->modInverse($n);
 
-             return $n->sub($temp);
 
-         }
 
-         
 
-         extract($this->extendedGcd($n));
 
-         
 
-         if (!$gcd->equals(1)) {
 
-             return false;
 
-         }
 
-         
 
-         $x = $x->sign() < 0 ? $x->add($n) : $x;
 
-         
 
-         return $this->sign() < 0 ? $n->sub($x) : $x;
 
-     }
 
-     
 
-     public function pow($x) {
 
-         return new BigInteger(bcpow($this->value, BigInteger::getBC($x), 0), true);
 
-     }
 
-     
 
-     public function powMod($x, $n) {
 
-         return new BigInteger(bcpowmod($this->value, BigInteger::getBC($x), BigInteger::getBC($n), 0), true);
 
-     }
 
-     
 
-     public function abs() {
 
-         return new BigInteger($this->value[0] == "-" ? substr($this->value, 1) : $this->value, true);
 
-     }
 
-     
 
-     public function neg() {
 
-         return new BigInteger($this->value[0] == "-" ? substr($this->value, 1) : "-" . $this->value, true);
 
-     }
 
-     
 
-     public function binaryAnd($x) {
 
-         $left = $this->toBytes();
 
-         $right = (new BigInteger($x))->toBytes();
 
-         
 
-         $length = max(strlen($left), strlen($right));
 
-         
 
-         $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
 
-         $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
 
-         
 
-         return new BigInteger($left & $right, 256);
 
-     }
 
-     
 
-     public function binaryOr($x) {
 
-         $left = $this->toBytes();
 
-         $right = (new BigInteger($x))->toBytes();
 
-         
 
-         $length = max(strlen($left), strlen($right));
 
-         
 
-         $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
 
-         $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
 
-         
 
-         return new BigInteger($left | $right, 256);
 
-     }
 
-     
 
-     public function binaryXor($x) {
 
-         $left = $this->toBytes();
 
-         $right = (new BigInteger($x))->toBytes();
 
-         
 
-         $length = max(strlen($left), strlen($right));
 
-         
 
-         $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
 
-         $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
 
-         
 
-         return new BigInteger($left ^ $right, 256);
 
-     }
 
-     
 
-     public function setbit($index, $bitOn = true) {
 
-         $bits = $this->toBits();
 
-         $bits[strlen($bits) - $index - 1] = $bitOn ? "1" : "0";
 
-         return new BigInteger($bits, 2);
 
-     }
 
-     
 
-     public function testbit($index) {
 
-         $bytes = $this->toBytes();
 
-         $bytesIndex = intval($index / 8);
 
-         $len = strlen($bytes);
 
-         $b = $bytesIndex >= $len ? 0 : ord($bytes[$len - $bytesIndex - 1]);
 
-         $v = 1 << ($index % 8);
 
-         return ($b & $v) === $v;
 
-     }
 
-     
 
-     public function scan0($start) {
 
-         $bits = $this->toBits();
 
-         $len = strlen($bits);
 
-         if ($start < 0 || $start >= $len) {
 
-             return -1;
 
-         }
 
-         $pos = strrpos($bits, "0", -1 - $start);
 
-         return $pos === false ? -1 : $len - $pos - 1;
 
-     }
 
-     
 
-     public function scan1($start) {
 
-         $bits = $this->toBits();
 
-         $len = strlen($bits);
 
-         if ($start < 0 || $start >= $len) {
 
-             return -1;
 
-         }
 
-         $pos = strrpos($bits, "1", -1 - $start);
 
-         return $pos === false ? -1 : $len - $pos - 1;
 
-     }
 
-     
 
-     public function cmp($x) {
 
-         return bccomp($this->value, BigInteger::getBC($x));
 
-     }
 
-     
 
-     public function equals($x) {
 
-         return $this->value === BigInteger::getBC($x);
 
-     }
 
-     
 
-     public function sign() {
 
-         return $this->value[0] === "-" ? -1 : ($this->value === "0" ? 0 : 1);
 
-     }
 
- }
 
- }
 
- else {
 
-     if (!defined("S_MATH_BIGINTEGER_QUIET")) {
 
-         throw new \Exception("Unsupported S_MATH_BIGINTEGER_MODE " . S_MATH_BIGINTEGER_MODE);
 
-     }
 
- }
 
 
  |