3 // Bitwise math of arbitrary precision numbers.
4 // From http://cct.me.ntut.edu.tw/chchting/aiahtm/computer/phphelp/ref.bc.php.htm
6 // MAX_BASE is the maximum base that can be represented in
7 // one byte on the host machine. On most modern systems, this
8 // value can be 256, but if there are still any systems with 7-bit
9 // bytes out there, you should use 128 for maximum
12 define('MAX_BASE', 256);
14 //// INTERFACE ROUTINES:
18 function bcand($x, $y)
20 return _bcbitwise_internal($x, $y, '_bcand');
27 return _bcbitwise_internal($x, $y, '_bcor');
32 function bcxor($x, $y)
34 return _bcbitwise_internal($x, $y, '_bcxor');
39 function bcleftshift($num, $shift)
41 return bcmul($num, bcpow(2, $shift), 0);
46 function bcrightshift($num, $shift)
48 return bcdiv($num, bcpow(2, $shift), 0);
51 // Convert decimal to hex (like PHP's builtin dechex)
53 function bcdechex($num)
57 $byte = bcand($num, 255);
59 if (strlen($hex) == 1) $hex = '0' . $hex;
61 $num = bcrightshift($num, 8);
63 if ($res == '') $res = 0;
67 // Convert hex to decimal (like PHP's builtin hexdec)
69 function bchexdec($hex) {
71 for ($i=0; $i<strlen($hex); $i++
) {
72 $res = bcadd(bcleftshift($res, 4), hexdec($hex[$i]));
77 // Convert args from hex and result to hex of a bcxxx operation.
79 function bcashex($operation, $x, $y) {
82 return bcdechex($operation($x, $y));
85 // Hex version of all the operators
87 function bcandhex($x, $y) {
88 return bcashex('bcand', $x, $y);
91 function bcorhex($x, $y) {
92 return bcashex('bcor', $x, $y);
95 function bcxorhex($x, $y) {
96 return bcashex('bcxor', $x, $y);
99 function bcleftshifthex($x, $y) {
100 return bcashex('bcleftshift', $x, $y);
103 function bcrightshifthex($x, $y) {
104 return bcashex('bcrightshift', $x, $y);
107 function bcaddhex($x, $y) {
108 return bcashex('bcadd', $x, $y);
111 function bcsubhex($x, $y) {
112 return bcashex('bcsub', $x, $y);
115 function bcmulhex($x, $y) {
116 return bcashex('bcmul', $x, $y);
119 function bcdivhex($x, $y) {
120 return bcashex('bcdiv', $x, $y);
124 //// INTERNAL ROUTINES
126 // These routines operate on only one byte. They are used to
127 // implement _bcbitwise_internal.
129 function _bcand($x, $y)
134 function _bcor($x, $y)
139 function _bcxor($x, $y)
144 // _bcbitwise_internal - The majority of the code that implements
145 // the bitwise functions bcand, bcor, and bcxor.
147 // arguments - $x and $y are the operands (in decimal format),
148 // and $op is the name of one of the three
149 // internal functions, _bcand, _bcor, or _bcxor.
152 // see also - The interfaces to this function: bcand, bcor,
155 function _bcbitwise_internal($x, $y, $op)
160 // Pad $bx and $by so that both are the same length.
162 equalbinpad($bx, $by);
167 for($ix = 0; $ix < strlen($bx); $ix++
)
169 $xd = substr($bx, $ix, 1);
170 $yd = substr($by, $ix, 1);
171 $ret .= call_user_func($op, $xd, $yd);
177 // equalbinpad - Pad the operands on the most-significant end
178 // so they have the same number of bytes.
180 // arguments - $x and $y, binary-format numbers (converted
181 // from decimal format with bc2bin()), passed
184 // notes - Both operands are modified by this function.
186 function equalbinpad(&$x, &$y)
191 $length = max($xlen, $ylen);
192 fixedbinpad($x, $length);
193 fixedbinpad($y, $length);
196 // fixedbinpad - Pad a binary number up to a certain length
198 // arguments - $num: The operand to be padded.
200 // - $length: The desired minimum length for
203 // notes - $num is modified by this function.
205 function fixedbinpad(&$num, $length)
208 for($ii = 0; $ii < $length-strlen($num); $ii++
)
216 // bc2bin - Convert a decimal number to the internal
217 // binary format used by this library.
219 // return value - The binary representation of $num.
221 function bc2bin($num)
223 return dec2base($num, MAX_BASE
);
226 // bin2bc - Reverse of bc2bin
228 function bin2bc($num)
230 return base2dec($num, MAX_BASE
);
233 // convert a decimal value to any other base value
234 function dec2base($dec,$base,$digits=FALSE) {
235 if($base<2 or $base>256) die("Invalid Base: ".$base);
238 if(!$digits) $digits=digits($base);
239 while($dec>$base-1) {
240 $rest=bcmod($dec,$base);
241 $dec=bcdiv($dec,$base);
242 $value=$digits[$rest].$value;
244 $value=$digits[intval($dec)].$value;
245 return (string) $value;
248 // convert another base value to its decimal value
249 function base2dec($value,$base,$digits=FALSE) {
250 if($base<2 or $base>256) die("Invalid Base: ".$base);
252 if($base<37) $value=strtolower($value);
253 if(!$digits) $digits=digits($base);
254 $size=strlen($value);
256 for($loop=0;$loop<$size;$loop++
) {
257 $element=strpos($digits,$value[$loop]);
258 $power=bcpow($base,$size-$loop-1);
259 $dec=bcadd($dec,bcmul($element,$power));
261 return (string) $dec;
264 function digits($base) {
267 for($loop=0;$loop<256;$loop++
) {
271 $digits ="0123456789abcdefghijklmnopqrstuvwxyz";
272 $digits.="ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
274 $digits=substr($digits,0,$base);
275 return (string) $digits;