Skip to content

Commit

Permalink
remove dependency on gmp extensions (but use them if available)
Browse files Browse the repository at this point in the history
  • Loading branch information
willf committed Mar 14, 2016
1 parent 7c44757 commit d4f345f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
3 changes: 1 addition & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
"description": "a generative testing library",
"license": "BSD-3-Clause",
"require": {
"php-64bit": ">=5.5.0",
"ext-gmp": "*"
"php-64bit": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8"
Expand Down
45 changes: 43 additions & 2 deletions src/QCheck/Random.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public static function rshiftu($a, $b)
if ($b == 0) {
return $a;
}

return ($a >> $b) & ~(1 << 63 >> ($b - 1));
}
public static function mask($val)
Expand All @@ -40,17 +41,57 @@ public function setSeed($seed)
}
protected function next($bits)
{
$temp = gmp_intval(gmp_mul($this->seed, self::MULTIPLIER));
$temp = self::general_intval(self::general_int_mul($this->seed, self::MULTIPLIER));
$this->seed = self::mask($temp + self::ADDEND);

return self::i32(self::rshiftu($this->seed, (48 - $bits)));
}
public function nextDouble()
{
return (($this->next(26) << 27) + $this->next(27))
/ (double)(1 << 53);
/ (double) (1 << 53);
}
public function nextInt()
{
return $this->next(32);
}

public function general_int_mul($a, $b) {
if (function_exists("gmp_mul")) return gmp_mul($a, $b);
return self::int_mul($a, $b);
}

public function general_intval($a) {
if (function_exists("gmp_intval")) return gmp_intval($a);
return intval($a);
}

// multiplication with only shifts and ands
// does Java/C/Go-like overflow
// http://stackoverflow.com/questions/4456442/multiplication-of-two-integers-using-bitwise-operators
public function int_mul($a, $b)
{
$result = 0;
while ($b != 0) {
// Iterate the loop till b==0
if ($b & 01) { // is $b odd?
$result = self::int_add($result, $a); // int_add result
}
$a <<= 1; // Left shifting the value contained in 'a' by 1
// multiplies a by 2 for each loop
$b >>= 1; // Right shifting the value contained in 'b' by 1.
}

return $result;
}

// addition with only shifts and ands
public function int_add($x, $y)
{
if ($y == 0) {
return $x;
} else {
return self::int_add($x ^ $y, ($x & $y) << 1);
}
}
}

0 comments on commit d4f345f

Please sign in to comment.