Numeric
Description
The library provides overloads of standard <numeric> algorithms for safe integer types.
These operate on the non-bounded types (u8, u16, u32, u64, u128).
#include <boost/safe_numbers/numeric.hpp>
gcd
Computes the greatest common divisor of two integers using the Euclidean algorithm.
template <non_bounded_integral_library_type T>
BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] constexpr auto gcd(const T m, const T n) noexcept -> T;
Returns the greatest common divisor of m and n.
Delegates to std::gcd on the underlying hardware type, or to int128::gcd for 128-bit types.
lcm
Computes the least common multiple of two integers.
template <non_bounded_integral_library_type T>
BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] constexpr auto lcm(const T m, const T n) noexcept -> T;
Returns the least common multiple of m and n.
Delegates to std::lcm on the underlying hardware type, or to int128::lcm for 128-bit types.
midpoint
Computes the midpoint of two integers without overflow.
The result is rounded towards the first argument a.
template <non_bounded_integral_library_type T>
BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] constexpr auto midpoint(const T a, const T b) noexcept -> T;
Returns the midpoint of a and b, computed without overflow.
Delegates to std::midpoint on the underlying hardware type, or to int128::midpoint for 128-bit types.
Examples
// Copyright 2026 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/safe_numbers/numeric.hpp>
#include <boost/safe_numbers/unsigned_integers.hpp>
#include <boost/safe_numbers/iostream.hpp>
#include <iostream>
int main()
{
using namespace boost::safe_numbers;
// gcd: greatest common divisor (Euclidean algorithm)
std::cout << "gcd(12, 8) = " << gcd(u32{12}, u32{8}) << '\n';
std::cout << "gcd(54, 24) = " << gcd(u32{54}, u32{24}) << '\n';
std::cout << "gcd(7, 11) = " << gcd(u32{7}, u32{11}) << '\n';
std::cout << "gcd(0, 42) = " << gcd(u32{0}, u32{42}) << '\n';
std::cout << '\n';
// lcm: least common multiple
std::cout << "lcm(4, 6) = " << lcm(u32{4}, u32{6}) << '\n';
std::cout << "lcm(12, 18) = " << lcm(u32{12}, u32{18}) << '\n';
std::cout << "lcm(7, 11) = " << lcm(u32{7}, u32{11}) << '\n';
std::cout << '\n';
// midpoint: average without overflow, rounded toward the first argument
std::cout << "midpoint(0, 10) = " << midpoint(u32{0}, u32{10}) << '\n';
std::cout << "midpoint(1, 4) = " << midpoint(u32{1}, u32{4}) << '\n';
std::cout << "midpoint(4, 1) = " << midpoint(u32{4}, u32{1}) << '\n';
return 0;
}
Output:
gcd(12, 8) = 4 gcd(54, 24) = 6 gcd(7, 11) = 1 gcd(0, 42) = 42 lcm(4, 6) = 12 lcm(12, 18) = 36 lcm(7, 11) = 77 midpoint(0, 10) = 5 midpoint(1, 4) = 2 midpoint(4, 1) = 3