/** * Return the ulp for the given float argument. The ulp is the * difference between the argument and the next larger float. Note * that the sign of the float argument is ignored, that is, * ulp(x) == ulp(-x). If the argument is a NaN, then NaN is returned. * If the argument is an infinity, then +Inf is returned. If the * argument is zero (either positive or negative), then * {@link Float#MIN_VALUE} is returned. * * @param float $f * * @return float */ public static function floatULP($f) { if (is_nan($f)) { return $f; } if (is_infinite($f)) { return INF; } // This handles both +0.0 and -0.0. if ($f == 0.0) { return Float . MIN_VALUE; } $bits = Math::floatToParts($f); $mantissa = $bits[2]; $exponent = $bits[1]; // Denormal number, so the answer is easy. if ($bits[1] == 0) { $bits[2] = 1; //set fraction to smallest possible value return Math::partsToFloat($bits); } // Conceptually we want to have '1' as the mantissa. Then we would // shift the mantissa over to make a normal number. If this underflows // the exponent, we will make a denormal result. $bits[1] -= 23; $bits[2] = 0; if ($bits[1] == 0) { $bits[2] = 1 << -($bits[1] - 1); $bits[1] = 0; } return Math::partsToFloat($bits); }