Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 194 additions & 0 deletions doc/modules/ROOT/pages/examples.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,35 @@ counter = 12
include::example$stream.cpp[]
----

.Expected Output
[listing]
----
=== Basic Streaming ===
Signed value: -42
Unsigned value (dec): 36893488147419103231
Unsigned value (hex): 0x1ffffffffffffffff
Unsigned value (oct): 03777777777777777777777
Upper unsigned value: 0X1FFFFFFFFFFFFFFFF
Lower unsigned value: 36893488147419103231

=== Large Values (Beyond 64-bit) ===
2^64 = 18446744073709551616
2^100 = 1267650600228229401496703205376
uint128_t max = 340282366920938463463374607431768211455
int128_t min = -170141183460469231731687303715884105728
int128_t max = 170141183460469231731687303715884105727

=== String Conversion with std::stringstream ===
uint128_t to string: "1267650600228229401496703205376"
String to uint128_t: 123456789012345678901234567890

=== Round-trip Conversion ===
Original: 68915718020162848918556923512
As string: "68915718020162848918556923512"
Round-tripped: 68915718020162848918556923512
Match: true
----

[#examples_bit]
== Bitwise Functions (<bit>)

Expand All @@ -123,6 +152,31 @@ include::example$bit.cpp[]
include::example$saturating_arithmetic.cpp[]
----

.Expected Output
[listing]
----
=== Saturating Arithmetic ===
uint128_t max = 340282366920938463463374607431768211455
int128_t max = 170141183460469231731687303715884105727
int128_t min = -170141183460469231731687303715884105728

=== Saturating Addition and Subtraction ===
add_sat(uint_max, uint_max) = 340282366920938463463374607431768211455 (saturates to uint_max)
sub_sat(0, uint_max) = 0 (saturates to 0, not underflow)

=== Saturating Multiplication ===
mul_sat(int_max, 2) = 170141183460469231731687303715884105727 (saturates to int_max)
mul_sat(-(int_max - 2), 5) = -170141183460469231731687303715884105728 (saturates to int_min)

=== Saturating Division ===
div_sat(int_min, -1) = 170141183460469231731687303715884105727 (saturates to int_max; normally this overflows)

=== Saturating Casts ===
saturate_cast<int128_t>(uint_max) = 170141183460469231731687303715884105727 (saturates to int_max)
saturate_cast<int64_t>(int_max) = 9223372036854775807 (saturates to INT64_MAX)
saturate_cast<int32_t>(uint_max) = 2147483647 (saturates to INT32_MAX)
----

[#examples_mixed_sign]
== Mixed Signedness Arithmetic

Expand All @@ -131,6 +185,26 @@ include::example$saturating_arithmetic.cpp[]
include::example$mixed_type_arithmetic.cpp[]
----

.Expected Output
[listing]
----
=== Mixed Type Arithmetic with uint128_t ===
unsigned_value = 3
unsigned_value + 1 = 4
unsigned_value - 1 = 2
unsigned_value * 2 = 6
unsigned_value / 3 = 1
unsigned_value % 3 = 0
unsigned_value + 5 = 8 (same as greater_unsigned_value: 8)

=== Mixed Type Arithmetic with int128_t ===
signed_value = -3
signed_value + 1U = -2
signed_value - 4U = -7
signed_value * 2 = -6
signed_value / 4U = 0
----

[#examples_boost_math_random]
== Boost.Math and Boost.Random Integration

Expand Down Expand Up @@ -166,3 +240,123 @@ Parsed "-170141183460469231731687303715884105728"
Parsed hex "DEADBEEFCAFEBABE12345678"
Result: 68915718020162848918556923512
----

[#examples_fmt_format]
== \{fmt} Library Integration

[source,c++]
----
include::example$fmt_format.cpp[]
----

.Expected Output
[listing]
----
=== Basic Formatting ===
Default (decimal): 68915718020162848918556923512
Signed value: -123456789012345678

=== Base Specifiers ===
Binary: 11111111
Octal: 377
Decimal: 255
Hexadecimal: ff
Hex (upper): FF

=== Alternate Form (Prefixes) ===
Binary with prefix: 0b11111111
Octal with prefix: 0377
Hex with prefix: 0xff
Hex upper prefix: 0XFF

=== Sign Options ===
Plus sign: +42 and -42
Minus only: 42 and -42
Space sign: 42 and -42

=== Zero Padding ===
8-digit padding: 00000255
16-digit padding: 0000000000000255

=== Large Values ===
uint128_t max: 340282366920938463463374607431768211455
uint128_t max (hex): 0xffffffffffffffffffffffffffffffff
int128_t min: -170141183460469231731687303715884105728

=== Combined Format Specifiers ===
Hex with prefix, uppercase, padded: 0XDEADBEEFCAFEBABE12345678
Signed with plus, padded: -00123456789012345678
----

[#examples_cstdlib]
== Division with Remainder (<cstdlib>)

[source,c++]
----
include::example$cstdlib.cpp[]
----

.Expected Output
[listing]
----
=== div() Function ===
Returns both quotient and remainder in a single operation

--- Unsigned Division ---
1000000000000000000 / 7 = 142857142857142857 remainder 1
Verification: 142857142857142857 * 7 + 1 = 1000000000000000000

--- Large Value Division ---
2^100 / 2^50 = 1125899906842624 remainder 0

--- Signed Division ---
-100 / 7 = -14 remainder -2

--- Sign Combinations ---
17 / 5 = 3 remainder 2
17 / -5 = -3 remainder 2
-17 / 5 = -3 remainder -2
-17 / -5 = 3 remainder -2

--- Edge Cases ---
3 / 10 = 0 remainder 3
----

[#examples_numeric_algorithms]
== Numeric Algorithms (<numeric>)

[source,c++]
----
include::example$numeric_algorithms.cpp[]
----

.Expected Output
[listing]
----
=== Greatest Common Divisor (gcd) ===
gcd(48, 18) = 6
gcd(123456789012345678, 987654321098765432) = 2
gcd(2^100, 2^80) = 1208925819614629174706176 (= 2^80)
gcd(-48, 18) = 6 (always positive)

=== Least Common Multiple (lcm) ===
lcm(12, 18) = 36
lcm(7, 11) = 77 (coprime: lcm = p * q)

Verifying gcd * lcm = a * b:
gcd(12, 18) * lcm(12, 18) = 216
12 * 18 = 216

=== Midpoint ===
midpoint(10, 20) = 15
midpoint(10, 21) = 15 (rounds toward first arg)
midpoint(21, 10) = 16 (rounds toward first arg)

--- Overflow-safe midpoint ---
midpoint(uint128_max, uint128_max - 10) = 340282366920938463463374607431768211450
(This would overflow if computed as (a + b) / 2)

--- Signed midpoint ---
midpoint(-100, 100) = 0
midpoint(-100, -50) = -75
----
77 changes: 77 additions & 0 deletions examples/cstdlib.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2025 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/int128/int128.hpp>
#include <boost/int128/cstdlib.hpp>
#include <boost/int128/iostream.hpp>
#include <iostream>

int main()
{
using boost::int128::uint128_t;
using boost::int128::int128_t;

std::cout << "=== div() Function ===" << std::endl;
std::cout << "Returns both quotient and remainder in a single operation" << std::endl;

// Unsigned division
std::cout << "\n--- Unsigned Division ---" << std::endl;

constexpr uint128_t dividend {1000000000000000000ULL};
constexpr uint128_t divisor {7};

auto uresult {boost::int128::div(dividend, divisor)};
std::cout << dividend << " / " << divisor << " = " << uresult.quot
<< " remainder " << uresult.rem << std::endl;

// Verify: quot * divisor + rem == dividend
std::cout << "Verification: " << uresult.quot << " * " << divisor
<< " + " << uresult.rem << " = " << (uresult.quot * divisor + uresult.rem) << std::endl;

// Large value division
std::cout << "\n--- Large Value Division ---" << std::endl;

constexpr uint128_t large_dividend {uint128_t{1} << 100}; // 2^100
constexpr uint128_t large_divisor {uint128_t{1} << 50}; // 2^50

auto large_result {boost::int128::div(large_dividend, large_divisor)};
std::cout << "2^100 / 2^50 = " << large_result.quot
<< " remainder " << large_result.rem << std::endl;

// Signed division
std::cout << "\n--- Signed Division ---" << std::endl;

constexpr int128_t signed_dividend {-100};
constexpr int128_t signed_divisor {7};

auto sresult {boost::int128::div(signed_dividend, signed_divisor)};
std::cout << signed_dividend << " / " << signed_divisor << " = " << sresult.quot
<< " remainder " << sresult.rem << std::endl;

// Different sign combinations
std::cout << "\n--- Sign Combinations ---" << std::endl;

constexpr int128_t pos {17};
constexpr int128_t neg {-17};
constexpr int128_t div_pos {5};
constexpr int128_t div_neg {-5};

auto pp {boost::int128::div(pos, div_pos)};
auto pn {boost::int128::div(pos, div_neg)};
auto np {boost::int128::div(neg, div_pos)};
auto nn {boost::int128::div(neg, div_neg)};

std::cout << " 17 / 5 = " << pp.quot << " remainder " << pp.rem << std::endl;
std::cout << " 17 / -5 = " << pn.quot << " remainder " << pn.rem << std::endl;
std::cout << "-17 / 5 = " << np.quot << " remainder " << np.rem << std::endl;
std::cout << "-17 / -5 = " << nn.quot << " remainder " << nn.rem << std::endl;

// Edge case: dividend smaller than divisor
std::cout << "\n--- Edge Cases ---" << std::endl;

auto small_div {boost::int128::div(uint128_t{3}, uint128_t{10})};
std::cout << "3 / 10 = " << small_div.quot << " remainder " << small_div.rem << std::endl;

return 0;
}
98 changes: 98 additions & 0 deletions examples/fmt_format.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2025 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

// This example demonstrates {fmt} library integration with int128 types.
// Requires {fmt} to be installed: https://github.com/fmtlib/fmt
//
// For C++20 std::format support, use <boost/int128/format.hpp> instead,
// which provides the same formatting capabilities with std::format.

#define FMT_HEADER_ONLY
#include <boost/int128/int128.hpp>
#include <boost/int128/fmt_format.hpp>

#ifdef BOOST_INT128_HAS_FMT_FORMAT

#include <fmt/format.h>
#include <iostream>

int main()
{
using boost::int128::int128_t;
using boost::int128::uint128_t;

std::cout << "=== Basic Formatting ===" << std::endl;

constexpr uint128_t unsigned_value {0xDEADBEEF, 0xCAFEBABE12345678};
constexpr int128_t signed_value {-123456789012345678};

// Default decimal formatting
std::cout << fmt::format("Default (decimal): {}", unsigned_value) << std::endl;
std::cout << fmt::format("Signed value: {}", signed_value) << std::endl;

std::cout << "\n=== Base Specifiers ===" << std::endl;

// Different bases: binary, octal, decimal, hex
constexpr uint128_t value {255};
std::cout << fmt::format("Binary: {:b}", value) << std::endl;
std::cout << fmt::format("Octal: {:o}", value) << std::endl;
std::cout << fmt::format("Decimal: {:d}", value) << std::endl;
std::cout << fmt::format("Hexadecimal: {:x}", value) << std::endl;
std::cout << fmt::format("Hex (upper): {:X}", value) << std::endl;

std::cout << "\n=== Alternate Form (Prefixes) ===" << std::endl;

// Using # for alternate form adds base prefixes
std::cout << fmt::format("Binary with prefix: {:#b}", value) << std::endl;
std::cout << fmt::format("Octal with prefix: {:#o}", value) << std::endl;
std::cout << fmt::format("Hex with prefix: {:#x}", value) << std::endl;
std::cout << fmt::format("Hex upper prefix: {:#X}", value) << std::endl;

std::cout << "\n=== Sign Options ===" << std::endl;

constexpr int128_t positive {42};
constexpr int128_t negative {-42};

// Sign specifiers: + (always show), - (default), space (space for positive)
std::cout << fmt::format("Plus sign: {:+} and {:+}", positive, negative) << std::endl;
std::cout << fmt::format("Minus only: {} and {}", positive, negative) << std::endl;
std::cout << fmt::format("Space sign: {: } and {: }", positive, negative) << std::endl;

std::cout << "\n=== Zero Padding ===" << std::endl;

// Padding with zeros
std::cout << fmt::format("8-digit padding: {:08}", value) << std::endl;
std::cout << fmt::format("16-digit padding: {:016}", value) << std::endl;

std::cout << "\n=== Large Values ===" << std::endl;

// Demonstrate with values beyond 64-bit range
constexpr auto uint_max {std::numeric_limits<uint128_t>::max()};
constexpr auto int_min {std::numeric_limits<int128_t>::min()};

std::cout << fmt::format("uint128_t max: {}", uint_max) << std::endl;
std::cout << fmt::format("uint128_t max (hex): {:#x}", uint_max) << std::endl;
std::cout << fmt::format("int128_t min: {}", int_min) << std::endl;

std::cout << "\n=== Combined Format Specifiers ===" << std::endl;

// Combining multiple specifiers
std::cout << fmt::format("Hex with prefix, uppercase, padded: {:#016X}", unsigned_value) << std::endl;
std::cout << fmt::format("Signed with plus, padded: {:+020}", signed_value) << std::endl;

return 0;
}

#else

#include <iostream>

int main()
{
std::cout << "This example requires {fmt} library to be installed." << std::endl;
std::cout << "Install from: https://github.com/fmtlib/fmt" << std::endl;
return 0;
}

#endif
Loading
Loading