Current File : //opt/cpanel/ea-php80/root/usr/share/tests/pecl/imagick/util/functions.php |
<?php
// Mirrored from https://github.com/Danack/HexFloat
require_once __DIR__ . "/FloatInfo.php";
require_once __DIR__ . "/Float32Info.php";
use HexFloat\FloatInfo;
use HexFloat\Float32Info;
/**
* Returns a string containing a hexadecimal representation of the given float,
* using 64 bits of info
*
* @param float $number
* @return string
*/
function floathex(float $number)
{
return strrev(unpack('h*', pack('d', $number))[1]);
}
/**
* Returns a string containing a hexadecimal representation of the given float,
* using 32 bits of info
*
* @param float $number
* @return string
*/
function floathex32(float $num)
{
return strrev(unpack('h*', pack('f', $num))[1]);
}
/**
* Convert a floating point number to a FloatInfo object,
* which contains string representations of the float's sign,
* exponent and mantissa
* @param float $num
* @return FloatInfo
*/
function float_info(float $num)
{
$float64 = floathex($num);
//Sign bit: 1 bit
//Exponent: 11 bits
//Significand precision: 53 bits (52 explicitly stored)
$chars = str_split($float64);
// 3 bits from this
$byte1 = hexdec($chars[0]);
// 4 bits from this
$byte2 = hexdec($chars[1]);
// 1 bit from this
$byte3 = hexdec($chars[2]);
$sign = '0';
if ($byte1 >= 8) {
$sign = '1';
}
$exponentString = substr($float64, 0, 3);
$exponentValue = hexdec($exponentString) & 0x7ff;
$exponent = sprintf("%b", $exponentValue);
$exponent = str_pad($exponent, 11, '0', STR_PAD_LEFT);
$mantissa = substr($float64, 2);
$mantissa = hexdec($mantissa) & 0xfffffffffffff;
$mantissa = sprintf("%b", $mantissa);
$mantissa = str_pad($mantissa, 52, '0', STR_PAD_LEFT);
return new FloatInfo(
$sign,
$exponent,
$mantissa
);
}
/**
* Convert a floating point number to a Float32Info object,
* which contains string representations of the float's sign,
* exponent and mantissa
*
* @param float $num
* @return Float32Info
*/
function float_info_32(float $num)
{
$float32 = floathex32($num);
$chars = str_split($float32);
// 3 bits from this
$byte1 = hexdec($chars[0]);
// 4 bits from this
$byte2 = hexdec($chars[1]);
// 1 bit from this
$byte3 = hexdec($chars[2]);
$sign = '0';
if ($byte1 >= 8) {
$sign = '1';
}
$exponent3Bits = ($byte1 & 0x7);
$exponent4Bits = $byte2;
$exponent1Bit = ($byte3 & 0x8) >> 3;
$exponent = ($exponent3Bits << 5) | ($exponent4Bits << 1) | $exponent1Bit;
$exponent = sprintf("%b", $exponent);
$exponent = str_pad($exponent, 8, '0', STR_PAD_LEFT);
$mantissa = substr($float32, 2, 6);
$mantissa = hexdec($mantissa) & 0x7fffff;
$mantissa = sprintf("%b", $mantissa);
$mantissa = str_pad($mantissa, 23, '0', STR_PAD_LEFT);
return new Float32Info(
$sign,
$exponent,
$mantissa
);
}
/**
* Produce a debug string that shows the Sign, Exponent and Mantissa for
* two floating point numbers, using 64bit precision
*
*
* @param float $value1
* @param float $value2
* @return string
*
* Example result
* ┌──────┬─────────────┬──────────────────────────────────────────────────────┐
* │ Sign │ Exponent │ Mantissa │
* │ 0 │ 01111111011 │ 1001100110011001100110011001100110011001100110011010 │
* │ 0 │ 10000011001 │ 0111110101111000010000000100000000000000000000000000 │
* └──────┴─────────────┴──────────────────────────────────────────────────────┘
*
*/
function float_compare(float $value1, float $value2)
{
$float_info_1 = float_info($value1);
$float_info_2 = float_info($value2);
//Sign bit: 1 bit
//Exponent: 11 bits
//Significand precision: 53 bits (52 explicitly stored)
$output = "┌──────┬─────────────┬──────────────────────────────────────────────────────┐\n";
$output .= "│ Sign │ Exponent │ Mantissa │\n";
$format_string = "│ %s │ %s │ %s │\n";
$output .= sprintf($format_string, $float_info_1->getSign(), $float_info_1->getExponent(), $float_info_1->getMantissa());
$output .= sprintf($format_string, $float_info_2->getSign(), $float_info_2->getExponent(), $float_info_2->getMantissa());
$output .= "└──────┴─────────────┴──────────────────────────────────────────────────────┘\n";
return $output;
}
/**
* Produce a debug string that shows the Sign, Exponent and Mantissa for
* two floating point numbers, using 32bit precision
*
* @param float $value1
* @param float $value2
* @return string
*
* Example result
* ┌──────┬──────────┬─────────────────────────┐
* │ Sign │ Exponent │ Mantissa │
* │ 0 │ 01111011 │ 10011001100110011001101 │
* │ 0 │ 10011001 │ 01111101011110000100000 │
* └──────┴──────────┴─────────────────────────┘
*
*/
function float_compare_32(float $value1, float $value2)
{
$float_info_1 = float_info_32($value1);
$float_info_2 = float_info_32($value2);
$output = "┌──────┬──────────┬─────────────────────────┐\n";
$output .= "│ Sign │ Exponent │ Mantissa │\n";
$format_string = "│ %s │ %s │ %s │\n";
$output .= sprintf($format_string, $float_info_1->getSign(), $float_info_1->getExponent(), $float_info_1->getMantissa());
$output .= sprintf($format_string, $float_info_2->getSign(), $float_info_2->getExponent(), $float_info_2->getMantissa());
$output .= "└──────┴──────────┴─────────────────────────┘\n";
return $output;
}