From 78bc28b0455b2ec4028ead08d61ece74ae0121bb Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 13 Mar 2016 21:49:01 +0100 Subject: [PATCH] Draft All these files need further edits + other optimization files + moving of files --- Math/Fibunacci.php | 62 ++++++++++++ Math/Functions.php | 101 +++++++++++++++++++ Math/Number/Numbers.php | 28 +++++ Math/Optimization/EdgeInterface.php | 0 Math/Optimization/GaussianElimination.php | 61 +++++++++++ Math/Optimization/Graph/Dijkstra.php | 68 +++++++++++++ Math/Optimization/Graph/FloydWarshall.php | 0 Math/Optimization/GraphAbstract.php | 69 +++++++++++++ Math/Optimization/NullEdge.php | 0 Math/Optimization/NullVertice.php | 0 Math/Optimization/VerticeInterface.php | 0 Math/Permutation.php | 24 +++++ Math/Prime.php | 88 ++++++++++++++++ Security/Encryption/Ceasar.php | 1 + Security/Encryption/EncryptionInterface.php | 0 Utils/Compression/CompressionInterface.php | 0 Utils/Compression/LZW.php | 70 +++++++++++++ Utils/Encoding/EncodingInterface.php | 0 Utils/Encoding/Gray.php | 19 ++++ Utils/Encoding/Huffman.php | 6 ++ Utils/MultiMap.php | 10 +- Utils/Random/ArrayRandomize.php | 30 ++++++ Utils/Random/LinearCongruentialGenerator.php | 17 ++++ Validation/Base/CreditCard.php | 16 +++ Validation/Base/IBAN.php | 1 + Validation/BitcoinValidator.php | 66 ++++++++++++ 26 files changed, 736 insertions(+), 1 deletion(-) create mode 100644 Math/Fibunacci.php create mode 100644 Math/Number/Numbers.php create mode 100644 Math/Optimization/EdgeInterface.php create mode 100644 Math/Optimization/GaussianElimination.php create mode 100644 Math/Optimization/Graph/Dijkstra.php create mode 100644 Math/Optimization/Graph/FloydWarshall.php create mode 100644 Math/Optimization/GraphAbstract.php create mode 100644 Math/Optimization/NullEdge.php create mode 100644 Math/Optimization/NullVertice.php create mode 100644 Math/Optimization/VerticeInterface.php create mode 100644 Math/Permutation.php create mode 100644 Math/Prime.php create mode 100644 Security/Encryption/Ceasar.php create mode 100644 Security/Encryption/EncryptionInterface.php create mode 100644 Utils/Compression/CompressionInterface.php create mode 100644 Utils/Compression/LZW.php create mode 100644 Utils/Encoding/EncodingInterface.php create mode 100644 Utils/Encoding/Gray.php create mode 100644 Utils/Encoding/Huffman.php create mode 100644 Utils/Random/ArrayRandomize.php create mode 100644 Utils/Random/LinearCongruentialGenerator.php create mode 100644 Validation/BitcoinValidator.php diff --git a/Math/Fibunacci.php b/Math/Fibunacci.php new file mode 100644 index 000000000..3b1664d7f --- /dev/null +++ b/Math/Fibunacci.php @@ -0,0 +1,62 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ + +namespace phpOMS\Math; + +/** + * Well known functions class. + * + * @category Framework + * @package phpOMS\DataStorage\Database + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +class Fibunacci +{ + public static function isFibunacci(int $n) + { + return Functions::isSquare(5*$n**2+4) || Functions::isSquare(5*$n**2-4); + } + + public static function fibunacci(int $n, int $start = 1) : int + { + if($n < 2) { + return 0; + } elseif ($n < 4) { + return $start; + } + + $old_1 = 0; + $old_2 = $start; + $fib = 0; + + for($i = 4; $i < $n; $i++) { + $fib = $old_1 + $old_2 + $old_1 = $old_2; + $old_2 = $fib; + } + + return $fib; + } + + public static function binet(int $n) : int + { + return (int) (((1+sqrt(5))**$n - (1-sqrt(5))**$n)/(2**$n * sqrt(5))); + } +} \ No newline at end of file diff --git a/Math/Functions.php b/Math/Functions.php index 66d38c14d..6653461a4 100644 --- a/Math/Functions.php +++ b/Math/Functions.php @@ -115,4 +115,105 @@ class Functions return $fact / $fact2; } + + public static function ackermann(int $m, int $n) + { + if($m === 0) { + return $n+1; + } elseif($n === 0) { + return self::ackermann($m-1, 1); + } + + return ackermann($m-1, ackermann($m, $n-1)); + } + + public static function isSquare(int $x) { + $goodMask; // 0xC840C04048404040 computed below + + for ($i = 0; $i < 64; ++$i) { + $goodMask |= PHP_INT_MIN >>> ($i*$i); + } + + // This tests if the 6 least significant bits are right. + // Moving the to be tested bit to the highest position saves us masking. + if ($goodMask << $x >= 0) return false; + + $numberOfTrailingZeros = self::countTrailingZeros($x); + // Each square ends with an even number of zeros. + if (($numberOfTrailingZeros & 1) !== 0) return false; + + $x >>= $numberOfTrailingZeros; + // Now x is either 0 or odd. + // In binary each odd square ends with 001. + // Postpone the sign test until now; handle zero in the branch. + if (($x&7) != 1 | $x <= 0) return $x === 0; + // Do it in the classical way. + // The correctness is not trivial as the conversion from long to double is lossy! + $tst = (int) sqrt($x); + + return $tst * $tst == $x; + } + + public static function countTrailingZeros(int $n) : int + { + $count = 0; + while ($n !== 0) { + if ($n & 1 == 1) { + break; + } else { + $count++; + $n = $n >> 1; + } + } + + return $count; + } + + public static function greatestCommonDivisor(int $n, int $m) : int + { + while(true) { + if($n === $m) { + return $m; + } if($n > $m) { + $n -= $m; + } else { + $m -= $n; + } + } + } + + public static function invMod($a,$n){ + if ($n < 0) { + $n = -$n; + } + + if ($a < 0) { + $a = $n - (-$a % $n); + } + + $t = 0; + $nt = 1; + $r = $n; + $nr = $a % $n; + + while ($nr != 0) { + $quot = intval($r/$nr); + $tmp = $nt; + $nt = $t - $quot*$nt; + $t = $tmp; + $tmp = $nr; + $nr = $r - $quot*$nr; + $r = $tmp; + } + + if ($r > 1) { + return -1; + } + + if ($t < 0) { + $t += $n; + } + + return $t; + } } diff --git a/Math/Number/Numbers.php b/Math/Number/Numbers.php new file mode 100644 index 000000000..bb0628680 --- /dev/null +++ b/Math/Number/Numbers.php @@ -0,0 +1,28 @@ + $value) { + if (substr_count($number, $place) != $value) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/Math/Optimization/EdgeInterface.php b/Math/Optimization/EdgeInterface.php new file mode 100644 index 000000000..e69de29bb diff --git a/Math/Optimization/GaussianElimination.php b/Math/Optimization/GaussianElimination.php new file mode 100644 index 000000000..87cfe1236 --- /dev/null +++ b/Math/Optimization/GaussianElimination.php @@ -0,0 +1,61 @@ + $max) { + $j = $i; + $max = $tmp; + } + } + + $this->swapRows($A, $b, $col, $j); + + for ($i = $col + 1; $i < $limit; $i++) { + $tmp = $A[$i][$col] / $A[$col][$col]; + + for ($j = $col + 1; $j < $limit; $j++) { + $A[$i][$j] -= $tmp * $A[$col][$j]; + } + + $A[$i][$col] = 0; + $b[$i] -= $tmp * $b[$col]; + } + } + + $x = []; + + for ($col = $limit - 1; $col >= 0; $col--) { + $tmp = $b[$col]; + + for ($j = $limit - 1; $j > $col; $j--) { + $tmp -= $x[$j] * $A[$col][$j]; + } + + $x[$col] = $tmp / $A[$col][$col]; + } + + return $x; + } +} \ No newline at end of file diff --git a/Math/Optimization/Graph/Dijkstra.php b/Math/Optimization/Graph/Dijkstra.php new file mode 100644 index 000000000..d4dd7695d --- /dev/null +++ b/Math/Optimization/Graph/Dijkstra.php @@ -0,0 +1,68 @@ + $edge[1], "cost" => $edge[2]); + $neighbours[$edge[1]][] = array("end" => $edge[0], "cost" => $edge[2]); + } + + $vertices = array_unique($vertices); + + foreach ($vertices as $vertex) { + $dist[$vertex] = INF; + $previous[$vertex] = NULL; + } + + $dist[$source] = 0; + $Q = $vertices; + + while (count($Q) > 0) { + + // TODO - Find faster way to get minimum + $min = INF; + + foreach ($Q as $vertex){ + if ($dist[$vertex] < $min) { + $min = $dist[$vertex]; + $u = $vertex; + } + } + + $Q = array_diff($Q, array($u)); + + if ($dist[$u] == INF || $u == $target) { + break; + } + + if (isset($neighbours[$u])) { + foreach ($neighbours[$u] as $arr) { + $alt = $dist[$u] + $arr["cost"]; + + if ($alt < $dist[$arr["end"]]) { + $dist[$arr["end"]] = $alt; + $previous[$arr["end"]] = $u; + } + } + } + } + + $path = array(); + $u = $target; + + while (isset($previous[$u])) { + array_unshift($path, $u); + $u = $previous[$u]; + } + + array_unshift($path, $u); + + return $path; + } +} \ No newline at end of file diff --git a/Math/Optimization/Graph/FloydWarshall.php b/Math/Optimization/Graph/FloydWarshall.php new file mode 100644 index 000000000..e69de29bb diff --git a/Math/Optimization/GraphAbstract.php b/Math/Optimization/GraphAbstract.php new file mode 100644 index 000000000..c63f3c78b --- /dev/null +++ b/Math/Optimization/GraphAbstract.php @@ -0,0 +1,69 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Math\Optimization; + +class GraphAbstract { + private $vertices = []; + + private $edges = null; + + public function __construct() + { + $this->edges = new MultiMap(KeyType::STRICT, OrderType::LOOSE); + } + + public function addVertice(VerticeInterface $Vertice) : bool + { + if(!isset($this->vertices[$Vertice->getId()])) { + $this->vertices[$Vertice->getId()] = $Vertice; + + return true; + } + + return false; + } + + public function removeVertice($id) : bool + { + if(isset($this->vertices[$id])) { + unset($this->vertices[$id]); + + return true; + } + + return false; + } + + public function getVertice($id) : VerticeInterface + { + return $this->vertices[$id] ?? new NullVertice(); + } + + public function getEdge($a, $b) : EdgeInterface + { + return $this->edges->get($a, $b) ?? new NullEdge(); + } + + public function countVertices() : int + { + return count($this->vertices); + } + + public function countEdges() : int + { + return count($this->edges); + } +} \ No newline at end of file diff --git a/Math/Optimization/NullEdge.php b/Math/Optimization/NullEdge.php new file mode 100644 index 000000000..e69de29bb diff --git a/Math/Optimization/NullVertice.php b/Math/Optimization/NullVertice.php new file mode 100644 index 000000000..e69de29bb diff --git a/Math/Optimization/VerticeInterface.php b/Math/Optimization/VerticeInterface.php new file mode 100644 index 000000000..e69de29bb diff --git a/Math/Permutation.php b/Math/Permutation.php new file mode 100644 index 000000000..a77c89bfe --- /dev/null +++ b/Math/Permutation.php @@ -0,0 +1,24 @@ + $val){ + $newArr = $toPermute; + $newres = $result; + $newres[] = $val; + unset($newArr[$key]); + $permutations += permut($newArr, $newres); + } + } + + return $permutations; + } +} \ No newline at end of file diff --git a/Math/Prime.php b/Math/Prime.php new file mode 100644 index 000000000..e3eee90c5 --- /dev/null +++ b/Math/Prime.php @@ -0,0 +1,88 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ + +namespace phpOMS\Math; + +/** + * Well known functions class. + * + * @category Framework + * @package phpOMS\DataStorage\Database + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +class Prime +{ + public static function isMersenne(int $n) + { + $mersenne = log($n+1)/2; + + return $mersenne - (int) $mersenne < 0.00001 + } + + public static function mersenne(int $p) + { + return power(2, $p) - 1; + } + + public static function rabinTest(int $n, int $k) : bool + { + if ($n == 2) { + return true; + } + + if ($n < 2 || $n % 2 == 0){ + return false; + } + + $d = $n - 1; + $s = 0; + + while ($d % 2 == 0) { + $d /= 2; + $s++; + } + + for ($i = 0; $i < $k; $i++) { + $a = mt_rand(2, $n-1); + + $x = bcpowmod($a, $d, $n); + + if ($x == 1 || $x == $n-1) { + continue; + } + + for ($j = 1; $j < $s; $j++) { + $x = bcmod(bcmul($x, $x), $n); + + if ($x == 1) { + return false; + } + + if ($x == $n-1) { + continue 2; + } + } + + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/Security/Encryption/Ceasar.php b/Security/Encryption/Ceasar.php new file mode 100644 index 000000000..b3d9bbc7f --- /dev/null +++ b/Security/Encryption/Ceasar.php @@ -0,0 +1 @@ +> 1); + } + + public static function decode(int $gray) : int + { + $source = $gray; + + while($gray >>= 1) { + $source ^= $gray; + } + + return $source; + } +} \ No newline at end of file diff --git a/Utils/Encoding/Huffman.php b/Utils/Encoding/Huffman.php new file mode 100644 index 000000000..ac961924f --- /dev/null +++ b/Utils/Encoding/Huffman.php @@ -0,0 +1,6 @@ + */ - public function __construct() + public function __construct(int $key = KeyType::LOOSE, int $order = OrderType::LOOSE) { + $this->keyType = $key; + $this->orderType = $order; } /** diff --git a/Utils/Random/ArrayRandomize.php b/Utils/Random/ArrayRandomize.php new file mode 100644 index 000000000..ba0249388 --- /dev/null +++ b/Utils/Random/ArrayRandomize.php @@ -0,0 +1,30 @@ + 0; $i--){ + $rnd = mt_rand(0, $i); + $shuffled[$i] = $arr[$rnd]; + $shuffled[$rand] = $arr[$i]; + } + + return $shuffled; + } +} \ No newline at end of file diff --git a/Utils/Random/LinearCongruentialGenerator.php b/Utils/Random/LinearCongruentialGenerator.php new file mode 100644 index 000000000..84756d208 --- /dev/null +++ b/Utils/Random/LinearCongruentialGenerator.php @@ -0,0 +1,17 @@ +> 16; + }; + } +} \ No newline at end of file diff --git a/Validation/Base/CreditCard.php b/Validation/Base/CreditCard.php index 200b3b010..bf78b1175 100644 --- a/Validation/Base/CreditCard.php +++ b/Validation/Base/CreditCard.php @@ -71,4 +71,20 @@ abstract class CreditCard extends ValidatorAbstract // If the total mod 10 equals 0, the value is valid return ($total % 10 == 0) ? true : false; } + + public static function luhnTest(string $num) { + $len = strlen($num); + + for ($i = $len-1; $i >= 0; $i--) { + $ord = ord($num[$i]); + + if (($len - 1) & $i) { + $sum += $ord; + } else { + $sum += $ord / 5 + (2 * $ord) % 10; + } + } + + return $sum % 10 == 0; + } } diff --git a/Validation/Base/IBAN.php b/Validation/Base/IBAN.php index d003c2ba1..3427c094e 100644 --- a/Validation/Base/IBAN.php +++ b/Validation/Base/IBAN.php @@ -44,6 +44,7 @@ abstract class IBAN extends ValidatorAbstract /** * {@inheritdoc} */ + // todo: this is bad see wiki for better checks... public static function isValid($value) { $value = strtolower(str_replace(' ', '', $value)); diff --git a/Validation/BitcoinValidator.php b/Validation/BitcoinValidator.php new file mode 100644 index 000000000..cb89631b9 --- /dev/null +++ b/Validation/BitcoinValidator.php @@ -0,0 +1,66 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Validation; + +class BitcoinValidator +{ + public static function validate(string $addr) : bool + { + $decoded = decodeBase58($address); + + $d1 = hash("sha256", substr($decoded,0,21), true); + $d2 = hash("sha256", $d1, true); + + if(substr_compare($decoded, $d2, 21, 4)){ + return false + } + + return true; + } + + public static function decodeBase58(string $input) : string + { + $alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + + $out = array_fill(0, 25, 0); + $len = strlen($input); + + for($i = 0; $i < $len; $i++){ + if(($p=strpos($alphabet, $input[$i]))===false){ + throw new \Exception("invalid character found"); + } + + $c = $p; + for ($j = 25; $j--; ) { + $c += (int)(58 * $out[$j]); + $out[$j] = (int)($c % 256); + $c /= 256; + $c = (int)$c; + } + + if($c !== 0){ + throw new \Exception("address too long"); + } + } + + $result = ""; + foreach($out as $val){ + $result .= chr($val); + } + + return $result; + } +} \ No newline at end of file