| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 | 
							- <?php
 
- /**
 
-  * This script stress tests calculators with random large numbers and ensures that all implementations return the same
 
-  * results. It is designed to run in an infinite loop unless a bug is found.
 
-  */
 
- declare(strict_types=1);
 
- require __DIR__ . '/vendor/autoload.php';
 
- use Brick\Math\Internal\Calculator;
 
- (new class(30) { // max digits
 
-     private $gmp;
 
-     private $bcmath;
 
-     private $native;
 
-     private $maxDigits;
 
-     public function __construct(int $maxDigits)
 
-     {
 
-         $this->gmp    = new Calculator\GmpCalculator();
 
-         $this->bcmath = new Calculator\BcMathCalculator();
 
-         $this->native = new Calculator\NativeCalculator();
 
-         $this->maxDigits = $maxDigits;
 
-     }
 
-     public function __invoke() : void
 
-     {
 
-         for (;;) {
 
-             $a = $this->generateRandomNumber();
 
-             $b = $this->generateRandomNumber();
 
-             $c = $this->generateRandomNumber();
 
-             $this->runTests($a, $b);
 
-             $this->runTests($b, $a);
 
-             if ($a !== '0') {
 
-                 $this->runTests("-$a", $b);
 
-                 $this->runTests($b, "-$a");
 
-             }
 
-             if ($b !== '0') {
 
-                 $this->runTests($a, "-$b");
 
-                 $this->runTests("-$b", $a);
 
-             }
 
-             if ($a !== '0' && $b !== '0') {
 
-                 $this->runTests("-$a", "-$b");
 
-                 $this->runTests("-$b", "-$a");
 
-             }
 
-             if ($c !== '0') {
 
-                 $this->test("$a POW $b MOD $c", function(Calculator $calc) use($a, $b, $c) {
 
-                     return $calc->modPow($a, $b, $c);
 
-                 });
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      * @param string $a The left operand.
 
-      * @param string $b The right operand.
 
-      */
 
-     function runTests(string $a, string $b) : void
 
-     {
 
-         $this->test("$a + $b", function(Calculator $c) use($a, $b) {
 
-             return $c->add($a, $b);
 
-         });
 
-         $this->test("$a - $b", function(Calculator $c) use($a, $b) {
 
-             return $c->sub($a, $b);
 
-         });
 
-         $this->test("$a * $b", function(Calculator $c) use($a, $b) {
 
-             return $c->mul($a, $b);
 
-         });
 
-         if ($b !== '0') {
 
-             $this->test("$a / $b", function(Calculator $c) use($a, $b) {
 
-                 return $c->divQR($a, $b);
 
-             });
 
-             $this->test("$a MOD $b", function(Calculator $c) use($a, $b) {
 
-                 return $c->mod($a, $b);
 
-             });
 
-         }
 
-         if ($b !== '0' && $b[0] !== '-') {
 
-             $this->test("INV $a MOD $b", function(Calculator $c) use($a, $b) {
 
-                 return $c->modInverse($a, $b);
 
-             });
 
-         }
 
-         $this->test("GCD $a, $b", function(Calculator $c) use($a, $b) {
 
-             return $c->gcd($a, $b);
 
-         });
 
-         if ($a[0] !== '-') {
 
-             $this->test("SQRT $a", function(Calculator $c) use($a, $b) {
 
-                 return $c->sqrt($a);
 
-             });
 
-         }
 
-         $this->test("$a AND $b", function(Calculator $c) use($a, $b) {
 
-             return $c->and($a, $b);
 
-         });
 
-         $this->test("$a OR $b", function(Calculator $c) use($a, $b) {
 
-             return $c->or($a, $b);
 
-         });
 
-         $this->test("$a XOR $b", function(Calculator $c) use($a, $b) {
 
-             return $c->xor($a, $b);
 
-         });
 
-     }
 
-     /**
 
-      * @param string  $test     A string representing the test being executed.
 
-      * @param Closure $callback A callback function accepting a Calculator instance and returning a calculation result.
 
-      */
 
-     private function test(string $test, Closure $callback) : void
 
-     {
 
-         static $counter = 0;
 
-         static $lastOutputTime = null;
 
-         $gmpResult    = $callback($this->gmp);
 
-         $bcmathResult = $callback($this->bcmath);
 
-         $nativeResult = $callback($this->native);
 
-         if ($gmpResult !== $bcmathResult) {
 
-             self::failure('GMP', 'BCMath', $test);
 
-         }
 
-         if ($gmpResult !== $nativeResult) {
 
-             self::failure('GMP', 'Native', $test);
 
-         }
 
-         $counter++;
 
-         $time = microtime(true);
 
-         if ($lastOutputTime === null) {
 
-             $lastOutputTime = $time;
 
-         } elseif ($time - $lastOutputTime >= 0.1) {
 
-             echo "\r", number_format($counter);
 
-             $lastOutputTime = $time;
 
-         }
 
-     }
 
-     /**
 
-      * @param string $c1   The name of the first calculator.
 
-      * @param string $c2   The name of the second calculator.
 
-      * @param string $test A string representing the test being executed.
 
-      */
 
-     private static function failure(string $c1, string $c2, string $test) : void
 
-     {
 
-         echo PHP_EOL;
 
-         echo 'FAILURE!', PHP_EOL;
 
-         echo $c1, ' vs ', $c2, PHP_EOL;
 
-         echo $test, PHP_EOL;
 
-         die;
 
-     }
 
-     private function generateRandomNumber() : string
 
-     {
 
-         $length = random_int(1, $this->maxDigits);
 
-         $number = '';
 
-         for ($i = 0; $i < $length; $i++) {
 
-             $number .= random_int(0, 9);
 
-         }
 
-         $number = ltrim($number, '0');
 
-         if ($number === '') {
 
-             return '0';
 
-         }
 
-         return $number;
 
-     }
 
- })();
 
 
  |