Comparison to Boost.Multiprecision
An easy question to ask is why this is a separate library from Boost.Multiprecision, which already provides a 256-bit integer. There are several reasons why:
-
The two types are not the same shape.
boost::multiprecision::uint256_tisnumber<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void>>, which stores a limb count and a sign next to the limbs, sosizeofis larger than 32 bytes and the object representation is not simply the value.uint256is exactly 32 bytes, trivially copyable, and standard layout, so it can bememcpy-ed, written into a packet or a file format, stored in an array that a hardware instruction can load, or handed to a GPU kernel. -
The signed comparison is sharper still.
boost::multiprecision::int256_tisnumber<cpp_int_backend<256, 256, signed_magnitude, checked, void>>: a sign-magnitude representation withcheckedoverflow, whose range is+-(2^256 - 1), one more negative value’s worth wider on the positive side and one narrower on the negative side than a 256-bit two’s-complement type, and whose default arithmetic throwsstd::overflow_errorrather than wrapping.int256is two’s complement over the same fourstd::uint64_t words[4]uint256uses, with range[-2255, 2255 - 1], and it wraps on overflow rather than throwing, matching a built-in signed integer’sis_modulobehavior.boost::mp::int256_tis still the benchmark baseline (see int256 Benchmarks) because no platform has a hardware 256-bit type to compare against instead, not because the two types model the same thing. -
The goal is for this library to be extremely lightweight. It has no Boost dependencies at all, whereas Boost.Multiprecision has a module weight of 25.
-
In Boost.Multiprecision every type is built on the high-level
numbertemplate so that all of the backends interoperate.uint256is a single concrete struct with individually implemented operators, designed to work with and act like the built-in integer types. -
uint256is usable in constant expressions from C++14 onward, and on CUDA and SYCL devices, neither of which acpp_intbacked type supports.
None of that makes this library a replacement for Boost.Multiprecision.
If the width is not fixed, or if more than 256 bits, signed magnitude arithmetic, checked arithmetic, or rational and floating-point backends are needed, Boost.Multiprecision is the right tool.
The library’s own differential tests use boost::multiprecision::uint256_t as the oracle for exactly that reason.