How to Use absl::int128 and absl::uint128 in Abseil-C++
absl::int128 and absl::uint128 are portable 128-bit integer types that provide full arithmetic support, implicit construction from integrals, and utility functions for splitting values into 64-bit halves, backed by native compiler intrinsics when available.
The Abseil-C++ library delivers robust 128-bit integer arithmetic through absl::int128 and absl::uint128, defined in absl/numeric/int128.h. These types ensure consistent behavior across compilers, automatically utilizing native __int128 support when present or falling back to a software implementation using dual 64-bit halves.
What Are absl::int128 and absl::uint128?
Design Overview and Portability
Both types are declared in [absl/numeric/int128.h](https://github.com/abseil/abseil-cpp/blob/master/absl/numeric/int128.h). absl::uint128 provides a full-featured unsigned 128-bit integer interface, while absl::int128 serves as its signed counterpart. The forward declaration for the signed variant appears at line 60.
When the compiler defines ABSL_HAVE_INTRINSIC_INT128—indicating native __int128 support—Abseil implements these types as alignas wrappers around the built-in compiler type. This guarantees binary-compatible layout with zero abstraction overhead. On platforms without native support, the implementation uses a composite structure storing separate high and low 64-bit values.
Core API and Usage Patterns
Construction and Initialization
The types support implicit construction from any integral type. As implemented at lines 15-21, you can initialize values directly:
absl::uint128 u = 42; // implicit from int
absl::int128 i = -42; // signed construction
absl::uint128 v = absl::MakeUint128(1, 0); // high=1, low=0
The absl::MakeUint128(high, low) function constructs a uint128 from two 64-bit parts, declared just after line 100.
Explicit Conversion Operators
When narrowing to smaller types, use static_cast or the explicit conversion operators defined at lines 44-66:
uint64_t lower = static_cast<uint64_t>(u); // truncates to low 64 bits
int64_t signed_part = static_cast<int64_t>(i);
Arithmetic and Bitwise Operations
All standard operators are provided starting around line 74. This includes assignment operators (+=, -=, *=, etc.) and their non-assignment forms (+, -, *, /, %, <<, >>, &, |, ^).
absl::uint128 sum = u + v;
absl::uint128 prod = u * 2;
absl::int128 diff = i - absl::int128(u);
absl::uint128 shifted = u << 64;
Accessing 64-bit Halves
Extract the high and low 64-bit components using the friend functions declared at lines 92-99:
uint64_t low = absl::Uint128Low64(u); // extracts bits 0-63
uint64_t high = absl::Uint128High64(u); // extracts bits 64-127
Integration with Abseil Components
The 128-bit types integrate throughout the Abseil codebase:
- String parsing: Used in [
absl/strings/numbers.h](https://github.com/abseil/abseil-cpp/blob/master/absl/strings/numbers.h) for high-precision integer conversion (seeFastIntToBufferat line 206). - Random number generation: Wide multiplication in [
absl/random/internal/wide_multiply.h](https://github.com/abseil/abseil-cpp/blob/master/absl/random/internal/wide_multiply.h) utilizesMultiplyU128ToU256at line 58 to produce 256-bit results from 128-bit inputs. - String formatting: Formatting support resides in [
absl/strings/internal/str_format/arg.h](https://github.com/abseil/abseil-cpp/blob/master/absl/strings/internal/str_format/arg.h) viaFormatConvertImploverloads at lines 334-336.
Complete Working Example
The following example demonstrates construction, arithmetic, component extraction, and basic output:
#include "absl/numeric/int128.h"
#include <iostream>
int main() {
// Construction
absl::uint128 u1 = 1; // implicit from int
absl::uint128 u2 = absl::MakeUint128(0, 5); // high=0, low=5
absl::int128 i1 = -42; // signed construction
// Arithmetic
absl::uint128 sum = u1 + u2; // 6
absl::uint128 prod = u1 * u2; // 5
absl::int128 diff = i1 - absl::int128(u1); // -43
// Access halves
uint64_t low = absl::Uint128Low64(u2); // 5
uint64_t high = absl::Uint128High64(u2); // 0
// Output (cast to 64-bit for demonstration; use absl::StrCat for full precision)
std::cout << "sum = " << static_cast<unsigned long long>(sum) << '\n';
std::cout << "high=" << high << " low=" << low << '\n';
}
Summary
absl::int128andabsl::uint128provide portable 128-bit arithmetic inabsl/numeric/int128.h, wrapping native__int128when available viaABSL_HAVE_INTRINSIC_INT128.- Construction supports implicit integral conversion and explicit 64-bit pair assembly via
absl::MakeUint128(). - Operations include all standard arithmetic, bitwise, and shift operators with full assignment support.
- Component access uses
absl::Uint128Low64()andabsl::Uint128High64()to extract 64-bit halves. - Integration extends to string parsing, random number generation, and formatting throughout the Abseil library.
Frequently Asked Questions
How do I convert absl::int128 to a string?
While direct std::cout support requires casting to a smaller type, the recommended approach uses Abseil's string formatting utilities. According to the implementation in absl/strings/internal/str_format/arg.h, you can use absl::StrCat() or absl::Format() which provide overloads for int128 and uint128 types at lines 334-336.
What is the difference between absl::int128 and compiler-native __int128?
When ABSL_HAVE_INTRINSIC_INT128 is defined, absl::int128 is merely an alignas wrapper around the compiler's native __int128, ensuring zero overhead and binary compatibility. On compilers without native support, Abseil provides a complete software implementation using two 64-bit integers, ensuring portability at the cost of software emulation.
How do I construct an absl::uint128 from two 64-bit values?
Use the absl::MakeUint128(high, low) function declared in absl/numeric/int128.h just after line 100. The first parameter becomes the high 64 bits, and the second becomes the low 64 bits: auto val = absl::MakeUint128(0x1234, 0x5678);.
Does absl::int128 support constexpr construction?
Yes, the constructors and many operations are constexpr compatible where supported by the compiler, allowing compile-time computation with 128-bit values. The implicit constructors at lines 15-21 and conversion operators enable constant expression usage in appropriate contexts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →