add distance methods

This commit is contained in:
Trevor Spiteri 2021-05-04 23:27:38 +02:00
parent 454f4cbe1d
commit 2284f817b5
6 changed files with 516 additions and 32 deletions

View File

@ -95,10 +95,18 @@ The conversions supported cover the following cases.
* Fixed-point numbers can now be formatted as hexadecimal with [`Debug`]
similarly to primitive integers, for example formatting with `{:X?}` will
produce upper-case hexadecimal fixed-point numbers.
* The following method was added to all fixed-point numbers, to the
* The following methods were added to all fixed-point numbers, to the
[`Fixed`][tf-1-9] trait, and to the [`Wrapping`][w-1-9] and
[`Unwrapped`][u-1-9] wrappers:
* [`is_zero`][f-iz-1-9]
* [`distance`][f-d-1-9]
* The following methods were added to all fixed-point numbers and to the
[`Fixed`][tf-1-9] trait:
* [`checked_distance`][f-cd-1-9], [`saturating_distance`][f-sd-1-9],
[`wrapping_distance`][f-wd-1-9], [`unwrapped_distance`][f-ud-1-9],
[`overflowing_distance`][f-od-1-9]
* The [`unsigned_distance`][f-ud-1-9] method was added to all signed
fixed-point types and to the [`FixedSigned`][tfs-1-9] trait.
* The following associated types were added to the [`Fixed`][tf-1-9] trait:
* [`Signed`][tf-s-1-9], [`Unsigned`][tf-u-1-9]
* The following traits from the [*bytemuck* crate] were implemented for all
@ -127,7 +135,14 @@ The conversions supported cover the following cases.
[bm-p-1]: https://docs.rs/bytemuck/^1/bytemuck/trait.Pod.html
[bm-tw-1]: https://docs.rs/bytemuck/^1/bytemuck/trait.TransparentWrapper.html
[bm-z-1]: https://docs.rs/bytemuck/^1/bytemuck/trait.Zeroable.html
[f-cd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.checked_distance
[f-d-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.distance
[f-iz-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.is_zero
[f-od-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.overflowing_distance
[f-sd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.saturating_distance
[f-ud-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_distance
[f-unsd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unsigned_distance
[f-wd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.wrapping_distance
[fof-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedOptionalFeatures.html
[leu128-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU128.html
[leu16-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU16.html
@ -137,6 +152,7 @@ The conversions supported cover the following cases.
[tf-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html
[tf-s-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#associatedtype.Signed
[tf-u-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#associatedtype.Unsigned
[tfs-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedSigned.html
[u-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.Unwrapped.html
[uns-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.Unsigned.html
[w-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.Wrapping.html

View File

@ -11,10 +11,18 @@ Version 1.9.0 (unreleased)
* Fixed-point numbers can now be formatted as hexadecimal with [`Debug`]
similarly to primitive integers, for example formatting with `{:X?}` will
produce upper-case hexadecimal fixed-point numbers.
* The following method was added to all fixed-point numbers, to the
* The following methods were added to all fixed-point numbers, to the
[`Fixed`][tf-1-9] trait, and to the [`Wrapping`][w-1-9] and
[`Unwrapped`][u-1-9] wrappers:
* [`is_zero`][f-iz-1-9]
* [`distance`][f-d-1-9]
* The following methods were added to all fixed-point numbers and to the
[`Fixed`][tf-1-9] trait:
* [`checked_distance`][f-cd-1-9], [`saturating_distance`][f-sd-1-9],
[`wrapping_distance`][f-wd-1-9], [`unwrapped_distance`][f-ud-1-9],
[`overflowing_distance`][f-od-1-9]
* The [`unsigned_distance`][f-ud-1-9] method was added to all signed
fixed-point types and to the [`FixedSigned`][tfs-1-9] trait.
* The following associated types were added to the [`Fixed`][tf-1-9] trait:
* [`Signed`][tf-s-1-9], [`Unsigned`][tf-u-1-9]
* The following traits from the [*bytemuck* crate] were implemented for all
@ -43,7 +51,14 @@ Compatibility notes
[bm-p-1]: https://docs.rs/bytemuck/^1/bytemuck/trait.Pod.html
[bm-tw-1]: https://docs.rs/bytemuck/^1/bytemuck/trait.TransparentWrapper.html
[bm-z-1]: https://docs.rs/bytemuck/^1/bytemuck/trait.Zeroable.html
[f-cd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.checked_distance
[f-d-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.distance
[f-iz-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.is_zero
[f-od-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.overflowing_distance
[f-sd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.saturating_distance
[f-ud-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unwrapped_distance
[f-unsd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.unsigned_distance
[f-wd-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.FixedI32.html#method.wrapping_distance
[fof-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedOptionalFeatures.html
[leu128-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU128.html
[leu16-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.LeEqU16.html
@ -53,6 +68,7 @@ Compatibility notes
[tf-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html
[tf-s-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#associatedtype.Signed
[tf-u-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.Fixed.html#associatedtype.Unsigned
[tfs-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/traits/trait.FixedSigned.html
[u-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.Unwrapped.html
[uns-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/types/extra/trait.Unsigned.html
[w-1-9]: https://tspiteri.gitlab.io/fixed/dev/fixed/struct.Wrapping.html

View File

@ -922,6 +922,114 @@ assert_eq!(Fix::MIN.unsigned_abs(), min_as_unsigned);
}
}
comment! {
"Returns the distance from `self` to `other`.
The distance is the absolute value of the difference.
",
if_signed_else_empty_str! {
$Signedness;
"# 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_distance`] instead.
",
},
"# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::ONE.distance(Fix::from_num(5)), Fix::from_num(4));
",
if_signed_else_empty_str! {
$Signedness;
"assert_eq!(Fix::from_num(-1).distance(Fix::from_num(2)), Fix::from_num(3));
",
},
"```
",
if_signed_else_empty_str! {
$Signedness;
"
[`wrapping_distance`]: Self::wrapping_distance
"
};
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn distance(self, other: $Fixed<Frac>) -> $Fixed<Frac> {
let s = self.to_bits();
let o = other.to_bits();
let d = if s < o { o - s } else { s - o };
Self::from_bits(d)
}
}
if_signed! {
$Signedness;
comment! {
"Returns the distance from `self` to `other` using an
unsigned type without any wrapping or panicking.
The distance is the absolute value of the difference.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, ", ", $s_ufixed, "};
type Fix = ", $s_fixed, "<U4>;
type UFix = ", $s_ufixed, "<U4>;
assert_eq!(Fix::from_num(-1).unsigned_distance(Fix::from_num(2)), UFix::from_num(3));
assert_eq!(Fix::MIN.unsigned_distance(Fix::MAX), UFix::MAX);
```
";
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn unsigned_distance(self, other: $Fixed<Frac>) -> $UFixed<Frac> {
let s = self.to_bits();
let o = other.to_bits();
let d = if s < o {
o.wrapping_sub(s)
} else {
s.wrapping_sub(o)
};
$UFixed::from_bits(d as $UInner)
}
}
}
comment! {
"Returns the mean of `self` and `other`.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::from_num(3).mean(Fix::from_num(4)), Fix::from_num(3.5));
",
if_signed_else_empty_str! {
$Signedness;
"assert_eq!(Fix::from_num(-3).mean(Fix::from_num(4)), Fix::from_num(0.5));
",
},
"```
";
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn mean(self, other: $Fixed<Frac>) -> $Fixed<Frac> {
// a & b == common bits
// a ^ b == different bits
// a + b == 2 * (a & b) + (a ^ b)
// (a + b) / 2 = (a & b) + (a ^ b) / 2
let (a, b) = (self.to_bits(), other.to_bits());
$Fixed::from_bits((a & b) + ((a ^ b) >> 1))
}
}
if_unsigned! {
$Signedness;
comment! {
@ -986,35 +1094,6 @@ assert_eq!(Fix::from_num(6.5).next_power_of_two(), Fix::from_num(8));
}
}
comment! {
"Returns the mean of `self` and `other`.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::from_num(3).mean(Fix::from_num(4)), Fix::from_num(3.5));
",
if_signed_else_empty_str! {
$Signedness;
"assert_eq!(Fix::from_num(-3).mean(Fix::from_num(4)), Fix::from_num(0.5));
",
},
"```
";
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn mean(self, other: $Fixed<Frac>) -> $Fixed<Frac> {
// a & b == common bits
// a ^ b == different bits
// a + b == 2 * (a & b) + (a ^ b)
// (a + b) / 2 = (a & b) + (a ^ b) / 2
let (a, b) = (self.to_bits(), other.to_bits());
$Fixed::from_bits((a & b) + ((a ^ b) >> 1))
}
}
comment! {
"Bitwise NOT. Usable in constant context.
@ -1492,6 +1571,53 @@ assert_eq!(Fix::MIN.checked_abs(), None);
}
}
comment! {
"Checked distance. Returns the distance from `self` to `other`",
if_signed_else_empty_str! { $Signedness; ", or [`None`] on overflow" },
".
The distance is the absolute value of the difference.
",
if_unsigned_else_empty_str! {
$Signedness;
"Can never overflow for unsigned types.
",
},
"# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::ONE.checked_distance(Fix::from_num(5)), Some(Fix::from_num(4)));
",
if_signed_unsigned!(
$Signedness,
"assert_eq!(Fix::MIN.checked_distance(Fix::ZERO), None);",
"assert_eq!(Fix::ZERO.checked_distance(Fix::MAX), Some(Fix::MAX));",
),
"
```
";
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn checked_distance(self, other: $Fixed<Frac>) -> Option<$Fixed<Frac>> {
if_signed! {
$Signedness;
if self.to_bits() < other.to_bits() {
other.checked_sub(self)
} else {
self.checked_sub(other)
}
}
if_unsigned! {
$Signedness;
Some(self.distance(other))
}
}
}
if_unsigned! {
$Signedness;
comment! {
@ -1603,7 +1729,7 @@ type Fix = ", $s_fixed, "<U4>;
"assert_eq!(Fix::ONE.saturating_sub(Fix::from_num(3)), Fix::from_num(-2));
assert_eq!(Fix::MIN.saturating_sub(Fix::ONE), Fix::MIN);",
"assert_eq!(Fix::from_num(5).saturating_sub(Fix::from_num(3)), Fix::from_num(2));
assert_eq!(Fix::ZERO.saturating_sub(Fix::from_num(1)), Fix::from_num(0));",
assert_eq!(Fix::ZERO.saturating_sub(Fix::ONE), Fix::ZERO);",
),
"
```
@ -1748,6 +1874,52 @@ assert_eq!(Fix::MIN.saturating_abs(), Fix::MAX);
}
}
comment! {
"Saturating distance. Returns the distance from `self` to `other`",
if_signed_else_empty_str! { $Signedness; ", saturating on overflow" },
".
The distance is the absolute value of the difference.
",
if_unsigned_else_empty_str! {
$Signedness;
"Can never overflow for unsigned types.
",
},
"# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::ONE.saturating_distance(Fix::from_num(5)), Fix::from_num(4));
",
if_signed_unsigned!(
$Signedness,
"assert_eq!(Fix::MIN.saturating_distance(Fix::MAX), Fix::MAX);",
"assert_eq!(Fix::ZERO.saturating_distance(Fix::MAX), Fix::MAX);",
),
"
```
";
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn saturating_distance(self, other: $Fixed<Frac>) -> $Fixed<Frac> {
if_signed! {
$Signedness;
match self.checked_distance(other) {
None => $Fixed::MAX,
Some(dist) => dist,
}
}
if_unsigned! {
$Signedness;
self.distance(other)
}
}
}
comment! {
"Wrapping negation. Returns the negated value, wrapping on overflow.
@ -1995,6 +2167,46 @@ assert_eq!(Fix::MIN.wrapping_abs(), Fix::MIN);
}
}
comment! {
"Wrapping distance. Returns the distance from `self` to `other`",
if_signed_else_empty_str! { $Signedness; ", wrapping on overflow" },
".
The distance is the absolute value of the difference.
",
if_unsigned_else_empty_str! {
$Signedness;
"Can never overflow for unsigned types.
",
},
"# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::ONE.wrapping_distance(Fix::from_num(5)), Fix::from_num(4));
",
if_signed_unsigned!(
$Signedness,
"assert_eq!(Fix::MIN.wrapping_distance(Fix::MAX), -Fix::DELTA);",
"assert_eq!(Fix::ZERO.wrapping_distance(Fix::MAX), Fix::MAX);",
),
"
```
";
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn wrapping_distance(self, other: $Fixed<Frac>) -> $Fixed<Frac> {
if_signed_unsigned!(
$Signedness,
self.overflowing_distance(other).0,
self.distance(other),
)
}
}
if_unsigned! {
$Signedness;
comment! {
@ -2463,6 +2675,60 @@ let _overflow = Fix::MIN.unwrapped_abs();
}
}
comment! {
"Unwrapped distance. Returns the distance from `self` to `other`",
if_signed_else_empty_str! { $Signedness; ", panicking on overflow" },
".
The distance is the absolute value of the difference.
",
if_signed_unsigned!(
$Signedness,
"# Panics
Panics if the result does not fit.",
"Can never overflow for unsigned types.",
),
"
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(Fix::ONE.unwrapped_distance(Fix::from_num(5)), Fix::from_num(4));
",
if_unsigned_else_empty_str! {
$Signedness;
"assert_eq!(Fix::ZERO.unwrapped_distance(Fix::MAX), Fix::MAX);
"
},
"```
",
if_signed_else_empty_str! {
$Signedness;
"
The following panics because of overflow.
```should_panic
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
let _overflow = Fix::MIN.unwrapped_distance(Fix::ZERO);
```
"
};
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn unwrapped_distance(self, other: $Fixed<Frac>) -> $Fixed<Frac> {
if_signed_unsigned!(
$Signedness,
self.checked_distance(other).expect("overflow"),
self.distance(other),
)
}
}
if_unsigned! {
$Signedness;
comment! {
@ -2810,6 +3076,65 @@ assert_eq!(Fix::MIN.overflowing_abs(), (Fix::MIN, true));
}
}
}
comment! {
"Overflowing distance.
Returns a [tuple] of the distance from `self` to `other` and ",
if_signed_unsigned!(
$Signedness,
"a [`bool`] indicating whether an overflow has
occurred. On overflow, the wrapped value is returned.",
"[`false`], as overflow can never happen for unsigned types.",
),
"
The distance is the absolute value of the difference.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
Fix::ONE.overflowing_distance(Fix::from_num(5)),
(Fix::from_num(4), false)
);
",
if_signed_unsigned!(
$Signedness,
"assert_eq!(
Fix::MIN.overflowing_distance(Fix::MAX),
(-Fix::DELTA, true)
);",
"assert_eq!(
Fix::ZERO.overflowing_distance(Fix::MAX),
(Fix::MAX, false)
);",
),
"
```
";
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn overflowing_distance(
self,
other: $Fixed<Frac>,
) -> ($Fixed<Frac>, bool) {
if_signed! {
$Signedness;
if self.to_bits() < other.to_bits() {
other.overflowing_sub(self)
} else {
self.overflowing_sub(other)
}
}
if_unsigned! {
$Signedness;
(self.distance(other), false)
}
}
}
}
};
}

View File

@ -1199,6 +1199,13 @@ where
/// <code>FixedU32::[is\_zero][FixedU32::is_zero]</code>.
fn is_zero(self) -> bool;
/// Returns the distance from `self` to `other`.
///
/// See also <code>FixedI32::[distance][FixedI32::distance]</code> and
/// <code>FixedU32::[distance][FixedU32::distance]</code>.
#[must_use = "this returns the result of the operation, without modifying the original"]
fn distance(self, other: Self) -> Self;
/// Returns the mean of `self` and `other`.
///
/// See also <code>FixedI32::[mean][FixedI32::mean]</code> and
@ -1449,6 +1456,16 @@ where
#[must_use = "this returns the result of the operation, without modifying the original"]
fn checked_shr(self, rhs: u32) -> Option<Self>;
/// Checked distance. Returns the distance from `self` to `other`, or
/// [`None`] on overflow.
///
/// See also
/// <code>FixedI32::[checked\_distance][FixedI32::checked_distance]</code>
/// and
/// <code>FixedU32::[checked\_distance][FixedU32::checked_distance]</code>.
#[must_use = "this returns the result of the operation, without modifying the original"]
fn checked_distance(self, other: Self) -> Option<Self>;
/// Saturated negation. Returns the negated value, saturating on overflow.
///
/// See also
@ -1571,6 +1588,16 @@ where
#[must_use = "this returns the result of the operation, without modifying the original"]
fn saturating_rem_euclid_int(self, rhs: Self::Bits) -> Self;
/// Saturating distance. Returns the distance from `self` to `other`,
/// saturating on overflow.
///
/// See also
/// <code>FixedI32::[saturating\_distance][FixedI32::saturating_distance]</code>
/// and
/// <code>FixedU32::[saturating\_distance][FixedU32::saturating_distance]</code>.
#[must_use = "this returns the result of the operation, without modifying the original"]
fn saturating_distance(self, other: Self) -> Self;
/// Wrapping negation. Returns the negated value, wrapping on overflow.
///
/// See also <code>FixedI32::[wrapping\_neg][FixedI32::wrapping_neg]</code>
@ -1720,6 +1747,16 @@ where
#[must_use = "this returns the result of the operation, without modifying the original"]
fn wrapping_shr(self, rhs: u32) -> Self;
/// Wrapping distance. Returns the distance from `self` to `other`, wrapping
/// on overflow.
///
/// See also
/// <code>FixedI32::[wrapping\_distance][FixedI32::wrapping_distance]</code>
/// and
/// <code>FixedU32::[wrapping\_distance][FixedU32::wrapping_distance]</code>.
#[must_use = "this returns the result of the operation, without modifying the original"]
fn wrapping_distance(self, other: Self) -> Self;
/// Unwrapped negation. Returns the negated value, panicking on overflow.
///
/// See also
@ -1968,6 +2005,20 @@ where
#[must_use = "this returns the result of the operation, without modifying the original"]
fn unwrapped_shr(self, rhs: u32) -> Self;
/// Unwrapped distance. Returns the distance from `self` to `other`,
/// panicking on overflow.
///
/// # Panics
///
/// Panics if the result does not fit.
///
/// See also
/// <code>FixedI32::[unwrapped\_distance][FixedI32::unwrapped_distance]</code>
/// and
/// <code>FixedU32::[unwrapped\_distance][FixedU32::unwrapped_distance]</code>.
#[must_use = "this returns the result of the operation, without modifying the original"]
fn unwrapped_distance(self, other: Self) -> Self;
/// Overflowing negation.
///
/// Returns a [tuple] of the negated value and a [`bool`],
@ -2174,6 +2225,19 @@ where
/// <code>FixedU32::[overflowing\_shr][FixedU32::overflowing_shr]</code>.
#[must_use = "this returns the result of the operation, without modifying the original"]
fn overflowing_shr(self, rhs: u32) -> (Self, bool);
/// Overflowing distance.
///
/// Returns a [tuple] of the distance from `self` to `other` and a [`bool`],
/// indicating whether an overflow has occurred. On overflow, the wrapped
/// value is returned.
///
/// See also
/// <code>FixedI32::[overflowing\_distance][FixedI32::overflowing_distance]</code>
/// and
/// <code>FixedU32::[overflowing\_distance][FixedU32::overflowing_distance]</code>.
#[must_use = "this returns the result of the operation, without modifying the original"]
fn overflowing_distance(self, other: Self) -> (Self, bool);
}
/// This trait provides methods common to all signed fixed-point numbers.
@ -2214,6 +2278,13 @@ where
/// See also <code>FixedI32::[unsigned\_abs][FixedI32::unsigned_abs]</code>.
fn unsigned_abs(self) -> Self::Unsigned;
/// Returns the distance from `self` to `other` using an unsigned type
/// without any wrapping or panicking.
///
/// See also
/// <code>FixedI32::[unsigned\_distance][FixedI32::unsigned_distance]</code>.
fn unsigned_distance(self, other: Self) -> Self::Unsigned;
/// Returns a number representing the sign of `self`.
///
/// See also <code>FixedI32::[signum][FixedI32::signum]</code>.
@ -3296,6 +3367,7 @@ macro_rules! impl_fixed {
trait_delegate! { fn rotate_left(self, n: u32) -> Self }
trait_delegate! { fn rotate_right(self, n: u32) -> Self }
trait_delegate! { fn is_zero(self) -> bool }
trait_delegate! { fn distance(self, other: Self) -> Self }
trait_delegate! { fn mean(self, other: Self) -> Self }
trait_delegate! { fn recip(self) -> Self }
trait_delegate! { fn mul_add(self, mul: Self, add: Self) -> Self }
@ -3322,6 +3394,7 @@ macro_rules! impl_fixed {
trait_delegate! { fn checked_rem_euclid_int(self, rhs: Self::Bits) -> Option<Self> }
trait_delegate! { fn checked_shl(self, rhs: u32) -> Option<Self> }
trait_delegate! { fn checked_shr(self, rhs: u32) -> Option<Self> }
trait_delegate! { fn checked_distance(self, other: Self) -> Option<Self> }
trait_delegate! { fn saturating_neg(self) -> Self }
trait_delegate! { fn saturating_add(self, rhs: Self) -> Self }
trait_delegate! { fn saturating_sub(self, rhs: Self) -> Self }
@ -3334,6 +3407,7 @@ macro_rules! impl_fixed {
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 saturating_distance(self, other: Self) -> 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 }
@ -3349,6 +3423,7 @@ macro_rules! impl_fixed {
trait_delegate! { fn wrapping_rem_euclid_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn wrapping_shl(self, rhs: u32) -> Self }
trait_delegate! { fn wrapping_shr(self, rhs: u32) -> Self }
trait_delegate! { fn wrapping_distance(self, other: Self) -> Self }
trait_delegate! { fn unwrapped_neg(self) -> Self }
trait_delegate! { fn unwrapped_add(self, rhs: Self) -> Self }
trait_delegate! { fn unwrapped_sub(self, rhs: Self) -> Self }
@ -3367,6 +3442,7 @@ macro_rules! impl_fixed {
trait_delegate! { fn unwrapped_rem_euclid_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn unwrapped_shl(self, rhs: u32) -> Self }
trait_delegate! { fn unwrapped_shr(self, rhs: u32) -> Self }
trait_delegate! { fn unwrapped_distance(self, other: Self) -> Self }
trait_delegate! { fn overflowing_neg(self) -> (Self, bool) }
trait_delegate! { fn overflowing_add(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_sub(self, rhs: Self) -> (Self, bool) }
@ -3382,6 +3458,7 @@ macro_rules! impl_fixed {
trait_delegate! { fn overflowing_rem_euclid_int(self, rhs: Self::Bits) -> (Self, bool) }
trait_delegate! { fn overflowing_shl(self, rhs: u32) -> (Self, bool) }
trait_delegate! { fn overflowing_shr(self, rhs: u32) -> (Self, bool) }
trait_delegate! { fn overflowing_distance(self, other: Self) -> (Self, bool) }
}
impl<Frac: $LeEqU> FromFixed for $Fixed<Frac> {
@ -3582,6 +3659,7 @@ macro_rules! impl_fixed {
trait_delegate! { fn signed_bits(self) -> u32 }
trait_delegate! { fn abs(self) -> Self }
trait_delegate! { fn unsigned_abs(self) -> Self::Unsigned }
trait_delegate! { fn unsigned_distance(self, other: Self) -> Self::Unsigned }
trait_delegate! { fn signum(self) -> Self }
trait_delegate! { fn checked_abs(self) -> Option<Self> }
trait_delegate! { fn checked_signum(self) -> Option<Self> }

View File

@ -995,6 +995,36 @@ impl<F: Fixed> Unwrapped<F> {
self.0.is_zero()
}
/// Returns the distance from `self` to `other`.
///
/// See also <code>FixedI32::[distance][FixedI32::distance]</code> and
/// <code>FixedU32::[distance][FixedU32::distance]</code>.
///
/// # Panics
///
/// Panics on overflow.
///
/// # Examples
///
/// ```rust
/// use fixed::{types::I16F16, Unwrapped};
/// type Unwr = Unwrapped<I16F16>;
/// assert_eq!(Unwr::from_num(-1).distance(Unwr::from_num(4)), Unwr::from_num(5));
/// ```
///
/// The following panics because of overflow.
///
/// ```should_panic
/// use fixed::{types::I16F16, Unwrapped};
/// type Unwr = Unwrapped<I16F16>;
/// let _overflow = Unwr::MIN.distance(Unwr::ZERO);
/// ```
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn distance(self, other: Unwrapped<F>) -> Unwrapped<F> {
Unwrapped(self.0.unwrapped_distance(other.0))
}
/// Returns the mean of `self` and `other`.
///
/// See also <code>FixedI32::[mean][FixedI32::mean]</code> and

View File

@ -943,6 +943,25 @@ impl<F: Fixed> Wrapping<F> {
self.0.is_zero()
}
/// Returns the distance from `self` to `other`.
///
/// See also <code>FixedI32::[distance][FixedI32::distance]</code> and
/// <code>FixedU32::[distance][FixedU32::distance]</code>.
///
/// # Examples
///
/// ```rust
/// use fixed::{types::I16F16, Wrapping};
/// type Wr = Wrapping<I16F16>;
/// assert_eq!(Wr::from_num(-1).distance(Wr::from_num(4)), Wr::from_num(5));
/// assert_eq!(Wr::MIN.distance(Wr::MAX), -Wr::DELTA);
/// ```
#[inline]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn distance(self, other: Wrapping<F>) -> Wrapping<F> {
Wrapping(self.0.wrapping_distance(other.0))
}
/// Returns the mean of `self` and `other`.
///
/// See also <code>FixedI32::[mean][FixedI32::mean]</code> and