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
113 changes: 102 additions & 11 deletions doc/modules/ROOT/pages/unsigned_integers.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ Narrowing conversions cause a compile-time error.

== Comparison Operators

Full three-way comparison is supported via `operator<=>`, which returns `std::strong_ordering`. All comparison operators (`<`, `<=`, `>`, `>=`, `==`, `!=`) are available.
Full three-way comparison is supported via `pass:[operator<=>]`, which returns `std::strong_ordering`.
All comparison operators (`<`, `<=`, `>`, `>=`, `==`, `!=`) are available.

== Arithmetic Operators

Expand Down Expand Up @@ -103,32 +104,121 @@ Operations between different width safe integer types are compile-time errors. T
For cases where throwing exceptions is not desired, saturating arithmetic functions are provided.
These functions clamp the result to the representable range instead of throwing.

=== add_sat
[source, c++]
----
namespace boost::safe_numbers {

template <UnsignedLibType T>
constexpr T saturating_add(const T lhs, const T rhs) noexcept;

template <UnsignedLibType T>
constexpr T saturating_sub(const T lhs, const T rhs) noexcept;

template <UnsignedLibType T>
constexpr T saturating_mul(const T lhs, const T rhs) noexcept;

template <UnsignedLibType T>
constexpr T saturating_div(const T lhs, const T rhs);

template <UnsignedLibType T>
constexpr T saturating_mod(const T lhs, const T rhs);

} // namespace boost::safe_numbers
----

=== saturating_add

Returns the sum of two values, saturating at the maximum value on overflow (i.e., returns `std::numeric_limits::max`).

=== saturating_sub

Returns the difference of two values, saturating at the minimum value on underflow (i.e., returns `std::numeric_limits::min`).

=== saturating_mul

Returns the product of two values, saturating at the maximum value on overflow (i.e., returns `std::numeric_limits::max`).

=== saturating_div

Returns the quotient of two values, and throws `std::range_error` in the event of division by 0.
Otherwise, overflow and underflow are impossible.

=== saturating_div

Returns the remainder of two values, and throws `std::range_error` in the event of division by 0.
Otherwise, overflow and underflow are impossible.

== Overflowing Arithmetic

This family of functions provides well-defined wrapping semantics as well as a flag to alert the consumer if overflow occurred.
This follows normal C family unsigned rollover where `UINT_MAX + 1 == 0` and `UINT_MIN - 1 == UINT_MAX`.

[source, c++]
----
namespace boost::safe_numbers {

template <UnsignedLibType T>
constexpr std::pair<T, bool> overflowing_add(const T lhs, const T rhs) noexcept;

template <UnsignedLibType T>
constexpr std::pair<T, bool> overflowing_sub(const T lhs, const T rhs) noexcept;

template <UnsignedLibType T>
constexpr std::pair<T, bool> overflowing_mul(const T lhs, const T rhs) noexcept;

template <UnsignedLibType T>
constexpr std::pair<T, bool> overflowing_div(const T lhs, const T rhs);

template <UnsignedLibType T>
constexpr std::pair<T, bool> overflowing_mod(const T lhs, const T rhs);

} // namespace boost::safe_numbers
----

=== overflowing_add

Returns the sum of two values, wrapping the sum and setting the `bool` in the return to `true` as required.

=== overflowing_sub

Returns the difference of two values, wrapping the difference and setting the `bool` in the return to `true` as required.

=== overflowing_mul

Returns the product of two values, wrapping the product and setting the `bool` in the return to `true` as required.

=== overflowing_div

Returns the quotient of two values, and throws `std::range_error` in the event of division by 0.
Otherwise, overflow and underflow are impossible.

=== overflowing_mod

Returns the sum of two values, saturating at the maximum value on overflow.
Returns the remainder of two values, and throws `std::range_error` in the event of division by 0.
Otherwise, overflow and underflow are impossible.

== Exception Summary

|===
| Operation | Exception Type | Condition

| `+`, `+=`
| `pass:[+]`, `pass:[+=]`
| `std::overflow_error`
| Result exceeds maximum value
| The result exceeds maximum value

| `-`, `-=`
| `std::underflow_error`
| Result would be negative
| The result would be negative

| `*`, `*=`
| `pass:[*]`, `pass:[*=]`
| `std::overflow_error`
| Result exceeds maximum value
| The result exceeds maximum value

| `/`, `/=`
| `/`, `/=`, `saturating_div`
| `std::domain_error`
| Division by zero

| `%`, `%=`
| `%`, `%=`, `saturating_mod`
| `std::domain_error`
| Modulo by zero

Expand All @@ -143,4 +233,5 @@ Returns the sum of two values, saturating at the maximum value on overflow.

== Constexpr Support

All operations are `constexpr`-compatible when evaluated at compile time. Overflow at compile time results in a compile error.
All operations are `constexpr`-compatible.
Overflow at compile time results in a compiler error.
1 change: 1 addition & 0 deletions include/boost/safe_numbers/detail/int128/format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <boost/safe_numbers/detail/int128/int128.hpp>
#include <string>
#include <format>
#include <tuple>

#define BOOST_SAFE_NUMBERS_DETAIL_INT128_HAS_FORMAT

Expand Down
3 changes: 2 additions & 1 deletion include/boost/safe_numbers/detail/overflow_policy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ namespace boost::safe_numbers::detail {
enum class overflow_policy
{
throw_exception,
saturate
saturate,
overflow_tuple,
};

} // namespace boost::safe_numbers::detail
Expand Down
Loading
Loading