3,7 → 3,7 |
/* |
* PHP GMP-Supplement implemented using BCMath |
* Copyright 2020 Daniel Marschall, ViaThinkSoft |
* Version 2020-02-27 |
* Version 2020-02-29 |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
77,7 → 77,7 |
// Calculates binomial coefficient |
function gmp_binomial($n, $k) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_binomial() NOT IMPLEMENTED"); |
} |
|
// gmp_clrbit ( GMP $a , int $index ) : void |
114,7 → 114,7 |
|
// gmp_div_q ( GMP $a , GMP $b [, int $round = GMP_ROUND_ZERO ] ) : GMP |
// Divide numbers |
function gmp_div_q($a, $b, $round = GMP_ROUND_ZERO/*not implemented*/) { |
function gmp_div_q($a, $b, $round = GMP_ROUND_ZERO/*$round not implemented*/) { |
bcscale(0); |
|
// bcdiv ( string $dividend , string $divisor [, int $scale = 0 ] ) : string |
123,7 → 123,7 |
|
// Divide numbers and get quotient and remainder |
// gmp_div_qr ( GMP $n , GMP $d [, int $round = GMP_ROUND_ZERO ] ) : array |
function gmp_div_qr($n, $d, $round = GMP_ROUND_ZERO/*not implemented*/) { |
function gmp_div_qr($n, $d, $round = GMP_ROUND_ZERO/*$round not implemented*/) { |
bcscale(0); |
return array( |
gmp_div_q($n, $d, $round), |
133,7 → 133,7 |
|
// Remainder of the division of numbers |
// gmp_div_r ( GMP $n , GMP $d [, int $round = GMP_ROUND_ZERO ] ) : GMP |
function gmp_div_r($n, $d, $round = GMP_ROUND_ZERO/*not implemented*/) { |
function gmp_div_r($n, $d, $round = GMP_ROUND_ZERO/*$round not implemented*/) { |
bcscale(0); |
// The remainder operator can be used with negative integers. The rule is: |
// - Perform the operation as if both operands were positive. |
147,7 → 147,7 |
|
// gmp_div ( GMP $a , GMP $b [, int $round = GMP_ROUND_ZERO ] ) : GMP |
// Divide numbers |
function gmp_div($a, $b, $round = GMP_ROUND_ZERO/*not implemented*/) { |
function gmp_div($a, $b, $round = GMP_ROUND_ZERO/*$round not implemented*/) { |
bcscale(0); |
return gmp_div_q($a, $b, $round); // Alias von gmp_div_q |
} |
162,8 → 162,12 |
// gmp_export ( GMP $gmpnumber [, int $word_size = 1 [, int $options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN ]] ) : string |
// Export to a binary string |
function gmp_export($gmpnumber, $word_size = 1, $options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN) { |
if ($word_size != 1) die("Word size != 1 not implemented"); |
if ($options != GMP_MSW_FIRST | GMP_NATIVE_ENDIAN) die("Different options not implemented"); |
|
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
$gmpnumber = bcmul($gmpnumber,"1"); // normalize |
return gmp_init(bin2hex($gmpnumber), 16); |
} |
|
// gmp_fact ( mixed $a ) : GMP |
176,6 → 180,7 |
// gmp_gcd ( GMP $a , GMP $b ) : GMP |
// Calculate GCD |
function gmp_gcd($a, $b) { |
bcscale(0); |
return gmp_gcdext($a, $b)['g']; |
} |
|
219,7 → 224,7 |
// Hamming distance |
function gmp_hamdist($a, $b) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_hamdist() NOT IMPLEMENTED"); |
} |
|
// gmp_import ( string $data [, int $word_size = 1 [, int $options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN ]] ) : GMP |
226,7 → 231,11 |
// Import from a binary string |
function gmp_import($data, $word_size=1, $options=GMP_MSW_FIRST | GMP_NATIVE_ENDIAN) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
|
if ($word_size != 1) die("Word size != 1 not implemented"); |
if ($options != GMP_MSW_FIRST | GMP_NATIVE_ENDIAN) die("Different options not implemented"); |
|
return gmp_init(hex2bin(gmp_strval(gmp_init($data), 16))); |
} |
|
// gmp_init ( mixed $number [, int $base = 0 ] ) : GMP |
265,21 → 274,77 |
// Inverse by modulo |
function gmp_invert($a, $b) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
|
// Source: https://github.com/CityOfZion/neo-php/blob/master/src/Crypto/NumberTheory.php#L246 |
|
while (bccomp($a, 0)==-1) { |
$a=bcadd($m, $a); |
} |
while (bccomp($m, $a)==-1) { |
$a=bcmod($a, $m); |
} |
$c=$a; |
$d=$m; |
$uc=1; |
$vc=0; |
$ud=0; |
$vd=1; |
while (bccomp($c, 0)!=0) { |
$temp1=$c; |
$q=bcdiv($d, $c, 0); |
$c=bcmod($d, $c); |
$d=$temp1; |
$temp2=$uc; |
$temp3=$vc; |
$uc=bcsub($ud, bcmul($q, $uc)); |
$vc=bcsub($vd, bcmul($q, $vc)); |
$ud=$temp2; |
$vd=$temp3; |
} |
$result=''; |
if (bccomp($d, 1)==0) { |
if (bccomp($ud, 0)==1) { |
$result=$ud; |
} else { |
$result=bcadd($ud, $m); |
} |
} else { |
throw new ErrorException("ERROR: $a and $m are NOT relatively prime."); |
} |
return $result; |
} |
|
// gmp_jacobi ( GMP $a , GMP $p ) : int |
// Jacobi symbol |
function gmp_jacobi($a, $p) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
|
// Source: https://github.com/CityOfZion/neo-php/blob/master/src/Crypto/NumberTheory.php#L136 |
|
if ($n>=3 && $n%2==1) { |
$a = bcmod($a, $n); |
if ($a == 0) return 0; |
if ($a == 1) return 1; |
$a1 = $a; |
$e = 0; |
while (bcmod($a1, 2) == 0) { |
$a1 = bcdiv($a1, 2); |
$e = bcadd($e, 1); |
} |
$s = (bcmod($e, 2)==0 || bcmod($n, 8)==1 || bcmod($n, 8)==7) ? 1 : -1; |
if ($a1 == 1) return $s; |
if (bcmod($n, 4)==3 && bcmod($a1, 4)==3) $s = -$s; |
return bcmul($s, gmp_jacobi(bcmod($n, $a1), $a1)); |
} else { |
return false; |
} |
} |
|
// gmp_kronecker ( mixed $a , mixed $b ) : int |
// Kronecker symbol |
function gmp_kronecker($a, $b) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_kronecker() NOT IMPLEMENTED"); |
} |
|
// gmp_lcm ( mixed $a , mixed $b ) : GMP |
286,14 → 351,19 |
// Calculate LCM |
function gmp_lcm($a, $b) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
|
if ((bccomp($a,'0')==0) && (bccomp($b,'0')==0)) { |
return 0; |
} else { |
return gmp_div(gmp_abs(gmp_mul($a,$b)), gmp_gcd($a,$b)); |
} |
} |
|
// gmp_legendre ( GMP $a , GMP $p ) : int |
// Legendre symbol |
function gmp_legendre($a, $p) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_legendre() NOT IMPLEMENTED"); |
} |
|
// gmp_mod ( GMP $n , GMP $d ) : GMP |
325,8 → 395,18 |
// Find next prime number |
function gmp_nextprime($a) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
|
// Source: https://github.com/CityOfZion/neo-php/blob/master/src/Crypto/NumberTheory.php#L692 |
|
if (bccomp($starting_value, 2) == -1) { |
return 2; |
} |
$result = gmp_or(bcadd($starting_value, 1), 1); |
while (!gmp_prob_prime($result)) { |
$result = bcadd($result, 2); |
} |
return $result; |
} |
|
// gmp_or ( GMP $a , GMP $b ) : GMP |
// Bitwise OR |
353,7 → 433,7 |
// Perfect power check |
function gmp_perfect_power($a) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_perfect_power() NOT IMPLEMENTED"); |
} |
|
// gmp_perfect_square ( GMP $a ) : bool |
360,7 → 440,7 |
// Perfect square check |
function gmp_perfect_square($a) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_perfect_square() NOT IMPLEMENTED"); |
} |
|
// gmp_popcount ( GMP $a ) : int |
367,7 → 447,8 |
// Population count |
function gmp_popcount($a) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
$ab = bc_dec2bin($a); |
return substr_count($ab, '1'); |
} |
|
// gmp_pow ( GMP $base , int $exp ) : GMP |
392,14 → 473,47 |
// Check if number is "probably prime" |
function gmp_prob_prime($a, $reps=10) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
|
// Source: https://github.com/CityOfZion/neo-php/blob/master/src/Crypto/NumberTheory.php#L655 |
|
$t = 40; |
$k = 0; |
$m = bcsub($n, 1); |
while (bcmod($m, 2) == 0) { |
$k = bcadd($k, 1); |
$m = bcdiv($m, 2); |
} |
for ($i=0; $i<$t; $i++) { |
$a = bcrand(1, bcsub($n, 1)); |
if ($m < 0) { |
return new ErrorException("Negative exponents ($m) not allowed"); |
} else { |
$b0 = bcpowmod($a, $m, $n); |
} |
if ($b0!=1 && $b0!=bcsub($n, 1)) { |
$j = 1; |
while ($j<=$k-1 && $b0!=bcsub($n, 1)) { |
$b0 = bcpowmod($b0, 2, $n); |
if ($b0 == 1) { |
return false; |
} |
$j++; |
} |
if ($b0 != bcsub($n, 1)) { |
return false; |
} |
} |
} |
return true; |
} |
|
// gmp_random_bits ( int $bits ) : GMP |
// Random number |
function gmp_random_bits($bits) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
$min = 0; |
$max = bcsub(bcpow('2', $bits), '1'); |
return bcrand($min, $max); |
} |
|
// gmp_random_range ( GMP $min , GMP $max ) : GMP |
406,7 → 520,7 |
// Random number |
function gmp_random_range($min, $max) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
return bcrand($min, $max); |
} |
|
// gmp_random_seed ( mixed $seed ) : void |
413,7 → 527,7 |
// Sets the RNG seed |
function gmp_random_seed($seed) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
bcrand_seed($seed); |
} |
|
// gmp_random ([ int $limiter = 20 ] ) : GMP |
420,7 → 534,7 |
// Random number (deprecated) |
function gmp_random($limiter=20) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_random() is deprecated! Please use gmp_random_bits() or gmp_random_range() instead."); |
} |
|
// gmp_root ( GMP $a , int $nth ) : GMP |
427,7 → 541,7 |
// Take the integer part of nth root |
function gmp_root($a, $nth) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_root() NOT IMPLEMENTED"); |
} |
|
// gmp_rootrem ( GMP $a , int $nth ) : array |
434,7 → 548,7 |
// Take the integer part and remainder of nth root |
function gmp_rootrem($a, $nth) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_rootrem() NOT IMPLEMENTED"); |
} |
|
// gmp_scan0 ( GMP $a , int $start ) : int |
511,7 → 625,7 |
// Square root with remainder |
function gmp_sqrtrem($a) { |
bcscale(0); |
throw new Exception("NOT IMPLEMENTED"); |
throw new Exception("gmp_sqrtrem() NOT IMPLEMENTED"); |
} |
|
// gmp_strval ( GMP $gmpnumber [, int $base = 10 ] ) : string |
656,6 → 770,7 |
return true; |
} |
function gmp_not($a) { |
bcscale(0); |
return bcnot($a); |
} |
|
665,6 → 780,7 |
return bcmul($num, bcpow('2', $bits)); |
} |
function gmp_shiftl($num, $bits) { |
bcscale(0); |
return bcshiftl($num, $bits); |
} |
|
674,6 → 790,7 |
return bcdiv($num, bcpow('2', $bits)); |
} |
function gmp_shiftr($num, $bits) { |
bcscale(0); |
return bcshiftr($num, $bits); |
} |
|
693,4 → 810,22 |
|
return $result; |
} |
|
// Newly added (used by gmp_prob_prime, gmp_random_range and gmp_random_bits) |
function bcrand($min, $max = false) { |
bcscale(0); |
// Source: https://github.com/CityOfZion/neo-php/blob/master/src/Crypto/BCMathUtils.php#L7 |
// Fixed: https://github.com/CityOfZion/neo-php/issues/16 |
if (!$max) { |
$max = $min; |
$min = 0; |
} |
return bcadd(bcmul(bcdiv(mt_rand(), mt_getrandmax(), strlen($max)), bcsub(bcadd($max, 1), $min)), $min); |
} |
|
// Newly added (used by gmp_random_seed) |
function bcrand_seed($seed) { |
bcscale(0); |
mt_srand($seed); |
} |
} |