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 converts to a uint128 (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 and uint128 (cross-type),

  • int128 / uint128 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 and uint128 (same rank, mixed sign)

uint128

uint128

int128 and unsigned __int128 (same rank, mixed sign)

uint128

uint128

uint128 and __int128 (same rank, mixed sign)

uint128

uint128

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

int128

int128

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

uint128

uint128

For shift operators (<<, >>), the result type follows the LHS type regardless of the RHS, matching the built-in shift rules. A shift count that is negative or greater than or equal to 128 (the width of the shifted operand) is undefined behavior, exactly as for the built-in shift operators; see the shift operator reference for the precise 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 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator==(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator!=(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator!=(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator<(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator<(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator<=(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator<=(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator>(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator>(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator>=(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr bool operator>=(int128 lhs, uint128 rhs);

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

BOOST_INT128_HOST_DEVICE constexpr uint128 operator+(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator+(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator-(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator-(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator*(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator*(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator/(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator/(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator%(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator%(int128 lhs, uint128 rhs);

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

BOOST_INT128_HOST_DEVICE constexpr uint128 operator|(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator|(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator&(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator&(int128 lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator^(uint128 lhs, int128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator^(int128 lhs, uint128 rhs);

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

BOOST_INT128_HOST_DEVICE constexpr int128  operator<<(int128  lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator<<(uint128 lhs, int128  rhs);
BOOST_INT128_HOST_DEVICE constexpr int128  operator>>(int128  lhs, uint128 rhs);
BOOST_INT128_HOST_DEVICE constexpr uint128 operator>>(uint128 lhs, int128  rhs);

} // namespace int128
} // namespace boost

The cross-type arithmetic and bitwise operators return the same value as static_cast<uint128>(lhs) op static_cast<uint128>(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 op __int128, unsigned __int128 op int128). The result type follows the same rules as the table above (uint128 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.