add wrapping/traits to reciprocal methods

This commit is contained in:
Trevor Spiteri 2020-10-20 21:23:14 +02:00
parent b09acfdf56
commit 6ec8433128
5 changed files with 121 additions and 1 deletions

View File

@ -8,6 +8,12 @@ as-is, without any warranty. -->
Version 1.4.0 (unreleased)
==========================
* The following methods were added to all fixed-point types, to the
[`Fixed`][tf-1-4] trait, and to the [`Wrapping`][w-1-4] wrapper:
* [`recip`][f-rec-1-4], [`checked_recip`][f-crec-1-4],
[`saturating_recip`][f-srec-1-4],
[`wrapping_recip`][f-wrec-1-4],
[`overflowing_recip`][f-orec-1-4]
* For the experimental feature [`num-traits`][feat-exp-1-4], the
following traits were implemented where applicable ([issue 23]):
* [`Num`][nt-0-2-num]
@ -21,6 +27,11 @@ Version 1.4.0 (unreleased)
to write manually ([issue 24]). This makes it incompatible with
the version in 1.3.0.
[f-crec-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.checked_recip
[f-orec-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.overflowing_recip
[f-rec-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.recip
[f-srec-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.saturating_recip
[f-wrec-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.wrapping_recip
[feat-exp-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/#experimental-optional-features
[issue 23]: https://gitlab.com/tspiteri/fixed/-/issues/23
[issue 24]: https://gitlab.com/tspiteri/fixed/-/issues/24
@ -33,6 +44,8 @@ Version 1.4.0 (unreleased)
[nt-0-2-signed]: https://docs.rs/num-traits/^0.2/num_traits/sign/trait.Signed.html
[nt-0-2-tp]: https://docs.rs/num-traits/^0.2/num_traits/cast/trait.ToPrimitive.html
[nt-0-2-unsigned]: https://docs.rs/num-traits/^0.2/num_traits/sign/trait.Unsigned.html
[tf-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html
[w-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.Wrapping.html
Version 1.3.0 (2020-10-15)
==========================

View File

@ -110,7 +110,7 @@ macro_rules! impl_traits {
type Output = Self;
#[inline]
fn inv(self) -> Self::Output {
Self::one() / self
self.recip()
}
}

View File

@ -847,6 +847,13 @@ where
/// Shifts to the right by `n` bits, wrapping the truncated bits to the left end.
fn rotate_right(self, n: u32) -> Self;
/// Returns the reciprocal.
///
/// # Panics
///
/// Panics if `self` is zero.
fn recip(self) -> Self;
/// Multiply and add. Returns `self` × `mul` + `add`.
fn mul_add(self, mul: Self, add: Self) -> Self;
@ -910,6 +917,12 @@ where
/// [`None`]: https://doc.rust-lang.org/nightly/core/option/enum.Option.html#variant.None
fn checked_rem(self, rhs: Self) -> Option<Self>;
/// Checked reciprocal. Returns the reciprocal, or [`None`] if
/// `self` is zero or on overflow.
///
/// [`None`]: https://doc.rust-lang.org/nightly/core/option/enum.Option.html#variant.None
fn checked_recip(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
@ -993,6 +1006,13 @@ where
/// Panics if the divisor is zero.
fn saturating_div(self, rhs: Self) -> Self;
/// Saturating reciprocal.
///
/// # Panics
///
/// Panics if `self` is zero.
fn saturating_recip(self) -> Self;
/// Saturating multiply and add. Returns `self` × `mul` + `add`, saturating on overflow.
fn saturating_mul_add(self, mul: Self, add: Self) -> Self;
@ -1025,6 +1045,13 @@ where
/// Panics if the divisor is zero.
fn wrapping_div(self, rhs: Self) -> Self;
/// Wrapping reciprocal.
///
/// # Panics
///
/// Panics if `self` is zero.
fn wrapping_recip(self) -> Self;
/// Wrapping multiply and add. Returns `self` × `mul` + `add`, wrapping on overflow.
fn wrapping_mul_add(self, mul: Self, add: Self) -> Self;
@ -1138,6 +1165,19 @@ where
/// [exp]: ../index.html#experimental-optional-features
fn unwrapped_div(self, rhs: Self) -> Self;
#[cfg(feature = "unwrapped")]
/// Unwrapped reciprocal. Returns reciprocal, panicking on overflow.
///
/// This method is only available when the [`unwrapped`
/// experimental feature][exp] is enabled.
///
/// # Panics
///
/// Panics if `self` is zero or on overflow.
///
/// [exp]: ../index.html#experimental-optional-features
fn unwrapped_recip(self) -> Self;
#[cfg(feature = "unwrapped")]
/// Unwrapped multiply and add. Returns `self` × `mul` + `add`, panicking on overflow.
///
@ -1302,6 +1342,20 @@ where
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
fn overflowing_div(self, rhs: Self) -> (Self, bool);
/// Overflowing reciprocal.
///
/// Returns a [tuple] of the reciprocal of `self` and a [`bool`],
/// indicating whether an overflow has occurred. On overflow, the
/// wrapped value is returned.
///
/// # Panics
///
/// Panics if `self` 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_recip(self) -> (Self, bool);
/// Overflowing multiply and add.
///
/// Returns a [tuple] of `self` × `mul` + `add` and a [`bool`],
@ -2407,6 +2461,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 recip(self) -> 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 }
@ -2418,6 +2473,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_recip(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> }
@ -2433,6 +2489,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_recip(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 }
@ -2441,6 +2498,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_recip(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 }
@ -2460,6 +2518,8 @@ macro_rules! impl_fixed {
#[cfg(feature = "unwrapped")]
trait_delegate! { fn unwrapped_div(self, rhs: Self) -> Self }
#[cfg(feature = "unwrapped")]
trait_delegate! { fn unwrapped_recip(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 }
@ -2480,6 +2540,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_recip(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) }

View File

@ -619,6 +619,32 @@ impl<F: Fixed> Unwrapped<F> {
Unwrapped(self.0.rotate_right(n))
}
/// Returns the reciprocal (inverse), 1/`self`.
///
/// # Panics
///
/// Panics if `self` is zero or on overflow.
///
/// # Examples
///
/// ```rust
/// use fixed::{types::I8F24, Unwrapped};
/// let quarter = Unwrapped(I8F24::from_num(0.25));
/// assert_eq!(quarter.recip(), Unwrapped(I8F24::from_num(4)));
/// ```
///
/// The following panics because of overflow.
///
/// ```should_panic
/// use fixed::{types::I8F24, Unwrapped};
/// let frac_1_512 = Unwrapped(I8F24::from_num(1) / 512);
/// let _overflow = frac_1_512.recip();
/// ```
#[inline]
pub fn recip(self) -> Unwrapped<F> {
Unwrapped(self.0.recip())
}
/// Multiply and add. Returns `self` × `mul` + `add`.
///
/// # Panics

View File

@ -570,6 +570,26 @@ impl<F: Fixed> Wrapping<F> {
Wrapping(self.0.rotate_right(n))
}
/// Returns the reciprocal (inverse), 1/`self`.
///
/// # Panics
///
/// Panics if `self` is zero.
///
/// # Examples
///
/// ```rust
/// use fixed::{types::I8F24, Wrapping};
/// let quarter = Wrapping(I8F24::from_num(0.25));
/// let frac_1_512 = Wrapping(I8F24::from_num(1) / 512);
/// assert_eq!(quarter.recip(), Wrapping(I8F24::from_num(4)));
/// assert_eq!(frac_1_512.recip(), Wrapping(I8F24::from_num(0)));
/// ```
#[inline]
pub fn recip(self) -> Wrapping<F> {
Wrapping(self.0.wrapping_recip())
}
/// Multiply and add. Returns `self` × `mul` + `add`.
///
/// # Examples