Math
[ class tree: Math ] [ index: Math ] [ all elements ]

Source for file BinaryUtils.php

Documentation is available at BinaryUtils.php

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

Documentation generated on Mon, 11 Mar 2019 14:30:26 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.