/** * Determines if the supplied double fits into this float as a subnormal. * * @param Float64 $float The float (represented in 64 bit). * @return boolean Whether the double fits as a subnormal inside this float type. */ public static function fitsAsSubnormal(Float64 $float) { // If the exponent is lower than the lowest subnormal, it can't fit if ($float->getExponent() < 1 - static::getExponentOffset() - static::getNumSignificandBits()) { return false; } // If the exponent is larger than the negative exponent offset, it can't fit if ($float->getExponent() > 1 - static::getExponentOffset()) { return false; } // Make sure the significand (+1 implicit digit) actually fits in the required number of bits if (($float->getSignificand() << 1) + 1 > self::getMaxSignificand()) { return false; } // Trash all the trailing zeros in the significand $significand = $float->getSignificand(); // Convert the significand into a binary string $significand = decbin($significand); // Trim leading zeros $significand = ltrim($significand, '0'); // Add a 1 to the start of the string, it's implicit in normal numbers, but not in subnormals $significand = bindec('1' . $significand); // Determine the number of "exponent bits" you have free $exponentBits = static::getNumSignificandBits() - strlen($significand); // Compute the minimum exponent you can do with those free bits $minExponent = -1 * (static::getExponentOffset() + $exponentBits); // If the exponent fits return $float->getExponent() >= $minExponent; }
/** * Decodes a double value. * * @param int $length Size of the number, in bytes. * @param array $bytes The messages byte array. * @return float The decoded double. * @throws CborException If there aren't enough bytes in the remaining byte string. */ private static function decodeDouble($length, &$bytes) { // Not enough bytes if ($length > count($bytes)) { throw new CborException("The supplied byte string is too short to decode the specified double type."); } // Grab the required number of bytes $byteArray = array_splice($bytes, 0, $length); // Unpack a 32 bit double if ($length == 4) { return Float32::decode($byteArray); } else { if ($length == 8) { return Float64::decode($byteArray); } else { return Float16::decode($byteArray); } } }