#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <utility>
union Float_t
{
Float_t(float num = 0.0f) : f(num) {}
bool Negative() const { return (i >> 31) != 0; }
std::int32_t RawMantissa() const { return i & ((1 << 23) - 1); }
std::int32_t RawExponent() const { return (i >> 23) & 0xFF; }
std::int32_t i;
float f;
struct
{
std::uint32_t mantissa : 23;
std::uint32_t exponent : 8;
std::uint32_t sign : 1;
} parts;
};
template<typename T>
unsigned int ulpDistance(T value1, T value2)
{
// Simplified version not treating special cases from
// http://stackoverflow.com/questions/13940316/floating-point-comparison-revisited
int minExponent, maxExponent;
T minSignificand = std::frexp(value1, &minExponent);
T maxSignificand = std::frexp(value2, &maxExponent);
if (minExponent > maxExponent) {
std::swap(minSignificand, maxSignificand);
std::swap(minExponent, maxExponent);
}
const T scaledMinSignificand = std::ldexp(
minSignificand, minExponent - maxExponent
);
return 2 * std::abs(maxSignificand - scaledMinSignificand) /
std::numeric_limits<T>::epsilon();
}
int main(int argc, char **argv)
{
Float_t first = 1.999999f;
Float_t number = first.f;
do
{
std::printf(
"float(%1.8e), int(0x%08X), exponent(%d), mantissa(0x%06X)\n",
number.f, number.i,
number.parts.exponent, number.parts.mantissa
);
if (ulpDistance(first.f, number.f) != number.i - first.i) {
std::printf(" %d != %d\n",
ulpDistance(first.f, number.f), number.i - first.i);
}
number.i += 1;
} while (number.f < 2.000001f);
return 0;
}
I2luY2x1ZGUgPGNtYXRoPgojaW5jbHVkZSA8Y3N0ZGRlZj4KI2luY2x1ZGUgPGNzdGRpbnQ+CiNpbmNsdWRlIDxjc3RkaW8+CiNpbmNsdWRlIDxsaW1pdHM+CiNpbmNsdWRlIDx1dGlsaXR5PgoKCnVuaW9uIEZsb2F0X3QKewogICAgRmxvYXRfdChmbG9hdCBudW0gPSAwLjBmKSA6IGYobnVtKSB7fQogICAgCiAgICBib29sIE5lZ2F0aXZlKCkgY29uc3QgeyByZXR1cm4gKGkgPj4gMzEpICE9IDA7IH0KICAgIHN0ZDo6aW50MzJfdCBSYXdNYW50aXNzYSgpIGNvbnN0IHsgcmV0dXJuIGkgJiAoKDEgPDwgMjMpIC0gMSk7IH0KICAgIHN0ZDo6aW50MzJfdCBSYXdFeHBvbmVudCgpIGNvbnN0IHsgcmV0dXJuIChpID4+IDIzKSAmIDB4RkY7IH0KICAgIAogICAgc3RkOjppbnQzMl90IGk7CiAgICBmbG9hdCBmOwogICAgCiAgICBzdHJ1Y3QKICAgIHsKICAgICAgICBzdGQ6OnVpbnQzMl90IG1hbnRpc3NhIDogMjM7CiAgICAgICAgc3RkOjp1aW50MzJfdCBleHBvbmVudCA6IDg7CiAgICAgICAgc3RkOjp1aW50MzJfdCBzaWduIDogMTsKICAgIH0gcGFydHM7Cn07CgoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KdW5zaWduZWQgaW50IHVscERpc3RhbmNlKFQgdmFsdWUxLCBUIHZhbHVlMikKewogICAgLy8gU2ltcGxpZmllZCB2ZXJzaW9uIG5vdCB0cmVhdGluZyBzcGVjaWFsIGNhc2VzIGZyb20KICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTM5NDAzMTYvZmxvYXRpbmctcG9pbnQtY29tcGFyaXNvbi1yZXZpc2l0ZWQKICAgIAogICAgaW50IG1pbkV4cG9uZW50LCBtYXhFeHBvbmVudDsKICAgIFQgbWluU2lnbmlmaWNhbmQgPSBzdGQ6OmZyZXhwKHZhbHVlMSwgJm1pbkV4cG9uZW50KTsKICAgIFQgbWF4U2lnbmlmaWNhbmQgPSBzdGQ6OmZyZXhwKHZhbHVlMiwgJm1heEV4cG9uZW50KTsKICAgIGlmIChtaW5FeHBvbmVudCA+IG1heEV4cG9uZW50KSB7CiAgICAgICAgc3RkOjpzd2FwKG1pblNpZ25pZmljYW5kLCBtYXhTaWduaWZpY2FuZCk7CiAgICAgICAgc3RkOjpzd2FwKG1pbkV4cG9uZW50LCBtYXhFeHBvbmVudCk7CiAgICB9CiAgICAKICAgIGNvbnN0IFQgc2NhbGVkTWluU2lnbmlmaWNhbmQgPSBzdGQ6OmxkZXhwKAogICAgICAgIG1pblNpZ25pZmljYW5kLCBtaW5FeHBvbmVudCAtIG1heEV4cG9uZW50CiAgICApOwogICAgCiAgICByZXR1cm4gMiAqIHN0ZDo6YWJzKG1heFNpZ25pZmljYW5kIC0gc2NhbGVkTWluU2lnbmlmaWNhbmQpIC8KICAgICAgICBzdGQ6Om51bWVyaWNfbGltaXRzPFQ+OjplcHNpbG9uKCk7Cn0KCgppbnQgbWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpCnsKICAgIEZsb2F0X3QgZmlyc3QgPSAxLjk5OTk5OWY7CiAgICBGbG9hdF90IG51bWJlciA9IGZpcnN0LmY7CiAgICAKICAgIGRvCiAgICB7CiAgICAgICAgc3RkOjpwcmludGYoCiAgICAgICAgICAgICJmbG9hdCglMS44ZSksIGludCgweCUwOFgpLCBleHBvbmVudCglZCksIG1hbnRpc3NhKDB4JTA2WClcbiIsCiAgICAgICAgICAgIG51bWJlci5mLCBudW1iZXIuaSwKICAgICAgICAgICAgbnVtYmVyLnBhcnRzLmV4cG9uZW50LCBudW1iZXIucGFydHMubWFudGlzc2EKICAgICAgICApOwogICAgICAgIAogICAgICAgIGlmICh1bHBEaXN0YW5jZShmaXJzdC5mLCBudW1iZXIuZikgIT0gbnVtYmVyLmkgLSBmaXJzdC5pKSB7CiAgICAgICAgICAgIHN0ZDo6cHJpbnRmKCIgICVkICE9ICVkXG4iLAogICAgICAgICAgICAgICAgICAgICAgICB1bHBEaXN0YW5jZShmaXJzdC5mLCBudW1iZXIuZiksIG51bWJlci5pIC0gZmlyc3QuaSk7CiAgICAgICAgfQogICAgICAgIAogICAgICAgIG51bWJlci5pICs9IDE7CiAgICB9IHdoaWxlIChudW1iZXIuZiA8IDIuMDAwMDAxZik7CiAgICAKICAgIHJldHVybiAwOwp9Cg==
float(1.99999905e+00), int(0x3FFFFFF8), exponent(127), mantissa(0x7FFFF8)
float(1.99999917e+00), int(0x3FFFFFF9), exponent(127), mantissa(0x7FFFF9)
float(1.99999928e+00), int(0x3FFFFFFA), exponent(127), mantissa(0x7FFFFA)
float(1.99999940e+00), int(0x3FFFFFFB), exponent(127), mantissa(0x7FFFFB)
float(1.99999952e+00), int(0x3FFFFFFC), exponent(127), mantissa(0x7FFFFC)
float(1.99999964e+00), int(0x3FFFFFFD), exponent(127), mantissa(0x7FFFFD)
float(1.99999976e+00), int(0x3FFFFFFE), exponent(127), mantissa(0x7FFFFE)
float(1.99999988e+00), int(0x3FFFFFFF), exponent(127), mantissa(0x7FFFFF)
float(2.00000000e+00), int(0x40000000), exponent(128), mantissa(0x000000)
4 != 8
float(2.00000024e+00), int(0x40000001), exponent(128), mantissa(0x000001)
5 != 9
float(2.00000048e+00), int(0x40000002), exponent(128), mantissa(0x000002)
6 != 10
float(2.00000072e+00), int(0x40000003), exponent(128), mantissa(0x000003)
7 != 11