*/ function mod( int $number, int $modulus ) : int { // return (x - (div(x, y) * y)); if ($modulus <= 0) { throw (new \Exception('invalid divisor')); } else { return ( ($number >= 0) ? ($number%$modulus) : (($modulus-((-$number)%$modulus))%$modulus) ); } } /** * computes the power of a number in a residue class ring via square and multiply * * @author Christian Fraß */ function modpow( int $base, int $exponent, int $modulus ) : int { if ($exponent === 0) { return 1; } else { $a = modpow($base, $exponent >> 1, $modulus); $a = mod(($a * $a), $modulus); if (($exponent & 1) != 0) { $a = mod(($a * $base), $modulus); } return $a; } } /** * @template TypeElement * @param \Closure {function,boolean>} * @param array $set1 {list} * @param array $set2 {list} * @return array {list} * @author Christian Fraß */ function set_sub/**/( \Closure $collation, array $set1, array $set2 ) : bool { foreach ($set1 as $element1) { $present = false; foreach ($set2 as $element2) { if ($collation($element1, $element2)) { $present = true; break; } } if (! $present) { return false; break; } } return true; } /** * @param \Closure function,boolean> * @param array $set1 {list} * @param array $set2 {list} * @return array {list} * @author Christian Fraß */ function set_union/**/( \Closure $collation, array $set1, array $set2 ) : array { $set3 = []; foreach ([$set1, $set2] as $source) { foreach ($source as $element) { $add = true; foreach ($set3 as $element_) { if ($collation($element, $element_)) { $add = false; break; } } if ($add) { array_push($set3, $element); } } } return $set3; } /** * @param \Closure function,boolean> * @param array $set1 {list} * @param array $set2 {list} * @return array {list} * @author Christian Fraß */ function set_intersection/**/( \Closure $collation, array $set1, array $set2 ) : array { $set3 = []; foreach ($set1 as $element1) { $add = false; foreach ($set2 as $element2) { if ($collation($element1, $element2)) { $add = true; break; } } if ($add) { array_push($set3, $element1); } } return $set3; } /** * @param \Closure function,boolean> * @param array $set1 {list} * @param array $set2 {list} * @return array {list} * @author Christian Fraß */ function set_difference/**/( \Closure $collation, array $set1, array $set2 ) : array { $set3 = []; foreach ($set1 as $element1) { $add = true; foreach ($set2 as $element2) { if ($collation($element1, $element2)) { $add = false; break; } } if ($add) { array_push($set3, $element1); } } return $set3; } /** * applies the lexicographic order * * @template type_element * @param order Closure {function} * @param array $list1 {list} * @param array $list2 {list} * @return boolean * @author Christian Fraß */ function order_lexicographic( \Closure $order, array $list1, array $list2 ) : bool { if (empty($list1)) { if (empty($list2)) { return true; } else { return true; } } else { if (empty($list2)) { return false; } else { $le = $order($list1[0], $list2[0]); $ge = $order($list2[0], $list1[0]); if (! $le) { if (! $ge) { // impossible: badly defined order } else { return false; } } else { if (! $ge) { return true; } else { return order_lexicographic( $order, array_slice($list1, 1), array_slice($list2, 1) ); } } } } } ?>