Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:ClickHouse ClickHouse Wide Integer Impl

From Leeroopedia
Revision as of 14:38, 16 February 2026 by Admin (talk | contribs) (Auto-imported from implementations/ClickHouse_ClickHouse_Wide_Integer_Impl.md)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)


Knowledge Sources
Domains Numeric_Types, Arithmetic
Last Updated 2026-02-08 00:00 GMT

Overview

A template-based implementation of arbitrary-width integers (128-bit, 256-bit, etc.) providing complete arithmetic operations for multi-precision integer calculations.

Description

This code implements the `wide::integer<Bits, Signed>` template class that provides integers wider than the native CPU word size. The implementation stores large integers as arrays of 64-bit base values and implements all arithmetic operations (addition, subtraction, multiplication, division), bitwise operations, shifts, and conversions. For 256-bit integers on x86-64, the code can leverage Clang's builtin `_BitInt(256)` type for improved performance. The class supports conversions from/to standard integer types, floating point, and provides specializations for 128-bit and 256-bit multiplication using native compiler `__int128` support. The implementation handles both signed and unsigned variants with proper two's complement arithmetic.

Usage

Use this when you need integer arithmetic beyond 64 bits, such as for precise decimal arithmetic in financial calculations, cryptographic operations, UUID manipulation, or exact integer math in scientific computing. The `UInt128` and `Int128` types are commonly used for storing very large counters, precise timestamps, or 128-bit identifiers. The `UInt256` and `Int256` types support even larger values for specialized applications.

Code Reference

Source Location

Signature

namespace wide {

template <size_t Bits, typename Signed>
class integer {
public:
    using base_type = uint64_t;
    using signed_base_type = int64_t;

    base_type items[Bits / (sizeof(base_type) * 8)];

    // Constructors
    constexpr integer() noexcept;
    template <typename T> constexpr integer(T rhs) noexcept;
    constexpr integer(const integer & other) = default;

    // Assignment
    template <typename T> constexpr integer & operator=(T rhs) noexcept;

    // Arithmetic operators
    template <typename T> constexpr auto operator+(const T & rhs) const noexcept;
    template <typename T> constexpr auto operator-(const T & rhs) const noexcept;
    template <typename T> constexpr auto operator*(const T & rhs) const noexcept;
    template <typename T> constexpr auto operator/(const T & rhs) const;
    template <typename T> constexpr auto operator%(const T & rhs) const;

    // Compound assignment
    template <typename T> constexpr integer & operator+=(const T & rhs) noexcept;
    template <typename T> constexpr integer & operator-=(const T & rhs) noexcept;
    template <typename T> constexpr integer & operator*=(const T & rhs) noexcept;
    template <typename T> constexpr integer & operator/=(const T & rhs);

    // Bitwise operators
    constexpr integer operator~() const noexcept;
    template <typename T> constexpr integer operator&(const T & rhs) const noexcept;
    template <typename T> constexpr integer operator|(const T & rhs) const noexcept;
    template <typename T> constexpr integer operator^(const T & rhs) const noexcept;

    // Shifts
    constexpr integer operator<<(unsigned shift) const noexcept;
    constexpr integer operator>>(unsigned shift) const noexcept;

    // Comparison
    template <typename T> constexpr bool operator==(const T & rhs) const noexcept;
    template <typename T> constexpr bool operator!=(const T & rhs) const noexcept;
    template <typename T> constexpr bool operator<(const T & rhs) const noexcept;
    template <typename T> constexpr bool operator>(const T & rhs) const noexcept;

    // Unary operators
    constexpr integer operator+() const noexcept;
    constexpr integer operator-() const noexcept;

    // Conversions
    template <typename T> explicit constexpr operator T() const noexcept;
};

using Int128 = integer<128, signed>;
using UInt128 = integer<128, unsigned>;
using Int256 = integer<256, signed>;
using UInt256 = integer<256, unsigned>;

} // namespace wide

Import

#include <base/wide_integer_impl.h>
// Or use the type aliases:
#include <base/extended_types.h>

I/O Contract

Inputs

Name Type Required Description
value Integer, floating point, or wide integer Yes Value to construct from or assign
shift unsigned Yes Bit shift amount for left/right shift operations
rhs Integer or wide integer Yes Right-hand side operand for binary operations

Outputs

Name Type Description
result wide::integer<Bits, Signed> Result of arithmetic or bitwise operation
comparison bool Result of comparison operation
converted Native type Converted value from wide integer

Usage Examples

#include <base/extended_types.h>
#include <iostream>

// Create 128-bit integers
UInt128 a = 1000000000000ULL;
UInt128 b = 2000000000000ULL;

// Arithmetic operations
UInt128 sum = a + b;           // 3000000000000
UInt128 product = a * b;       // Very large value
UInt128 difference = b - a;    // 1000000000000

// Mixed-type arithmetic
UInt128 c = a + 500;           // Automatic conversion
Int128 negative = -Int128(a);  // Signed negation

// Bitwise operations
UInt128 mask = (UInt128(1) << 64) - 1;  // Lower 64 bits set
UInt128 masked = product & mask;

// Comparison
if (a < b) {
    // a is less than b
}

// Large constants
UInt128 large = UInt128(0xFFFFFFFFFFFFFFFFULL) << 64 | 0xFFFFFFFFFFFFFFFFULL;
// Represents 2^128 - 1

// 256-bit integers
UInt256 huge = UInt256(1) << 200;  // 2^200
UInt256 enormous = huge * huge;    // 2^400 (within 256-bit range)

// Conversion to native types
UInt128 value = 42;
uint64_t native = static_cast<uint64_t>(value);  // 42

// Division and modulo
UInt128 dividend = 1000000;
UInt128 divisor = 37;
UInt128 quotient = dividend / divisor;
UInt128 remainder = dividend % divisor;

// Building large values
UInt128 high_bits = UInt128(12345) << 64;
UInt128 low_bits = 67890;
UInt128 combined = high_bits | low_bits;

// From floating point
double d = 1.23e20;
UInt128 from_double = UInt128(d);

// To floating point
UInt128 big_int = UInt128(1) << 100;
double as_double = static_cast<double>(big_int);

// Exact decimal arithmetic (financial)
Int128 cents = 12345;  // $123.45 in cents
Int128 quantity = 1000;
Int128 total_cents = cents * quantity;  // Exact multiplication

// Counter that won't overflow
UInt128 event_counter = 0;
for (int i = 0; i < 1000000; ++i) {
    event_counter += i;
}

// Large timestamp (nanoseconds since epoch)
UInt128 nanoseconds = UInt128(std::time(nullptr)) * 1'000'000'000ULL;

// UUID (128-bit identifier)
struct UUID {
    UInt128 value;

    static UUID generate() {
        // Generate random 128-bit value
        return UUID{/* random UInt128 */};
    }
};

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment