diff --git a/README.md b/README.md index 3026c00..6952fc1 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,8 @@ The conversions supported cover the following cases. that can represent the value 1. * The following methods were added to all fixed-point numbers and to the [`Fixed`][tf-1-8] trait: + * [`saturating_div_euclid_int`][f-sdei-1-8], + [`saturating_rem_euclid_int`][f-srei-1-8] * [`unwrapped_rem`][f-ur-1-8], [`unwrapped_rem_euclid`][f-ure-1-8] * [`unwrapped_rem_int`][f-uri-1-8] @@ -98,6 +100,8 @@ The conversions supported cover the following cases. [f-d-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#associatedconstant.DELTA [f-o-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#associatedconstant.ONE +[f-sdei-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.saturating_div_euclid_int +[f-srei-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.saturating_rem_euclid_int [f-ur-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_rem [f-ure-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_rem_euclid [f-uri-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_rem_int diff --git a/RELEASES.md b/RELEASES.md index 7fa9ee9..b5c603d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -16,6 +16,8 @@ Version 1.8.0 (unreleased) that can represent the value 1. * The following methods were added to all fixed-point numbers and to the [`Fixed`][tf-1-8] trait: + * [`saturating_div_euclid_int`][f-sdei-1-8], + [`saturating_rem_euclid_int`][f-srei-1-8] * [`unwrapped_rem`][f-ur-1-8], [`unwrapped_rem_euclid`][f-ure-1-8] * [`unwrapped_rem_int`][f-uri-1-8] @@ -23,6 +25,8 @@ Version 1.8.0 (unreleased) [f-d-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#associatedconstant.DELTA [f-o-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#associatedconstant.ONE +[f-sdei-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.saturating_div_euclid_int +[f-srei-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.saturating_rem_euclid_int [f-ur-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_rem [f-ure-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_rem_euclid [f-uri-1-8]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_rem_int diff --git a/src/macros_frac.rs b/src/macros_frac.rs index 78ea7a5..57d1966 100644 --- a/src/macros_frac.rs +++ b/src/macros_frac.rs @@ -855,6 +855,89 @@ assert_eq!(Fix::MIN.saturating_div_euclid(Fix::from_num(0.25)), Fix::MIN); } } + comment! { + "Saturating Euclidean division by an integer. Returns the quotient", + if_signed_unsigned! { + $Signedness, + ", saturating on overflow. + +Overflow can only occur when dividing the minimum value by −1.", + ". + +Can never overflow for unsigned values.", + }, + " + +# Panics + +Panics if the divisor is zero. + +# Examples + +```rust +use fixed::{types::extra::U4, ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +assert_eq!(Fix::from_num(7.5).saturating_div_euclid_int(2), Fix::from_num(3)); +", + if_signed_else_empty_str! { + $Signedness, + "assert_eq!(Fix::from_num(-7.5).saturating_div_euclid_int(2), Fix::from_num(-4)); +assert_eq!(Fix::MIN.saturating_div_euclid_int(-1), Fix::MAX); +", + }, + "``` +"; + #[inline] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn saturating_div_euclid_int(self, rhs: $Inner) -> $Fixed { + match self.overflowing_div_euclid_int(rhs) { + (val, false) => val, + (_, true) => $Fixed::MAX, + } + } + } + + comment! { + "Saturating remainder for Euclidean division by an integer. Returns the remainder", + if_signed_unsigned! { + $Signedness, + ", saturating on overflow.", + ". + +Can never overflow for unsigned values.", + }, + " + +# Panics + +Panics if the divisor is zero. + +# Examples + +```rust +use fixed::{types::extra::U", $s_nbits_m4, ", ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +assert_eq!(Fix::from_num(7.5).saturating_rem_euclid_int(2), Fix::from_num(1.5)); +", + if_signed_else_empty_str! { + $Signedness, + "assert_eq!(Fix::from_num(-7.5).saturating_rem_euclid_int(2), Fix::from_num(0.5)); +// −8 ≤ Fix < 8, so the answer 12.5 saturates +assert_eq!(Fix::from_num(-7.5).saturating_rem_euclid_int(20), Fix::MAX); +", + }, + "``` +"; + #[inline] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn saturating_rem_euclid_int(self, rhs: $Inner) -> $Fixed { + match self.overflowing_rem_euclid_int(rhs) { + (val, false) => val, + (_, true) => $Fixed::MAX, + } + } + } + if_signed! { $Signedness; comment! { diff --git a/src/traits.rs b/src/traits.rs index 5d1da3b..729ab93 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -918,6 +918,24 @@ where #[must_use = "this returns the result of the operation, without modifying the original"] fn saturating_mul_int(self, rhs: Self::Bits) -> Self; + /// Saturating Euclidean division by an integer. Returns the + /// quotient, saturating on overflow. + /// + /// # Panics + /// + /// Panics if the divisor is zero. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn saturating_div_euclid_int(self, rhs: Self::Bits) -> Self; + + /// Saturating remainder for Euclidean division by an integer. + /// Returns the remainder, saturating on overflow. + /// + /// # Panics + /// + /// Panics if the divisor is zero. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn saturating_rem_euclid_int(self, rhs: Self::Bits) -> Self; + /// Wrapping negation. Returns the negated value, wrapping on overflow. fn wrapping_neg(self) -> Self; @@ -2383,6 +2401,8 @@ macro_rules! impl_fixed { trait_delegate! { fn saturating_mul_add(self, mul: Self, add: Self) -> Self } trait_delegate! { fn saturating_div_euclid(self, rhs: Self) -> Self } trait_delegate! { fn saturating_mul_int(self, rhs: Self::Bits) -> Self } + trait_delegate! { fn saturating_div_euclid_int(self, rhs: Self::Bits) -> Self } + trait_delegate! { fn saturating_rem_euclid_int(self, rhs: Self::Bits) -> Self } trait_delegate! { fn wrapping_neg(self) -> Self } trait_delegate! { fn wrapping_add(self, rhs: Self) -> Self } trait_delegate! { fn wrapping_sub(self, rhs: Self) -> Self }