ArkScript
A small, fast, functional and scripting language for video games
IEEE754Serializer.hpp
Go to the documentation of this file.
1#ifndef ARK_COMPILER_SERIALIZATION_IEEE754SERIALIZER_HPP
2#define ARK_COMPILER_SERIALIZATION_IEEE754SERIALIZER_HPP
3
4#include <climits>
5#include <cmath>
6#include <limits>
7#include <vector>
8#include <bit>
9
11{
12 // Narrowing conversion from long long to double, 9223372036854775807 becomes 9223372036854775808.
13 // This gives us an error margin of 1.08420217248550443400745280086994171142578125 * 10^-19,
14 // which is acceptable.
15 static constexpr auto MaxLong = static_cast<double>(std::numeric_limits<std::int64_t>::max());
16
17#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
18 template <class T>
19 constexpr T bswap(T i)
20 {
21 return i;
22 }
23#else
24 // https://stackoverflow.com/a/36937049/21584
25 template <class T, std::size_t... N>
26 constexpr T bswap_impl(T i, std::index_sequence<N...>)
27 {
28 return (((i >> N * CHAR_BIT & static_cast<std::uint8_t>(-1)) << (sizeof(T) - 1 - N) * CHAR_BIT) | ...);
29 }
30 template <class T, class U = std::make_unsigned_t<T>>
31 constexpr T bswap(T i)
32 {
33 return std::bit_cast<T>(bswap_impl<U>(std::bit_cast<U>(i), std::make_index_sequence<sizeof(T)> {}));
34 }
35#endif
36
38 {
39 int32_t exponent;
40 int64_t mantissa;
41 };
42
43 [[nodiscard]] inline DecomposedDouble serialize(const double n)
44 {
45 int exp = 0;
46 const auto mant = static_cast<std::int64_t>(MaxLong * std::frexp(n, &exp));
47
48 return DecomposedDouble {
49 .exponent = std::bit_cast<int32_t>(bswap(exp)),
50 .mantissa = bswap(mant)
51 };
52 }
53
54 [[nodiscard]] inline double deserialize(const DecomposedDouble d)
55 {
56 return std::ldexp(static_cast<double>(bswap(d.mantissa)) / MaxLong, std::bit_cast<int32_t>(bswap(d.exponent)));
57 }
58}
59
60#endif // ARK_COMPILER_SERIALIZATION_IEEE754SERIALIZER_HPP
DecomposedDouble serialize(const double n)
double deserialize(const DecomposedDouble d)
static constexpr auto MaxLong