#![no_std]
#![warn(missing_docs)]
#![doc(html_root_url = "https://docs.rs/fixed/0.3.2")]
#![doc(test(attr(deny(warnings))))]
#![cfg_attr(feature = "fail-on-warnings", deny(warnings))]
#[cfg(feature = "f16")]
extern crate half;
#[cfg(feature = "serde")]
extern crate serde;
extern crate typenum;
#[macro_use]
mod macros;
mod arith;
mod cmp;
mod convert;
mod display;
pub mod frac;
pub mod sealed;
mod sealed_fixed;
mod sealed_float;
mod sealed_int;
#[cfg(feature = "serde")]
mod serdeize;
pub mod types;
mod wide_div;
mod wrapping;
use arith::MulDivDir;
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8};
#[cfg(feature = "f16")]
use half::f16;
use sealed::{Fixed, Float, Int, SealedFixed, SealedFloat, SealedInt, Widest};
pub use wrapping::Wrapping;
#[macro_use]
mod macros_from_to;
#[macro_use]
mod macros_round;
#[macro_use]
mod macros_checked_arith;
#[macro_use]
mod macros_deprecated;
macro_rules! fixed {
($description:expr, $Fixed:ident($Inner:ty, $Len:tt, $s_nbits:expr), $Signedness:tt) => {
fixed! {
$description,
$Fixed[stringify!($Fixed)]($Inner[stringify!($Inner)], $Len, $s_nbits),
$Signedness
}
};
(
$description:expr,
$Fixed:ident[$s_fixed:expr]($Inner:ty[$s_inner:expr], $Len:tt, $s_nbits:expr),
$Signedness:tt
) => {
comment!(
$description,
" with `Frac` fractional bits.
Currently `Frac` is an [`Unsigned`] as provided by the
[typenum crate]; it is planned to move to [const generics] when they
are implemented by the Rust compiler.
# Examples
```rust
use fixed::frac::U3;
use fixed::",
$s_fixed,
";
let eleven = ",
$s_fixed,
"::<U3>::from_int(11);
assert_eq!(eleven, ",
$s_fixed,
"::<U3>::from_bits(11 << 3));
assert_eq!(eleven, 11);
assert_eq!(eleven.to_string(), \"11.0\");
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\");
```
[`Unsigned`]: https://docs.rs/typenum/^1.3/typenum/marker_traits/trait.Unsigned.html
[const generics]: https://github.com/rust-lang/rust/issues/44580
[typenum crate]: https://crates.io/crates/typenum
";
#[repr(transparent)]
pub struct $Fixed<Frac>(($Inner, PhantomData<Frac>))
where
Frac: Unsigned + IsLessOrEqual<$Len, Output = True>;
);
impl<Frac> Clone for $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$Len, Output = True>,
{
#[inline]
fn clone(&self) -> $Fixed<Frac> {
Self::from_bits(self.to_bits())
}
}
impl<Frac> Copy for $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$Len, Output = True>,
{}
impl<Frac> Default for $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$Len, Output = True>,
{
#[inline]
fn default() -> $Fixed<Frac> {
Self::from_bits(<$Inner>::default())
}
}
impl<Frac> Hash for $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$Len, Output = True>,
{
#[inline]
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.to_bits().hash(state);
}
}
impl<Frac> $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$Len, Output = True>,
{
delegate!(
"Returns the smallest value that can be represented.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!(Fix::min_value(), Fix::from_bits(",
$s_inner,
"::min_value()));
```
";
$Fixed($Inner) => fn min_value()
);
delegate!(
"Returns the largest value that can be represented.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!(Fix::max_value(), Fix::from_bits(",
$s_inner,
"::max_value()));
```
";
$Fixed($Inner) => fn max_value()
);
comment!(
"Returns the number of integer bits.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U6>;
assert_eq!(Fix::int_nbits(), ",
$s_nbits,
" - 6);
```
";
#[inline]
pub fn int_nbits() -> u32 {
Self::INT_NBITS
}
);
comment!(
"Returns the number of fractional bits.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U6>;
assert_eq!(Fix::frac_nbits(), 6);
```
";
#[inline]
pub fn frac_nbits() -> u32 {
Self::FRAC_NBITS
}
);
fixed_from_to! { $Fixed[$s_fixed]($Inner[$s_inner], $s_nbits), $Signedness }
fixed_round! { $Fixed[$s_fixed]($s_nbits), $Signedness }
delegate!(
"Returns the number of ones in the binary
representation.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
let f = Fix::from_bits(0b11_0010);
assert_eq!(f.count_ones(), 3);
```
";
$Fixed($Inner) => fn count_ones(self) -> u32
);
delegate!(
"Returns the number of zeros in the binary
representation.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
let f = Fix::from_bits(!0b11_0010);
assert_eq!(f.count_zeros(), 3);
```
";
$Fixed($Inner) => fn count_zeros(self) -> u32
);
delegate!(
"Returns the number of leading zeros in the binary
representation.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
let f = Fix::from_bits(0b10_0000);
assert_eq!(f.leading_zeros(), ",
$s_nbits,
" - 6);
```
";
$Fixed($Inner) => fn leading_zeros(self) -> u32
);
delegate!(
"Returns the number of trailing zeros in the binary
representation.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
let f = Fix::from_bits(0b10_0000);
assert_eq!(f.trailing_zeros(), 5);
```
";
$Fixed($Inner) => fn trailing_zeros(self) -> u32
);
delegate!(
"Shifts to the left by *n* bits, wrapping the
truncated bits to the right end.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
let bits: ",
$s_inner,
" = (0b111 << (",
$s_nbits,
" - 3)) | 0b1010;
let rot = 0b1010111;
assert_eq!(bits.rotate_left(3), rot);
assert_eq!(Fix::from_bits(bits).rotate_left(3), Fix::from_bits(rot));
```
";
$Fixed($Inner) => fn rotate_left(self, n: u32)
);
delegate!(
"Shifts to the right by *n* bits, wrapping the
truncated bits to the left end.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
let bits: ",
$s_inner,
" = 0b1010111;
let rot = (0b111 << (",
$s_nbits,
" - 3)) | 0b1010;
assert_eq!(bits.rotate_right(3), rot);
assert_eq!(Fix::from_bits(bits).rotate_right(3), Fix::from_bits(rot));
```
";
$Fixed($Inner) => fn rotate_right(self, n: u32)
);
if_signed! {
$Signedness;
delegate!(
"Returns the absolute value.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
let five = Fix::from_int(5);
let minus_five = Fix::from_int(-5);
assert_eq!(five.abs(), five);
assert_eq!(minus_five.abs(), five);
```
";
$Fixed($Inner) => fn abs(self)
);
comment!(
"Returns a number representing the sign of `self`.
# Panics
This method panics:
* if the value is positive and the fixed-point number has zero
or one integer bits such that it cannot hold the value 1.
* if the value is negative and the fixed-point number has zero
integer bits, such that it cannot hold the value −1.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert_eq!(Fix::from_int(5).signum(), 1);
assert_eq!(Fix::from_int(0).signum(), 0);
assert_eq!(Fix::from_int(-5).signum(), -1);
```
";
#[inline]
pub fn signum(self) -> $Fixed<Frac> {
match self.to_bits().cmp(&0) {
Ordering::Equal => Self::from_bits(0),
Ordering::Greater => Self::one().expect("overflow"),
Ordering::Less => Self::minus_one().expect("overflow"),
}
}
);
}
fixed_checked_arith! { $Fixed[$s_fixed]($Inner, $s_nbits), $Signedness }
if_unsigned! {
$Signedness;
delegate!(
"Returns `true` if the fixed-point number is
2<sup><i>k</i></sup> for some integer <i>k</i>.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
// 3/8 is 0.0110
let three_eights = Fix::from_bits(0b0110);
// 1/2 is 0.1000
let half = Fix::from_bits(0b1000);
assert!(!three_eights.is_power_of_two());
assert!(half.is_power_of_two());
```
";
$Fixed($Inner) => fn is_power_of_two(self) -> bool
);
delegate!(
"Returns the smallest power of two ≥ `self`.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
// 3/8 is 0.0110
let three_eights = Fix::from_bits(0b0110);
// 1/2 is 0.1000
let half = Fix::from_bits(0b1000);
assert_eq!(three_eights.next_power_of_two(), half);
assert_eq!(half.next_power_of_two(), half);
```
";
$Fixed($Inner) => fn next_power_of_two(self)
);
comment!(
"Returns the smallest power of two ≥ `self`, or
[`None`] if the next power of two is too large to represent.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
// 3/8 is 0.0110
let three_eights = Fix::from_bits(0b0110);
// 1/2 is 0.1000
let half = Fix::from_bits(0b1000);
assert_eq!(three_eights.checked_next_power_of_two(), Some(half));
assert!(Fix::max_value().checked_next_power_of_two().is_none());
```
[`None`]: https://doc.rust-lang.org/nightly/std/option/enum.Option.html#variant.None
";
#[inline]
pub fn checked_next_power_of_two(self) -> Option<$Fixed<Frac>> {
<$Inner>::checked_next_power_of_two(self.to_bits()).map(Self::from_bits)
}
);
}
if_signed! {
$Signedness;
delegate!(
"Returns `true` if the number is > 0.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert!(Fix::from_int(5).is_positive());
assert!(!Fix::from_int(0).is_positive());
assert!(!Fix::from_int(-5).is_positive());
```
";
$Fixed($Inner) => fn is_positive(self) -> bool
);
delegate!(
"Returns `true` if the number is < 0.
# Examples
```rust
type Fix = fixed::",
$s_fixed,
"<fixed::frac::U4>;
assert!(!Fix::from_int(5).is_negative());
assert!(!Fix::from_int(0).is_negative());
assert!(Fix::from_int(-5).is_negative());
```
";
$Fixed($Inner) => fn is_negative(self) -> bool
);
}
fixed_deprecated! { $Fixed($Inner) }
}
};
}
fixed! { "An eight-bit fixed-point unsigned integer", FixedU8(u8, U8, "8"), Unsigned }
fixed! { "A 16-bit fixed-point unsigned integer", FixedU16(u16, U16, "16"), Unsigned }
fixed! { "A 32-bit fixed-point unsigned integer", FixedU32(u32, U32, "32"), Unsigned }
fixed! { "A 64-bit fixed-point unsigned integer", FixedU64(u64, U64, "64"), Unsigned }
fixed! { "A 128-bit fixed-point unsigned integer", FixedU128(u128, U128, "128"), Unsigned }
fixed! { "An eight-bit fixed-point signed integer", FixedI8(i8, U8, "8"), Signed }
fixed! { "A 16-bit fixed-point signed integer", FixedI16(i16, U16, "16"), Signed }
fixed! { "A 32-bit fixed-point signed integer", FixedI32(i32, U32, "32"), Signed }
fixed! { "A 64-bit fixed-point signed integer", FixedI64(i64, U64, "64"), Signed }
fixed! { "A 128-bit fixed-point signed integer", FixedI128(i128, U128, "128"), Signed }
#[cfg(test)]
mod tests {
use *;
#[cfg_attr(feature = "cargo-clippy", allow(clippy::cyclomatic_complexity))]
#[test]
fn rounding() {
use frac::{U16, U32};
type I0F32 = FixedI32<U32>;
let f = I0F32::from_bits(-1 << 31);
assert_eq!(f.to_int::<i32>(), -1);
assert_eq!(f.overflowing_ceil(), (I0F32::from_int(0), false));
assert_eq!(f.overflowing_floor(), (I0F32::from_int(0), true));
assert_eq!(f.overflowing_round(), (I0F32::from_int(0), true));
let f = I0F32::from_bits((-1 << 31) + 1);
assert_eq!(f.to_int::<i32>(), -1);
assert_eq!(f.overflowing_ceil(), (I0F32::from_int(0), false));
assert_eq!(f.overflowing_floor(), (I0F32::from_int(0), true));
assert_eq!(f.overflowing_round(), (I0F32::from_int(0), false));
let f = I0F32::from_bits((1 << 30) - 1 + (1 << 30));
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (I0F32::from_int(0), true));
assert_eq!(f.overflowing_floor(), (I0F32::from_int(0), false));
assert_eq!(f.overflowing_round(), (I0F32::from_int(0), false));
type U0F32 = FixedU32<U32>;
let f = U0F32::from_bits((1 << 31) - 1);
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (U0F32::from_int(0), true));
assert_eq!(f.overflowing_floor(), (U0F32::from_int(0), false));
assert_eq!(f.overflowing_round(), (U0F32::from_int(0), false));
let f = U0F32::from_bits(1 << 31);
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (U0F32::from_int(0), true));
assert_eq!(f.overflowing_floor(), (U0F32::from_int(0), false));
assert_eq!(f.overflowing_round(), (U0F32::from_int(0), true));
let f = U0F32::from_bits((1 << 31) + 1);
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (U0F32::from_int(0), true));
assert_eq!(f.overflowing_floor(), (U0F32::from_int(0), false));
assert_eq!(f.overflowing_round(), (U0F32::from_int(0), true));
type I16F16 = FixedI32<U16>;
let f = I16F16::from_bits(((-7) << 15) - 1);
assert_eq!(f.to_int::<i32>(), -4);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(-3), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(-4), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(-4), false));
let f = I16F16::from_bits((-7) << 15);
assert_eq!(f.to_int::<i32>(), -4);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(-3), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(-4), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(-4), false));
let f = I16F16::from_bits(((-7) << 15) + 1);
assert_eq!(f.to_int::<i32>(), -4);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(-3), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(-4), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(-3), false));
let f = I16F16::from_bits(((-1) << 15) - 1);
assert_eq!(f.to_int::<i32>(), -1);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(0), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(-1), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(-1), false));
let f = I16F16::from_bits((-1) << 15);
assert_eq!(f.to_int::<i32>(), -1);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(0), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(-1), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(-1), false));
let f = I16F16::from_bits(((-1) << 15) + 1);
assert_eq!(f.to_int::<i32>(), -1);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(0), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(-1), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(0), false));
let f = I16F16::from_bits((1 << 15) - 1);
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(1), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(0), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(0), false));
let f = I16F16::from_bits(1 << 15);
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(1), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(0), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(1), false));
let f = I16F16::from_bits((1 << 15) + 1);
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(1), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(0), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(1), false));
let f = I16F16::from_bits((7 << 15) - 1);
assert_eq!(f.to_int::<i32>(), 3);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(4), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(3), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(3), false));
let f = I16F16::from_bits(7 << 15);
assert_eq!(f.to_int::<i32>(), 3);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(4), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(3), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(4), false));
let f = I16F16::from_bits((7 << 15) + 1);
assert_eq!(f.to_int::<i32>(), 3);
assert_eq!(f.overflowing_ceil(), (I16F16::from_int(4), false));
assert_eq!(f.overflowing_floor(), (I16F16::from_int(3), false));
assert_eq!(f.overflowing_round(), (I16F16::from_int(4), false));
type U16F16 = FixedU32<U16>;
let f = U16F16::from_bits((1 << 15) - 1);
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (U16F16::from_int(1), false));
assert_eq!(f.overflowing_floor(), (U16F16::from_int(0), false));
assert_eq!(f.overflowing_round(), (U16F16::from_int(0), false));
let f = U16F16::from_bits(1 << 15);
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (U16F16::from_int(1), false));
assert_eq!(f.overflowing_floor(), (U16F16::from_int(0), false));
assert_eq!(f.overflowing_round(), (U16F16::from_int(1), false));
let f = U16F16::from_bits((1 << 15) + 1);
assert_eq!(f.to_int::<i32>(), 0);
assert_eq!(f.overflowing_ceil(), (U16F16::from_int(1), false));
assert_eq!(f.overflowing_floor(), (U16F16::from_int(0), false));
assert_eq!(f.overflowing_round(), (U16F16::from_int(1), false));
let f = U16F16::from_bits((7 << 15) - 1);
assert_eq!(f.to_int::<i32>(), 3);
assert_eq!(f.overflowing_ceil(), (U16F16::from_int(4), false));
assert_eq!(f.overflowing_floor(), (U16F16::from_int(3), false));
assert_eq!(f.overflowing_round(), (U16F16::from_int(3), false));
let f = U16F16::from_bits(7 << 15);
assert_eq!(f.to_int::<i32>(), 3);
assert_eq!(f.overflowing_ceil(), (U16F16::from_int(4), false));
assert_eq!(f.overflowing_floor(), (U16F16::from_int(3), false));
assert_eq!(f.overflowing_round(), (U16F16::from_int(4), false));
let f = U16F16::from_bits((7 << 15) + 1);
assert_eq!(f.to_int::<i32>(), 3);
assert_eq!(f.overflowing_ceil(), (U16F16::from_int(4), false));
assert_eq!(f.overflowing_floor(), (U16F16::from_int(3), false));
assert_eq!(f.overflowing_round(), (U16F16::from_int(4), false));
}
}