Design Decisions

Exactly 128 Bits on Every Platform

The central design goal is that sizeof(uint128) and sizeof(int128) are exactly 16 bytes on every supported platform. The compiler’s __int128 extension is only available on some 64-bit targets and is absent on MSVC, while multiprecision types typically carry an additional word of bookkeeping. By fixing the layout at two 64-bit words, the library provides a drop-in 128-bit integer whose size and alignment match a built-in type where one exists. See Comparison to Boost.Multiprecision for the tradeoffs relative to a multiprecision number.

Intrinsics with a Portable Fallback

Where the compiler provides a native 128-bit integer or a suitable intrinsic, the operators forward to it for native performance. Elsewhere (including MSVC and 32-bit targets) the library uses optimized software implementations over the two 64-bit words. This keeps behavior and results identical across platforms while still taking advantage of hardware support when it is present.

C++14 and constexpr

The library targets C++14 as its minimum standard. Relaxed C++14 constexpr allows nearly all functionality to be evaluated at compile time, so the types can be used in constant expressions much like a built-in integer. Meeting the C++14 bar also satisfies the conceptual requirements of libraries such as Boost.Math and Boost.Random, which this library integrates with directly.

Emulating a Built-in Integer

To behave like a built-in integer in generic code, the types provide implicit conversions to and from the built-in integer and floating-point types, and implicit conversion between int128 and uint128. The single exception is operator bool, which is explicit to match the standard library convention and to avoid unintended participation in arithmetic and overload resolution.

Mixed-sign and mixed-width operations follow the usual arithmetic conversions of the language. In particular, an operation mixing a signed and an unsigned 128-bit operand produces a uint128, identical to the value the equivalent built-in unsigned __int128 operation would produce, with two’s-complement wrap-around. See Mixed Type Operations for the complete result-type rules.

Layout and Alignment

Each type is a struct of two 64-bit words, low and high, whose declaration order depends on the endianness of the target so that the in-memory representation matches a native 128-bit integer. Both words are std::uint64_t in both types; int128 interprets the pair as two’s complement and exposes signed_high() for the sign. Keeping the two halves the same type is what lets a compiler treat the pair as one wide access, so loops over int128 vectorize instead of being scalarized. See Storage and signed_high. When a native 128-bit type is available the struct is over-aligned to match it, except on 32-bit x86 where the native alignment is not forced.

GPU Support

The types and many of the free functions are annotated with BOOST_INT128_HOST_DEVICE so they can be used unchanged in CUDA device code when the library is compiled with BOOST_INT128_ENABLE_CUDA. See Configuration Macros.