add {saturating,wrapping,overflowing}_div_euclid

This commit is contained in:
Trevor Spiteri 2020-02-12 14:48:10 +01:00
parent 43926daa62
commit bf7c2024e1
4 changed files with 154 additions and 1 deletions

View File

@ -77,6 +77,9 @@ The conversions supported cover the following cases.
* [`checked_rem`]
* [`div_euclid`], [`rem_euclid`]
* [`checked_div_euclid`], [`checked_rem_euclid`]
* [`saturating_div_euclid`]
* [`wrapping_div_euclid`]
* [`overflowing_div_euclid`]
[`RemAssign`]: https://doc.rust-lang.org/nightly/core/ops/trait.RemAssign.html
[`Rem`]: https://doc.rust-lang.org/nightly/core/ops/trait.Rem.html
@ -84,7 +87,10 @@ The conversions supported cover the following cases.
[`checked_rem_euclid`]: https://docs.rs/fixed/0.5.3/fixed/struct.FixedI32.html#method.checked_rem_euclid
[`checked_rem`]: https://docs.rs/fixed/0.5.3/fixed/struct.FixedI32.html#method.checked_rem
[`div_euclid`]: https://docs.rs/fixed/0.5.3/fixed/struct.FixedI32.html#method.div_euclid
[`overflowing_div_euclid`]: https://docs.rs/fixed/0.5.3/fixed/struct.FixedI32.html#method.overflowing_div_euclid
[`rem_euclid`]: https://docs.rs/fixed/0.5.3/fixed/struct.FixedI32.html#method.rem_euclid
[`saturating_div_euclid`]: https://docs.rs/fixed/0.5.3/fixed/struct.FixedI32.html#method.saturating_div_euclid
[`wrapping_div_euclid`]: https://docs.rs/fixed/0.5.3/fixed/struct.FixedI32.html#method.wrapping_div_euclid
### Version 0.5.2 news (2020-02-02)

View File

@ -13,7 +13,10 @@ Version 0.5.3 (unreleased)
the `Fixed` trait:
* `checked_rem`
* `div_euclid`, `rem_euclid`
* `checked_div_euclid`, `checked_rem_euclid`
* `checked_div_euclid`, `checked_rem_euclid`
* `saturating_div_euclid`
* `wrapping_div_euclid`
* `overflowing_div_euclid`
Version 0.5.2 (2020-02-02)
==========================

View File

@ -324,6 +324,47 @@ assert_eq!(Fix::max_value().saturating_div(one_half), Fix::max_value());
}
}
comment! {
"Saturating Euclidean division. Returns the quotient,
saturating on overflow.
# Panics
Panics if the divisor is zero.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::from_num(7.5).saturating_div_euclid(Fix::from_num(2)), Fix::from_num(3));
assert_eq!(Fix::max_value().saturating_div_euclid(Fix::from_num(0.25)), Fix::max_value());
",
if_signed_else_empty_str! {
$Signedness,
"assert_eq!(Fix::from_num(-7.5).saturating_div_euclid(Fix::from_num(2)), Fix::from_num(-4));
assert_eq!(Fix::min_value().saturating_div_euclid(Fix::from_num(0.25)), Fix::min_value());
",
},
"```
[`None`]: https://doc.rust-lang.org/nightly/core/option/enum.Option.html#variant.None
";
#[inline]
pub fn saturating_div_euclid(self, rhs: $Fixed<Frac>) -> $Fixed<Frac> {
if rhs.to_bits() == 0 {
panic!("division by zero");
}
self.checked_div_euclid(rhs).unwrap_or_else(|| {
if (self.to_bits() > 0) == (rhs.to_bits() > 0) {
Self::max_value()
} else {
Self::min_value()
}
})
}
}
comment! {
"Wrapping multiplication. Returns the product, wrapping on overflow.
@ -370,6 +411,29 @@ assert_eq!(Fix::max_value().wrapping_div(quarter), wrapped);
}
}
comment! {
"Wrapping Euclidean division. Returns the quotient, wrapping on overflow.
# Panics
Panics if the divisor is zero.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::from_num(7.5).wrapping_div_euclid(Fix::from_num(2)), Fix::from_num(3));
let wrapped = Fix::max_value().wrapping_mul_int(4).round_to_zero();
assert_eq!(Fix::max_value().wrapping_div_euclid(Fix::from_num(0.25)), wrapped);
```
";
#[inline]
pub fn wrapping_div_euclid(self, rhs: $Fixed<Frac>) -> $Fixed<Frac> {
self.overflowing_div_euclid(rhs).0
}
}
comment! {
"Overflowing multiplication.
@ -417,6 +481,9 @@ let quarter = Fix::from_num(1) / 4;
let wrapped = Fix::from_bits(!0 << 2);
assert_eq!(Fix::max_value().overflowing_div(quarter), (wrapped, true));
```
[`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
[tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
";
#[inline]
pub fn overflowing_div(self, rhs: $Fixed<Frac>) -> ($Fixed<Frac>, bool) {
@ -424,6 +491,52 @@ assert_eq!(Fix::max_value().overflowing_div(quarter), (wrapped, true));
(Self::from_bits(ans), overflow)
}
}
comment! {
"Overflowing Euclidean division.
Returns a [tuple] of the quotient and a [`bool`] indicating whether an
overflow has occurred. On overflow, the wrapped value is returned.
# Panics
Panics if the divisor is zero.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::from_num(7.5).overflowing_div_euclid(Fix::from_num(2)), (Fix::from_num(3), false));
let wrapped = Fix::max_value().wrapping_mul_int(4).round_to_zero();
assert_eq!(Fix::max_value().overflowing_div_euclid(Fix::from_num(0.25)), (wrapped, true));
```
[`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
[tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
";
#[inline]
pub fn overflowing_div_euclid(self, rhs: $Fixed<Frac>) -> ($Fixed<Frac>, bool) {
let (mut q, overflow) = self.overflowing_div(rhs);
q = q.round_to_zero();
if_signed! {
$Signedness;
if (self % rhs).is_negative() {
let one = match Self::checked_from_num(1) {
None => return (q, true),
Some(one) => one,
};
let (q, overflow2) = if rhs.is_positive() {
q.overflowing_sub(one)
} else {
q.overflowing_add(one)
};
return (q, overflow | overflow2);
}
}
(q, overflow)
}
}
}
};
}

View File

@ -728,6 +728,13 @@ where
/// Panics if the divisor is zero.
fn saturating_div(self, rhs: Self) -> Self;
/// Saturating Euclidean division. Returns the quotient, saturating on overflow.
///
/// # Panics
///
/// Panics if the divisor is zero.
fn saturating_div_euclid(self, rhs: Self) -> Self;
/// Saturating multiplication by an integer. Returns the product, saturating on overflow.
fn saturating_mul_int(self, rhs: Self::Bits) -> Self;
@ -750,6 +757,13 @@ where
/// Panics if the divisor is zero.
fn wrapping_div(self, rhs: Self) -> Self;
/// Wrapping Euclidean division. Returns the quotient, wrapping on overflow.
///
/// # Panics
///
/// Panics if the divisor is zero.
fn wrapping_div_euclid(self, rhs: Self) -> Self;
/// Wrapping multiplication by an integer. Returns the product, wrapping on overflow.
fn wrapping_mul_int(self, rhs: Self::Bits) -> Self;
@ -854,6 +868,20 @@ where
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
fn overflowing_div(self, rhs: Self) -> (Self, bool);
/// Overflowing Euclidean division.
///
/// Returns a [tuple] of the quotient and a [`bool`], indicating
/// whether an overflow has occurred. On overflow, the wrapped
/// value is returned.
///
/// # Panics
///
/// Panics if the divisor is zero.
///
/// [`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool);
/// Overflowing multiplication by an integer.
///
/// Returns a [tuple] of the product and a [`bool`], indicating
@ -1576,12 +1604,14 @@ macro_rules! impl_fixed {
trait_delegate! { fn saturating_sub(self, rhs: Self) -> Self }
trait_delegate! { fn saturating_mul(self, rhs: Self) -> Self }
trait_delegate! { fn saturating_div(self, rhs: 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 wrapping_neg(self) -> Self }
trait_delegate! { fn wrapping_add(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_sub(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_mul(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_div(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_div_euclid(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_mul_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn wrapping_div_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn wrapping_rem_int(self, rhs: Self::Bits) -> Self }
@ -1594,6 +1624,7 @@ macro_rules! impl_fixed {
trait_delegate! { fn overflowing_sub(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_mul(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_div(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_mul_int(self, rhs: Self::Bits) -> (Self, bool) }
trait_delegate! { fn overflowing_div_int(self, rhs: Self::Bits) -> (Self, bool) }
trait_delegate! { fn overflowing_rem_int(self, rhs: Self::Bits) -> (Self, bool) }