Mixed Type Operations

Conversions

Conversion between the two types is implicit: each type provides a non-explicit converting constructor from the other, so an int128_t converts to a uint128_t (and vice versa) wherever the target type is expected, as documented in the above class descriptions.

Operator Overloads Across Types

All comparison, arithmetic, bitwise, and shift operators are provided across:

  • int128_t and uint128_t (cross-type),

  • int128_t / uint128_t and any built-in integer type (signed or unsigned, including the compiler’s 128-bit __int128 / unsigned __int128 where supported).

The behavior and return type of every mixed-sign overload follow the C++ usual arithmetic conversions, identical to what the equivalent built-in __int128 / unsigned __int128 operation would produce, including two’s-complement wrap-around semantics.

Result Type Rules

Operands Common type Result of arithmetic / bitwise

int128_t and uint128_t (same rank, mixed sign)

uint128_t

uint128_t

int128_t and unsigned __int128 (same rank, mixed sign)

uint128_t

uint128_t

uint128_t and __int128 (same rank, mixed sign)

uint128_t

uint128_t

int128_t and a small unsigned built-in (uint8_t to uint64_t)

int128_t

int128_t

uint128_t and a small signed built-in (int8_t to int64_t)

uint128_t

uint128_t

For shift operators (<<, >>), the result type follows the LHS type regardless of the RHS, matching the built-in shift rules.

For comparison operators (==, !=, <, <=, >, >=), the return type is always bool and the comparison is performed on the operands after they have been converted to the common type above.

Cross-type Operator Signatures

namespace boost {
namespace int128 {

//=====================================
// Comparison Operators
//=====================================

BOOST_INT128_HOST_DEVICE constexpr bool operator==(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator==(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator!=(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator!=(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator<(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator<(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator<=(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator<=(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator>(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator>(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator>=(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator>=(int128_t lhs, uint128_t rhs);

//=====================================
// Arithmetic Operators
//=====================================

BOOST_INT128_HOST_DEVICE constexpr uint128_t operator+(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator+(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator-(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator-(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator*(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator*(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator/(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator/(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator%(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator%(int128_t lhs, uint128_t rhs);

//=====================================
// Bitwise Operators
//=====================================

BOOST_INT128_HOST_DEVICE constexpr uint128_t operator|(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator|(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator&(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator&(int128_t lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator^(uint128_t lhs, int128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator^(int128_t lhs, uint128_t rhs);

//=====================================
// Shift Operators
//=====================================
// Result type follows the LHS.

BOOST_INT128_HOST_DEVICE constexpr int128_t  operator<<(int128_t  lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator<<(uint128_t lhs, int128_t  rhs);
BOOST_INT128_HOST_DEVICE constexpr int128_t  operator>>(int128_t  lhs, uint128_t rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128_t operator>>(uint128_t lhs, int128_t  rhs);

} // namespace int128
} // namespace boost

The cross-type arithmetic and bitwise operators return the same value as static_cast<uint128_t>(lhs) op static_cast<uint128_t>(rhs). The comparison operators return the same value as that expression compared with the matching unsigned operator.

Operations with built-in __int128 / unsigned __int128

When the compiler provides 128-bit built-in integer types, all of the operators above are also available between a library type and the built-in type of opposite signedness (e.g. uint128_t op __int128, unsigned __int128 op int128_t). The result type follows the same rules as the table above (uint128_t for arithmetic and bitwise; the LHS type for shifts; bool for comparisons), and the produced value is identical to what an all-built-in computation would yield.