= 0 || $nᵗʰ % 2 === 0) { return \pow($x, 1 / $nᵗʰ); } return - \pow(\abs($x), 1 / $nᵗʰ); } /** * Cube root ³√x * This function is necessary because pow($x, 1/3) returns NAN for negative values. * PHP does not have the cbrt built-in function. * * @param float $x * * @return float */ public static function cubeRoot(float $x): float { return self::root($x, 3); } /** * Integer square root |_√x_| * The positive integer which is the greatest integer less than or equal to the square root * https://en.wikipedia.org/wiki/Integer_square_root * * @param float $x * * @return int * * @throws BadParameterException */ public static function isqrt(float $x): int { if ($x < 0) { throw new Exception\BadParameterException("x must be non-negative for isqrt - got $x"); } return (int)\floor(\sqrt($x)); } /** * Digit sum * Sum of all an integer's digits. * https://en.wikipedia.org/wiki/Digit_sum * * log x 1 * ∑ -- (x mod bⁿ⁺¹ - x mod bⁿ) * ⁿ⁼⁰ bⁿ * * Example (base 10): 5031 = 5 + 0 + 3 + 1 = 9 * Example (base 2): 0b1010 = 1 + 0 + 1 + 0 = 2 * * @param int $x * @param int $b Base (Default is base 10) * * @return int */ public static function digitSum(int $x, int $b = 10): int { $logx = \log($x, $b); $∑1/bⁿ⟮x mod bⁿ⁺¹ − x mod bⁿ⟯ = 0; for ($n = 0; $n <= $logx; $n++) { $∑1/bⁿ⟮x mod bⁿ⁺¹ − x mod bⁿ⟯ += \intdiv(($x % \pow($b, $n + 1)) - ($x % $b ** $n), ($b ** $n)); } return $∑1/bⁿ⟮x mod bⁿ⁺¹ − x mod bⁿ⟯; } /** * Digital root (iterated digit sum, repeated digital sum) * The single digit value obtained by an iterative process of summing digits, * on each iteration using the result from the previous iteration to compute a digit sum. * The process continues until a single-digit number is reached. * https://en.wikipedia.org/wiki/Digital_root * * Example: 65,536 is 7, because 6 + 5 + 5 + 3 + 6 = 25 and 2 + 5 = 7 * * @param int $x * * @return int */ public static function digitalRoot(int $x): int { $root = $x; while ($root >= 10) { $root = self::digitSum($root); } return $root; } /** * Test if two numbers are almost equal, within a tolerance ε * * @param float $x * @param float $y * @param float $ε tolerance * * @return bool true if the numbers are equal within a tolerance; false if they are not */ public static function almostEqual(float $x, float $y, $ε = 0.000000000001): bool { return \abs($x - $y) <= $ε; } /** * Returns the magnitude value with the sign of the sign number * * @param float $magnitude * @param float $sign * * @return float $magnitude with the sign of $sign */ public static function copySign(float $magnitude, float $sign): float { return $sign >= 0 ? \abs($magnitude) : -\abs($magnitude); } /** * Modulo (Binary operation) * * Modulo is different from the remainder function. * The PHP % operator is the remainder function, where the result has the same sign as the dividend. * The mod function's result has the same sign as the divisor. * * For positive dividends and divisors, the modulo function is the same as the remainder (%) operator. * For negative dividends or divisors, the modulo function has different behavior than the remainder (%) operator. * * a mod n * a - n ⌊a/n⌋ for n ≠ 0 * a for n = 0 * where * a is the dividend (integer) * n is the divisor, also known as the modulus (integer) * ⌊⌋ is the floor function * * https://en.wikipedia.org/wiki/Modulo_operation * https://en.wikipedia.org/wiki/Modulo_(mathematics) * Knuth, Donald. E. (1972). The Art of Computer Programming. Volume 1 Fundamental Algorithms. Addison-Wesley. * Graham, Knuth, Patashnik (1994). Concrete Mathematics, A Foundation For Computer Science. Addison-Wesley. * * @param int $a dividend * @param int $n divisor, also known as the modulus * * @return int */ public static function modulo(int $a, int $n): int { if ($n === 0) { return $a; } return (int)($a - $n * \floor($a / $n)); } }