Several operators cannot be efficiently auto-vectorized, e.g., & | ^. This is because different types are used for Hi and Lo: Hi -> int64_t, Lo -> uint64_t.
Solution 1
For the conversion constructor, we use std::bit_cast. However, this isn’t feasible because C++14 must be supported. But in C++14, there is no constexpr std::bit_cast.
So: Solution 1 -> Trash.
Solution 2
The same base definition is used for int128_t and uint128_t:
struct integer128_base
{
#if BOOST_INT128_ENDIAN_LITTLE_BYTE
uint64_t L{};
uint64_t H{};
#else
uint64_t H{};
uint64_t L{};
#endif
};
struct uint128_t : public integer128_base;
struct int128_t : public integer128_base;
and only the operators distinguish between signed and unsigned when necessary.
see https://godbolt.org/z/enW711M1d
Several operators cannot be efficiently auto-vectorized, e.g., & | ^. This is because different types are used for Hi and Lo: Hi -> int64_t, Lo -> uint64_t.
Solution 1
For the conversion constructor, we use std::bit_cast. However, this isn’t feasible because C++14 must be supported. But in C++14, there is no constexpr std::bit_cast.
So: Solution 1 -> Trash.
Solution 2
The same base definition is used for int128_t and uint128_t:
struct integer128_base
{
#if BOOST_INT128_ENDIAN_LITTLE_BYTE
uint64_t L{};
uint64_t H{};
#else
uint64_t H{};
uint64_t L{};
#endif
};
struct uint128_t : public integer128_base;
struct int128_t : public integer128_base;
and only the operators distinguish between signed and unsigned when necessary.
see https://godbolt.org/z/enW711M1d