home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / Math / BinaryUtils.php next >
Encoding:
PHP Script  |  2008-07-02  |  24.6 KB  |  889 lines

  1. <?php
  2.  
  3. // {{{ license
  4.  
  5. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
  6. //
  7. // +----------------------------------------------------------------------+
  8. // | PHP Version 4                                                        |
  9. // +----------------------------------------------------------------------+
  10. // | Copyright (c) 1997-2002 The PHP Group                                |
  11. // +----------------------------------------------------------------------+
  12. // | This source file is subject to version 2.0 of the PHP license,       |
  13. // | that is bundled with this package in the file LICENSE, and is        |
  14. // | available at through the world-wide-web at                           |
  15. // | http://www.php.net/license/2_02.txt.                                 |
  16. // | If you did not receive a copy of the PHP license and are unable to   |
  17. // | obtain it through the world-wide-web, please send a note to          |
  18. // | license@php.net so we can mail you a copy immediately.               |
  19. // +----------------------------------------------------------------------+
  20. // | Authors: Markus Nix <mnix@docuverse.de>                              |
  21. // +----------------------------------------------------------------------+
  22. //
  23.  
  24. // }}}
  25.  
  26.  
  27. // {{{ defines
  28. define('MATH_BINARYUTILS_BIG_ENDIAN',    0x0000);
  29. define('MATH_BINARYUTILS_LITTLE_ENDIAN', 0x0001);
  30. // }}}
  31.  
  32.  
  33. /**
  34.  * Class with static helpers for easy handling of bit and byte stuff.
  35.  *
  36.  * @author  Markus Nix <mnix@docuverse.de>
  37.  * @access  public
  38.  * @package Math
  39.  * @version $Id: BinaryUtils.php,v 1.2 2004/09/08 11:56:11 docuverse_de Exp $
  40.  * @static
  41.  */
  42.  
  43. class Math_BinaryUtils
  44. {
  45.     // {{{ add
  46.     /**
  47.      * Binary add.
  48.      *
  49.      * @param  int    $num1
  50.      * @param  int    $num2
  51.      * @access public
  52.      * @static
  53.      */
  54.     function add($num1, $num2)
  55.     {
  56.         $carry = $num1 & $num2;
  57.  
  58.         do {
  59.             $carry = $carry << 1;
  60.             $num1  = $num1 ^ $num2;
  61.             $sum   = $num1 ^ $carry;
  62.             $num2  = $carry;
  63.             $carry = $num1 & $num2;
  64.         } while ($carry != 0);
  65.  
  66.         return $sum;
  67.     }
  68.     // }}}
  69.  
  70.     // {{{ subtract
  71.     /**
  72.      * Binary subtract.
  73.      *
  74.      * @param  int    $num1
  75.      * @param  int    $num2
  76.      * @access public
  77.      * @static
  78.      */
  79.     function subtract($num1, $num2)
  80.     {
  81.         // compute two's compliment
  82.         $num2 =~ $num2;
  83.         $num2 =  Math_BinaryUtils::add($num2, 1);
  84.         $diff =  Math_BinaryUtils::add($num1, $num2);
  85.  
  86.         return $diff;
  87.     }
  88.     // }}}
  89.  
  90.     // {{{ binToDec
  91.     /**
  92.      * Bin to dec conversion.
  93.      *
  94.      * @param  string  $binstring
  95.      * @return int
  96.      * @access public
  97.      * @static
  98.      */
  99.     function binToDec($binstring)
  100.     {
  101.         $decvalue = 0;
  102.  
  103.         for ($i = 0; $i < strlen($binstring); $i++) {
  104.             $decvalue += ((int)substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
  105.         }
  106.  
  107.         return Math_BinaryUtils::_castAsInt($decvalue);
  108.     }
  109.     // }}}
  110.  
  111.     // {{{ decToBin
  112.     /**
  113.      * Dec to bin conversion.
  114.      *
  115.      * @param  int    $number
  116.      * @access public
  117.      * @static
  118.      */
  119.     function decToBin($number)
  120.     {
  121.         while ( $number >= 256 ) {
  122.             $bytes[] = (($number / 256) - (floor($number / 256))) * 256;
  123.             $number  = floor($number / 256);
  124.         }
  125.  
  126.         $bytes[]   = $number;
  127.         $binstring = '';
  128.  
  129.         for ($i = 0; $i < count( $bytes ); $i++) {
  130.             $binstring = (($i == count($bytes) - 1)? decbin($bytes["$i"]) : str_pad(decbin($bytes["$i"]), 8, '0', STR_PAD_LEFT)) . $binstring;
  131.         }
  132.  
  133.         return $binstring;
  134.     }
  135.     // }}}
  136.  
  137.     // {{{ floatToBin
  138.     /**
  139.      * Converts a single-precision floating point number
  140.      * to a 6 byte binary string.
  141.      *
  142.      * @param  float  $num  the float to convert
  143.      * @return string       the binary string representing the float
  144.      * @access public
  145.      * @static
  146.      */
  147.     function floatToBin($num)
  148.     {
  149.         // Save the sign bit.
  150.         $sign = ($num < 0)? 0x8000 : 0x0000;
  151.  
  152.         // Now treat the number as positive...
  153.         if ($num < 0)
  154.             $num = -$num;
  155.  
  156.         // Get the exponent and limit to 15 bits.
  157.         $exponent = (1 + (int)floor(log10($num))) & 0x7FFF;
  158.  
  159.         // Convert the number into a fraction.
  160.         $num /= pow(10, $exponent);
  161.  
  162.         // Now convert the fraction to a 31bit int.
  163.         // We don't use the full 32bits, because the -ve numbers
  164.         // stuff us up -- this results in better than single
  165.         // precision floats, but not as good as double precision.
  166.         $fraction = (int)floor($num * 0x7FFFFFFF);
  167.  
  168.         // Pack the number into a 6 byte binary string
  169.         return Math_BinaryUtils::_decToBin_bytes($sign | $exponent, 2) . Math_BinaryUtils::_decToBin_bytes($fraction, 4);
  170.     }
  171.     // }}}
  172.  
  173.     // {{{ binToFloat
  174.     /**
  175.      * Converts a 6 byte binary string to a single-precision
  176.      * floating point number.
  177.      *
  178.      * @param  string  $data  the binary string to convert
  179.      * @return the floating point number
  180.      * @access public
  181.      * @static
  182.      */
  183.     function binToFloat(&$data)
  184.     {
  185.         // Extract the sign bit and exponent.
  186.         $exponent  = Math_BinaryUtils::_binToDec_length(substr($data, 0, 2), 2);
  187.         $sign      = (($exponent & 0x8000) == 0)? 1 : -1;
  188.         $exponent &= 0x7FFF;
  189.  
  190.         // Extract the fractional part.
  191.         $fraction = Math_BinaryUtils::_binToDec_length(substr($data, 2, 4), 4);
  192.  
  193.         // Return the reconstructed float.
  194.         return $sign * pow(10, $exponent) * $fraction / 0x7FFFFFFF;
  195.     }
  196.     // }}}
  197.  
  198.     // {{{ binToString
  199.     /**
  200.      * Bin to string conversion. For example,
  201.      * return 'hi' for input of '0110100001101001'.
  202.      *
  203.      * @param  string  $binstring
  204.      * @return string
  205.      * @access public
  206.      * @static
  207.      */
  208.     function binToString($binstring)
  209.     {
  210.         $string = '';
  211.         $binstringreversed = strrev($binstring);
  212.  
  213.         for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
  214.             $string = chr(Math_BinaryUtils::binToDec(strrev(substr($binstringreversed, $i, 8)))) . $string;
  215.         }
  216.  
  217.         return $string;
  218.     }
  219.     // }}}
  220.  
  221.     // {{{ decbin_pad
  222.     /**
  223.      * Converts Decimal -> Binary, and left-pads it with $padvalue 0's.
  224.      *
  225.      * @param  int    $inputdec
  226.      * @param  int    $padvalue
  227.      * @return string
  228.      * @access public
  229.      * @static
  230.      */
  231.     function decbin_pad($inputdec, $padvalue)
  232.     {
  233.         return str_pad(decbin($inputdec), $padvalue, "0", STR_PAD_LEFT);
  234.     }
  235.     // }}}
  236.  
  237.     // {{{ binToDec_fraction
  238.     /**
  239.      * Bin to dec conversion with fractions.
  240.      *
  241.      * @return int
  242.      * @access public
  243.      * @static
  244.      */
  245.     function binToDec_fraction($inputfraction)
  246.     {
  247.         $binRep = Math_BinaryUtils::decbin_pad($inputfraction, 8);
  248.         $old    = 0;
  249.  
  250.         for ($i = 8; $i--; $i > 0) {
  251.             $old = ($old + $binRep[$i]) / 2;
  252.         }
  253.  
  254.         return $old;
  255.     }
  256.     // }}}
  257.  
  258.     // {{{ getNativeOrder
  259.     /**
  260.      * Retrieve native byte order of this OS.
  261.      * Little Endian: Intel's 80x86 processors and their clones,
  262.      * Big Endian: SPARC, Motorola's 68K, and the PowerPC families.
  263.      *
  264.      * @access  public
  265.      * @return  int
  266.      * @static
  267.      */
  268.     function getNativeOrder()
  269.     {
  270.         switch (pack('d', 1)) {
  271.         case "\77\360\0\0\0\0\0\0":
  272.             return MATH_BINARYUTILS_BIG_ENDIAN;
  273.  
  274.         case "\0\0\0\0\0\0\360\77":
  275.             return MATH_BINARYUTILS_LITTLE_ENDIAN;
  276.         }
  277.     }
  278.     // }}}
  279.  
  280.     // {{{ littleEndianToString
  281.     /**
  282.      * Little Endian to String conversion.
  283.      *
  284.      * @param  int    $number
  285.      * @param  int    $minbytes
  286.      * @param  bool   $synchsafe
  287.      * @return string
  288.      * @access public
  289.      * @static
  290.      */
  291.     function littleEndianToString($number, $minbytes = 1, $synchsafe = false)
  292.     {
  293.         while ($number > 0) {
  294.             if ($synchsafe) {
  295.                 $intstring = $intstring . chr($number & 127);
  296.                 $number >>= 7;
  297.             } else {
  298.                 $intstring = $intstring . chr($number & 255);
  299.                 $number >>= 8;
  300.             }
  301.         }
  302.  
  303.         return $intstring;
  304.     }
  305.     // }}}
  306.  
  307.     // {{{ bigEndianToString
  308.     /**
  309.      * Big Endian to String conversion.
  310.      *
  311.      * @param  int    $number
  312.      * @param  int    $minbytes
  313.      * @param  bool   $synchsafe
  314.      * @param  bool   $signed
  315.      * @return string
  316.      * @access public
  317.      * @static
  318.      */
  319.     function bigEndianToString($number, $minbytes = 1, $synchsafe = false, $signed = false)
  320.     {
  321.         if ( $number < 0 ) {
  322.             return false;
  323.         }
  324.  
  325.         $maskbyte  = (($synchsafe || $signed)? 0x7F : 0xFF);
  326.         $intstring = '';
  327.  
  328.         if ($signed) {
  329.             if ( $minbytes > 4 ) {
  330.                 return false;
  331.             }
  332.  
  333.             $number = $number & (0x80 << (8 * ($minbytes - 1)));
  334.         }
  335.  
  336.         while ($number != 0) {
  337.             $quotient  = ($number / ($maskbyte + 1));
  338.             $intstring = chr(ceil( ($quotient - floor($quotient)) * $maskbyte)) . $intstring;
  339.             $number    = floor($quotient);
  340.         }
  341.  
  342.         return str_pad($intstring, $minbytes, chr(0), STR_PAD_LEFT);
  343.     }
  344.     // }}}
  345.  
  346.     // {{{ performPack
  347.     /**
  348.      * Perform pack.
  349.      *
  350.      * @param  int    $val
  351.      * @param  int    $bytes
  352.      * @return string
  353.      * @access public
  354.      * @static
  355.      */
  356.     function performPack($val, $bytes = 2)
  357.     {
  358.         for ($ret = '', $i = 0; $i < $bytes; $i++, $val = floor($val / 256)) {
  359.             $ret .= chr($val % 256);
  360.         }
  361.  
  362.         return $ret;
  363.     }
  364.     // }}}
  365.  
  366.     // {{{ performUnpack
  367.     /**
  368.      * Perform unpack.
  369.      *
  370.      * @param  string $val
  371.      * @return int
  372.      * @access public
  373.      * @static
  374.      */
  375.     function performUnpack($val)
  376.     {
  377.         for ($len = strlen($val), $ret = 0, $i = 0; $i < $len; $i++) {
  378.             $ret += (int)ord(substr($val, $i, 1)) * pow(2, 8 * $i);
  379.         }
  380.  
  381.         return $ret;
  382.     }
  383.     // }}}
  384.  
  385.     // {{{ bytestringToGUID
  386.     /**
  387.      * Transform bytestring to GUID.
  388.      *
  389.      * @param  string $byte_str
  390.      * @return string GUID string
  391.      * @access public
  392.      * @static
  393.      */
  394.     function bytestringToGUID($byte_str)
  395.     {
  396.         $guid_str  = strtoupper(str_pad(dechex(ord($byte_str{3} )), 2, '0', STR_PAD_LEFT));
  397.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{2} )), 2, '0', STR_PAD_LEFT));
  398.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{1} )), 2, '0', STR_PAD_LEFT));
  399.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{0} )), 2, '0', STR_PAD_LEFT));
  400.         $guid_str .= '-';
  401.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{5} )), 2, '0', STR_PAD_LEFT));
  402.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{4} )), 2, '0', STR_PAD_LEFT));
  403.         $guid_str .= '-';
  404.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{7} )), 2, '0', STR_PAD_LEFT));
  405.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{6} )), 2, '0', STR_PAD_LEFT));
  406.         $guid_str .= '-';
  407.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{8} )), 2, '0', STR_PAD_LEFT));
  408.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{9} )), 2, '0', STR_PAD_LEFT));
  409.         $guid_str .= '-';
  410.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{10})), 2, '0', STR_PAD_LEFT));
  411.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{11})), 2, '0', STR_PAD_LEFT));
  412.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{12})), 2, '0', STR_PAD_LEFT));
  413.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{13})), 2, '0', STR_PAD_LEFT));
  414.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{14})), 2, '0', STR_PAD_LEFT));
  415.         $guid_str .= strtoupper(str_pad(dechex(ord($byte_str{15})), 2, '0', STR_PAD_LEFT));
  416.  
  417.         return $guid_str;
  418.     }
  419.     // }}}
  420.  
  421.     // {{{ GUIDToBytestring
  422.     /**
  423.      * Transform GUID to bytestring.
  424.      *
  425.      * @param  string $guid_str
  426.      * @return string byte string
  427.      * @access public
  428.      * @static
  429.      */
  430.     function GUIDToBytestring($guid_str)
  431.     {
  432.         // Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
  433.         // first 4 bytes are in little-endian order
  434.         // next 2 bytes are appended in little-endian order
  435.         // next 2 bytes are appended in little-endian order
  436.         // next 2 bytes are appended in big-endian order
  437.         // next 6 bytes are appended in big-endian order
  438.  
  439.         // AaBbCcDd-EeFf-GgHh-IiJj-KkLlMmNnOoPp is stored as this 16-byte string:
  440.         // $Dd $Cc $Bb $Aa $Ff $Ee $Hh $Gg $Ii $Jj $Kk $Ll $Mm $Nn $Oo $Pp
  441.  
  442.         $hexbytechar_str  = chr(hexdec(substr($guid_str,  6, 2)));
  443.         $hexbytechar_str .= chr(hexdec(substr($guid_str,  4, 2)));
  444.         $hexbytechar_str .= chr(hexdec(substr($guid_str,  2, 2)));
  445.         $hexbytechar_str .= chr(hexdec(substr($guid_str,  0, 2)));
  446.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 11, 2)));
  447.         $hexbytechar_str .= chr(hexdec(substr($guid_str,  9, 2)));
  448.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 16, 2)));
  449.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 14, 2)));
  450.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 19, 2)));
  451.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 21, 2)));
  452.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 24, 2)));
  453.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 26, 2)));
  454.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 28, 2)));
  455.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 30, 2)));
  456.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 32, 2)));
  457.         $hexbytechar_str .= chr(hexdec(substr($guid_str, 34, 2)));
  458.  
  459.         return $hexbytechar_str;
  460.     }
  461.     // }}}
  462.  
  463.     // {{{ littleEndianToInt
  464.     /**
  465.      * Little Endian to int conversion.
  466.      *
  467.      * @param  string $byteword
  468.      * @param  bool   $signed
  469.      * @return int
  470.      * @access public
  471.      * @static
  472.      */
  473.     function littleEndianToInt($byteword, $signed = false)
  474.     {
  475.         return Math_BinaryUtils::bigEndianToInt(strrev($byteword), false, $signed);
  476.     }
  477.     // }}}
  478.  
  479.     // {{{ bigEndianToInt
  480.     /**
  481.      * Big Endian to int conversion.
  482.      *
  483.      * @param  string $byteword
  484.      * @param  bool   $synchsafe
  485.      * @param  bool   $signed
  486.      * @return int
  487.      * @access public
  488.      * @static
  489.      */
  490.     function bigEndianToInt($byteword, $synchsafe = false, $signed = false)
  491.     {
  492.         $intvalue = 0;
  493.         $bytewordlen = strlen($byteword);
  494.  
  495.         for ($i = 0; $i < $bytewordlen; $i++) {
  496.             // disregard MSB, effectively 7-bit bytes
  497.             if ($synchsafe) {
  498.                 $intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7);
  499.             } else {
  500.                 $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i));
  501.             }
  502.         }
  503.  
  504.         if ($signed && !$synchsafe) {
  505.             // synchsafe ints are not allowed to be signed
  506.             switch ($bytewordlen) {
  507.             case 1:
  508.  
  509.             case 2:
  510.  
  511.             case 3:
  512.  
  513.             case 4:
  514.                 $signmaskbit = 0x80 << (8 * ($bytewordlen - 1));
  515.  
  516.                 if ($intvalue & $signmaskbit) {
  517.                     $intvalue = 0 - ($intvalue & ($signmaskbit - 1));
  518.                 }
  519.  
  520.                 break;
  521.  
  522.             default:
  523.                 break;
  524.             }
  525.         }
  526.  
  527.         return Math_BinaryUtils::_castAsInt($intvalue);
  528.     }
  529.     // }}}
  530.  
  531.     // {{{ littleEndianToBin
  532.     /**
  533.      * Little Endian to bin conversion.
  534.      *
  535.      * @param  string $byteword
  536.      * @return string
  537.      * @access public
  538.      * @static
  539.      * @note   untested
  540.      */
  541.     function littleEndianToBin($byteword)
  542.     {
  543.         return Math_BinaryUtils::bigEndianToBin(strrev($byteword));
  544.     }
  545.     // }}}
  546.  
  547.     // {{{ bigEndianToBin
  548.     /**
  549.      * Big Endian to bin conversion.
  550.      *
  551.      * @param  string $byteword
  552.      * @return string
  553.      * @access public
  554.      * @static
  555.      */
  556.     function bigEndianToBin($byteword)
  557.     {
  558.         $binvalue    = '';
  559.         $bytewordlen = strlen($byteword);
  560.  
  561.         for ($i = 0; $i < $bytewordlen; $i++) {
  562.             $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
  563.         }
  564.  
  565.         return $binvalue;
  566.     }
  567.     // }}}
  568.  
  569.     // {{{ littleEndianToFloat
  570.     /**
  571.      * Little Endian to float conversion.
  572.      *
  573.      * @param  string $byteword
  574.      * @return mixed  Either float or false on error
  575.      * @access public
  576.      * @static
  577.      */
  578.     function littleEndianToFloat($byteword)
  579.     {
  580.         return Math_BinaryUtils::bigEndianToFloat(strrev($byteword));
  581.     }
  582.     // }}}
  583.  
  584.     // {{{ bigEndianToFloat
  585.     /**
  586.      * Big Endian to float conversion.
  587.      *
  588.      * @param  string $byteword
  589.      * @return mixed  Either float or false on error
  590.      * @access public
  591.      * @static
  592.      */
  593.     function bigEndianToFloat($byteword)
  594.     {
  595.         // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
  596.         // http://www.psc.edu/general/software/packages/ieee/ieee.html
  597.         // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
  598.  
  599.         $bitword = Math_BinaryUtils::bigEndianToBin($byteword);
  600.         $signbit = $bitword{0};
  601.  
  602.         if (strlen($byteword) == 4) { // 32-bit DWORD
  603.             $exponentbits = 8;
  604.             $fractionbits = 23;
  605.         } else if (strlen($byteword) == 8) { // 64-bit QWORD
  606.             $exponentbits = 11;
  607.             $fractionbits = 52;
  608.         } else {
  609.             return false;
  610.         }
  611.  
  612.         $exponentstring = substr($bitword, 1, $exponentbits);
  613.         $fractionstring = substr($bitword, 9, $fractionbits);
  614.  
  615.         $exponent = Math_BinaryUtils::binToDec($exponentstring);
  616.         $fraction = Math_BinaryUtils::binToDec($fractionstring);
  617.  
  618.         if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
  619.             // Not a number
  620.             $float_val = false;
  621.         } else if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) {
  622.             if ($signbit == '1') {
  623.                 $float_val = '-infinity';
  624.             } else {
  625.                 $float_val = '+infinity';
  626.             }
  627.         } else if (($exponent == 0) && ($fraction == 0)) {
  628.             if ($signbit == '1') {
  629.                 $float_val = -0;
  630.             } else {
  631.                 $float_val = 0;
  632.             }
  633.  
  634.             $float_val = ($signbit? 0 : -0);
  635.         } else if (($exponent == 0) && ($fraction != 0)) {
  636.             // These are 'unnormalized' values
  637.             $float_val = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * Math_BinaryUtils::decimalBinaryToFloat($fractionstring);
  638.  
  639.             if ($signbit == '1') {
  640.                 $float_val *= -1;
  641.             }
  642.         } else if ($exponent != 0) {
  643.             $float_val = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + Math_BinaryUtils::decimalBinaryToFloat($fractionstring));
  644.  
  645.             if ($signbit == '1') {
  646.                 $float_val *= -1;
  647.             }
  648.         }
  649.  
  650.         return (float)$float_val;
  651.     }
  652.     // }}}
  653.  
  654.     // {{{ floatToBinaryDecimal
  655.     /**
  656.      * Transform float value to binary decimal.
  657.      *
  658.      * @param  float  $float_val
  659.      * @access public
  660.      * @static
  661.      */
  662.     function floatToBinaryDecimal($float_val)
  663.     {
  664.         $maxbits        = 128; // to how many bits of precision should the calculations be taken?
  665.         $intpart        = Math_BinaryUtils::_truncate($float_val);
  666.         $floatpart      = abs($float_val - $intpart);
  667.         $pointbitstring = '';
  668.  
  669.         while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
  670.             $floatpart      *= 2;
  671.             $pointbitstring .= (string)Math_BinaryUtils::_truncate($floatpart);
  672.             $floatpart      -= Math_BinaryUtils::_truncate($floatpart);
  673.         }
  674.  
  675.         $binarypointnumber = decbin($intpart) . '.' . $pointbitstring;
  676.         return $binarypointnumber;
  677.     }
  678.     // }}}
  679.  
  680.     // {{{ normalizeBinaryPoint
  681.     /**
  682.      * Normalize binary points.
  683.      *
  684.      * @param  string $binarypointnumber
  685.      * @param  int    $maxbits
  686.      * @return array
  687.      * @access public
  688.      * @static
  689.      */
  690.     function normalizeBinaryPoint($binarypointnumber, $maxbits = 52)
  691.     {
  692.         if (strpos($binarypointnumber, '.') === false) {
  693.             $binarypointnumber = '0.' . $binarypointnumber;
  694.         } else if ($binarypointnumber{0} == '.') {
  695.             $binarypointnumber = '0' . $binarypointnumber;
  696.         }
  697.  
  698.         $exponent = 0;
  699.  
  700.         while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
  701.             if (substr($binarypointnumber, 1, 1) == '.') {
  702.                 $exponent--;
  703.                 $binarypointnumber = substr($binarypointnumber, 2, 1) . '.' . substr($binarypointnumber, 3);
  704.             } else {
  705.                 $pointpos  = strpos($binarypointnumber, '.');
  706.                 $exponent += ($pointpos - 1);
  707.  
  708.                 $binarypointnumber = str_replace('.', '', $binarypointnumber);
  709.                 $binarypointnumber = $binarypointnumber{0} . '.' . substr($binarypointnumber, 1);
  710.             }
  711.         }
  712.  
  713.         $binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
  714.  
  715.         return array(
  716.             'normalized' => $binarypointnumber,
  717.             'exponent'   => (int)$exponent
  718.         );
  719.     }
  720.     // }}}
  721.  
  722.     // {{{ decimalBinaryToFloat
  723.     /**
  724.      * Transform decimal binary to float.
  725.      *
  726.      * @param  string $binarynumerator
  727.      * @return float
  728.      * @access public
  729.      * @static
  730.      */
  731.     function decimalBinaryToFloat($binarynumerator)
  732.     {
  733.         $numerator   = Math_BinaryUtils::binToDec($binarynumerator);
  734.         $denominator = Math_BinaryUtils::binToDec(str_repeat('1', strlen($binarynumerator)));
  735.  
  736.         return ($numerator / $denominator);
  737.     }
  738.     // }}}
  739.  
  740.     // {{{ getHexBytes
  741.     /**
  742.      * Get hex bytes.
  743.      *
  744.      * @param  string $string
  745.      * @return string
  746.      * @access public
  747.      * @static
  748.      */
  749.     function getHexBytes($string)
  750.     {
  751.         $ret_str = '';
  752.  
  753.         for ($i = 0; $i < strlen($string); $i++) {
  754.             $ret_str .= str_pad(dechex(ord(substr($string, $i, 1))), 2, '0', STR_PAD_LEFT) . ' ';
  755.         }
  756.  
  757.         return $ret_str;
  758.     }
  759.     // }}}
  760.  
  761.     // {{{ getTextBytes
  762.     /**
  763.      * Get text bytes.
  764.      *
  765.      * @param  string $string
  766.      * @return string
  767.      * @access public
  768.      * @static
  769.      */
  770.     function getTextBytes($string)
  771.     {
  772.         $ret_str = '';
  773.  
  774.         for ($i = 0; $i < strlen($string); $i++ ) {
  775.             if (ord(substr($string, $i, 1)) <= 31 ) {
  776.                 $ret_str .= '   ';
  777.             } else {
  778.                 $ret_str .= ' ' . substr($string, $i, 1) . ' ';
  779.             }
  780.         }
  781.  
  782.         return $ret_str;
  783.     }
  784.     // }}}
  785.  
  786.  
  787.     // private methods
  788.  
  789.     // {{{ _truncate
  790.     /**
  791.      * Tuncates a floating-point number at the decimal point
  792.      * returns int (if possible, otherwise double)
  793.      *
  794.      * @param  float   $float_val
  795.      * @return int
  796.      * @access private
  797.      * @static
  798.      */
  799.     function _truncate($float_val)
  800.     {
  801.         if ($float_val >= 1) {
  802.             $truncatednumber = floor($float_val);
  803.         } else if ($float_val <= -1) {
  804.             $truncatednumber = ceil($float_val);
  805.         } else {
  806.             $truncatednumber = 0;
  807.         }
  808.  
  809.         if ($truncatednumber <= pow(2, 30)) {
  810.             $truncatednumber = (int)$truncatednumber;
  811.         }
  812.  
  813.         return $truncatednumber;
  814.     }
  815.     // }}}
  816.  
  817.     // {{{ _castAsInt
  818.     /**
  819.      * Convert a float to type int, only if possible.
  820.      *
  821.      * @param  float   $float_val
  822.      * @return int
  823.      * @access private
  824.      * @static
  825.      */
  826.     function _castAsInt($float_val)
  827.     {
  828.         if (Math_BinaryUtils::_truncate($float_val) == $float_val) {
  829.             // it's not floating point
  830.             if ($float_val <= pow(2, 30)) {
  831.                 // it's within int range
  832.                 $float_val = (int)$float_val;
  833.             }
  834.         }
  835.  
  836.         return $float_val;
  837.     }
  838.     // }}}
  839.  
  840.     // {{{ _decToBin_bytes
  841.     /**
  842.      * Converts an int to a binary string, low byte first.
  843.      *
  844.      * @param  int     $num    number to convert
  845.      * @param  int     $bytes  minimum number of bytes to covert to
  846.      * @return string  the binary string form of the number
  847.      * @access private
  848.      * @static
  849.      */
  850.     function _decToBin_bytes($num, $bytes)
  851.     {
  852.         $result = "";
  853.  
  854.         for ($i = 0; $i < $bytes; ++$i) {
  855.             $result .= chr($num & 0xFF);
  856.             $num = $num >> 8;
  857.         }
  858.  
  859.         return $result;
  860.     }
  861.     // }}}
  862.  
  863.     // {{{ _binToDec_length
  864.     /**
  865.      * Converts a binary string to an int, low byte first.
  866.      *
  867.      * @param  string  $str   binary string to convert
  868.      * @param  int     $len   length of the binary string to convert
  869.      * @return int     the int version of the binary string
  870.      * @access private
  871.      * @static
  872.      */
  873.     function _binToDec_length(&$str, $len)
  874.     {
  875.         $shift  = 0;
  876.         $result = 0;
  877.  
  878.         for ($i = 0; $i < $len; ++$i) {
  879.             $result |= (@ord($str[$i]) << $shift);
  880.             $shift  += 8;
  881.         }
  882.  
  883.         return $result;
  884.     }
  885.     // }}}
  886. }
  887.  
  888. ?>
  889.