PageRenderTime 56ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/Math/BinaryUtils.php

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