add round_ties_to_even and checked variants
This commit is contained in:
parent
b3796a46f0
commit
0eade78071
|
@ -65,11 +65,14 @@ Various conversion methods are available:
|
|||
* The following methods are now `const` functions:
|
||||
* [`abs`], [`wrapping_abs`], [`overflowing_abs`]
|
||||
* [`is_power_of_two`]
|
||||
* The method [`round_ties_to_even`] and its checked variants were
|
||||
added.
|
||||
|
||||
[`abs`]: https://docs.rs/fixed/0.4.3/fixed/struct.FixedI32.html#method.abs
|
||||
[`is_power_of_two`]: https://docs.rs/fixed/0.4.3/fixed/struct.FixedU32.html#method.is_power_of_two
|
||||
[`overflowing_abs`]: https://docs.rs/fixed/0.4.3/fixed/struct.FixedI32.html#method.overflowing_abs
|
||||
[`wrapping_abs`]: https://docs.rs/fixed/0.4.3/fixed/struct.FixedI32.html#method.wrapping_abs
|
||||
[`round_ties_to_even`]: https://docs.rs/fixed/0.4.3/fixed/struct.FixedI32.html#method.round_ties_to_even
|
||||
|
||||
### Version 0.4.3 news (2019-08-20)
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ Version 0.4.4 (unreleased)
|
|||
* The following methods are now `const` functions:
|
||||
* `abs`, `wrapping_abs`, `overflowing_abs`
|
||||
* `is_power_of_two`
|
||||
* The method `round_ties_to_even` and its checked variants were
|
||||
added.
|
||||
|
||||
Version 0.4.3 (2019-08-20)
|
||||
==========================
|
||||
|
|
177
src/lib.rs
177
src/lib.rs
|
@ -391,19 +391,20 @@ fixed! { "A 32-bit fixed-point signed", FixedI32(i32, LeEqU32, "32"), u32, Signe
|
|||
fixed! { "A 64-bit fixed-point signed", FixedI64(i64, LeEqU64, "64"), u64, Signed }
|
||||
fixed! { "A 128-bit fixed-point signed", FixedI128(i128, LeEqU128, "128"), u128, Signed }
|
||||
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::cognitive_complexity))]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::{I0F32, I16F16, U0F32, U16F16};
|
||||
use crate::types::{I0F32, I16F16, I1F31, U0F32, U16F16};
|
||||
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::cognitive_complexity))]
|
||||
#[test]
|
||||
fn rounding() {
|
||||
fn rounding_signed() {
|
||||
// -0.5
|
||||
let f = I0F32::from_bits(-1 << 31);
|
||||
assert_eq!(f.to_num::<i32>(), -1);
|
||||
assert_eq!(f.overflowing_ceil(), (I0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_floor(), (I0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_round(), (I0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I0F32::from_num(0), false));
|
||||
|
||||
// -0.5 + Δ
|
||||
let f = I0F32::from_bits((-1 << 31) + 1);
|
||||
|
@ -411,6 +412,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_floor(), (I0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_round(), (I0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I0F32::from_num(0), false));
|
||||
|
||||
// 0.5 - Δ
|
||||
let f = I0F32::from_bits((1 << 30) - 1 + (1 << 30));
|
||||
|
@ -418,27 +420,55 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_floor(), (I0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (I0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I0F32::from_num(0), false));
|
||||
|
||||
// -0.5 - Δ
|
||||
let f = I1F31::from_bits(((-1) << 30) - 1);
|
||||
assert_eq!(f.to_num::<i32>(), -1);
|
||||
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(0), false));
|
||||
assert_eq!(f.overflowing_floor(), (I1F31::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round(), (I1F31::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::from_num(-1), false));
|
||||
|
||||
// -0.5
|
||||
let f = I1F31::from_bits((-1) << 30);
|
||||
assert_eq!(f.to_num::<i32>(), -1);
|
||||
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(0), false));
|
||||
assert_eq!(f.overflowing_floor(), (I1F31::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round(), (I1F31::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::from_num(0), false));
|
||||
|
||||
// -0.5 + Δ
|
||||
let f = I1F31::from_bits(((-1) << 30) + 1);
|
||||
assert_eq!(f.to_num::<i32>(), -1);
|
||||
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(0), false));
|
||||
assert_eq!(f.overflowing_floor(), (I1F31::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round(), (I1F31::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::from_num(0), false));
|
||||
|
||||
// 0.5 - Δ
|
||||
let f = U0F32::from_bits((1 << 31) - 1);
|
||||
let f = I1F31::from_bits((1 << 30) - 1);
|
||||
assert_eq!(f.to_num::<i32>(), 0);
|
||||
assert_eq!(f.overflowing_ceil(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_floor(), (U0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (U0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(-1), true));
|
||||
assert_eq!(f.overflowing_floor(), (I1F31::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (I1F31::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::from_num(0), false));
|
||||
|
||||
// 0.5
|
||||
let f = U0F32::from_bits(1 << 31);
|
||||
let f = I1F31::from_bits(1 << 30);
|
||||
assert_eq!(f.to_num::<i32>(), 0);
|
||||
assert_eq!(f.overflowing_ceil(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_floor(), (U0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(-1), true));
|
||||
assert_eq!(f.overflowing_floor(), (I1F31::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (I1F31::from_num(-1), true));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::from_num(0), false));
|
||||
|
||||
// 0.5 + Δ
|
||||
let f = U0F32::from_bits((1 << 31) + 1);
|
||||
let f = I1F31::from_bits((1 << 30) + 1);
|
||||
assert_eq!(f.to_num::<i32>(), 0);
|
||||
assert_eq!(f.overflowing_ceil(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_floor(), (U0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(-1), true));
|
||||
assert_eq!(f.overflowing_floor(), (I1F31::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (I1F31::from_num(-1), true));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::from_num(-1), true));
|
||||
|
||||
// -3.5 - Δ
|
||||
let f = I16F16::from_bits(((-7) << 15) - 1);
|
||||
|
@ -446,6 +476,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(-3), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-4), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(-4), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(-4), false));
|
||||
|
||||
// -3.5
|
||||
let f = I16F16::from_bits((-7) << 15);
|
||||
|
@ -453,6 +484,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(-3), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-4), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(-4), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(-4), false));
|
||||
|
||||
// -3.5 + Δ
|
||||
let f = I16F16::from_bits(((-7) << 15) + 1);
|
||||
|
@ -460,6 +492,31 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(-3), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-4), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(-3), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(-3), false));
|
||||
|
||||
// -2.5 - Δ
|
||||
let f = I16F16::from_bits(((-5) << 15) - 1);
|
||||
assert_eq!(f.to_num::<i32>(), -3);
|
||||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(-2), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-3), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(-3), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(-3), false));
|
||||
|
||||
// -2.5
|
||||
let f = I16F16::from_bits((-5) << 15);
|
||||
assert_eq!(f.to_num::<i32>(), -3);
|
||||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(-2), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-3), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(-3), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(-2), false));
|
||||
|
||||
// -2.5 + Δ
|
||||
let f = I16F16::from_bits(((-5) << 15) + 1);
|
||||
assert_eq!(f.to_num::<i32>(), -3);
|
||||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(-2), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-3), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(-2), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(-2), false));
|
||||
|
||||
// -0.5 - Δ
|
||||
let f = I16F16::from_bits(((-1) << 15) - 1);
|
||||
|
@ -467,6 +524,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(-1), false));
|
||||
|
||||
// -0.5
|
||||
let f = I16F16::from_bits((-1) << 15);
|
||||
|
@ -474,6 +532,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(0), false));
|
||||
|
||||
// -0.5 + Δ
|
||||
let f = I16F16::from_bits(((-1) << 15) + 1);
|
||||
|
@ -481,6 +540,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-1), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(0), false));
|
||||
|
||||
// 0.5 - Δ
|
||||
let f = I16F16::from_bits((1 << 15) - 1);
|
||||
|
@ -488,6 +548,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(0), false));
|
||||
|
||||
// 0.5
|
||||
let f = I16F16::from_bits(1 << 15);
|
||||
|
@ -495,6 +556,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(0), false));
|
||||
|
||||
// 0.5 + Δ
|
||||
let f = I16F16::from_bits((1 << 15) + 1);
|
||||
|
@ -502,6 +564,31 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(1), false));
|
||||
|
||||
// 2.5 - Δ
|
||||
let f = I16F16::from_bits((5 << 15) - 1);
|
||||
assert_eq!(f.to_num::<i32>(), 2);
|
||||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(2), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(2), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(2), false));
|
||||
|
||||
// 2.5
|
||||
let f = I16F16::from_bits(5 << 15);
|
||||
assert_eq!(f.to_num::<i32>(), 2);
|
||||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(2), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(2), false));
|
||||
|
||||
// 2.5 + Δ
|
||||
let f = I16F16::from_bits((5 << 15) + 1);
|
||||
assert_eq!(f.to_num::<i32>(), 2);
|
||||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(2), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(3), false));
|
||||
|
||||
// 3.5 - Δ
|
||||
let f = I16F16::from_bits((7 << 15) - 1);
|
||||
|
@ -509,6 +596,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(3), false));
|
||||
|
||||
// 3.5
|
||||
let f = I16F16::from_bits(7 << 15);
|
||||
|
@ -516,6 +604,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(4), false));
|
||||
|
||||
// 3.5 + Δ
|
||||
let f = I16F16::from_bits((7 << 15) + 1);
|
||||
|
@ -523,6 +612,34 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_floor(), (I16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round(), (I16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::from_num(4), false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rounding_unsigned() {
|
||||
// 0.5 - Δ
|
||||
let f = U0F32::from_bits((1 << 31) - 1);
|
||||
assert_eq!(f.to_num::<i32>(), 0);
|
||||
assert_eq!(f.overflowing_ceil(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_floor(), (U0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (U0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U0F32::from_num(0), false));
|
||||
|
||||
// 0.5
|
||||
let f = U0F32::from_bits(1 << 31);
|
||||
assert_eq!(f.to_num::<i32>(), 0);
|
||||
assert_eq!(f.overflowing_ceil(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_floor(), (U0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U0F32::from_num(0), false));
|
||||
|
||||
// 0.5 + Δ
|
||||
let f = U0F32::from_bits((1 << 31) + 1);
|
||||
assert_eq!(f.to_num::<i32>(), 0);
|
||||
assert_eq!(f.overflowing_ceil(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_floor(), (U0F32::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (U0F32::from_num(0), true));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U0F32::from_num(0), true));
|
||||
|
||||
// 0.5 - Δ
|
||||
let f = U16F16::from_bits((1 << 15) - 1);
|
||||
|
@ -530,6 +647,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (U16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_floor(), (U16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (U16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::from_num(0), false));
|
||||
|
||||
// 0.5
|
||||
let f = U16F16::from_bits(1 << 15);
|
||||
|
@ -537,6 +655,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (U16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_floor(), (U16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (U16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::from_num(0), false));
|
||||
|
||||
// 0.5 + Δ
|
||||
let f = U16F16::from_bits((1 << 15) + 1);
|
||||
|
@ -544,6 +663,31 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (U16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_floor(), (U16F16::from_num(0), false));
|
||||
assert_eq!(f.overflowing_round(), (U16F16::from_num(1), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::from_num(1), false));
|
||||
|
||||
// 2.5 - Δ
|
||||
let f = U16F16::from_bits((5 << 15) - 1);
|
||||
assert_eq!(f.to_num::<i32>(), 2);
|
||||
assert_eq!(f.overflowing_ceil(), (U16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_floor(), (U16F16::from_num(2), false));
|
||||
assert_eq!(f.overflowing_round(), (U16F16::from_num(2), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::from_num(2), false));
|
||||
|
||||
// 2.5
|
||||
let f = U16F16::from_bits(5 << 15);
|
||||
assert_eq!(f.to_num::<i32>(), 2);
|
||||
assert_eq!(f.overflowing_ceil(), (U16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_floor(), (U16F16::from_num(2), false));
|
||||
assert_eq!(f.overflowing_round(), (U16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::from_num(2), false));
|
||||
|
||||
// 2.5 + Δ
|
||||
let f = U16F16::from_bits((5 << 15) + 1);
|
||||
assert_eq!(f.to_num::<i32>(), 2);
|
||||
assert_eq!(f.overflowing_ceil(), (U16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_floor(), (U16F16::from_num(2), false));
|
||||
assert_eq!(f.overflowing_round(), (U16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::from_num(3), false));
|
||||
|
||||
// 3.5 - Δ
|
||||
let f = U16F16::from_bits((7 << 15) - 1);
|
||||
|
@ -551,6 +695,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (U16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_floor(), (U16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round(), (U16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::from_num(3), false));
|
||||
|
||||
// 3.5
|
||||
let f = U16F16::from_bits(7 << 15);
|
||||
|
@ -558,6 +703,7 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (U16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_floor(), (U16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round(), (U16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::from_num(4), false));
|
||||
|
||||
// 3.5 + Δ
|
||||
let f = U16F16::from_bits((7 << 15) + 1);
|
||||
|
@ -565,5 +711,6 @@ mod tests {
|
|||
assert_eq!(f.overflowing_ceil(), (U16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_floor(), (U16F16::from_num(3), false));
|
||||
assert_eq!(f.overflowing_round(), (U16F16::from_num(4), false));
|
||||
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::from_num(4), false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,6 +212,37 @@ assert_eq!(two_half.round(), Fix::from_num(3));
|
|||
}
|
||||
}
|
||||
|
||||
comment! {
|
||||
"Rounds to the nearest integer, with ties rounded to even.
|
||||
|
||||
# Panics
|
||||
|
||||
When debug assertions are enabled, panics if the result does not fit.
|
||||
When debug assertions are not enabled, the wrapped result can be
|
||||
returned, but it is not considered a breaking change if in the future
|
||||
it panics; if wrapping is required use [`wrapping_round_ties_to_even`]
|
||||
instead.
|
||||
|
||||
# Examples
|
||||
|
||||
```rust
|
||||
use fixed::{types::extra::U4, ", $s_fixed, "};
|
||||
type Fix = ", $s_fixed, "<U4>;
|
||||
assert_eq!(Fix::from_num(2.5).round_ties_to_even(), Fix::from_num(2));
|
||||
assert_eq!(Fix::from_num(3.5).round_ties_to_even(), Fix::from_num(4));
|
||||
```
|
||||
|
||||
[`wrapping_round_ties_to_even`]: #method.wrapping_round_ties_to_even
|
||||
";
|
||||
#[inline]
|
||||
pub fn round_ties_to_even(self) -> $Fixed<Frac> {
|
||||
let (round, overflow) = self.overflowing_round_ties_to_even();
|
||||
debug_assert!(!overflow, "overflow");
|
||||
let _ = overflow;
|
||||
round
|
||||
}
|
||||
}
|
||||
|
||||
comment! {
|
||||
"Checked ceil. Rounds to the next integer towards +∞,
|
||||
returning [`None`] on overflow.
|
||||
|
@ -325,6 +356,29 @@ assert_eq!(two_half.checked_round(), Some(Fix::from_num(3)));
|
|||
}
|
||||
}
|
||||
|
||||
comment! {
|
||||
"Checked round. Rounds to the nearest integer, with ties
|
||||
rounded to even, returning [`None`] on overflow.
|
||||
|
||||
# Examples
|
||||
|
||||
```rust
|
||||
use fixed::{types::extra::U4, ", $s_fixed, "};
|
||||
type Fix = ", $s_fixed, "<U4>;
|
||||
assert_eq!(Fix::from_num(2.5).checked_round_ties_to_even(), Some(Fix::from_num(2)));
|
||||
assert_eq!(Fix::from_num(3.5).checked_round_ties_to_even(), Some(Fix::from_num(4)));
|
||||
assert!(Fix::max_value().checked_round_ties_to_even().is_none());
|
||||
```
|
||||
|
||||
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
|
||||
";
|
||||
#[inline]
|
||||
pub fn checked_round_ties_to_even(self) -> Option<$Fixed<Frac>> {
|
||||
let (round, overflow) = self.overflowing_round_ties_to_even();
|
||||
if overflow { None } else { Some(round) }
|
||||
}
|
||||
}
|
||||
|
||||
comment! {
|
||||
"Saturating ceil. Rounds to the next integer towards +∞,
|
||||
saturating on overflow.
|
||||
|
@ -430,6 +484,32 @@ assert_eq!(two_half.saturating_round(), Fix::from_num(3));
|
|||
}
|
||||
}
|
||||
|
||||
comment! {
|
||||
"Saturating round. Rounds to the nearest integer, with
|
||||
ties rounded to even, and saturating on overflow.
|
||||
|
||||
# Examples
|
||||
|
||||
```rust
|
||||
use fixed::{types::extra::U4, ", $s_fixed, "};
|
||||
type Fix = ", $s_fixed, "<U4>;
|
||||
assert_eq!(Fix::from_num(2.5).saturating_round_ties_to_even(), Fix::from_num(2));
|
||||
assert_eq!(Fix::from_num(3.5).saturating_round_ties_to_even(), Fix::from_num(4));
|
||||
assert_eq!(Fix::max_value().saturating_round_ties_to_even(), Fix::max_value());
|
||||
```
|
||||
";
|
||||
#[inline]
|
||||
pub fn saturating_round_ties_to_even(self) -> $Fixed<Frac> {
|
||||
let saturated = if self.to_bits() > 0 {
|
||||
$Fixed::max_value()
|
||||
} else {
|
||||
$Fixed::min_value()
|
||||
};
|
||||
let (round, overflow) = self.overflowing_round_ties_to_even();
|
||||
if overflow { saturated } else { round }
|
||||
}
|
||||
}
|
||||
|
||||
comment! {
|
||||
"Wrapping ceil. Rounds to the next integer towards +∞,
|
||||
wrapping on overflow.
|
||||
|
@ -527,6 +607,26 @@ assert_eq!(two_half.wrapping_round(), Fix::from_num(3));
|
|||
}
|
||||
}
|
||||
|
||||
comment! {
|
||||
"Wrapping round. Rounds to the next integer to the
|
||||
nearest, with ties rounded to even, and wrapping on overflow.
|
||||
|
||||
# Examples
|
||||
|
||||
```rust
|
||||
use fixed::{types::extra::U4, ", $s_fixed, "};
|
||||
type Fix = ", $s_fixed, "<U4>;
|
||||
assert_eq!(Fix::from_num(2.5).wrapping_round_ties_to_even(), Fix::from_num(2));
|
||||
assert_eq!(Fix::from_num(3.5).wrapping_round_ties_to_even(), Fix::from_num(4));
|
||||
assert_eq!(Fix::max_value().wrapping_round_ties_to_even(), Fix::min_value());
|
||||
```
|
||||
";
|
||||
#[inline]
|
||||
pub fn wrapping_round_ties_to_even(self) -> $Fixed<Frac> {
|
||||
self.overflowing_round_ties_to_even().0
|
||||
}
|
||||
}
|
||||
|
||||
comment! {
|
||||
"Overflowing ceil. Rounds to the next integer towards +∞.
|
||||
|
||||
|
@ -681,6 +781,7 @@ assert_eq!(two_half.overflowing_round(), (Fix::from_num(3), false));
|
|||
return (int, false);
|
||||
}
|
||||
if Self::INT_NBITS == 1 {
|
||||
// increment is -1, so subtract it
|
||||
return int.overflowing_sub(increment);
|
||||
}
|
||||
int.overflowing_add(increment)
|
||||
|
@ -694,5 +795,57 @@ assert_eq!(two_half.overflowing_round(), (Fix::from_num(3), false));
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
comment! {
|
||||
"Overflowing round. Rounds to the next integer to the
|
||||
nearest, with ties rounded to even.
|
||||
|
||||
Returns a [tuple] of the fixed-point number and a [`bool`] indicating
|
||||
whether an overflow has occurred. On overflow, the wrapped value is
|
||||
returned.
|
||||
|
||||
# Examples
|
||||
|
||||
```rust
|
||||
use fixed::{types::extra::U4, ", $s_fixed, "};
|
||||
type Fix = ", $s_fixed, "<U4>;
|
||||
assert_eq!(Fix::from_num(2.5).overflowing_round_ties_to_even(), (Fix::from_num(2), false));
|
||||
assert_eq!(Fix::from_num(3.5).overflowing_round_ties_to_even(), (Fix::from_num(4), false));
|
||||
assert_eq!(Fix::max_value().overflowing_round_ties_to_even(), (Fix::min_value(), 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_round_ties_to_even(self) -> ($Fixed<Frac>, bool) {
|
||||
let int = self.int();
|
||||
if (self.to_bits() & Self::FRAC_MSB) == 0 {
|
||||
return (int, false);
|
||||
}
|
||||
if self.frac().to_bits() == Self::FRAC_MSB && (int.to_bits() & Self::INT_LSB) == 0 {
|
||||
return (int, false);
|
||||
}
|
||||
let increment = Self::from_bits(Self::INT_LSB);
|
||||
if_signed! {
|
||||
$Signedness;
|
||||
// If INT_NBITS is 0, increment is zero, and -0.5 ≤ self < 0.5,
|
||||
// so we're fine returning 0.overflowing_add(0).
|
||||
if Self::INT_NBITS == 1 {
|
||||
// increment is -1, so subtract it
|
||||
int.overflowing_sub(increment)
|
||||
} else {
|
||||
int.overflowing_add(increment)
|
||||
}
|
||||
}
|
||||
if_unsigned! {
|
||||
$Signedness;
|
||||
if Self::INT_NBITS == 0 {
|
||||
return (int, true);
|
||||
}
|
||||
int.overflowing_add(increment)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -421,6 +421,9 @@ where
|
|||
/// Rounds to the nearest integer, with ties rounded away from zero.
|
||||
fn round(self) -> Self;
|
||||
|
||||
/// Rounds to the nearest integer, with ties rounded to even.
|
||||
fn round_ties_to_even(self) -> Self;
|
||||
|
||||
/// Checked ceil. Rounds to the next integer towards +∞, returning
|
||||
/// [`None`] on overflow.
|
||||
///
|
||||
|
@ -439,6 +442,12 @@ where
|
|||
/// [`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
|
||||
fn checked_round(self) -> Option<Self>;
|
||||
|
||||
/// Checked round. Rounds to the nearest integer, with ties
|
||||
/// rounded to even, returning [`None`] on overflow.
|
||||
///
|
||||
/// [`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
|
||||
fn checked_round_ties_to_even(self) -> Option<Self>;
|
||||
|
||||
/// Saturating ceil. Rounds to the next integer towards +∞,
|
||||
/// saturating on overflow.
|
||||
fn saturating_ceil(self) -> Self;
|
||||
|
@ -451,6 +460,10 @@ where
|
|||
/// rounded away from zero, and saturating on overflow.
|
||||
fn saturating_round(self) -> Self;
|
||||
|
||||
/// Saturating round. Rounds to the nearest integer, with ties
|
||||
/// rounded to_even, and saturating on overflow.
|
||||
fn saturating_round_ties_to_even(self) -> Self;
|
||||
|
||||
/// Wrapping ceil. Rounds to the next integer towards +∞, wrapping
|
||||
/// on overflow.
|
||||
fn wrapping_ceil(self) -> Self;
|
||||
|
@ -463,6 +476,10 @@ where
|
|||
/// with ties rounded away from zero, and wrapping on overflow.
|
||||
fn wrapping_round(self) -> Self;
|
||||
|
||||
/// Wrapping round. Rounds to the next integer to the nearest,
|
||||
/// with ties rounded to even, and wrapping on overflow.
|
||||
fn wrapping_round_ties_to_even(self) -> Self;
|
||||
|
||||
/// Overflowing ceil. Rounds to the next integer towards +∞.
|
||||
///
|
||||
/// Returns a [tuple] of the fixed-point number and a [`bool`],
|
||||
|
@ -494,6 +511,17 @@ where
|
|||
/// [tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
|
||||
fn overflowing_round(self) -> (Self, bool);
|
||||
|
||||
/// Overflowing round. Rounds to the next integer to the nearest,
|
||||
/// with ties rounded to even.
|
||||
///
|
||||
/// Returns a [tuple] of the fixed-point number 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_round_ties_to_even(self) -> (Self, bool);
|
||||
|
||||
/// Returns the number of ones in the binary representation.
|
||||
fn count_ones(self) -> u32;
|
||||
|
||||
|
@ -1447,18 +1475,23 @@ macro_rules! impl_fixed {
|
|||
trait_delegate! { fn ceil(self) -> Self }
|
||||
trait_delegate! { fn floor(self) -> Self }
|
||||
trait_delegate! { fn round(self) -> Self }
|
||||
trait_delegate! { fn round_ties_to_even(self) -> Self }
|
||||
trait_delegate! { fn checked_ceil(self) -> Option<Self> }
|
||||
trait_delegate! { fn checked_floor(self) -> Option<Self> }
|
||||
trait_delegate! { fn checked_round(self) -> Option<Self> }
|
||||
trait_delegate! { fn checked_round_ties_to_even(self) -> Option<Self> }
|
||||
trait_delegate! { fn saturating_ceil(self) -> Self }
|
||||
trait_delegate! { fn saturating_floor(self) -> Self }
|
||||
trait_delegate! { fn saturating_round(self) -> Self }
|
||||
trait_delegate! { fn saturating_round_ties_to_even(self) -> Self }
|
||||
trait_delegate! { fn wrapping_ceil(self) -> Self }
|
||||
trait_delegate! { fn wrapping_floor(self) -> Self }
|
||||
trait_delegate! { fn wrapping_round(self) -> Self }
|
||||
trait_delegate! { fn wrapping_round_ties_to_even(self) -> Self }
|
||||
trait_delegate! { fn overflowing_ceil(self) -> (Self, bool) }
|
||||
trait_delegate! { fn overflowing_floor(self) -> (Self, bool) }
|
||||
trait_delegate! { fn overflowing_round(self) -> (Self, bool) }
|
||||
trait_delegate! { fn overflowing_round_ties_to_even(self) -> (Self, bool) }
|
||||
trait_delegate! { fn count_ones(self) -> u32 }
|
||||
trait_delegate! { fn count_zeros(self) -> u32 }
|
||||
trait_delegate! { fn leading_zeros(self) -> u32 }
|
||||
|
|
Loading…
Reference in New Issue