implement reciprocal methods
This commit is contained in:
parent
20e5243c45
commit
b09acfdf56
86
src/lib.rs
86
src/lib.rs
|
@ -382,7 +382,7 @@ macro_rules! fixed {
|
||||||
$s_nbits_m1:expr, $s_nbits_m2:expr, $s_nbits_m3:expr, $s_nbits_m4:expr
|
$s_nbits_m1:expr, $s_nbits_m2:expr, $s_nbits_m3:expr, $s_nbits_m4:expr
|
||||||
),
|
),
|
||||||
$nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
|
$nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
|
||||||
$UInner:ty, $Signedness:tt,
|
$UFixed:ident, $UInner:ty, $Signedness:tt,
|
||||||
$LeEqU_C0:tt, $LeEqU_C1:tt, $LeEqU_C2:tt, $LeEqU_C3:tt
|
$LeEqU_C0:tt, $LeEqU_C1:tt, $LeEqU_C2:tt, $LeEqU_C3:tt
|
||||||
) => {
|
) => {
|
||||||
fixed! {
|
fixed! {
|
||||||
|
@ -392,7 +392,7 @@ macro_rules! fixed {
|
||||||
$s_nbits_m1, $s_nbits_m2, $s_nbits_m3, $s_nbits_m4
|
$s_nbits_m1, $s_nbits_m2, $s_nbits_m3, $s_nbits_m4
|
||||||
),
|
),
|
||||||
$nbytes, $bytes_val, $be_bytes, $le_bytes,
|
$nbytes, $bytes_val, $be_bytes, $le_bytes,
|
||||||
$UInner, $Signedness,
|
$UFixed, $UInner, $Signedness,
|
||||||
$LeEqU_C0, $LeEqU_C1, $LeEqU_C2, $LeEqU_C3
|
$LeEqU_C0, $LeEqU_C1, $LeEqU_C2, $LeEqU_C3
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -403,7 +403,7 @@ macro_rules! fixed {
|
||||||
$s_nbits_m1:expr, $s_nbits_m2:expr, $s_nbits_m3:expr, $s_nbits_m4:expr
|
$s_nbits_m1:expr, $s_nbits_m2:expr, $s_nbits_m3:expr, $s_nbits_m4:expr
|
||||||
),
|
),
|
||||||
$nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
|
$nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
|
||||||
$UInner:ty, $Signedness:tt,
|
$UFixed:ident, $UInner:ty, $Signedness:tt,
|
||||||
$LeEqU_C0:tt, $LeEqU_C1:tt, $LeEqU_C2:tt, $LeEqU_C3:tt
|
$LeEqU_C0:tt, $LeEqU_C1:tt, $LeEqU_C2:tt, $LeEqU_C3:tt
|
||||||
) => {
|
) => {
|
||||||
comment! {
|
comment! {
|
||||||
|
@ -477,7 +477,7 @@ assert_eq!(two_point_75.to_string(), \"2.8\");
|
||||||
// inherent methods that require Frac bounds, and cannot be const
|
// inherent methods that require Frac bounds, and cannot be const
|
||||||
fixed_frac! {
|
fixed_frac! {
|
||||||
$Fixed[$s_fixed]($Inner[$s_inner], $LeEqU, $s_nbits, $s_nbits_m1, $s_nbits_m4),
|
$Fixed[$s_fixed]($Inner[$s_inner], $LeEqU, $s_nbits, $s_nbits_m1, $s_nbits_m4),
|
||||||
$UInner, $Signedness
|
$UFixed, $UInner, $Signedness
|
||||||
}
|
}
|
||||||
fixed_const! {
|
fixed_const! {
|
||||||
$Fixed[$s_fixed]($LeEqU, $s_nbits, $s_nbits_m1, $s_nbits_m2, $s_nbits_m3, $s_nbits_m4),
|
$Fixed[$s_fixed]($LeEqU, $s_nbits, $s_nbits_m1, $s_nbits_m2, $s_nbits_m3, $s_nbits_m4),
|
||||||
|
@ -491,21 +491,21 @@ fixed! {
|
||||||
"An eight-bit fixed-point unsigned",
|
"An eight-bit fixed-point unsigned",
|
||||||
FixedU8(u8, LeEqU8, "8", "7", "6", "5", "4"),
|
FixedU8(u8, LeEqU8, "8", "7", "6", "5", "4"),
|
||||||
1, "0x12", "[0x12]", "[0x12]",
|
1, "0x12", "[0x12]", "[0x12]",
|
||||||
u8, Unsigned,
|
FixedU8, u8, Unsigned,
|
||||||
U8, U7, U6, U5
|
U8, U7, U6, U5
|
||||||
}
|
}
|
||||||
fixed! {
|
fixed! {
|
||||||
"A 16-bit fixed-point unsigned",
|
"A 16-bit fixed-point unsigned",
|
||||||
FixedU16(u16, LeEqU16, "16", "15", "14", "13", "12"),
|
FixedU16(u16, LeEqU16, "16", "15", "14", "13", "12"),
|
||||||
2, "0x1234", "[0x12, 0x34]", "[0x34, 0x12]",
|
2, "0x1234", "[0x12, 0x34]", "[0x34, 0x12]",
|
||||||
u16, Unsigned,
|
FixedU16, u16, Unsigned,
|
||||||
U16, U15, U14, U13
|
U16, U15, U14, U13
|
||||||
}
|
}
|
||||||
fixed! {
|
fixed! {
|
||||||
"A 32-bit fixed-point unsigned",
|
"A 32-bit fixed-point unsigned",
|
||||||
FixedU32(u32, LeEqU32, "32", "31", "30", "29", "28"),
|
FixedU32(u32, LeEqU32, "32", "31", "30", "29", "28"),
|
||||||
4, "0x1234_5678", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]",
|
4, "0x1234_5678", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]",
|
||||||
u32, Unsigned,
|
FixedU32, u32, Unsigned,
|
||||||
U32, U31, U30, U29
|
U32, U31, U30, U29
|
||||||
}
|
}
|
||||||
fixed! {
|
fixed! {
|
||||||
|
@ -514,7 +514,7 @@ fixed! {
|
||||||
8, "0x1234_5678_9ABC_DEF0",
|
8, "0x1234_5678_9ABC_DEF0",
|
||||||
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
|
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
|
||||||
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
|
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
|
||||||
u64, Unsigned,
|
FixedU64, u64, Unsigned,
|
||||||
U64, U63, U62, U61
|
U64, U63, U62, U61
|
||||||
}
|
}
|
||||||
fixed! {
|
fixed! {
|
||||||
|
@ -525,28 +525,28 @@ fixed! {
|
||||||
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
|
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
|
||||||
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, \
|
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, \
|
||||||
0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
|
0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
|
||||||
u128, Unsigned,
|
FixedU128, u128, Unsigned,
|
||||||
U128, U127, U126, U125
|
U128, U127, U126, U125
|
||||||
}
|
}
|
||||||
fixed! {
|
fixed! {
|
||||||
"An eight-bit fixed-point signed",
|
"An eight-bit fixed-point signed",
|
||||||
FixedI8(i8, LeEqU8, "8", "7", "6", "5", "4"),
|
FixedI8(i8, LeEqU8, "8", "7", "6", "5", "4"),
|
||||||
1, "0x12", "[0x12]", "[0x12]",
|
1, "0x12", "[0x12]", "[0x12]",
|
||||||
u8, Signed,
|
FixedU8, u8, Signed,
|
||||||
U7, U6, U5, U4
|
U7, U6, U5, U4
|
||||||
}
|
}
|
||||||
fixed! {
|
fixed! {
|
||||||
"A 16-bit fixed-point signed",
|
"A 16-bit fixed-point signed",
|
||||||
FixedI16(i16, LeEqU16, "16", "15", "14", "13", "12"),
|
FixedI16(i16, LeEqU16, "16", "15", "14", "13", "12"),
|
||||||
2, "0x1234", "[0x12, 0x34]", "[0x34, 0x12]",
|
2, "0x1234", "[0x12, 0x34]", "[0x34, 0x12]",
|
||||||
u16, Signed,
|
FixedU16, u16, Signed,
|
||||||
U15, U14, U13, U12
|
U15, U14, U13, U12
|
||||||
}
|
}
|
||||||
fixed! {
|
fixed! {
|
||||||
"A 32-bit fixed-point signed",
|
"A 32-bit fixed-point signed",
|
||||||
FixedI32(i32, LeEqU32, "32", "31", "30", "29", "28"),
|
FixedI32(i32, LeEqU32, "32", "31", "30", "29", "28"),
|
||||||
4, "0x1234_5678", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]",
|
4, "0x1234_5678", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]",
|
||||||
u32, Signed,
|
FixedU32, u32, Signed,
|
||||||
U31, U30, U29, U28
|
U31, U30, U29, U28
|
||||||
}
|
}
|
||||||
fixed! {
|
fixed! {
|
||||||
|
@ -555,7 +555,7 @@ fixed! {
|
||||||
8, "0x1234_5678_9ABC_DEF0",
|
8, "0x1234_5678_9ABC_DEF0",
|
||||||
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
|
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
|
||||||
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
|
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
|
||||||
u64, Signed,
|
FixedU64, u64, Signed,
|
||||||
U63, U62, U61, U60
|
U63, U62, U61, U60
|
||||||
}
|
}
|
||||||
fixed! {
|
fixed! {
|
||||||
|
@ -566,7 +566,7 @@ fixed! {
|
||||||
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
|
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
|
||||||
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, \
|
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, \
|
||||||
0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
|
0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
|
||||||
u128, Signed,
|
FixedU128, u128, Signed,
|
||||||
U127, U126, U125, U124
|
U127, U126, U125, U124
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1316,4 +1316,62 @@ mod tests {
|
||||||
(U16F16::from_num(4), false)
|
(U16F16::from_num(4), false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reciprocals() {
|
||||||
|
// 4/3 wraps to 1/3 = 0x0.5555_5555
|
||||||
|
assert_eq!(
|
||||||
|
U0F32::from_num(0.75).overflowing_recip(),
|
||||||
|
(U0F32::from_bits(0x5555_5555), true)
|
||||||
|
);
|
||||||
|
// 8/3 wraps to 2/3 = 0x0.AAAA_AAAA
|
||||||
|
assert_eq!(
|
||||||
|
U0F32::from_num(0.375).overflowing_recip(),
|
||||||
|
(U0F32::from_bits(0xAAAA_AAAA), true)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 8/3 wraps to 2/3 = 0x0.AAAA_AAAA, which is -0x0.5555_5556
|
||||||
|
assert_eq!(
|
||||||
|
I0F32::from_num(0.375).overflowing_recip(),
|
||||||
|
(I0F32::from_bits(-0x5555_5556), true)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
I0F32::from_num(-0.375).overflowing_recip(),
|
||||||
|
(I0F32::from_bits(0x5555_5556), true)
|
||||||
|
);
|
||||||
|
// -2 wraps to 0
|
||||||
|
assert_eq!(
|
||||||
|
I0F32::from_num(-0.5).overflowing_recip(),
|
||||||
|
(I0F32::from_num(0), true)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 8/3 wraps to 2/3 = 0x0.AAAA_AAAA (bits 0x5555_5555)
|
||||||
|
assert_eq!(
|
||||||
|
I1F31::from_num(0.375).overflowing_recip(),
|
||||||
|
(I1F31::from_bits(0x5555_5555), true)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
I1F31::from_num(-0.375).overflowing_recip(),
|
||||||
|
(I1F31::from_bits(-0x5555_5555), true)
|
||||||
|
);
|
||||||
|
// 4/3 = 0x1.5555_5554 (bits 0xAAAA_AAAA, or -0x5555_5556)
|
||||||
|
assert_eq!(
|
||||||
|
I1F31::from_num(0.75).overflowing_recip(),
|
||||||
|
(I1F31::from_bits(-0x5555_5556), true)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
I1F31::from_num(-0.75).overflowing_recip(),
|
||||||
|
(I1F31::from_bits(0x5555_5556), true)
|
||||||
|
);
|
||||||
|
// -2 wraps to 0
|
||||||
|
assert_eq!(
|
||||||
|
I1F31::from_num(-0.5).overflowing_recip(),
|
||||||
|
(I1F31::from_num(0), true)
|
||||||
|
);
|
||||||
|
// -1 does not overflow
|
||||||
|
assert_eq!(
|
||||||
|
I1F31::from_num(-1).overflowing_recip(),
|
||||||
|
(I1F31::from_num(-1), false)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ macro_rules! fixed_frac {
|
||||||
$Fixed:ident[$s_fixed:expr](
|
$Fixed:ident[$s_fixed:expr](
|
||||||
$Inner:ty[$s_inner:expr], $LeEqU:tt, $s_nbits:expr, $s_nbits_m1:expr, $s_nbits_m4:expr
|
$Inner:ty[$s_inner:expr], $LeEqU:tt, $s_nbits:expr, $s_nbits_m1:expr, $s_nbits_m4:expr
|
||||||
),
|
),
|
||||||
$UInner:ty, $Signedness:tt
|
$UFixed:ident, $UInner:ty, $Signedness:tt
|
||||||
) => {
|
) => {
|
||||||
/// The implementation of items in this block depends on the
|
/// The implementation of items in this block depends on the
|
||||||
/// number of fractional bits `Frac`.
|
/// number of fractional bits `Frac`.
|
||||||
|
@ -223,6 +223,35 @@ assert_eq!(Fix::from_num(-5).signum(), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comment! {
|
||||||
|
"Returns the reciprocal (inverse) of the fixed-point number, 1/`self`.
|
||||||
|
|
||||||
|
# Panics
|
||||||
|
|
||||||
|
Panics if the fixed-point number is zero.
|
||||||
|
|
||||||
|
When debug assertions are enabled, this method also panics if the
|
||||||
|
reciprocal 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_recip`] instead.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use fixed::{types::extra::U4, ", $s_fixed, "};
|
||||||
|
type Fix = ", $s_fixed, "<U4>;
|
||||||
|
assert_eq!(Fix::from_num(2).recip(), Fix::from_num(0.5));
|
||||||
|
```
|
||||||
|
|
||||||
|
[`wrapping_recip`]: #method.wrapping_recip
|
||||||
|
";
|
||||||
|
#[inline] pub fn recip(self) -> $Fixed<Frac> {
|
||||||
|
let (ans, overflow) = self.overflowing_recip();
|
||||||
|
debug_assert!(!overflow, "overflow"); ans
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
comment! {
|
comment! {
|
||||||
"Euclidean division.
|
"Euclidean division.
|
||||||
|
|
||||||
|
@ -443,6 +472,34 @@ assert_eq!(Fix::MAX.checked_div(Fix::from_num(1) / 2), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comment! {
|
||||||
|
"Checked reciprocal. Returns the reciprocal, or
|
||||||
|
[`None`] if `self` is zero or on overflow.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use fixed::{types::extra::U4, ", $s_fixed, "};
|
||||||
|
type Fix = ", $s_fixed, "<U4>;
|
||||||
|
assert_eq!(Fix::from_num(2).checked_recip(), Some(Fix::from_num(0.5)));
|
||||||
|
assert_eq!(Fix::from_num(0).checked_recip(), None);
|
||||||
|
```
|
||||||
|
|
||||||
|
[`None`]: https://doc.rust-lang.org/nightly/core/option/enum.Option.html#variant.None
|
||||||
|
";
|
||||||
|
#[inline]
|
||||||
|
pub fn checked_recip(self) -> Option<$Fixed<Frac>> {
|
||||||
|
if self.to_bits() == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
match self.overflowing_recip() {
|
||||||
|
(ans, false) => Some(ans),
|
||||||
|
(_, true) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
comment! {
|
comment! {
|
||||||
"Checked Euclidean division. Returns the quotient, or
|
"Checked Euclidean division. Returns the quotient, or
|
||||||
[`None`] if the divisor is zero or on overflow.
|
[`None`] if the divisor is zero or on overflow.
|
||||||
|
@ -730,6 +787,44 @@ assert_eq!(Fix::MAX.saturating_div(one_half), Fix::MAX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comment! {
|
||||||
|
"Saturating reciprocal. Returns the reciprocal,
|
||||||
|
saturating on overflow.
|
||||||
|
|
||||||
|
# Panics
|
||||||
|
|
||||||
|
Panics if the fixed-point number is zero.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use fixed::{types::extra::U", $s_nbits_m1, ", ", $s_fixed, "};
|
||||||
|
// only one integer bit
|
||||||
|
type Fix = ", $s_fixed, "<U", $s_nbits_m1, ">;
|
||||||
|
assert_eq!(Fix::from_num(0.25).saturating_recip(), Fix::MAX);
|
||||||
|
",
|
||||||
|
if_signed_else_empty_str! {
|
||||||
|
$Signedness,
|
||||||
|
"assert_eq!(Fix::from_num(-0.25).saturating_recip(), Fix::MIN);
|
||||||
|
",
|
||||||
|
},
|
||||||
|
"```
|
||||||
|
";
|
||||||
|
#[inline]
|
||||||
|
pub fn saturating_recip(self) -> $Fixed<Frac> {
|
||||||
|
match self.overflowing_recip() {
|
||||||
|
(ans, false) => ans,
|
||||||
|
(_, true) => {
|
||||||
|
if self < 0 {
|
||||||
|
Self::MIN
|
||||||
|
} else {
|
||||||
|
Self::MAX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
comment! {
|
comment! {
|
||||||
"Saturating Euclidean division. Returns the quotient,
|
"Saturating Euclidean division. Returns the quotient,
|
||||||
saturating on overflow.
|
saturating on overflow.
|
||||||
|
@ -859,6 +954,30 @@ assert_eq!(Fix::MAX.wrapping_div(quarter), wrapped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comment! {
|
||||||
|
"Wrapping reciprocal. Returns the reciprocal,
|
||||||
|
wrapping on overflow.
|
||||||
|
|
||||||
|
# Panics
|
||||||
|
|
||||||
|
Panics if the fixed-point number is zero.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use fixed::{types::extra::U", $s_nbits_m1, ", ", $s_fixed, "};
|
||||||
|
// only one integer bit
|
||||||
|
type Fix = ", $s_fixed, "<U", $s_nbits_m1, ">;
|
||||||
|
assert_eq!(Fix::from_num(0.25).wrapping_recip(), Fix::from_num(0));
|
||||||
|
```
|
||||||
|
";
|
||||||
|
#[inline]
|
||||||
|
pub fn wrapping_recip(self) -> $Fixed<Frac> {
|
||||||
|
let (ans, _) = self.overflowing_recip();
|
||||||
|
ans
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
comment! {
|
comment! {
|
||||||
"Wrapping Euclidean division. Returns the quotient, wrapping on overflow.
|
"Wrapping Euclidean division. Returns the quotient, wrapping on overflow.
|
||||||
|
|
||||||
|
@ -1083,6 +1202,32 @@ let _overflow = Fix::MAX.unwrapped_div(quarter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unwrapped")]
|
||||||
|
comment! {
|
||||||
|
"Unwrapped reciprocal. Returns the reciprocal,
|
||||||
|
panicking on overflow.
|
||||||
|
|
||||||
|
# Panics
|
||||||
|
|
||||||
|
Panics if the fixed-point number is zero or on overflow.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use fixed::{types::extra::U4, ", $s_fixed, "};
|
||||||
|
type Fix = ", $s_fixed, "<U4>;
|
||||||
|
assert_eq!(Fix::from_num(0.25).unwrapped_recip(), Fix::from_num(4));
|
||||||
|
```
|
||||||
|
";
|
||||||
|
#[inline]
|
||||||
|
pub fn unwrapped_recip(self) -> $Fixed<Frac> {
|
||||||
|
match self.overflowing_recip() {
|
||||||
|
(_, true) => panic!("overflow"),
|
||||||
|
(ans, false) => ans,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unwrapped")]
|
#[cfg(feature = "unwrapped")]
|
||||||
comment! {
|
comment! {
|
||||||
"Unwrapped Euclidean division. Returns the quotient, panicking on overflow.
|
"Unwrapped Euclidean division. Returns the quotient, panicking on overflow.
|
||||||
|
@ -1343,6 +1488,68 @@ assert_eq!(Fix::MAX.overflowing_div(quarter), (wrapped, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comment! {
|
||||||
|
"Overflowing reciprocal.
|
||||||
|
|
||||||
|
Returns a [tuple] of the reciprocal and a [`bool`] indicating whether
|
||||||
|
an overflow has occurred. On overflow, the wrapped value is returned.
|
||||||
|
|
||||||
|
# Panics
|
||||||
|
|
||||||
|
Panics if the fixed-point number is zero.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use fixed::{
|
||||||
|
types::extra::{U4, U", $s_nbits_m1, "},
|
||||||
|
", $s_fixed, ",
|
||||||
|
};
|
||||||
|
type Fix = ", $s_fixed, "<U4>;
|
||||||
|
// only one integer bit
|
||||||
|
type Small = ", $s_fixed, "<U", $s_nbits_m1, ">;
|
||||||
|
assert_eq!(Fix::from_num(0.25).overflowing_recip(), (Fix::from_num(4), false));
|
||||||
|
assert_eq!(Small::from_num(0.25).overflowing_recip(), (Small::from_num(0), 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_recip(self) -> ($Fixed<Frac>, bool) {
|
||||||
|
if let Some(one) = Self::checked_from_num(1) {
|
||||||
|
return one.overflowing_div(self);
|
||||||
|
}
|
||||||
|
if_signed! {
|
||||||
|
$Signedness;
|
||||||
|
use crate::int_helper::IntHelper;
|
||||||
|
let (neg, abs) = self.to_bits().neg_abs();
|
||||||
|
let uns_abs = $UFixed::<Frac>::from_bits(abs);
|
||||||
|
let (uns_wrapped, overflow1) = uns_abs.overflowing_recip();
|
||||||
|
let (wrapped, overflow2) =
|
||||||
|
$Fixed::<Frac>::overflowing_from_num(uns_wrapped);
|
||||||
|
if wrapped == $Fixed::<Frac>::MIN && neg {
|
||||||
|
return (wrapped, overflow1);
|
||||||
|
}
|
||||||
|
if neg {
|
||||||
|
// if we do not have overflow yet, we will not overflow now
|
||||||
|
(wrapped.wrapping_neg(), overflow1 | overflow2)
|
||||||
|
} else {
|
||||||
|
(wrapped, overflow1 | overflow2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if_unsigned! {
|
||||||
|
$Signedness;
|
||||||
|
// 0 < x < 1: 1/x = 1 + (1 - x) / x, wrapped to (1 - x) / x
|
||||||
|
// x.wrapping_neg() = 1 - x
|
||||||
|
|
||||||
|
// x = 0: we still get division by zero
|
||||||
|
|
||||||
|
(self.wrapping_neg().wrapping_div(self), true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
comment! {
|
comment! {
|
||||||
"Overflowing Euclidean division.
|
"Overflowing Euclidean division.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue