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 (link 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]));
78 //// INTERNAL ROUTINES
80 // These routines operate on only one byte. They are used to
81 // implement _bcbitwise_internal.
83 function _bcand($x, $y)
88 function _bcor($x, $y)
93 function _bcxor($x, $y)
98 // _bcbitwise_internal - The majority of the code that implements
99 // the bitwise functions bcand, bcor, and bcxor.
101 // arguments - $x and $y are the operands (in decimal format),
102 // and $op is the name of one of the three
103 // internal functions, _bcand, _bcor, or _bcxor.
106 // see also - The interfaces to this function: bcand, bcor,
109 function _bcbitwise_internal($x, $y, $op)
114 // Pad $bx and $by so that both are the same length.
116 equalbinpad($bx, $by);
121 for($ix = 0; $ix < strlen($bx); $ix++
)
123 $xd = substr($bx, $ix, 1);
124 $yd = substr($by, $ix, 1);
125 $ret .= call_user_func($op, $xd, $yd);
131 // equalbinpad - Pad the operands on the most-significant end
132 // so they have the same number of bytes.
134 // arguments - $x and $y, binary-format numbers (converted
135 // from decimal format with bc2bin()), passed
138 // notes - Both operands are modified by this function.
140 function equalbinpad(&$x, &$y)
145 $length = max($xlen, $ylen);
146 fixedbinpad($x, $length);
147 fixedbinpad($y, $length);
150 // fixedbinpad - Pad a binary number up to a certain length
152 // arguments - $num: The operand to be padded.
154 // - $length: The desired minimum length for
157 // notes - $num is modified by this function.
159 function fixedbinpad(&$num, $length)
162 for($ii = 0; $ii < $length-strlen($num); $ii++
)
170 // bc2bin - Convert a decimal number to the internal
171 // binary format used by this library.
173 // return value - The binary representation of $num.
175 function bc2bin($num)
177 return dec2base($num, MAX_BASE
);
180 // bin2bc - Reverse of bc2bin
182 function bin2bc($num)
184 return base2dec($num, MAX_BASE
);
187 // convert a decimal value to any other base value
188 function dec2base($dec,$base,$digits=FALSE) {
189 if($base<2 or $base>256) die("Invalid Base: ".$base);
192 if(!$digits) $digits=digits($base);
193 while($dec>$base-1) {
194 $rest=bcmod($dec,$base);
195 $dec=bcdiv($dec,$base);
196 $value=$digits[$rest].$value;
198 $value=$digits[intval($dec)].$value;
199 return (string) $value;
202 // convert another base value to its decimal value
203 function base2dec($value,$base,$digits=FALSE) {
204 if($base<2 or $base>256) die("Invalid Base: ".$base);
206 if($base<37) $value=strtolower($value);
207 if(!$digits) $digits=digits($base);
208 $size=strlen($value);
210 for($loop=0;$loop<$size;$loop++
) {
211 $element=strpos($digits,$value[$loop]);
212 $power=bcpow($base,$size-$loop-1);
213 $dec=bcadd($dec,bcmul($element,$power));
215 return (string) $dec;
218 function digits($base) {
221 for($loop=0;$loop<256;$loop++
) {
225 $digits ="0123456789abcdefghijklmnopqrstuvwxyz";
226 $digits.="ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
228 $digits=substr($digits,0,$base);
229 return (string) $digits;