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
4 changes: 0 additions & 4 deletions doc/modules/ROOT/pages/bounded_float.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,12 @@ public:
friend constexpr auto operator-(bounded_float, bounded_float) -> bounded_float;
friend constexpr auto operator*(bounded_float, bounded_float) -> bounded_float;
friend constexpr auto operator/(bounded_float, bounded_float) -> bounded_float;
friend constexpr auto operator%(bounded_float, bounded_float) -> bounded_float;

// Compound assignment
constexpr auto operator+=(bounded_float) -> bounded_float&;
constexpr auto operator-=(bounded_float) -> bounded_float&;
constexpr auto operator*=(bounded_float) -> bounded_float&;
constexpr auto operator/=(bounded_float) -> bounded_float&;
constexpr auto operator%=(bounded_float) -> bounded_float&;
};

} // namespace boost::safe_numbers
Expand All @@ -117,8 +115,6 @@ public:
| Multiplication underflow | `std::underflow_error`
| Division producing NaN (e.g., 0/0, inf/inf) | `std::domain_error`
| Division by zero (finite numerator) | `std::domain_error`
| Modulo with zero divisor | `std::domain_error`
| Modulo with infinite numerator | `std::domain_error`
| Narrowing conversion (e.g., f64 -> f32) overflowing to infinity | `std::overflow_error`
|===

Expand Down
18 changes: 4 additions & 14 deletions doc/modules/ROOT/pages/floats.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,6 @@ template <compatible_float_type BasisType>
constexpr auto operator/(float_basis<BasisType> lhs,
float_basis<BasisType> rhs) -> float_basis<BasisType>;

template <compatible_float_type BasisType>
constexpr auto operator%(float_basis<BasisType> lhs,
float_basis<BasisType> rhs) -> float_basis<BasisType>;

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

Expand Down Expand Up @@ -179,21 +175,17 @@ constexpr auto operator*(float_basis<BasisType> lhs,
template <compatible_float_type BasisType>
constexpr auto operator/(float_basis<BasisType> lhs,
float_basis<BasisType> rhs) -> float_basis<BasisType>;

template <compatible_float_type BasisType>
constexpr auto operator%(float_basis<BasisType> lhs,
float_basis<BasisType> rhs) -> float_basis<BasisType>;
----

Each arithmetic operator computes the result, classifies it according to IEEE 754-2008 sections 6 and 7, and throws when the result is an exceptional value:

- `pass:[+]`, `-`: Throw `std::overflow_error` on saturation to positive infinity and `std::underflow_error` on saturation to negative infinity. Subtracting like-signed infinities, or adding opposite-signed infinities, is an invalid operation and throws `std::domain_error`.
- `pass:[*]`: Throws `std::overflow_error` or `std::underflow_error` on saturation to an infinity. Multiplying zero by an infinity is an invalid operation and throws `std::domain_error`.
- `/`: Throws `std::overflow_error` or `std::underflow_error` on saturation to an infinity. Dividing zero by zero or infinity by infinity is an invalid operation and throws `std::domain_error`. Dividing a finite non-zero value by zero throws `std::domain_error`.
- `%`: Computes the IEEE 754 remainder via `std::fmod`. Modulo by zero, or modulo of an infinite dividend, throws `std::domain_error`. The remainder cannot overflow or underflow.

In every operation, an operand that is a quiet or signaling NaN causes the operation to throw `std::domain_error`.
The `%` operator borrows the spelling of the integer modulo operator but performs floating-point remainder, mirroring `std::fmod` rather than truncated integer division.

NOTE: There is no `operator%` for `f32`/`f64`. C++ has no built-in floating-point remainder operator; use the `xref:cmath.adoc[fmod]` function instead.

== Exception Behavior

Expand All @@ -204,14 +196,12 @@ The following table summarizes the exceptional conditions and the exception each

| Result saturates to positive infinity | `pass:[+]` `-` `pass:[*]` `/` | `std::overflow_error`
| Result saturates to negative infinity | `pass:[+]` `-` `pass:[*]` `/` | `std::underflow_error`
| Either operand is a quiet NaN | `pass:[+]` `-` `pass:[*]` `/` `%` | `std::domain_error`
| Either operand is a signaling NaN | `pass:[+]` `-` `pass:[*]` `/` `%` | `std::domain_error`
| Either operand is a quiet NaN | `pass:[+]` `-` `pass:[*]` `/` | `std::domain_error`
| Either operand is a signaling NaN | `pass:[+]` `-` `pass:[*]` `/` | `std::domain_error`
| Addition of opposite-signed infinities, or subtraction of like-signed infinities | `pass:[+]` `-` | `std::domain_error`
| Multiplication of zero by an infinity | `pass:[*]` | `std::domain_error`
| Division of zero by zero, or infinity by infinity | `/` | `std::domain_error`
| Division of a finite non-zero value by zero | `/` | `std::domain_error`
| Modulo of zero by zero, or with an infinite dividend | `%` | `std::domain_error`
| Modulo by zero with a finite non-zero dividend | `%` | `std::domain_error`
|===

NOTE: Saturation to an infinity (IEEE 754 section 6.1) maps to `std::overflow_error` or `std::underflow_error` according to sign. The invalid-operation cases (section 7.2), NaN propagation (section 6.2), and division by zero of a finite numerator (section 7.3) are all reported as `std::domain_error`.
Expand Down
27 changes: 0 additions & 27 deletions include/boost/safe_numbers/bounded_floats.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@ class bounded_float
constexpr auto operator*=(bounded_float<Min, Max> rhs) -> bounded_float&;

constexpr auto operator/=(bounded_float<Min, Max> rhs) -> bounded_float&;

constexpr auto operator%=(bounded_float<Min, Max> rhs) -> bounded_float&;
};

// ------------------------------
Expand Down Expand Up @@ -200,17 +198,6 @@ template <auto Min, auto Max>
return bounded_float<Min, Max>{lhs_b / rhs_b};
}

template <auto Min, auto Max>
[[nodiscard]] constexpr auto operator%(const bounded_float<Min, Max> lhs,
const bounded_float<Min, Max> rhs) -> bounded_float<Min, Max>
{
using basis = typename bounded_float<Min, Max>::basis_type;
using underlying = detail::underlying_type_t<basis>;
const basis lhs_b {static_cast<underlying>(lhs)};
const basis rhs_b {static_cast<underlying>(rhs)};
return bounded_float<Min, Max>{lhs_b % rhs_b};
}

// ------------------------------
// Compound assignment
// ------------------------------
Expand Down Expand Up @@ -267,19 +254,6 @@ constexpr auto bounded_float<Min, Max>::operator/=(bounded_float<Min, Max> rhs)
return *this;
}

template <auto Min, auto Max>
requires (detail::valid_float_bound<decltype(Min)> &&
detail::valid_float_bound<decltype(Max)> &&
std::is_same_v<decltype(Min), decltype(Max)> &&
detail::float_raw_value(Min) == detail::float_raw_value(Min) &&
detail::float_raw_value(Max) == detail::float_raw_value(Max) &&
detail::float_raw_value(Max) > detail::float_raw_value(Min))
constexpr auto bounded_float<Min, Max>::operator%=(bounded_float<Min, Max> rhs) -> bounded_float&
{
*this = *this % rhs;
return *this;
}

} // namespace boost::safe_numbers

// Mixed-bounds blocking for bounded_float
Expand Down Expand Up @@ -308,7 +282,6 @@ BOOST_SAFE_NUMBERS_DEFINE_MIXED_BOUNDED_FLOAT_OP("addition", operator+)
BOOST_SAFE_NUMBERS_DEFINE_MIXED_BOUNDED_FLOAT_OP("subtraction", operator-)
BOOST_SAFE_NUMBERS_DEFINE_MIXED_BOUNDED_FLOAT_OP("multiplication", operator*)
BOOST_SAFE_NUMBERS_DEFINE_MIXED_BOUNDED_FLOAT_OP("division", operator/)
BOOST_SAFE_NUMBERS_DEFINE_MIXED_BOUNDED_FLOAT_OP("modulo", operator%)

} // namespace boost::safe_numbers

Expand Down
Loading
Loading