Viewing file: Basex.php (11.66 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2003 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Dave Mertens <dmertens@zyprexia.com> | // +----------------------------------------------------------------------+ // // $Id: Basex.php,v 1.6 2003/06/04 14:48:44 et Exp $
require_once "PEAR.php";
if (!defined('MATH_BASEX_MATHEXTENSION')) { if (PEAR::loadExtension('bcmath')) { define('MATH_BASEX_MATHEXTENSION', 'bcmath'); } elseif (PEAR::loadExtension('gmp')) { define('MATH_BASEX_MATHEXTENSION', 'gmp'); } else { define('MATH_BASEX_MATHEXTENSION', 'none'); } }
/** * base X coding class * * I noticed that value of an int is different on most systems. * On my system (linux 2.4.18 with glibc 2.2.5) i can use 8-byte integers * (also called int64 or int8) * On my laptop (Windows 2000) i only could use numbers up to 4-byte (32 bit) * integers. * So you might want to test this first! * * Note that you can without much effort also use the bcmath extentions to * increase the length of your numbers. * * @author Dave Mertens <dmertens@zyprexia.com> * @version 0.3 * @access public * @package Math_Basex * @category Math */ class Math_Basex { /** * @var character base set * @access private; */ var $_baseChars;
/** * @var base length (for binair 2, dec 10, hex 16, yours ??) * @access private; */ var $_length; /** * Constructor for class * * @param tokens string Character base set (Each character is only allowed * once!) * @return void */ function Math_Basex($tokens = "") { //set initial length $this->_length = 0; //if we did get already a character set, set it.. if (!empty($tokens)) { $this->setBase($tokens); } } /** * Change the character base set. Behaves the same way the constructor does. * * @param tokens string Character base set (Each character is only allowed * once!) * @return void * @access public */ function setBase($tokens) { if (!$this->_checkBase($tokens)) { return PEAR::raiseError("Each character is only allowed once"); } $this->_baseChars = $tokens; $this->_length = strlen($tokens); return true; } /** * toBase translates a decimal (base 10) number into your base 'code' * * @param number (int64 or double without floats, both are 8-byte number * types). This allows you to use numbers up to 18446744073709551616. * @return string encoded 'code' of yout decimal number */ function toBase($number) { if (!is_numeric($number)) { return PEAR::raiseError("You must supply a decimal number"); } if ($this->_length == 0) { return PEAR::raiseError("Character base isn't defined yet.."); } if (is_float($number)) { $number = ltrim(sprintf('%22.0f',$number)); }
$code = ""; do { $this->_splitnumber($number, $full, $mod); $code = $this->_getToken($mod) . $code; $number = $full; } while ($number > 0); return $code; } /** * toDecimal decodes the baseX 'code' back to a decimal number * * @param string code to decode * @return int64 decimal (base 10) number */ function todecimal($code) { $length = strlen($code); $total = 0; if (strspn($code, $this->_baseChars) != $length) { return PEAR::raiseError("Your Base X code contains invalid" ." characters"); }
for ($i=0; $i < $length; $i++) { $sum = $this->_getNumber($code[$length - $i - 1]) * $this->_pow($this->_length, $i); $total = $this->_add($total,$sum); } return $total; } /** * Returns the base scale. Note that this is onyl the count of the * characters used for the encoding and decoding. * Please do not use base_convert with this class, because it might result * in rare results * * @access public * @return integer */ function getBase() { return $this->_length; } /** * Validates whether each character is unique * * @param string tokens Character base set * @access private * @return boolean true if all characters are unique */ function _checkBase($tokens) { $length = strlen($tokens); for ($i=0; $i < $length; $i++) { if (substr_count($tokens, $tokens[$i]) > 1) return false; //character is specified more than one time! } //if we come here, all characters are unique return true; } /** * Helper function for encoding function. * * @access private; * @param number integer number to spilt for base conversion * @param full integer non-float, unrounded number (will be passed as * reference) * @param modules float floating number between 0 and 1 * (will be passed as reference) * * @return void */ function _splitNumber($number, &$full, &$modules) { $full = $this->_div($number, $this->_length); $modules = $this->_mod($number, $this->_length); }
/** * Helper function; Returns character at position x * * @param oneDigit integer number between 0 and basex->getBase() * @return character from base character set * @access private; */ function _getToken($oneDigit) { return substr($this->_baseChars, $oneDigit, 1); } /** * Helper function; Returns position of character X * * @param oneDigit string Character in base character set * @return integer number between 0 and basex->getBase() * @access private; */ function _getNumber($oneDigit) { return strpos($this->_baseChars, $oneDigit); }
/** * Add two numbers, utilize Math extensions * * @param mixed a First operand * @param mixed b Second operand * @return mixed * @access private */ function _add($a, $b) { switch (MATH_BASEX_MATHEXTENSION) { case 'bcmath': return bcadd($a, $b); case 'gmp': return gmp_strval(gmp_add($a, $b)); case 'none': return $a + $b; } }
/** * Multiply two numbers, utilize Math extensions * * @param mixed a First operand * @param mixed b Second operand * @return mixed * @access private */ function _mul($a, $b) { switch (MATH_BASEX_MATHEXTENSION) { case 'bcmath': return bcmul($a, $b); case 'gmp': return gmp_strval(gmp_mul($a, $b)); case 'none': return $a * $b; }
}
/** * Return the modulo of two numbers, utilize Math extensions * * @param mixed a First operand * @param mixed b Second operand * @return mixed * @access private */ function _mod($a, $b) { switch (MATH_BASEX_MATHEXTENSION) { case 'bcmath': return bcmod($a, $b); case 'gmp': return gmp_strval(gmp_mod($a, $b)); case 'none': return $a % $b; } }
/** * Divide two integers, utilize Math extensions * * @param mixed a First operand * @param mixed b Second operand * @return mixed * @access private */ function _div($a, $b) { switch (MATH_BASEX_MATHEXTENSION) { case 'bcmath': return bcdiv($a, $b); case 'gmp': return gmp_strval(gmp_div($a, $b)); case 'none': return floor($a / $b); } }
/** * Raise one number to the power of the other, utilize Math extensions * * @param mixed a First operand * @param mixed b Second operand * @return mixed * @access private */ function _pow($a, $b) { switch (MATH_BASEX_MATHEXTENSION) { case 'bcmath': return bcpow($a, $b); case 'gmp': return gmp_strval(gmp_pow($a, $b)); case 'none': return pow($a,$b); } }
/** * Returns a common set of digits (0-9A-Za-z), length is given as parameter * * @param int length Optional How many characters to return, defaults to 62. * @return string * @access public */ function stdBase($n = 62) { return substr("0123456789" ."ABCDEFGHIJKLMNOPQRSTUVWXYZ" ."abcdefghijklmnopqrstuvwxyz", 0, $n); }
/** * Converts a number from one base into another. May be called statically. * * @param mixed number The number to convert * @param int from_base The base to convert from * @param int to_base The base to convert to * @param string from_cs Optional character set of the number that is * converted * @param string to_cs Optional character set of the target number * @return string * @access public */ function baseConvert($number, $from_base, $to_base, $from_cs = null, $to_cs = null) { if (isset($this)) { $obj = &$this; } else { $obj = &Math_Basex::instance(); } if (!isset($from_cs)) { $from_cs = $obj->stdBase(); } if (!isset($to_cs)) { $to_cs = $obj->stdBase(); } if (strlen($from_cs) < $from_base) { return PEAR::raiseError('Character set isn\'t long enough for the' .'given base.'); } if (strlen($to_cs) < $to_base) { return PEAR::raiseError('Character set isn\'t long enough for the' .'given base.'); } $from_cs = substr($from_cs, 0, $from_base); $to_cs = substr($to_cs, 0, $to_base); if ($tmp = $obj->setBase($from_cs) !== true) { return $tmp; } $number = $obj->toDecimal($number); if (PEAR::isError($number)) { return $number; } if ($tmp = $obj->setBase($to_cs) !== true) { return $tmp; } $number = $obj->toBase($number); return $number; }
/** * Singleton method, call statically * * @return object * @access public */ function &instance() { static $ins = null; if (is_null($ins)) { $ins = new Math_Basex; } return $ins; } }
?>
|