function powmod($base, $exponent, $modulus) { if (function_exists('gmp_powm')) { // fast return gmp_strval(gmp_powm($base, $exponent, $modulus)); } if (function_exists('bi_powmod')) { // not tested return bi_sto_str(bi_powmod($base, $exponent, $modulus)); } if (function_exists('bcpowmod')) { // slow return bcpowmod($base, $exponent, $modulus); } // emulation, slow $square = bcmod($base, $modulus); $result = 1; while (bccomp($exponent, 0) > 0) { if (bcmod($exponent, 2)) { $result = bcmod(bcmul($result, $square), $modulus); } $square = bcmod(bcmul($square, $square), $modulus); $exponent = bcdiv($exponent, 2); } return $result; }
function powm($base, $exponent, $modulus) { if (function_exists('gmp_powm')) { return gmp_strval(gmp_powm($base, $exponent, $modulus)); } else { if (function_exists('bi_powmod')) { return bi_sto_str(bi_powmod($base, $exponent, $modulus)); } else { if (function_exists('bcpowmod')) { return bcpowmod($base, $exponent, $modulus); } else { if (preg_match("/^\\d+,\\d+,\\d+\$/", "{$base},{$exponent},{$modulus}")) { //@FIX: this is insecure - a bi-directional proc_open() is required if (is_executable("/usr/bin/python")) { $r = trim(`python -c "print pow({$base}, {$exponent}, {$modulus})"`); } else { $r = trim(`perl -e "use Math::BigInt; print Math::BigInt->new('{$base}')->bmodpow('{$exponent}', '{$modulus}')->bstr();"`); } if (preg_match("/^\\d+\$/", $r)) { return $r; } } } } } trigger_error("powmod: unsupported or non-integer argument", E_USER_ERROR); }