New article: Trubanc Server Working
[loomclient.git] / bcbitwise.php
blob529026737a92cfed5f0fdf7784a2769ce41317a5
1 <?php
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
10 // portability.
12 define('MAX_BASE', 256);
14 //// INTERFACE ROUTINES:
16 // Bitwise AND
18 function bcand($x, $y)
20 return _bcbitwise_internal($x, $y, '_bcand');
23 // Bitwise OR
25 function bcor($x, $y)
27 return _bcbitwise_internal($x, $y, '_bcor');
30 // Bitwise XOR
32 function bcxor($x, $y)
34 return _bcbitwise_internal($x, $y, '_bcxor');
37 // Left shift (<<)
39 function bcleftshift($num, $shift)
41 return bcmul($num, bcpow(2, $shift), 0);
44 // Right shift (>>)
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)
55 $res = "";
56 while ($num != '0') {
57 $byte = bcand($num, 255);
58 $hex = dechex($byte);
59 if (strlen($hex) == 1) $hex = '0' . $hex;
60 $res = $hex . $res;
61 $num = bcrightshift($num, 8);
63 if ($res == '') $res = 0;
64 return $res;
67 // Convert hex to decimal (like PHP's builtin hexdec)
69 function bchexdec($hex) {
70 $res = 0;
71 for ($i=0; $i<strlen($hex); $i++) {
72 $res = bcadd(bcleftshift($res, 4), hexdec($hex[$i]));
74 return $res;
77 // Convert args from hex and result to hex of a bcxxx operation.
79 function bcashex($operation, $x, $y) {
80 $x = bchexdec($x);
81 $y = bchexdec($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)
131 return $x & $y;
134 function _bcor($x, $y)
136 return $x | $y;
139 function _bcxor($x, $y)
141 return $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,
153 // and bcxor
155 function _bcbitwise_internal($x, $y, $op)
157 $bx = bc2bin($x);
158 $by = bc2bin($y);
160 // Pad $bx and $by so that both are the same length.
162 equalbinpad($bx, $by);
164 $ix=0;
165 $ret = '';
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);
174 return bin2bc($ret);
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
182 // by reference.
184 // notes - Both operands are modified by this function.
186 function equalbinpad(&$x, &$y)
188 $xlen = strlen($x);
189 $ylen = strlen($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
201 // $num
203 // notes - $num is modified by this function.
205 function fixedbinpad(&$num, $length)
207 $pad = '';
208 for($ii = 0; $ii < $length-strlen($num); $ii++)
210 $pad .= bc2bin('0');
213 $num = $pad . $num;
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);
236 bcscale(0);
237 $value="";
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);
251 bcscale(0);
252 if($base<37) $value=strtolower($value);
253 if(!$digits) $digits=digits($base);
254 $size=strlen($value);
255 $dec="0";
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) {
265 if($base>64) {
266 $digits="";
267 for($loop=0;$loop<256;$loop++) {
268 $digits.=chr($loop);
270 } else {
271 $digits ="0123456789abcdefghijklmnopqrstuvwxyz";
272 $digits.="ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
274 $digits=substr($digits,0,$base);
275 return (string) $digits;