A bit of necromancy, since this came up in a web search.
- On Clang and ICX, the
__int128_tand__uint128_ttypes work with no warnings.#ifdef __clang__detects either of them. - On GCC, the
__int128__andunsigned __int128__types work with no warnings, even with-Wpedanticon. So you can remove those#pragma GCC diagnosticcommands. Since several other compilers also define__GNUC__, check this afterward. or test__GNUC >= 10(since other compilers that pretend to be GCC pretend to be a very early version). - MSVC does not have this type, but does support a few AVX intrinsics that can accelerate bitwise operations on 128-bit data, including left-shift, right-shift, and, or and xor. One way to synthesize multiplication would be from SIMD high- and low-word horizontal multiplications of the four 64-bit halves of the two operands.
- C23 now supports
_BitIntandunsigned _BitInt, and some compilers, including Clang, add that as an extension to C++. (This, however, does generate a compiler warning.) - A future implementation that adds support for
int128_twill be required to defineINT128_MAXin<cstdint>/<stdint.h>, so you can check that this is defined, at least before including any other headers that might define it.
Even though support is spotty and compilers do not accept constants larger than UINT64_MAX, the following declarations work for many definitions of these types:
#define INT128_MAX (~((int128_t)1 << 127U))
#define INT128_MIN ((int128_t)1 << 127U)
#define UINT128_MAX ((uint128_t)-1)
#define UINT128_MIN ((uint128_t)0)
With these definitions, GCC 20 and Clang 15 do not support stream output with <<, but do support <format>, so this works (although not in C++14):
std::println("{:L} {:L} {:#x} {:x}", INT128_MAX, INT128_MIN, UINT128_MAX, UINT128_MIN);
Most importantly, if you declare your 16-byte datatype alignas(1516), all atomic operations on it are lock-free on x86_64 and ARM64. This the most practical use for them (given that both targets have other ways to get the high word of 64-bit multiplication).