add mul_add methods

This commit is contained in:
Trevor Spiteri 2020-09-22 15:47:13 +02:00
parent b53fb709bf
commit a3d947776d
6 changed files with 498 additions and 2 deletions

View File

@ -80,10 +80,21 @@ The conversions supported cover the following cases.
### Version 1.3.0 news (unreleased)
* The following methods were added to all fixed-point types and to
the `Fixed` trait:
* [`mul_add`][f-ma-1-3], [`checked_mul_add`][f-cma-1-3],
[`saturating_mul_add`][f-sma-1-3],
[`wrapping_mul_add`][f-wma-1-3],
[`overflowing_mul_add`][f-oma-1-3]
* The new experimental feature [`unwrapped`][feat-un-1-3] was added,
providing arithmetic methods that panic on overflow even when
debug assertions are disabled.
[f-cma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.checked_mul_add
[f-ma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.mul_add
[f-oma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.overflowing_mul_add
[f-sma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.saturating_mul_add
[f-wma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.wrapping_mul_add
[feat-un-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/#experimental-optional-features
### Version 1.2.0 news (2020-09-02)

View File

@ -8,10 +8,21 @@ as-is, without any warranty. -->
Version 1.3.0 (unreleased)
==========================
* The following methods were added to all fixed-point types and to
the `Fixed` trait:
* [`mul_add`][f-ma-1-3], [`checked_mul_add`][f-cma-1-3],
[`saturating_mul_add`][f-sma-1-3],
[`wrapping_mul_add`][f-wma-1-3],
[`overflowing_mul_add`][f-oma-1-3]
* The new experimental feature [`unwrapped`][feat-un-1-3] was added,
providing arithmetic methods that panic on overflow even when
debug assertions are disabled.
[f-cma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.checked_mul_add
[f-ma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.mul_add
[f-oma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.overflowing_mul_add
[f-sma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.saturating_mul_add
[f-wma-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.wrapping_mul_add
[feat-un-1-3]: https://tspiteri.gitlab.io/fixed/dev/fixed/#experimental-optional-features
Version 1.2.0 (2020-09-02)

View File

@ -457,6 +457,7 @@ fixed_arith! { FixedI128(i128, LeEqU128, 128), Signed }
pub(crate) trait MulDivOverflow: Sized {
fn mul_overflow(self, rhs: Self, frac_nbits: u32) -> (Self, bool);
fn mul_add_overflow(self, mul: Self, add: Self, frac_nbits: u32) -> (Self, bool);
fn div_overflow(self, rhs: Self, frac_nbits: u32) -> (Self, bool);
}
@ -473,6 +474,41 @@ macro_rules! mul_div_widen {
((prod2 >> NBITS) as $Single, overflow)
}
#[inline]
fn mul_add_overflow(
self,
mul: $Single,
add: $Single,
frac_nbits: u32,
) -> ($Single, bool) {
type Unsigned = <$Single as IntHelper>::Unsigned;
const NBITS: u32 = <$Single>::NBITS;
let self2 = <$Double>::from(self);
let mul2 = <$Double>::from(mul);
let prod2 = self2 * mul2;
let lo = (prod2 >> frac_nbits) as Unsigned;
let hi = (prod2 >> frac_nbits >> NBITS) as $Single;
if_signed_unsigned! {
$Signedness,
{
let (uns, carry) = lo.overflowing_add(add as Unsigned);
let ans = uns as $Single;
let mut expected_hi = if ans < 0 { -1 } else { 0 };
if add < 0 {
expected_hi += 1;
}
if carry {
expected_hi -= 1;
}
(ans, hi != expected_hi)
},
{
let (ans, overflow) = lo.overflowing_add(add);
(ans, overflow || hi != 0)
},
}
}
#[inline]
fn div_overflow(self, rhs: $Single, frac_nbits: u32) -> ($Single, bool) {
const NBITS: u32 = <$Single>::NBITS;
@ -497,6 +533,7 @@ trait FallbackHelper: Sized {
fn shift_lo_up(self) -> Self;
fn shift_lo_up_unsigned(self) -> Self::Unsigned;
fn combine_lo_then_shl(self, lo: Self::Unsigned, shift: u32) -> (Self, bool);
fn combine_lo_then_shl_add(self, lo: Self::Unsigned, shift: u32, add: Self) -> (Self, bool);
fn carrying_add(self, other: Self) -> (Self, Self);
}
@ -532,6 +569,21 @@ impl FallbackHelper for u128 {
}
}
#[inline]
fn combine_lo_then_shl_add(self, lo: u128, shift: u32, add: u128) -> (u128, bool) {
let (combine, overflow1) = if shift == 128 {
(self, false)
} else if shift == 0 {
(lo, self != 0)
} else {
let lo = lo >> shift;
let hi = self << (128 - shift);
(lo | hi, self >> shift != 0)
};
let (ans, overflow2) = combine.overflowing_add(add);
(ans, overflow1 || overflow2)
}
#[inline]
fn carrying_add(self, rhs: u128) -> (u128, u128) {
let (sum, overflow) = self.overflowing_add(rhs);
@ -574,6 +626,30 @@ impl FallbackHelper for i128 {
}
}
#[inline]
fn combine_lo_then_shl_add(self, lo: u128, shift: u32, add: i128) -> (i128, bool) {
let (combine_lo, combine_hi) = if shift == 128 {
(self as u128, if self < 0 { -1 } else { 0 })
} else if shift == 0 {
(lo, self)
} else {
(
(lo >> shift) | (self << (128 - shift)) as u128,
self >> shift,
)
};
let (uns, carry) = combine_lo.overflowing_add(add as u128);
let ans = uns as i128;
let mut expected_hi = if ans < 0 { -1 } else { 0 };
if add < 0 {
expected_hi += 1;
}
if carry {
expected_hi -= 1;
}
(ans, combine_hi != expected_hi)
}
#[inline]
fn carrying_add(self, rhs: i128) -> (i128, i128) {
let (sum, overflow) = self.overflowing_add(rhs);
@ -616,6 +692,31 @@ macro_rules! mul_div_fallback {
}
}
#[inline]
fn mul_add_overflow(
self,
mul: $Single,
add: $Single,
frac_nbits: u32,
) -> ($Single, bool) {
// l * r + a
let (lh, ll) = self.hi_lo();
let (rh, rl) = mul.hi_lo();
let ll_rl = ll.wrapping_mul(rl);
let lh_rl = lh.wrapping_mul(rl);
let ll_rh = ll.wrapping_mul(rh);
let lh_rh = lh.wrapping_mul(rh);
let col01 = ll_rl as <$Single as FallbackHelper>::Unsigned;
let (col01_hi, col01_lo) = col01.hi_lo();
let partial_col12 = lh_rl + col01_hi as $Single;
let (col12, carry_col3) = partial_col12.carrying_add(ll_rh);
let (col12_hi, col12_lo) = col12.hi_lo();
let ans01 = col12_lo.shift_lo_up_unsigned() + col01_lo;
let ans23 = lh_rh + col12_hi + carry_col3.shift_lo_up();
ans23.combine_lo_then_shl_add(ans01, frac_nbits, add)
}
#[inline]
fn div_overflow(self, rhs: $Single, frac_nbits: u32) -> ($Single, bool) {
if frac_nbits == 0 {

View File

@ -444,7 +444,7 @@ assert_eq!(two_point_75.to_string(), \"2.8\");
// inherent methods that do not require Frac bounds, some of which can thus be const
fixed_no_frac! {
$Fixed[$s_fixed]($Inner[$s_inner], $s_nbits),
$Fixed[$s_fixed]($Inner[$s_inner], $LeEqU, $s_nbits),
$nbytes, $bytes_val, $be_bytes, $le_bytes,
$UInner, $Signedness
}

View File

@ -15,7 +15,7 @@
macro_rules! fixed_no_frac {
(
$Fixed:ident[$s_fixed:expr]($Inner:ty[$s_inner:expr], $s_nbits:expr),
$Fixed:ident[$s_fixed:expr]($Inner:ty[$s_inner:expr], $LeEqU:tt, $s_nbits:expr),
$nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
$UInner:ty, $Signedness:tt
) => {
@ -458,6 +458,66 @@ assert!(half.is_power_of_two());
}
}
comment! {
"Multiply and add. Returns `self` × `mul` + `add`.
",
if_signed_else_empty_str! {
$Signedness,
"The product `self` × `mul` does not need to be
representable for a valid computation: if the product would overflow
but the final result would not overflow, this method still returns the
correct result.
",
},
"The `mul` parameter can have a fixed-point type like
`self` but with a different number of fractional bits.
# Panics
When debug assertions are enabled, this method panics if the result
overflows. When debug assertions are not enabled, the wrapped value
can be returned, but it is not considered a breaking change if in the
future it panics; if wrapping is required use [`wrapping_mul_add`]
instead.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
Fix::from_num(4).mul_add(Fix::from_num(0.5), Fix::from_num(3)),
Fix::from_num(5)
);
",
if_signed_else_empty_str! {
$Signedness,
"// MAX × 1.5 MAX = MAX / 2, which does not overflow
assert_eq!(Fix::MAX.mul_add(Fix::from_num(1.5), -Fix::MAX), Fix::MAX / 2);
"
},
"```
[`wrapping_mul_add`]: #method.wrapping_mul_add
";
#[inline]
pub fn mul_add<MulFrac: $LeEqU>(
self,
mul: $Fixed<MulFrac>,
add: $Fixed<Frac>,
) -> $Fixed<Frac> {
let (ans, overflow) = self.to_bits().mul_add_overflow(
mul.to_bits(),
add.to_bits(),
MulFrac::U32,
);
debug_assert!(!overflow, "overflow");
Self::from_bits(ans)
}
}
comment! {
"Remainder for Euclidean division.
@ -654,6 +714,62 @@ assert_eq!(Fix::from_num(1.5).checked_rem(Fix::from_num(0)), None);
}
}
comment! {
"Checked multiply and add.
Returns `self` × `mul` + `add`, or [`None`] on overflow.
",
if_signed_else_empty_str! {
$Signedness,
"The product `self` × `mul` does not need to be
representable for a valid computation: if the product would overflow
but the final result would not overflow, this method still returns the
correct result.
",
},
"The `mul` parameter can have a fixed-point type like
`self` but with a different number of fractional bits.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
Fix::from_num(4).checked_mul_add(Fix::from_num(0.5), Fix::from_num(3)),
Some(Fix::from_num(5))
);
assert_eq!(Fix::MAX.checked_mul_add(Fix::from_num(1), Fix::from_num(0)), Some(Fix::MAX));
assert_eq!(Fix::MAX.checked_mul_add(Fix::from_num(1), Fix::from_bits(1)), None);
",
if_signed_else_empty_str! {
$Signedness,
"// MAX × 1.5 MAX = MAX / 2, which does not overflow
assert_eq!(Fix::MAX.checked_mul_add(Fix::from_num(1.5), -Fix::MAX), Some(Fix::MAX / 2));
"
},
"```
[`None`]: https://doc.rust-lang.org/nightly/core/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_mul_add<MulFrac: $LeEqU>(
self,
mul: $Fixed<MulFrac>,
add: $Fixed<Frac>,
) -> Option<$Fixed<Frac>> {
match self.to_bits().mul_add_overflow(
mul.to_bits(),
add.to_bits(),
MulFrac::U32,
) {
(ans, false) => Some(Self::from_bits(ans)),
(_, true) => None,
}
}
}
comment! {
"Checked multiplication by an integer. Returns the
product, or [`None`] on overflow.
@ -946,6 +1062,72 @@ assert_eq!(Fix::from_num(0).saturating_sub(Fix::from_num(1)), Fix::from_num(0));
}
}
comment! {
"Saturating multiply and add.
Returns `self` × `mul` + `add`, saturating on overflow.
",
if_signed_else_empty_str! {
$Signedness,
"The product `self` × `mul` does not need to be
representable for a valid computation: if the product would overflow
but the final result would not overflow, this method still returns the
correct result.
",
},
"The `mul` parameter can have a fixed-point type like
`self` but with a different number of fractional bits.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
Fix::from_num(4).saturating_mul_add(Fix::from_num(0.5), Fix::from_num(3)),
Fix::from_num(5)
);
let half_max = Fix::MAX / 2;
assert_eq!(half_max.saturating_mul_add(Fix::from_num(3), half_max), Fix::MAX);
",
if_signed_else_empty_str! {
$Signedness,
"assert_eq!(half_max.saturating_mul_add(Fix::from_num(-5), half_max), Fix::MIN);
// MAX × 1.5 MAX = MAX / 2, which does not overflow
assert_eq!(Fix::MAX.saturating_mul_add(Fix::from_num(1.5), -Fix::MAX), half_max);
"
},
"```
";
#[inline]
pub fn saturating_mul_add<MulFrac: $LeEqU>(
self,
mul: $Fixed<MulFrac>,
add: $Fixed<Frac>,
) -> $Fixed<Frac> {
match self.to_bits().mul_add_overflow(
mul.to_bits(),
add.to_bits(),
MulFrac::U32,
) {
(ans, false) => Self::from_bits(ans),
(_, true) => {
let negative = if_signed_unsigned! {
$Signedness,
self.is_negative() != mul.is_negative(),
false,
};
if negative {
Self::MIN
} else {
Self::MAX
}
}
}
}
}
comment! {
"Saturating multiplication by an integer. Returns the product, saturating on overflow.
@ -1083,6 +1265,43 @@ assert_eq!(Fix::from_num(0)",
}
}
comment! {
"Wrapping multiply and add.
Returns `self` × `mul` + `add`, wrapping on overflow.
The `mul` parameter can have a fixed-point type like
`self` but with a different number of fractional bits.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
Fix::from_num(4).wrapping_mul_add(Fix::from_num(0.5), Fix::from_num(3)),
Fix::from_num(5)
);
assert_eq!(Fix::MAX.wrapping_mul_add(Fix::from_num(1), Fix::from_num(0)), Fix::MAX);
assert_eq!(Fix::MAX.wrapping_mul_add(Fix::from_num(1), Fix::from_bits(1)), Fix::MIN);
let wrapped = Fix::from_bits(!0 << 2);
assert_eq!(Fix::MAX.wrapping_mul_add(Fix::from_num(3), Fix::MAX), wrapped);
```
";
#[inline]
pub fn wrapping_mul_add<MulFrac: $LeEqU>(
self,
mul: $Fixed<MulFrac>,
add: $Fixed<Frac>,
) -> $Fixed<Frac> {
let (ans, _) = self.to_bits().mul_add_overflow(
mul.to_bits(),
add.to_bits(),
MulFrac::U32,
);
Self::from_bits(ans)
}
}
comment! {
"Wrapping multiplication by an integer. Returns the product, wrapping on overflow.
@ -1366,6 +1585,69 @@ let _overflow = Fix::MIN.unwrapped_sub(Fix::from_bits(1));
}
}
#[cfg(feature = "unwrapped")]
comment! {
"Unwrapped multiply and add.
Returns `self` × `mul` + `add`, panicking on overflow.
",
if_signed_else_empty_str! {
$Signedness,
"The product `self` × `mul` does not need to be
representable for a valid computation: if the product would overflow
but the final result would not overflow, this method still returns the
correct result.
",
},
"The `mul` parameter can have a fixed-point type like
`self` but with a different number of fractional bits.
This method is only available when the [`unwrapped` experimental
feature][exp] is enabled.
# Panics
Panics if the result does not fit.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
Fix::from_num(4).unwrapped_mul_add(Fix::from_num(0.5), Fix::from_num(3)),
Fix::from_num(5)
);
",
if_signed_else_empty_str! {
$Signedness,
"// MAX × 1.5 MAX = MAX / 2, which does not overflow
assert_eq!(Fix::MAX.unwrapped_mul_add(Fix::from_num(1.5), -Fix::MAX), Fix::MAX / 2);
"
},
"```
The following panics because of overflow.
```should_panic
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
let _overflow = Fix::MAX.unwrapped_mul_add(Fix::from_num(1), Fix::from_bits(1));
```
[exp]: index.html#experimental-optional-features
";
#[inline]
pub fn unwrapped_mul_add<MulFrac: $LeEqU>(
self,
mul: $Fixed<MulFrac>,
add: $Fixed<Frac>,
) -> $Fixed<Frac> {
self.checked_mul_add(mul, add).expect("overflow")
}
}
#[cfg(feature = "unwrapped")]
comment! {
"Unwrapped multiplication by an integer. Returns the product, panicking on overflow.
@ -1718,6 +2000,53 @@ assert_eq!(Fix::from_num(0)",
}
}
comment! {
"Overflowing multiply and add.
Returns a [tuple] of `self` × `mul` + `add` and a [`bool`] indicating
whether an overflow has occurred. On overflow, the wrapped value is
returned.
The `mul` parameter can have a fixed-point type like
`self` but with a different number of fractional bits.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
Fix::MAX.overflowing_mul_add(Fix::from_num(1), Fix::from_num(0)),
(Fix::MAX, false)
);
assert_eq!(
Fix::MAX.overflowing_mul_add(Fix::from_num(1), Fix::from_bits(1)),
(Fix::MIN, true)
);
assert_eq!(
Fix::MAX.overflowing_mul_add(Fix::from_num(3), Fix::MAX),
(Fix::from_bits(!0 << 2), 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_mul_add<MulFrac: $LeEqU>(
self,
mul: $Fixed<MulFrac>,
add: $Fixed<Frac>,
) -> ($Fixed<Frac>, bool) {
let (ans, overflow) = self.to_bits().mul_add_overflow(
mul.to_bits(),
add.to_bits(),
MulFrac::U32,
);
(Self::from_bits(ans), overflow)
}
}
comment! {
"Overflowing multiplication by an integer.

View File

@ -838,6 +838,9 @@ where
/// Shifts to the right by `n` bits, wrapping the truncated bits to the left end.
fn rotate_right(self, n: u32) -> Self;
/// Multiply and add. Returns `self` × `mul` + `add`.
fn mul_add(self, mul: Self, add: Self) -> Self;
/// Euclidean division by an integer.
///
/// # Panics
@ -898,6 +901,11 @@ where
/// [`None`]: https://doc.rust-lang.org/nightly/core/option/enum.Option.html#variant.None
fn checked_rem(self, rhs: Self) -> Option<Self>;
/// Checked multiply and add. Returns `self` × `mul` + `add`, or [`None`] on overflow.
///
/// [`None`]: https://doc.rust-lang.org/nightly/core/option/enum.Option.html#variant.None
fn checked_mul_add(self, mul: Self, add: Self) -> Option<Self>;
/// Checked remainder for Euclidean division. Returns the
/// remainder, or [`None`] if the divisor is zero or the division
/// results in overflow.
@ -976,6 +984,9 @@ where
/// Panics if the divisor is zero.
fn saturating_div(self, rhs: Self) -> Self;
/// Saturating multiply and add. Returns `self` × `mul` + `add`, saturating on overflow.
fn saturating_mul_add(self, mul: Self, add: Self) -> Self;
/// Saturating Euclidean division. Returns the quotient, saturating on overflow.
///
/// # Panics
@ -1005,6 +1016,9 @@ where
/// Panics if the divisor is zero.
fn wrapping_div(self, rhs: Self) -> Self;
/// Wrapping multiply and add. Returns `self` × `mul` + `add`, wrapping on overflow.
fn wrapping_mul_add(self, mul: Self, add: Self) -> Self;
/// Wrapping Euclidean division. Returns the quotient, wrapping on overflow.
///
/// # Panics
@ -1115,6 +1129,19 @@ where
/// [exp]: ../index.html#experimental-optional-features
fn unwrapped_div(self, rhs: Self) -> Self;
#[cfg(feature = "unwrapped")]
/// Unwrapped multiply and add. Returns `self` × `mul` + `add`, panicking on overflow.
///
/// This method is only available when the [`unwrapped`
/// experimental feature][exp] is enabled.
///
/// # Panics
///
/// Panics if the result does not fit.
///
/// [exp]: ../index.html#experimental-optional-features
fn unwrapped_mul_add(self, mul: Self, add: Self) -> Self;
#[cfg(feature = "unwrapped")]
/// Unwrapped Euclidean division. Returns the quotient, panicking on overflow.
///
@ -1266,6 +1293,16 @@ where
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
fn overflowing_div(self, rhs: Self) -> (Self, bool);
/// Overflowing multiply and add.
///
/// Returns a [tuple] of `self` × `mul` + `add` and a [`bool`],
/// indicating whether an overflow has occurred. On overflow, the
/// wrapped value is returned.
///
/// [`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
fn overflowing_mul_add(self, mul: Self, add: Self) -> (Self, bool);
/// Overflowing Euclidean division.
///
/// Returns a [tuple] of the quotient and a [`bool`], indicating
@ -2361,6 +2398,7 @@ macro_rules! impl_fixed {
trait_delegate! { fn checked_int_log10(self) -> Option<i32> }
trait_delegate! { fn rotate_left(self, n: u32) -> Self }
trait_delegate! { fn rotate_right(self, n: u32) -> Self }
trait_delegate! { fn mul_add(self, mul: Self, add: Self) -> Self }
trait_delegate! { fn div_euclid(self, rhs: Self) -> Self }
trait_delegate! { fn rem_euclid(self, rhs: Self) -> Self }
trait_delegate! { fn div_euclid_int(self, rhs: Self::Bits) -> Self }
@ -2371,6 +2409,7 @@ macro_rules! impl_fixed {
trait_delegate! { fn checked_mul(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_div(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_rem(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_mul_add(self, mul: Self, add: Self) -> Option<Self> }
trait_delegate! { fn checked_div_euclid(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_rem_euclid(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_mul_int(self, rhs: Self::Bits) -> Option<Self> }
@ -2385,6 +2424,7 @@ 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_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 wrapping_neg(self) -> Self }
@ -2392,6 +2432,7 @@ macro_rules! impl_fixed {
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_mul_add(self, mul: Self, add: 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 }
@ -2410,6 +2451,8 @@ macro_rules! impl_fixed {
#[cfg(feature = "unwrapped")]
trait_delegate! { fn unwrapped_div(self, rhs: Self) -> Self }
#[cfg(feature = "unwrapped")]
trait_delegate! { fn unwrapped_mul_add(self, mul: Self, add: Self) -> Self }
#[cfg(feature = "unwrapped")]
trait_delegate! { fn unwrapped_div_euclid(self, rhs: Self) -> Self }
#[cfg(feature = "unwrapped")]
trait_delegate! { fn unwrapped_mul_int(self, rhs: Self::Bits) -> Self }
@ -2428,6 +2471,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_mul_add(self, mul: Self, add: 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) }