#include <iostream>
#include <limits>
#include <cmath>
template <typename precission_t>
struct encoded_floating_point
{
using type = precission_t;
static constexpr auto max { std::numeric_limits<precission_t>::max() };
const int exponent {};
const type mantissa {};
};
using encoded_float = encoded_floating_point<std::uint32_t>;
using encoded_double = encoded_floating_point<std::uint64_t>;
encoded_float encode_f(float value)
{
int exponent {};
encoded_float::type mantissa { encoded_float::max * std::frexp(value, &exponent) };
return {exponent, mantissa};
}
float decode_f(const encoded_float &encoded)
{
return std::ldexp(float {encoded.mantissa} / encoded_float::max, encoded.exponent);
}
encoded_double encode_d(double value)
{
int exponent {};
encoded_double::type mantissa { encoded_double::max * std::frexp(value, &exponent) };
return {exponent, mantissa};
}
double decode_d(const encoded_double &encoded)
{
return std::ldexp(double {encoded.mantissa} / encoded_double::max, encoded.exponent);
}
template <typename FPN> FPN test_numbers[]
{
1. / 3., 2. / 3., 3. / 3., 4. / 3., 5. / 3.,
1. / 6., 2. / 6., 3. / 6., 4. / 6., 5. / 6.,
1. / 7., 2. / 7., 3. / 7., 4. / 7., 5. / 7.,
1. / 9., 2. / 9., 3. / 9., 4. / 9., 5. / 9.,
1. / 11., 2. / 11., 3. / 11., 4. / 11., 5. / 11.,
1. / 13., 2. / 13., 3. / 13., 4. / 13., 5. / 13.
};
int main()
{
std::cout.precision(std::numeric_limits<float>::max_digits10);
for (const auto &f : test_numbers<float>)
{
const auto x = encode_f(f);
std::cout << f << ' ' << x.exponent << ' ' << x.mantissa << '\n'
<< decode_f(x) << '\n' << '\n';
}
std::cout.precision(std::numeric_limits<double>::max_digits10);
for (const auto &d : test_numbers<double>)
{
const auto x = encode_d(d);
std::cout << d << ' ' << x.exponent << ' ' << x.mantissa << '\n'
<< decode_d(x) << '\n' << '\n';
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bGltaXRzPgojaW5jbHVkZSA8Y21hdGg+Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgcHJlY2lzc2lvbl90PgpzdHJ1Y3QgZW5jb2RlZF9mbG9hdGluZ19wb2ludAp7Cgl1c2luZyB0eXBlID0gcHJlY2lzc2lvbl90OwoJc3RhdGljIGNvbnN0ZXhwciBhdXRvIG1heCAgIHsgc3RkOjpudW1lcmljX2xpbWl0czxwcmVjaXNzaW9uX3Q+OjptYXgoKSB9OwoKCWNvbnN0IGludCAgZXhwb25lbnQge307Cgljb25zdCB0eXBlIG1hbnRpc3NhIHt9Owp9OwoKdXNpbmcgZW5jb2RlZF9mbG9hdCAgPSBlbmNvZGVkX2Zsb2F0aW5nX3BvaW50PHN0ZDo6dWludDMyX3Q+Owp1c2luZyBlbmNvZGVkX2RvdWJsZSA9IGVuY29kZWRfZmxvYXRpbmdfcG9pbnQ8c3RkOjp1aW50NjRfdD47CgplbmNvZGVkX2Zsb2F0IGVuY29kZV9mKGZsb2F0IHZhbHVlKQp7CglpbnQgZXhwb25lbnQge307CgllbmNvZGVkX2Zsb2F0Ojp0eXBlIG1hbnRpc3NhIHsgZW5jb2RlZF9mbG9hdDo6bWF4ICogc3RkOjpmcmV4cCh2YWx1ZSwgJmV4cG9uZW50KSB9OwoKCXJldHVybiB7ZXhwb25lbnQsIG1hbnRpc3NhfTsKfQoKZmxvYXQgZGVjb2RlX2YoY29uc3QgZW5jb2RlZF9mbG9hdCAmZW5jb2RlZCkKewoJcmV0dXJuIHN0ZDo6bGRleHAoZmxvYXQge2VuY29kZWQubWFudGlzc2F9IC8gZW5jb2RlZF9mbG9hdDo6bWF4LCBlbmNvZGVkLmV4cG9uZW50KTsKfQoKZW5jb2RlZF9kb3VibGUgZW5jb2RlX2QoZG91YmxlIHZhbHVlKQp7CglpbnQgZXhwb25lbnQge307CgllbmNvZGVkX2RvdWJsZTo6dHlwZSBtYW50aXNzYSB7IGVuY29kZWRfZG91YmxlOjptYXggKiBzdGQ6OmZyZXhwKHZhbHVlLCAmZXhwb25lbnQpIH07CgoJcmV0dXJuIHtleHBvbmVudCwgbWFudGlzc2F9Owp9Cgpkb3VibGUgZGVjb2RlX2QoY29uc3QgZW5jb2RlZF9kb3VibGUgJmVuY29kZWQpCnsKCXJldHVybiBzdGQ6OmxkZXhwKGRvdWJsZSB7ZW5jb2RlZC5tYW50aXNzYX0gLyBlbmNvZGVkX2RvdWJsZTo6bWF4LCBlbmNvZGVkLmV4cG9uZW50KTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEZQTj4gRlBOIHRlc3RfbnVtYmVyc1tdCnsKCTEuIC8gMy4sICAyLiAvIDMuLCAgMy4gLyAzLiwgIDQuIC8gMy4sICA1LiAvIDMuLAoJMS4gLyA2LiwgIDIuIC8gNi4sICAzLiAvIDYuLCAgNC4gLyA2LiwgIDUuIC8gNi4sCgkxLiAvIDcuLCAgMi4gLyA3LiwgIDMuIC8gNy4sICA0LiAvIDcuLCAgNS4gLyA3LiwKCTEuIC8gOS4sICAyLiAvIDkuLCAgMy4gLyA5LiwgIDQuIC8gOS4sICA1LiAvIDkuLAoJMS4gLyAxMS4sIDIuIC8gMTEuLCAzLiAvIDExLiwgNC4gLyAxMS4sIDUuIC8gMTEuLAoJMS4gLyAxMy4sIDIuIC8gMTMuLCAzLiAvIDEzLiwgNC4gLyAxMy4sIDUuIC8gMTMuCn07CgppbnQgbWFpbigpCnsKCXN0ZDo6Y291dC5wcmVjaXNpb24oc3RkOjpudW1lcmljX2xpbWl0czxmbG9hdD46Om1heF9kaWdpdHMxMCk7Cglmb3IgKGNvbnN0IGF1dG8gJmYgOiB0ZXN0X251bWJlcnM8ZmxvYXQ+KQoJewoJCWNvbnN0IGF1dG8geCA9IGVuY29kZV9mKGYpOwoJCXN0ZDo6Y291dCA8PCBmIDw8ICcgJyA8PCB4LmV4cG9uZW50IDw8ICcgJyA8PCB4Lm1hbnRpc3NhIDw8ICdcbicKCSAgICAJICAgICAgPDwgZGVjb2RlX2YoeCkgPDwgJ1xuJyA8PCAnXG4nOwoJfQoKCXN0ZDo6Y291dC5wcmVjaXNpb24oc3RkOjpudW1lcmljX2xpbWl0czxkb3VibGU+OjptYXhfZGlnaXRzMTApOwoJZm9yIChjb25zdCBhdXRvICZkIDogdGVzdF9udW1iZXJzPGRvdWJsZT4pCgl7CgkJY29uc3QgYXV0byB4ID0gZW5jb2RlX2QoZCk7CgkJc3RkOjpjb3V0IDw8IGQgPDwgJyAnIDw8IHguZXhwb25lbnQgPDwgJyAnIDw8IHgubWFudGlzc2EgPDwgJ1xuJwoJICAgIAkgICAgICA8PCBkZWNvZGVfZCh4KSA8PCAnXG4nIDw8ICdcbic7Cgl9CglyZXR1cm4gMDsKfQ==