#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_docs)]
#![doc(html_root_url = "https://docs.rs/fixed/~1.8")]
#![doc(test(attr(deny(warnings))))]
#![cfg_attr(feature = "fail-on-warnings", deny(warnings))]
#![allow(clippy::manual_map, clippy::wrong_self_convention)]
#[cfg(all(not(feature = "std"), test))]
extern crate std;
#[macro_use]
mod macros;
mod arith;
mod cast;
mod cmp;
pub mod consts;
mod convert;
mod display;
mod float_helper;
mod from_str;
mod helpers;
#[cfg(feature = "num-traits")]
mod impl_num_traits;
mod int_helper;
mod log10;
#[cfg(feature = "serde")]
mod serdeize;
pub mod traits;
pub mod types;
mod unwrapped;
mod wide_div;
mod wrapping;
#[cfg(feature = "num-traits")]
pub use crate::impl_num_traits::RadixParseFixedError;
use crate::{
arith::MulDivOverflow,
from_str::FromStrRadix,
log10::IntFracLog10,
traits::{FromFixed, ToFixed},
types::extra::{
IsLessOrEqual, LeEqU128, LeEqU16, LeEqU32, LeEqU64, LeEqU8, Sum, True, Unsigned, U12, U124,
U125, U126, U127, U128, U13, U14, U15, U16, U28, U29, U30, U31, U32, U4, U5, U6, U60, U61,
U62, U63, U64, U7, U8,
},
};
pub use crate::{from_str::ParseFixedError, unwrapped::Unwrapped, wrapping::Wrapping};
use core::{
cmp::Ordering,
hash::{Hash, Hasher},
marker::PhantomData,
mem,
ops::Add,
};
pub mod prelude {
pub use crate::traits::{
FromFixed, LosslessTryFrom, LosslessTryInto, LossyFrom, LossyInto, ToFixed,
};
}
#[macro_use]
mod macros_from_to;
#[macro_use]
mod macros_round;
#[macro_use]
mod macros_no_frac;
#[macro_use]
mod macros_frac;
#[macro_use]
mod macros_const;
macro_rules! fixed {
(
$description:expr,
$Fixed:ident(
$Inner:ty, $LeEqU:tt, $s_nbits:expr,
$s_nbits_m1:expr, $s_nbits_m2:expr, $s_nbits_m3:expr, $s_nbits_m4:expr
),
$nbytes:expr, $bytes_val:expr, $rev_bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
$UFixed:ident, $UInner:ty, $Signedness:tt,
$LeEqU_C0:tt, $LeEqU_C1:tt, $LeEqU_C2:tt, $LeEqU_C3:tt,
$Double:ident, $DoubleInner:ty, $s_nbits_2:expr, $HasDouble:tt
) => {
fixed! {
$description,
$Fixed[stringify!($Fixed)](
$Inner[stringify!($Inner)], $LeEqU, $s_nbits,
$s_nbits_m1, $s_nbits_m2, $s_nbits_m3, $s_nbits_m4
),
$nbytes, $bytes_val, $rev_bytes_val, $be_bytes, $le_bytes,
$UFixed[stringify!($UFixed)], $UInner, $Signedness,
$LeEqU_C0, $LeEqU_C1, $LeEqU_C2, $LeEqU_C3,
$Double, $DoubleInner, $s_nbits_2, $HasDouble
}
};
(
$description:expr,
$Fixed:ident[$s_fixed:expr](
$Inner:ty[$s_inner:expr], $LeEqU:tt, $s_nbits:expr,
$s_nbits_m1:expr, $s_nbits_m2:expr, $s_nbits_m3:expr, $s_nbits_m4:expr
),
$nbytes:expr, $bytes_val:expr, $rev_bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
$UFixed:ident[$s_ufixed:expr], $UInner:ty, $Signedness:tt,
$LeEqU_C0:tt, $LeEqU_C1:tt, $LeEqU_C2:tt, $LeEqU_C3:tt,
$Double:ident, $DoubleInner:ty, $s_nbits_2:expr, $HasDouble:tt
) => {
comment! {
$description, "-bit ",
if_signed_unsigned!($Signedness, "signed", "unsigned"),
" number with `Frac` fractional bits.
The number has ", $s_nbits, " bits, of which <i>f</i> = `Frac` are fractional
bits and ", $s_nbits, " − <i>f</i> are integer bits. The value <i>x</i> can lie
in the range ",
if_signed_unsigned!(
$Signedness,
concat!("−2<sup>", $s_nbits_m1, "</sup>/2<sup><i>f</i></sup>"),
"0",
),
" ≤ <i>x</i> < 2<sup>",
if_signed_unsigned!($Signedness, $s_nbits_m1, $s_nbits),
"</sup>/2<sup><i>f</i></sup>. The difference between successive
numbers is constant throughout the range: <i>Δ</i> = 1/2<sup><i>f</i></sup>.
When <i>f</i> = 0, <i>Δ</i> = 1 and the fixed-point number behaves like ",
if_signed_unsigned!($Signedness, "an", "a"),
" [`", $s_inner, "`] with the value lying in the range ",
if_signed_unsigned!(
$Signedness,
concat!("−2<sup>", $s_nbits_m1, "</sup>"),
"0",
),
" ≤ <i>x</i> < 2<sup>",
if_signed_unsigned!($Signedness, $s_nbits_m1, $s_nbits),
"</sup>. When <i>f</i> = ", $s_nbits, ",
<i>Δ</i> = 1/2<sup>", $s_nbits, "</sup> and the value lies in the range ",
if_signed_unsigned!($Signedness, "−1/2 ≤ <i>x</i> < 1/2", "0 ≤ <i>x</i> < 1"),
".
`Frac` is an [`Unsigned`] as provided by the [*typenum* crate]; the plan is to
to have a major version 2 with [const generics] instead when the Rust compiler
support for them is powerful enough.
# Examples
```rust
use fixed::{types::extra::U3, ", $s_fixed, "};
let eleven = ", $s_fixed, "::<U3>::from_num(11);
assert_eq!(eleven, ", $s_fixed, "::<U3>::from_bits(11 << 3));
assert_eq!(eleven, 11);
assert_eq!(eleven.to_string(), \"11\");
let two_point_75 = eleven / 4;
assert_eq!(two_point_75, ", $s_fixed, "::<U3>::from_bits(11 << 1));
assert_eq!(two_point_75, 2.75);
assert_eq!(two_point_75.to_string(), \"2.8\");
```
[*typenum* crate]: https://crates.io/crates/typenum
[const generics]: https://github.com/rust-lang/rust/issues/44580
";
#[repr(transparent)]
pub struct $Fixed<Frac> {
bits: $Inner,
phantom: PhantomData<Frac>,
}
}
impl<Frac> Clone for $Fixed<Frac> {
#[inline]
fn clone(&self) -> $Fixed<Frac> {
$Fixed {
bits: self.bits,
phantom: PhantomData,
}
}
}
impl<Frac> Copy for $Fixed<Frac> {}
impl<Frac> Default for $Fixed<Frac> {
#[inline]
fn default() -> Self {
$Fixed {
bits: Default::default(),
phantom: PhantomData,
}
}
}
impl<Frac> Hash for $Fixed<Frac> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.bits.hash(state);
}
}
fixed_no_frac! {
$Fixed[$s_fixed]($Inner[$s_inner], $LeEqU, $s_nbits, $s_nbits_m1),
$nbytes, $bytes_val, $rev_bytes_val, $be_bytes, $le_bytes,
$UFixed[$s_ufixed], $UInner, $Signedness,
$Double, $DoubleInner, $s_nbits_2, $HasDouble
}
fixed_frac! {
$Fixed[$s_fixed]($Inner[$s_inner], $LeEqU, $s_nbits, $s_nbits_m1, $s_nbits_m4),
$UFixed, $UInner, $Signedness
}
fixed_const! {
$Fixed[$s_fixed]($LeEqU, $s_nbits, $s_nbits_m1, $s_nbits_m2, $s_nbits_m3, $s_nbits_m4),
$LeEqU_C0, $LeEqU_C1, $LeEqU_C2, $LeEqU_C3,
$Signedness
}
};
}
fixed! {
"An eight",
FixedU8(u8, LeEqU8, "8", "7", "6", "5", "4"),
1, "0x12", "0x12", "[0x12]", "[0x12]",
FixedU8, u8, Unsigned,
U8, U7, U6, U5,
FixedU16, u16, "16", True
}
fixed! {
"A 16",
FixedU16(u16, LeEqU16, "16", "15", "14", "13", "12"),
2, "0x1234", "0x3412", "[0x12, 0x34]", "[0x34, 0x12]",
FixedU16, u16, Unsigned,
U16, U15, U14, U13,
FixedU32, u32, "32", True
}
fixed! {
"A 32",
FixedU32(u32, LeEqU32, "32", "31", "30", "29", "28"),
4, "0x1234_5678", "0x7856_3412", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]",
FixedU32, u32, Unsigned,
U32, U31, U30, U29,
FixedU64, u64, "64", True
}
fixed! {
"A 64",
FixedU64(u64, LeEqU64, "64", "63", "62", "61", "60"),
8, "0x1234_5678_9ABC_DE0F", "0x0FDE_BC9A_7856_3412",
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0x0F]",
"[0x0F, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
FixedU64, u64, Unsigned,
U64, U63, U62, U61,
FixedU128, u128, "128", True
}
fixed! {
"A 128",
FixedU128(u128, LeEqU128, "128", "127", "126", "125", "124"),
16, "0x1234_5678_9ABC_DEF0_0102_0304_0506_0708",
"0x0807_0605_0403_0201_F0DE_BC9A_7856_3412",
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, \
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]",
"[0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, \
0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
FixedU128, u128, Unsigned,
U128, U127, U126, U125,
FixedU128, u128, "128", False
}
fixed! {
"An eight",
FixedI8(i8, LeEqU8, "8", "7", "6", "5", "4"),
1, "0x12", "0x12", "[0x12]", "[0x12]",
FixedU8, u8, Signed,
U7, U6, U5, U4,
FixedI16, i16, "16", True
}
fixed! {
"A 16",
FixedI16(i16, LeEqU16, "16", "15", "14", "13", "12"),
2, "0x1234", "0x3412", "[0x12, 0x34]", "[0x34, 0x12]",
FixedU16, u16, Signed,
U15, U14, U13, U12,
FixedI32, i32, "32", True
}
fixed! {
"A 32",
FixedI32(i32, LeEqU32, "32", "31", "30", "29", "28"),
4, "0x1234_5678", "0x7856_3412", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]",
FixedU32, u32, Signed,
U31, U30, U29, U28,
FixedI64, i64, "64", True
}
fixed! {
"A 64",
FixedI64(i64, LeEqU64, "64", "63", "62", "61", "60"),
8, "0x1234_5678_9ABC_DE0F", "0x0FDE_BC9A_7856_3412",
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0x0F]",
"[0x0F, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
FixedU64, u64, Signed,
U63, U62, U61, U60,
FixedI128, i128, "128", True
}
fixed! {
"A 128",
FixedI128(i128, LeEqU128, "128", "127", "126", "125", "124"),
16, "0x1234_5678_9ABC_DEF0_0102_0304_0506_0708",
"0x0807_0605_0403_0201_F0DE_BC9A_7856_3412",
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, \
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]",
"[0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, \
0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
FixedU128, u128, Signed,
U127, U126, U125, U124,
FixedI128, i128, "128", False
}
#[repr(transparent)]
#[derive(Clone, Copy, Default, Hash, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct F128Bits(pub u128);
impl F128Bits {
#[inline]
pub(crate) fn to_bits(self) -> u128 {
self.0
}
#[inline]
pub(crate) fn from_bits(bits: u128) -> F128Bits {
F128Bits(bits)
}
}
#[macro_export]
macro_rules! const_fixed_from_int {
($(const $NAME:ident: $Fixed:ty = $int:expr;)*) => { $(
const $NAME: $Fixed = <$Fixed>::from_bits({
let int = <$Fixed>::from_bits($int).to_bits();
let frac_nbits = <$Fixed>::FRAC_NBITS;
let one_a = <$Fixed>::DELTA.to_bits() << (frac_nbits / 2);
let one_b = <$Fixed>::DELTA.to_bits() << (frac_nbits - frac_nbits / 2);
int * one_a * one_b
});
)* };
}
fn _compile_fail_tests() {}
#[cfg(test)]
mod tests {
use crate::types::{I0F32, I16F16, I1F31, U0F32, U16F16};
#[test]
fn rounding_signed() {
let f = I0F32::from_bits(-1 << 31);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I0F32::ZERO, false));
assert_eq!(f.overflowing_floor(), (I0F32::ZERO, true));
assert_eq!(f.overflowing_round(), (I0F32::ZERO, true));
assert_eq!(f.overflowing_round_ties_to_even(), (I0F32::ZERO, false));
let f = I0F32::from_bits((-1 << 31) + 1);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I0F32::ZERO, false));
assert_eq!(f.overflowing_floor(), (I0F32::ZERO, true));
assert_eq!(f.overflowing_round(), (I0F32::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I0F32::ZERO, false));
let f = I0F32::from_bits(0);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I0F32::ZERO, false));
assert_eq!(f.overflowing_floor(), (I0F32::ZERO, false));
assert_eq!(f.overflowing_round(), (I0F32::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I0F32::ZERO, false));
let f = I0F32::from_bits((1 << 30) - 1 + (1 << 30));
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I0F32::ZERO, true));
assert_eq!(f.overflowing_floor(), (I0F32::ZERO, false));
assert_eq!(f.overflowing_round(), (I0F32::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I0F32::ZERO, false));
let f = I1F31::from_bits((-1) << 31);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), -1);
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(-1), 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)
);
let f = I1F31::from_bits(((-1) << 30) - 1);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I1F31::ZERO, 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)
);
let f = I1F31::from_bits((-1) << 30);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I1F31::ZERO, 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::ZERO, false));
let f = I1F31::from_bits(((-1) << 30) + 1);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I1F31::ZERO, false));
assert_eq!(f.overflowing_floor(), (I1F31::from_num(-1), false));
assert_eq!(f.overflowing_round(), (I1F31::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::ZERO, false));
let f = I1F31::from_bits((1 << 30) - 1);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(-1), true));
assert_eq!(f.overflowing_floor(), (I1F31::ZERO, false));
assert_eq!(f.overflowing_round(), (I1F31::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::ZERO, false));
let f = I1F31::from_bits(1 << 30);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(-1), true));
assert_eq!(f.overflowing_floor(), (I1F31::ZERO, false));
assert_eq!(f.overflowing_round(), (I1F31::from_num(-1), true));
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::ZERO, false));
let f = I1F31::from_bits(0);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I1F31::ZERO, false));
assert_eq!(f.overflowing_floor(), (I1F31::ZERO, false));
assert_eq!(f.overflowing_round(), (I1F31::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I1F31::ZERO, false));
let f = I1F31::from_bits((1 << 30) + 1);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I1F31::from_num(-1), true));
assert_eq!(f.overflowing_floor(), (I1F31::ZERO, false));
assert_eq!(f.overflowing_round(), (I1F31::from_num(-1), true));
assert_eq!(
f.overflowing_round_ties_to_even(),
(I1F31::from_num(-1), true)
);
let f = I16F16::from_bits(((-7) << 15) - 1);
assert_eq!(f.to_num::<i32>(), -4);
assert_eq!(f.round_to_zero(), -3);
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)
);
let f = I16F16::from_bits((-7) << 15);
assert_eq!(f.to_num::<i32>(), -4);
assert_eq!(f.round_to_zero(), -3);
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)
);
let f = I16F16::from_bits(((-7) << 15) + 1);
assert_eq!(f.to_num::<i32>(), -4);
assert_eq!(f.round_to_zero(), -3);
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)
);
let f = I16F16::from_bits(((-5) << 15) - 1);
assert_eq!(f.to_num::<i32>(), -3);
assert_eq!(f.round_to_zero(), -2);
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)
);
let f = I16F16::from_bits((-5) << 15);
assert_eq!(f.to_num::<i32>(), -3);
assert_eq!(f.round_to_zero(), -2);
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)
);
let f = I16F16::from_bits(((-5) << 15) + 1);
assert_eq!(f.to_num::<i32>(), -3);
assert_eq!(f.round_to_zero(), -2);
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)
);
let f = I16F16::from_bits((-1) << 16);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), -1);
assert_eq!(f.overflowing_ceil(), (I16F16::from_num(-1), 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)
);
let f = I16F16::from_bits(((-1) << 15) - 1);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::ZERO, 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)
);
let f = I16F16::from_bits((-1) << 15);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::ZERO, 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::ZERO, false));
let f = I16F16::from_bits(((-1) << 15) + 1);
assert_eq!(f.to_num::<i32>(), -1);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::ZERO, false));
assert_eq!(f.overflowing_floor(), (I16F16::from_num(-1), false));
assert_eq!(f.overflowing_round(), (I16F16::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::ZERO, false));
let f = I16F16::from_bits(0);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::ZERO, false));
assert_eq!(f.overflowing_floor(), (I16F16::ZERO, false));
assert_eq!(f.overflowing_round(), (I16F16::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::ZERO, false));
let f = I16F16::from_bits((1 << 15) - 1);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::ONE, false));
assert_eq!(f.overflowing_floor(), (I16F16::ZERO, false));
assert_eq!(f.overflowing_round(), (I16F16::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::ZERO, false));
let f = I16F16::from_bits(1 << 15);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::ONE, false));
assert_eq!(f.overflowing_floor(), (I16F16::ZERO, false));
assert_eq!(f.overflowing_round(), (I16F16::ONE, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::ZERO, false));
let f = I16F16::from_bits((1 << 15) + 1);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::ONE, false));
assert_eq!(f.overflowing_floor(), (I16F16::ZERO, false));
assert_eq!(f.overflowing_round(), (I16F16::ONE, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::ONE, false));
let f = I16F16::from_bits(1 << 16);
assert_eq!(f.to_num::<i32>(), 1);
assert_eq!(f.round_to_zero(), 1);
assert_eq!(f.overflowing_ceil(), (I16F16::ONE, false));
assert_eq!(f.overflowing_floor(), (I16F16::ONE, false));
assert_eq!(f.overflowing_round(), (I16F16::ONE, false));
assert_eq!(f.overflowing_round_ties_to_even(), (I16F16::ONE, false));
let f = I16F16::from_bits((5 << 15) - 1);
assert_eq!(f.to_num::<i32>(), 2);
assert_eq!(f.round_to_zero(), 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)
);
let f = I16F16::from_bits(5 << 15);
assert_eq!(f.to_num::<i32>(), 2);
assert_eq!(f.round_to_zero(), 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)
);
let f = I16F16::from_bits((5 << 15) + 1);
assert_eq!(f.to_num::<i32>(), 2);
assert_eq!(f.round_to_zero(), 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)
);
let f = I16F16::from_bits((7 << 15) - 1);
assert_eq!(f.to_num::<i32>(), 3);
assert_eq!(f.round_to_zero(), 3);
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)
);
let f = I16F16::from_bits(7 << 15);
assert_eq!(f.to_num::<i32>(), 3);
assert_eq!(f.round_to_zero(), 3);
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)
);
let f = I16F16::from_bits((7 << 15) + 1);
assert_eq!(f.to_num::<i32>(), 3);
assert_eq!(f.round_to_zero(), 3);
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() {
let f = U0F32::from_bits(0);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (U0F32::ZERO, false));
assert_eq!(f.overflowing_floor(), (U0F32::ZERO, false));
assert_eq!(f.overflowing_round(), (U0F32::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (U0F32::ZERO, false));
let f = U0F32::from_bits((1 << 31) - 1);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (U0F32::ZERO, true));
assert_eq!(f.overflowing_floor(), (U0F32::ZERO, false));
assert_eq!(f.overflowing_round(), (U0F32::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (U0F32::ZERO, false));
let f = U0F32::from_bits(1 << 31);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (U0F32::ZERO, true));
assert_eq!(f.overflowing_floor(), (U0F32::ZERO, false));
assert_eq!(f.overflowing_round(), (U0F32::ZERO, true));
assert_eq!(f.overflowing_round_ties_to_even(), (U0F32::ZERO, false));
let f = U0F32::from_bits((1 << 31) + 1);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (U0F32::ZERO, true));
assert_eq!(f.overflowing_floor(), (U0F32::ZERO, false));
assert_eq!(f.overflowing_round(), (U0F32::ZERO, true));
assert_eq!(f.overflowing_round_ties_to_even(), (U0F32::ZERO, true));
let f = U16F16::from_bits(0);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (U16F16::ZERO, false));
assert_eq!(f.overflowing_floor(), (U16F16::ZERO, false));
assert_eq!(f.overflowing_round(), (U16F16::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::ZERO, false));
let f = U16F16::from_bits((1 << 15) - 1);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (U16F16::ONE, false));
assert_eq!(f.overflowing_floor(), (U16F16::ZERO, false));
assert_eq!(f.overflowing_round(), (U16F16::ZERO, false));
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::ZERO, false));
let f = U16F16::from_bits(1 << 15);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (U16F16::ONE, false));
assert_eq!(f.overflowing_floor(), (U16F16::ZERO, false));
assert_eq!(f.overflowing_round(), (U16F16::ONE, false));
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::ZERO, false));
let f = U16F16::from_bits((1 << 15) + 1);
assert_eq!(f.to_num::<i32>(), 0);
assert_eq!(f.round_to_zero(), 0);
assert_eq!(f.overflowing_ceil(), (U16F16::ONE, false));
assert_eq!(f.overflowing_floor(), (U16F16::ZERO, false));
assert_eq!(f.overflowing_round(), (U16F16::ONE, false));
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::ONE, false));
let f = U16F16::from_bits(1 << 16);
assert_eq!(f.to_num::<i32>(), 1);
assert_eq!(f.round_to_zero(), 1);
assert_eq!(f.overflowing_ceil(), (U16F16::ONE, false));
assert_eq!(f.overflowing_floor(), (U16F16::ONE, false));
assert_eq!(f.overflowing_round(), (U16F16::ONE, false));
assert_eq!(f.overflowing_round_ties_to_even(), (U16F16::ONE, false));
let f = U16F16::from_bits((5 << 15) - 1);
assert_eq!(f.to_num::<i32>(), 2);
assert_eq!(f.round_to_zero(), 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)
);
let f = U16F16::from_bits(5 << 15);
assert_eq!(f.to_num::<i32>(), 2);
assert_eq!(f.round_to_zero(), 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)
);
let f = U16F16::from_bits((5 << 15) + 1);
assert_eq!(f.to_num::<i32>(), 2);
assert_eq!(f.round_to_zero(), 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)
);
let f = U16F16::from_bits((7 << 15) - 1);
assert_eq!(f.to_num::<i32>(), 3);
assert_eq!(f.round_to_zero(), 3);
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)
);
let f = U16F16::from_bits(7 << 15);
assert_eq!(f.to_num::<i32>(), 3);
assert_eq!(f.round_to_zero(), 3);
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)
);
let f = U16F16::from_bits((7 << 15) + 1);
assert_eq!(f.to_num::<i32>(), 3);
assert_eq!(f.round_to_zero(), 3);
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)
);
}
#[test]
fn reciprocals() {
assert_eq!(
U0F32::from_num(0.75).overflowing_recip(),
(U0F32::from_bits(0x5555_5555), true)
);
assert_eq!(
U0F32::from_num(0.375).overflowing_recip(),
(U0F32::from_bits(0xAAAA_AAAA), true)
);
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)
);
assert_eq!(
I0F32::from_num(-0.5).overflowing_recip(),
(I0F32::ZERO, true)
);
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)
);
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)
);
assert_eq!(
I1F31::from_num(-0.5).overflowing_recip(),
(I1F31::ZERO, true)
);
assert_eq!(
I1F31::from_num(-1).overflowing_recip(),
(I1F31::from_num(-1), false)
);
}
}