0) { $temp = $min; $min = $max; $max = $temp; } $min = self::dec2base($min, 256); $max = self::dec2base($max, 256); $buffer = array(); for ($i = 0; $i < strlen($min); ++$i) { $buffer[] = substr($min, -$i - 1, 1) & substr($max, -$i - 1, 1); } $buffer = array_reverse($buffer); $result = implode($buffer); return self::base2dec($result, 256); } private static function _bitwise(&$left, &$right, $bits = null) { if ($bits === null) { $bits = max(self::bits_needed($left), self::bits_needed($right)); } $left = self::dec2base($left, 2); $right = self::dec2base($right, 2); $len = max(strlen($left), strlen($right), (int)$bits); $left = sprintf("%0{$len}s", $left); $right = sprintf("%0{$len}s", $right); return $len; } public static function bits_needed($num, $boundary = 4) { $bits = 0; while ($num > 0) { $num = bcdiv($num, '2', 0); $bits++; } // round to nearest boundrary return $boundary ? ceil($bits / $boundary) * $boundary : $bits; } // Bitwise OR public static function bcor($x, $y) { if (extension_loaded('bcmath') && USE_EXT=='BCMATH') { return self::_bcbitwise_internal($x, $y, 'self::_bcor'); } else { throw new \ErrorException("Please install BCMATH"); } } // Bitwise XOR public static function bcxor($x, $y) { if (extension_loaded('bcmath') && USE_EXT=='BCMATH') { return self::_bcbitwise_internal($x, $y, 'self::_bcxor'); } else { throw new \ErrorException("Please install BCMATH"); } } // Left shift (<<) public static function bcleftshift($num, $shift) { if (extension_loaded('bcmath') && USE_EXT=='BCMATH') { bcscale(0); return bcmul($num, bcpow(2, $shift)); } else { throw new \ErrorException("Please install BCMATH"); } } // Right shift (>>) public static function bcrightshift($num, $shift) { if (extension_loaded('bcmath') && USE_EXT=='BCMATH') { bcscale(0); return bcdiv($num, bcpow(2, $shift)); } else { throw new \ErrorException("Please install BCMATH"); } } //// INTERNAL ROUTINES // These routines operate on only one byte. They are used to // implement _bcbitwise_internal. public static function _bcand($x, $y) { return $x & $y; } public static function _bcor($x, $y) { return $x | $y; } public static function _bcxor($x, $y) { return $x ^ $y; } // _bcbitwise_internal - The majority of the code that implements // the bitwise functions bcand, bcor, and bcxor. // // arguments - $x and $y are the operands (in decimal format), // and $op is the name of one of the three // internal functions, _bcand, _bcor, or _bcxor. // // // see also - The interfaces to this function: bcand, bcor, // and bcxor public static function _bcbitwise_internal($x, $y, $op) { $bx = self::bc2bin($x); $by = self::bc2bin($y); // Pad $bx and $by so that both are the same length. self::equalbinpad($bx, $by); $ix = 0; $ret = ''; for ($ix = 0; $ix < strlen($bx); $ix++) { $xd = substr($bx, $ix, 1); $yd = substr($by, $ix, 1); $ret .= call_user_func($op, $xd, $yd); } return self::bin2bc($ret); } public static function bc2bin($num) { return self::dec2base($num, MAX_BASE); } public static function bin2bc($num) { return self::base2dec($num, MAX_BASE); } public static function dec2base($dec, $base, $digits=FALSE) { if (extension_loaded('bcmath')) { if ($base < 2 or $base > 256) die("Invalid Base: " . $base); bcscale(0); $value = ""; if (!$digits) $digits = self::digits($base); while ($dec > $base - 1) { $rest = bcmod($dec, $base); $dec = bcdiv($dec, $base); $value = $digits[$rest] . $value; } $value = $digits[intval($dec)] . $value; return (string) $value; } else { throw new \ErrorException("Please install BCMATH"); } } public static function base2dec($value, $base, $digits=FALSE) { if (extension_loaded('bcmath')) { if ($base < 2 or $base > 256) die("Invalid Base: " . $base); bcscale(0); if ($base < 37) $value = strtolower($value); if (!$digits) $digits = self::digits($base); $size = strlen($value); $dec = "0"; for ($loop = 0; $loop < $size; $loop++) { $element = strpos($digits, $value[$loop]); $power = bcpow($base, $size - $loop - 1); $dec = bcadd($dec, bcmul($element, $power)); } return (string) $dec; } else { throw new \ErrorException("Please install BCMATH"); } } /** * Optimized for loop calls */ public static function digits($base) { static $cache; if ($base == 256 && $cache) { return $cache; } if ($base > 64) { $digits = ""; for ($loop = 0; $loop < 256; $loop++) { $digits .= chr($loop); } } else { $digits = "0123456789abcdefghijklmnopqrstuvwxyz"; $digits.="ABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; } $digits = substr($digits, 0, $base); if ($base == 256) { if (!$cache) $cache = (string) $digits; return $cache; } return (string) $digits; } public static function equalbinpad(&$x, &$y) { $xlen = strlen($x); $ylen = strlen($y); $length = max($xlen, $ylen); self::fixedbinpad($x, $length); self::fixedbinpad($y, $length); } public static function fixedbinpad(&$num, $length) { $pad = ''; for ($ii = 0; $ii < $length - strlen($num); $ii++) { $pad .= self::bc2bin('0'); } $num = $pad . $num; } }