diff --git a/.travis.yml b/.travis.yml index 50d4a67..4df8208 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,8 +15,10 @@ addons: apt: packages: - python3 + before_script: - composer update --dev +- "tests/install_deps.sh" script: - "tests/testing.php" diff --git a/README.md b/README.md index a35b758..1108321 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ Install python to enable the python module and the PHP curl extension to enable This library has 4 prime factorization modules (ordered by speed, huge semiprime is usually a 20 digit semiprime generated by [telegram](https://core.telegram.org), see the travis ci tests for more stats): +* native_cpp - A [native c++](https://github.com/danog/PrimeModule-ext) factorization module (it's the fastest), medium time 0.03943687915802 tested with 100 huge semiprime + * python - A [quadratic sieve](http://codegolf.stackexchange.com/questions/8629/fastest-semiprime-factorization) python module (usually it's faster than the pollard brent module, other times it just gets stuck (and then killed after 10 seconds by the lib), medium time 0.35134809732437 seconds calculated using 100 huge semiprimes, some of which caused the module to freeze and be killed. Usually it's 10 times faster than the pollard brent module) * python_alt - A [pollard brent](https://stackoverflow.com/questions/4643647/fast-prime-factorization-module) module also written in python (medium time 0.1801231908798 seconds calculated using 100 huge semiprimes) diff --git a/lib/danog/PrimeModule.php b/lib/danog/PrimeModule.php index aa0857d..b15e012 100644 --- a/lib/danog/PrimeModule.php +++ b/lib/danog/PrimeModule.php @@ -185,15 +185,21 @@ class PrimeModule return $res; } - - public static function python($what) + public static function native_single_cpp($what) { - $res = [self::python_single($what)]; + if (!extension_loaded('primemodule')) return false; + try { + return factorize($what); + } catch (\Exception $e) { return false; } + } + public static function native_cpp($what) + { + $res = [self::native_single_cpp($what)]; if ($res[0] === false) { return false; } while (array_product($res) !== $what) { - $res[] = self::python_single($what / array_product($res)); + $res[] = self::native_single_cpp($what / array_product($res)); } return $res; @@ -224,6 +230,10 @@ class PrimeModule public static function auto($what) { + $res = self::native_cpp($what); + if (is_array($res)) { + return $res; + } $res = self::python_alt($what); if (is_array($res)) { return $res; @@ -246,6 +256,10 @@ class PrimeModule public static function auto_single($what) { + $res = self::native_single_cpp($what); + if ($res !== false) { + return $res; + } $res = self::python_single_alt($what); if ($res !== false) { return $res; diff --git a/tests/install_deps.sh b/tests/install_deps.sh new file mode 100755 index 0000000..fc0fe4d --- /dev/null +++ b/tests/install_deps.sh @@ -0,0 +1,15 @@ +#!/bin/bash -e +cd /tmp +git clone https://github.com/CopernicaMarketingSoftware/PHP-CPP +cd PHP-CPP +make -j16 +sudo make install + +cd ../ +git clone https://github.com/danog/PrimeModule-ext +cd PrimeModule-ext +make -j16 +sudo make install + +cd .. + diff --git a/tests/testing.php b/tests/testing.php index f472e00..0df091e 100755 --- a/tests/testing.php +++ b/tests/testing.php @@ -23,9 +23,16 @@ function test($n) echo '|'.str_pad('Multiple factorization of '.$n, strlen($init) - 2, ' ', STR_PAD_BOTH).'|'.PHP_EOL; echo '|'.str_pad('', strlen($init) - 2, '_', STR_PAD_RIGHT).'|'.PHP_EOL; echo $init.PHP_EOL; + + list($time, $result) = get_time(['\danog\PrimeModule', 'native_cpp'], $n, true); + $GLOBALS['medium']['native_cpp'] += $time; + echo '| '.str_pad($result, 6, ' ', STR_PAD_RIGHT).' | native cpp | '.str_pad($time, 20, ' ', STR_PAD_RIGHT).' |'.PHP_EOL; + list($time, $result) = get_time(['\danog\PrimeModule', 'python_alt'], $n, true); $GLOBALS['medium']['python_alt'] += $time; echo '| '.str_pad($result, 6, ' ', STR_PAD_RIGHT).' | python alt | '.str_pad($time, 20, ' ', STR_PAD_RIGHT).' |'.PHP_EOL; + + list($time, $result) = get_time(['\danog\PrimeModule', 'python'], $n); $GLOBALS['medium']['python'] += $time; /* @@ -48,9 +55,14 @@ function test_single($n, $messy = false) echo '|'.str_pad('', strlen($init) - 2, '_', STR_PAD_RIGHT).'|'.PHP_EOL; echo $init.PHP_EOL; + list($time, $result) = get_time(['\danog\PrimeModule', 'native_single_cpp'], $n); + $GLOBALS['medium']['native_cpp'] += $time; + echo '| '.str_pad($result, strlen($n), ' ', STR_PAD_RIGHT).' | native cpp | '.str_pad($time, 20, ' ', STR_PAD_RIGHT).' |'.PHP_EOL; + list($time, $result) = get_time(['\danog\PrimeModule', 'python_single_alt'], $n); $GLOBALS['medium']['python_alt'] += $time; echo '| '.str_pad($result, strlen($n), ' ', STR_PAD_RIGHT).' | python alt | '.str_pad($time, 20, ' ', STR_PAD_RIGHT).' |'.PHP_EOL; + if (!$messy) { list($time, $result) = get_time(['\danog\PrimeModule', 'python_single'], $n); $GLOBALS['medium']['python'] += $time; @@ -84,7 +96,7 @@ function gen_payload() } echo PHP_EOL.'----------- HUGE SEMIPRIME TESTS (100 semiprimes) ----------'.PHP_EOL; -$GLOBALS['medium'] = ['python' => 0, 'python_alt' => 0, 'wolfram' => 0, 'native' => 0]; +$GLOBALS['medium'] = ['python' => 0, 'python_alt' => 0, 'wolfram' => 0, 'native' => 0, 'native_cpp' => 0]; $tg = fsockopen('tcp://149.154.167.40:443'); fwrite($tg, chr(239)); stream_set_timeout($tg, 1); @@ -100,7 +112,7 @@ foreach ($medium as $type => $total) { echo $type.': total time '.$total.', medium time '.($total / $tot).PHP_EOL; } echo PHP_EOL.'------------------- SMALL MULTIPLE FACTOR TESTS -------------------'.PHP_EOL; -$GLOBALS['medium'] = ['python' => 0, 'python_alt' => 0, 'wolfram' => 0, 'native' => 0]; +$GLOBALS['medium'] = ['python' => 0, 'python_alt' => 0, 'wolfram' => 0, 'native' => 0, 'native_cpp' => 0]; foreach ([200, 327, 35, 13589] as $multiple) { test($multiple);