LibExcessive provides a suite of fixed-width large integer types (e.g., 128, 256, 512 bits) optimized for high-performance applications that require exact bit-widths without the overhead of dynamic heap allocations. These types behave similarly to built-in C++ integer types but support much larger ranges.
UnsignedFixedWidthBigInt is designed to be a drop-in replacement for standard integers in performance-critical code:
uint64_t
“chunks.”+, -, *, /, %), bitwise (&,
|, ^, ~, <<, >>), and comparison (<, >, ==, etc.) operators.pow), roots (root, sqrt), and signed
operations (even though the type is technically unsigned).double and conversion to/from double with high
precision.#include "bigint.h"
#include <iostream>
void bigintExample() {
// Construct from hex strings
uint256_t a("0xFFCFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
uint256_t b("0x1234567890ABCDEF1234567890ABCDEF");
// Standard arithmetic
uint256_t sum = a + b;
uint256_t prod = a * b;
// Advanced math
uint256_t b_pow_4 = b.pow(4);
uint256_t a_sqrt = a.root(2);
// Conversion to string (produces "0x1204567890ABCDEF1234567890ABCDEE")
std::cout << "Sum: " << std::string(sum) << std::endl;
}
The template parameter N defines the number of 64-bit chunks (e.g., N=4 for a 256-bit integer).
uint128_t: UnsignedFixedWidthBigInt<2>uint192_t: UnsignedFixedWidthBigInt<3>uint256_t: UnsignedFixedWidthBigInt<4>uint384_t: UnsignedFixedWidthBigInt<6>uint512_t: UnsignedFixedWidthBigInt<8>UnsignedFixedWidthBigInt()
UnsignedFixedWidthBigInt(uint64_t value)
UnsignedFixedWidthBigInt(int value)
UnsignedFixedWidthBigInt(const char* s) / UnsignedFixedWidthBigInt(std::string_view s)
0x) as a hexadecimal number.UnsignedFixedWidthBigInt(double value)
UnsignedFixedWidthBigInt(const uint8_t* buffer, bool isBigEndian)
operator+(const UnsignedFixedWidthBigInt<N>& other) constoperator-(const UnsignedFixedWidthBigInt<N>& other) constoperator*(const UnsignedFixedWidthBigInt<N>& other) constoperator/(const UnsignedFixedWidthBigInt<N>& other) constoperator%(const UnsignedFixedWidthBigInt<N>& other) const
operator&(const UnsignedFixedWidthBigInt<N>& other) constoperator|(const UnsignedFixedWidthBigInt<N>& other) constoperator^(const UnsignedFixedWidthBigInt<N>& other) constoperator~() constoperator<<(int n) const / operator>>(int n) const
UnsignedFixedWidthBigInt<N> pow(int power) const
UnsignedFixedWidthBigInt<N> root(int root) const
UnsignedFixedWidthBigInt<N> sar(int n) const
void setBit(int index) / void resetBit(int index) / bool getBit(int index) const
uint16_t countBits() const
operator std::string() const
0x. Leading zeros are omitted.void toStr(char* buffer, bool forceSize = false, bool addPrefix = true) const
forceSize ensures the output matches the full
width of the type, in which case there may be a large number of leading zeros. addPrefix adds the 0x prefix.double toDouble() const
double.operator uint64_t() const (and uint32_t, int)
UnsignedFixedWidthBigInt implements multi-precision arithmetic by treating a large integer as a base-$2^{64}$ number.
The internal state is stored in a union containing an array of uint64_t (the chunks) and a corresponding raw byte
array. Chunks are stored in little-endian order (least significant chunk at index 0), which aligns with common CPU
architectures like x86_64. This layout allows for efficient indexing and interaction with standard integer registers.
N, this is highly efficient._internalBigintFastAdd) that operate directly on pointers, which the compiler can often inline or vectorize.The toDouble and fromDouble conversions work by extracting the most significant bits of the large integer and
adjusting the exponent of the IEEE 754 double-precision format. Multiplication with a double (operator*) is
performed by scaling the large integer in its base-$2^{64}$ form, effectively performing a fixed-point multiplication
where the double provides the scaling factor. This makes double multiplication extremely accurate.