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;
278 /* ***** BEGIN LICENSE BLOCK *****
279 * Version: MPL 1.1/GPL 2.0/LGPL 2.1/Apache 2.0
281 * The contents of this file are subject to the Mozilla Public License Version
282 * 1.1 (the "License"); you may not use this file except in compliance with
283 * the License. You may obtain a copy of the License at
284 * http://www.mozilla.org/MPL/
286 * Software distributed under the License is distributed on an "AS IS" basis,
287 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
288 * for the specific language governing rights and limitations under the
291 * The Original Code is LoomClient PHP library
293 * The Initial Developer of the Original Code is
295 * Portions created by the Initial Developer are Copyright (C) 2008
296 * the Initial Developer. All Rights Reserved.
299 * Bill St. Clair <bill@billstclair.com>
301 * Alternatively, the contents of this file may be used under the
302 * terms of the GNU General Public License Version 2 or later (the
303 * "GPL"), the GNU Lesser General Public License Version 2.1 or later
304 * (the "LGPL"), or The Apache License Version 2.0 (the "AL"), in
305 * which case the provisions of the GPL, LGPL, or AL are applicable
306 * instead of those above. If you wish to allow use of your version of
307 * this file only under the terms of the GPL, the LGPL, or the AL, and
308 * not to allow others to use your version of this file under the
309 * terms of the MPL, indicate your decision by deleting the provisions
310 * above and replace them with the notice and other provisions
311 * required by the GPL or the LGPL. If you do not delete the
312 * provisions above, a recipient may use your version of this file
313 * under the terms of any one of the MPL, the GPL the LGPL, or the AL.
314 ****** END LICENSE BLOCK ***** */