use crate::{
helpers::{FloatHelper, FloatKind, FromFloatHelper, IntHelper, Sealed, Widest},
types::extra::{LeEqU128, LeEqU16, LeEqU32, LeEqU64, LeEqU8, Unsigned},
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
FixedU8, ParseFixedError,
};
use core::{
fmt::{Binary, Debug, Display, LowerHex, Octal, UpperHex},
hash::Hash,
mem,
ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
SubAssign,
},
str::FromStr,
};
#[cfg(feature = "f16")]
use half::{bf16, f16};
#[cfg(feature = "serde")]
use serde::{de::Deserialize, ser::Serialize};
macro_rules! comment_features {
($comment:expr) => {
#[cfg(all(not(feature = "f16"), not(feature = "serde")))]
doc_comment! {
$comment;
pub trait FixedOptionalFeatures {}
}
#[cfg(all(feature = "f16", not(feature = "serde")))]
doc_comment! {
$comment;
pub trait FixedOptionalFeatures: PartialOrd<f16> + PartialOrd<bf16> {}
}
#[cfg(all(not(feature = "f16"), feature = "serde"))]
doc_comment! {
$comment;
pub trait FixedOptionalFeatures: Serialize + for<'de> Deserialize<'de> {}
}
#[cfg(all(feature = "f16", feature = "serde"))]
doc_comment! {
$comment;
pub trait FixedOptionalFeatures
where
Self: PartialOrd<f16> + PartialOrd<bf16>,
Self: Serialize + for<'de> Deserialize<'de>,
{
}
}
};
}
comment_features! {
"This trait is used to provide supertraits to the [`Fixed`] trait
depending on the crate’s [optional features].
1. If the `f16` feature is enabled,
<code>[PartialOrd][`PartialOrd`]<[f16][`f16`]></code> and
<code>[PartialOrd][`PartialOrd`]<[bf16][`bf16`]></code> are
supertraits of [`Fixed`].
2. If the `serde` feature is enabled, [`Serialize`] and
[`Deserialize`] are supertraits of [`Fixed`].
[`Deserialize`]: https://docs.rs/serde/^1/serde/de/trait.Deserialize.html
[`Fixed`]: trait.Fixed.html
[`PartialOrd`]: https://doc.rust-lang.org/nightly/core/cmp/trait.PartialOrd.html
[`Serialize`]: https://docs.rs/serde/^1/serde/ser/trait.Serialize.html
[`bf16`]: https://docs.rs/half/^1/half/struct.bf16.html
[`f16`]: https://docs.rs/half/^1/half/struct.f16.html
[optional features]: ../index.html#optional-features
"
}
pub trait Fixed
where
Self: Copy + Default + Hash + Ord,
Self: Debug + Display + Binary + Octal + LowerHex + UpperHex,
Self: FromStr<Err = ParseFixedError>,
Self: FromFixed + ToFixed,
Self: Add<Output = Self> + AddAssign + Sub<Output = Self> + SubAssign,
Self: Mul<Output = Self> + MulAssign + Div<Output = Self> + DivAssign,
Self: Rem<Output = Self> + RemAssign,
Self: Mul<<Self as Fixed>::Bits, Output = Self> + MulAssign<<Self as Fixed>::Bits>,
Self: Div<<Self as Fixed>::Bits, Output = Self> + DivAssign<<Self as Fixed>::Bits>,
Self: Rem<<Self as Fixed>::Bits, Output = Self> + RemAssign<<Self as Fixed>::Bits>,
Self: Not<Output = Self> + BitAnd<Output = Self> + BitAndAssign,
Self: BitOr<Output = Self> + BitOrAssign + BitXor<Output = Self> + BitXorAssign,
Self: Shl<u32, Output = Self> + ShlAssign<u32> + Shr<u32, Output = Self> + ShrAssign<u32>,
Self: PartialOrd<i8> + PartialOrd<i16> + PartialOrd<i32>,
Self: PartialOrd<i64> + PartialOrd<i128> + PartialOrd<isize>,
Self: PartialOrd<u8> + PartialOrd<u16> + PartialOrd<u32>,
Self: PartialOrd<u64> + PartialOrd<u128> + PartialOrd<usize>,
Self: PartialOrd<f32> + PartialOrd<f64>,
Self: FixedOptionalFeatures,
Self: Sealed,
{
type Bits;
type Bytes;
type Frac: Unsigned;
const MIN: Self;
const MAX: Self;
const INT_NBITS: u32;
const FRAC_NBITS: u32;
fn from_bits(bits: Self::Bits) -> Self;
fn to_bits(self) -> Self::Bits;
fn from_be_bytes(bytes: Self::Bytes) -> Self;
fn from_le_bytes(bytes: Self::Bytes) -> Self;
fn from_ne_bytes(bytes: Self::Bytes) -> Self;
fn to_be_bytes(self) -> Self::Bytes;
fn to_le_bytes(self) -> Self::Bytes;
fn to_ne_bytes(self) -> Self::Bytes;
fn from_num<Src: ToFixed>(src: Src) -> Self;
fn to_num<Dst: FromFixed>(self) -> Dst;
fn checked_from_num<Src: ToFixed>(src: Src) -> Option<Self>;
fn checked_to_num<Dst: FromFixed>(self) -> Option<Dst>;
fn saturating_from_num<Src: ToFixed>(src: Src) -> Self;
fn saturating_to_num<Dst: FromFixed>(self) -> Dst;
fn wrapping_from_num<Src: ToFixed>(src: Src) -> Self;
fn wrapping_to_num<Dst: FromFixed>(self) -> Dst;
fn overflowing_from_num<Src: ToFixed>(src: Src) -> (Self, bool);
fn overflowing_to_num<Dst: FromFixed>(self) -> (Dst, bool);
fn from_str_binary(src: &str) -> Result<Self, ParseFixedError>;
fn from_str_octal(src: &str) -> Result<Self, ParseFixedError>;
fn from_str_hex(src: &str) -> Result<Self, ParseFixedError>;
fn saturating_from_str(src: &str) -> Result<Self, ParseFixedError>;
fn saturating_from_str_binary(src: &str) -> Result<Self, ParseFixedError>;
fn saturating_from_str_octal(src: &str) -> Result<Self, ParseFixedError>;
fn saturating_from_str_hex(src: &str) -> Result<Self, ParseFixedError>;
fn wrapping_from_str(src: &str) -> Result<Self, ParseFixedError>;
fn wrapping_from_str_binary(src: &str) -> Result<Self, ParseFixedError>;
fn wrapping_from_str_octal(src: &str) -> Result<Self, ParseFixedError>;
fn wrapping_from_str_hex(src: &str) -> Result<Self, ParseFixedError>;
fn overflowing_from_str(src: &str) -> Result<(Self, bool), ParseFixedError>;
fn overflowing_from_str_binary(src: &str) -> Result<(Self, bool), ParseFixedError>;
fn overflowing_from_str_octal(src: &str) -> Result<(Self, bool), ParseFixedError>;
fn overflowing_from_str_hex(src: &str) -> Result<(Self, bool), ParseFixedError>;
fn int(self) -> Self;
fn frac(self) -> Self;
fn round_to_zero(self) -> Self;
fn ceil(self) -> Self;
fn floor(self) -> Self;
fn round(self) -> Self;
fn round_ties_to_even(self) -> Self;
fn checked_ceil(self) -> Option<Self>;
fn checked_floor(self) -> Option<Self>;
fn checked_round(self) -> Option<Self>;
fn checked_round_ties_to_even(self) -> Option<Self>;
fn saturating_ceil(self) -> Self;
fn saturating_floor(self) -> Self;
fn saturating_round(self) -> Self;
fn saturating_round_ties_to_even(self) -> Self;
fn wrapping_ceil(self) -> Self;
fn wrapping_floor(self) -> Self;
fn wrapping_round(self) -> Self;
fn wrapping_round_ties_to_even(self) -> Self;
fn overflowing_ceil(self) -> (Self, bool);
fn overflowing_floor(self) -> (Self, bool);
fn overflowing_round(self) -> (Self, bool);
fn overflowing_round_ties_to_even(self) -> (Self, bool);
fn count_ones(self) -> u32;
fn count_zeros(self) -> u32;
fn leading_ones(self) -> u32;
fn leading_zeros(self) -> u32;
fn trailing_ones(self) -> u32;
fn trailing_zeros(self) -> u32;
fn int_log2(self) -> i32;
fn int_log10(self) -> i32;
fn checked_int_log2(self) -> Option<i32>;
fn checked_int_log10(self) -> Option<i32>;
fn rotate_left(self, n: u32) -> Self;
fn rotate_right(self, n: u32) -> Self;
fn div_euclid(self, rhs: Self) -> Self;
fn rem_euclid(self, rhs: Self) -> Self;
fn div_euclid_int(self, rhs: Self::Bits) -> Self;
fn rem_euclid_int(self, rhs: Self::Bits) -> Self;
fn checked_neg(self) -> Option<Self>;
fn checked_add(self, rhs: Self) -> Option<Self>;
fn checked_sub(self, rhs: Self) -> Option<Self>;
fn checked_mul(self, rhs: Self) -> Option<Self>;
fn checked_div(self, rhs: Self) -> Option<Self>;
fn checked_rem(self, rhs: Self) -> Option<Self>;
fn checked_div_euclid(self, rhs: Self) -> Option<Self>;
fn checked_rem_euclid(self, rhs: Self) -> Option<Self>;
fn checked_mul_int(self, rhs: Self::Bits) -> Option<Self>;
fn checked_div_int(self, rhs: Self::Bits) -> Option<Self>;
fn checked_rem_int(self, rhs: Self::Bits) -> Option<Self>;
fn checked_div_euclid_int(self, rhs: Self::Bits) -> Option<Self>;
fn checked_rem_euclid_int(self, rhs: Self::Bits) -> Option<Self>;
fn checked_shl(self, rhs: u32) -> Option<Self>;
fn checked_shr(self, rhs: u32) -> Option<Self>;
fn saturating_neg(self) -> Self;
fn saturating_add(self, rhs: Self) -> Self;
fn saturating_sub(self, rhs: Self) -> Self;
fn saturating_mul(self, rhs: Self) -> Self;
fn saturating_div(self, rhs: Self) -> Self;
fn saturating_div_euclid(self, rhs: Self) -> Self;
fn saturating_mul_int(self, rhs: Self::Bits) -> Self;
fn wrapping_neg(self) -> Self;
fn wrapping_add(self, rhs: Self) -> Self;
fn wrapping_sub(self, rhs: Self) -> Self;
fn wrapping_mul(self, rhs: Self) -> Self;
fn wrapping_div(self, rhs: Self) -> Self;
fn wrapping_div_euclid(self, rhs: Self) -> Self;
fn wrapping_mul_int(self, rhs: Self::Bits) -> Self;
fn wrapping_div_int(self, rhs: Self::Bits) -> Self;
fn wrapping_div_euclid_int(self, rhs: Self::Bits) -> Self;
fn wrapping_rem_euclid_int(self, rhs: Self::Bits) -> Self;
fn wrapping_shl(self, rhs: u32) -> Self;
fn wrapping_shr(self, rhs: u32) -> Self;
fn overflowing_neg(self) -> (Self, bool);
fn overflowing_add(self, rhs: Self) -> (Self, bool);
fn overflowing_sub(self, rhs: Self) -> (Self, bool);
fn overflowing_mul(self, rhs: Self) -> (Self, bool);
fn overflowing_div(self, rhs: Self) -> (Self, bool);
fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool);
fn overflowing_mul_int(self, rhs: Self::Bits) -> (Self, bool);
fn overflowing_div_int(self, rhs: Self::Bits) -> (Self, bool);
fn overflowing_div_euclid_int(self, rhs: Self::Bits) -> (Self, bool);
fn overflowing_rem_euclid_int(self, rhs: Self::Bits) -> (Self, bool);
fn overflowing_shl(self, rhs: u32) -> (Self, bool);
fn overflowing_shr(self, rhs: u32) -> (Self, bool);
#[inline]
#[deprecated(since = "0.5.5", note = "replaced by `MIN`")]
fn min_value() -> Self {
Self::MIN
}
#[inline]
#[deprecated(since = "0.5.5", note = "replaced by `MAX`")]
fn max_value() -> Self {
Self::MAX
}
#[inline]
#[deprecated(since = "0.5.5", note = "replaced by `INT_NBITS`")]
fn int_nbits() -> u32 {
Self::INT_NBITS
}
#[inline]
#[deprecated(since = "0.5.5", note = "replaced by `FRAC_NBITS`")]
fn frac_nbits() -> u32 {
Self::FRAC_NBITS
}
#[inline]
#[deprecated(
since = "0.5.3",
note = "cannot overflow, use `%` or `Rem::rem` instead"
)]
fn wrapping_rem_int(self, rhs: Self::Bits) -> Self {
self % rhs
}
#[inline]
#[deprecated(
since = "0.5.3",
note = "cannot overflow, use `%` or `Rem::rem` instead"
)]
fn overflowing_rem_int(self, rhs: Self::Bits) -> (Self, bool) {
(self % rhs, false)
}
}
pub trait FixedSigned: Fixed + Neg<Output = Self> {
fn is_positive(self) -> bool;
fn is_negative(self) -> bool;
fn abs(self) -> Self;
fn signum(self) -> Self;
fn checked_abs(self) -> Option<Self>;
fn checked_signum(self) -> Option<Self>;
fn saturating_abs(self) -> Self;
fn saturating_signum(self) -> Self;
fn wrapping_abs(self) -> Self;
fn wrapping_signum(self) -> Self;
fn overflowing_abs(self) -> (Self, bool);
fn overflowing_signum(self) -> (Self, bool);
}
pub trait FixedUnsigned: Fixed {
fn is_power_of_two(self) -> bool;
fn next_power_of_two(self) -> Self;
fn checked_next_power_of_two(self) -> Option<Self>;
fn wrapping_next_power_of_two(self) -> Self;
}
pub trait LosslessTryFrom<Src>: Sized {
fn lossless_try_from(src: Src) -> Option<Self>;
}
pub trait LosslessTryInto<Dst> {
fn lossless_try_into(self) -> Option<Dst>;
}
impl<Src, Dst> LosslessTryInto<Dst> for Src
where
Dst: LosslessTryFrom<Src>,
{
fn lossless_try_into(self) -> Option<Dst> {
Dst::lossless_try_from(self)
}
}
pub trait LossyFrom<Src> {
fn lossy_from(src: Src) -> Self;
}
pub trait LossyInto<Dst> {
fn lossy_into(self) -> Dst;
}
impl<Src, Dst> LossyInto<Dst> for Src
where
Dst: LossyFrom<Src>,
{
fn lossy_into(self) -> Dst {
Dst::lossy_from(self)
}
}
pub trait FromFixed {
fn from_fixed<F: Fixed>(src: F) -> Self;
fn checked_from_fixed<F: Fixed>(src: F) -> Option<Self>
where
Self: Sized;
fn saturating_from_fixed<F: Fixed>(src: F) -> Self;
fn wrapping_from_fixed<F: Fixed>(src: F) -> Self;
fn overflowing_from_fixed<F: Fixed>(src: F) -> (Self, bool)
where
Self: Sized;
}
pub trait ToFixed {
fn to_fixed<F: Fixed>(self) -> F;
fn checked_to_fixed<F: Fixed>(self) -> Option<F>;
fn saturating_to_fixed<F: Fixed>(self) -> F;
fn wrapping_to_fixed<F: Fixed>(self) -> F;
fn overflowing_to_fixed<F: Fixed>(self) -> (F, bool);
}
impl ToFixed for bool {
#[inline]
fn to_fixed<F: Fixed>(self) -> F {
ToFixed::to_fixed(self as u8)
}
#[inline]
fn checked_to_fixed<F: Fixed>(self) -> Option<F> {
ToFixed::checked_to_fixed(self as u8)
}
#[inline]
fn saturating_to_fixed<F: Fixed>(self) -> F {
ToFixed::saturating_to_fixed(self as u8)
}
#[inline]
fn wrapping_to_fixed<F: Fixed>(self) -> F {
ToFixed::wrapping_to_fixed(self as u8)
}
#[inline]
fn overflowing_to_fixed<F: Fixed>(self) -> (F, bool) {
ToFixed::overflowing_to_fixed(self as u8)
}
}
macro_rules! impl_int {
($Int:ident) => {
impl FromFixed for $Int {
#[inline]
fn from_fixed<F: Fixed>(src: F) -> Self {
$Int::from_repr_fixed(FromFixed::from_fixed(src))
}
#[inline]
fn checked_from_fixed<F: Fixed>(src: F) -> Option<Self> {
FromFixed::checked_from_fixed(src).map($Int::from_repr_fixed)
}
#[inline]
fn saturating_from_fixed<F: Fixed>(src: F) -> Self {
$Int::from_repr_fixed(FromFixed::saturating_from_fixed(src))
}
#[inline]
fn wrapping_from_fixed<F: Fixed>(src: F) -> Self {
$Int::from_repr_fixed(FromFixed::wrapping_from_fixed(src))
}
#[inline]
fn overflowing_from_fixed<F: Fixed>(src: F) -> (Self, bool) {
let (repr_fixed, overflow) = FromFixed::overflowing_from_fixed(src);
($Int::from_repr_fixed(repr_fixed), overflow)
}
}
impl ToFixed for $Int {
#[inline]
fn to_fixed<F: Fixed>(self) -> F {
ToFixed::to_fixed(self.to_repr_fixed())
}
#[inline]
fn checked_to_fixed<F: Fixed>(self) -> Option<F> {
ToFixed::checked_to_fixed(self.to_repr_fixed())
}
#[inline]
fn saturating_to_fixed<F: Fixed>(self) -> F {
ToFixed::saturating_to_fixed(self.to_repr_fixed())
}
#[inline]
fn wrapping_to_fixed<F: Fixed>(self) -> F {
ToFixed::wrapping_to_fixed(self.to_repr_fixed())
}
#[inline]
fn overflowing_to_fixed<F: Fixed>(self) -> (F, bool) {
ToFixed::overflowing_to_fixed(self.to_repr_fixed())
}
}
};
}
impl_int! { i8 }
impl_int! { i16 }
impl_int! { i32 }
impl_int! { i64 }
impl_int! { i128 }
impl_int! { isize }
impl_int! { u8 }
impl_int! { u16 }
impl_int! { u32 }
impl_int! { u64 }
impl_int! { u128 }
impl_int! { usize }
macro_rules! impl_float {
($Float:ty, $link:expr) => {
impl FromFixed for $Float {
#[inline]
fn from_fixed<F: Fixed>(src: F) -> Self {
let helper = src.private_to_float_helper();
FloatHelper::from_to_float_helper(helper, F::FRAC_NBITS, F::INT_NBITS)
}
#[inline]
fn checked_from_fixed<F: Fixed>(src: F) -> Option<Self> {
Some(FromFixed::from_fixed(src))
}
#[inline]
fn saturating_from_fixed<F: Fixed>(src: F) -> Self {
FromFixed::from_fixed(src)
}
#[inline]
fn wrapping_from_fixed<F: Fixed>(src: F) -> Self {
FromFixed::from_fixed(src)
}
#[inline]
fn overflowing_from_fixed<F: Fixed>(src: F) -> (Self, bool) {
(FromFixed::from_fixed(src), false)
}
}
impl ToFixed for $Float {
comment! {
"Converts a floating-point number to a fixed-point number.
Rounding is to the nearest, with ties rounded to even.
# Panics
Panics if `self` is not [finite].
When debug assertions are enabled, also panics if the value does not
fit. 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_to_fixed`] instead.
[`wrapping_to_fixed`]: #method.wrapping_to_fixed
[finite]: ", $link, "#method.is_finite
";
#[inline]
fn to_fixed<F: Fixed>(self) -> F {
let (wrapped, overflow) = ToFixed::overflowing_to_fixed(self);
debug_assert!(!overflow, "{} overflows", self);
let _ = overflow;
wrapped
}
}
#[inline]
fn checked_to_fixed<F: Fixed>(self) -> Option<F> {
let kind = self.to_float_kind(F::FRAC_NBITS, F::INT_NBITS);
match kind {
FloatKind::Finite { .. } => {
let helper = FromFloatHelper { kind };
match F::private_overflowing_from_float_helper(helper) {
(_, true) => None,
(wrapped, false) => Some(wrapped),
}
}
_ => None,
}
}
comment! {
"Converts a floating-point number to a fixed-point
number, saturating if it does not fit.
Rounding is to the nearest, with ties rounded to even.
# Panics
Panics if `self` is [NaN].
[NaN]: ", $link, "#method.is_nan
";
#[inline]
fn saturating_to_fixed<F: Fixed>(self) -> F {
let kind = self.to_float_kind(F::FRAC_NBITS, F::INT_NBITS);
let helper = FromFloatHelper { kind };
F::private_saturating_from_float_helper(helper)
}
}
comment! {
"Converts a floating-point number to a fixed-point
number, wrapping if it does not fit.
Rounding is to the nearest, with ties rounded to even.
# Panics
Panics if `self` is not [finite].
[finite]: ", $link, "#method.is_finite
";
#[inline]
fn wrapping_to_fixed<F: Fixed>(self) -> F {
let (wrapped, _) = ToFixed::overflowing_to_fixed(self);
wrapped
}
}
comment! {
"Converts a floating-point number to a fixed-point number.
Returns a [tuple] of the fixed-point number and a [`bool`] indicating
whether an overflow has occurred. On overflow, the wrapped value is
returned.
Rounding is to the nearest, with ties rounded to even.
# Panics
Panics if `self` is not [finite].
[`bool`]: https://doc.rust-lang.org/nightly/std/primitive.bool.html
[finite]: ", $link, "#method.is_finite
[tuple]: https://doc.rust-lang.org/nightly/std/primitive.tuple.html
";
#[inline]
fn overflowing_to_fixed<F: Fixed>(self) -> (F, bool) {
let kind = self.to_float_kind(F::FRAC_NBITS, F::INT_NBITS);
let helper = FromFloatHelper { kind };
F::private_overflowing_from_float_helper(helper)
}
}
}
};
}
#[cfg(feature = "f16")]
impl_float! { f16, "https://docs.rs/half/^1/half/struct.f16.html" }
#[cfg(feature = "f16")]
impl_float! { bf16, "https://docs.rs/half/^1/half/struct.bf16.html" }
impl_float! { f32, "https://doc.rust-lang.org/nightly/std/primitive.f32.html" }
impl_float! { f64, "https://doc.rust-lang.org/nightly/std/primitive.f64.html" }
macro_rules! trait_delegate {
(fn $method:ident($($param:ident: $Param:ty),*) -> $Ret:ty) => {
#[inline]
fn $method($($param: $Param),*) -> $Ret {
Self::$method($($param),*)
}
};
(fn $method:ident(self $(, $param:ident: $Param:ty)*) -> $Ret:ty) => {
#[inline]
fn $method(self $(, $param: $Param)*) -> $Ret {
self.$method($($param),*)
}
};
(fn $method:ident<$Gen:ident: $Trait:ident>($($param:ident: $Param:ty),*) -> $Ret:ty) => {
#[inline]
fn $method<$Gen: $Trait>($($param: $Param),*) -> $Ret {
Self::$method($($param),*)
}
};
(fn $method:ident<$Gen:ident: $Trait:ident>(self $(, $param:ident: $Param:ty)*) -> $Ret:ty) => {
#[inline]
fn $method<$Gen: $Trait>(self $(, $param: $Param)*) -> $Ret {
self.$method($($param),*)
}
};
}
macro_rules! impl_fixed {
($Fixed:ident, $LeEqU:ident, $Bits:ident, $Signedness:tt) => {
impl<Frac: $LeEqU> FixedOptionalFeatures for $Fixed<Frac> {}
impl<Frac: $LeEqU> Fixed for $Fixed<Frac> {
type Bits = $Bits;
type Bytes = [u8; mem::size_of::<$Bits>()];
type Frac = Frac;
const MIN: Self = Self::MIN;
const MAX: Self = Self::MAX;
const INT_NBITS: u32 = Self::INT_NBITS;
const FRAC_NBITS: u32 = Self::FRAC_NBITS;
trait_delegate! { fn from_bits(bits: Self::Bits) -> Self }
trait_delegate! { fn to_bits(self) -> Self::Bits }
trait_delegate! { fn from_be_bytes(bits: Self::Bytes) -> Self }
trait_delegate! { fn from_le_bytes(bits: Self::Bytes) -> Self }
trait_delegate! { fn from_ne_bytes(bits: Self::Bytes) -> Self }
trait_delegate! { fn to_be_bytes(self) -> Self::Bytes }
trait_delegate! { fn to_le_bytes(self) -> Self::Bytes }
trait_delegate! { fn to_ne_bytes(self) -> Self::Bytes }
trait_delegate! { fn from_num<Src: ToFixed>(src: Src) -> Self }
trait_delegate! { fn to_num<Dst: FromFixed>(self) -> Dst }
trait_delegate! { fn checked_from_num<Src: ToFixed>(val: Src) -> Option<Self> }
trait_delegate! { fn checked_to_num<Dst: FromFixed>(self) -> Option<Dst> }
trait_delegate! { fn saturating_from_num<Src: ToFixed>(val: Src) -> Self }
trait_delegate! { fn saturating_to_num<Dst: FromFixed>(self) -> Dst }
trait_delegate! { fn wrapping_from_num<Src: ToFixed>(val: Src) -> Self }
trait_delegate! { fn wrapping_to_num<Dst: FromFixed>(self) -> Dst }
trait_delegate! { fn overflowing_from_num<Src: ToFixed>(val: Src) -> (Self, bool) }
trait_delegate! { fn overflowing_to_num<Dst: FromFixed>(self) -> (Dst, bool) }
trait_delegate! { fn from_str_binary(src: &str) -> Result<Self, ParseFixedError> }
trait_delegate! { fn from_str_octal(src: &str) -> Result<Self, ParseFixedError> }
trait_delegate! { fn from_str_hex(src: &str) -> Result<Self, ParseFixedError> }
trait_delegate! {
fn saturating_from_str(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn saturating_from_str_binary(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn saturating_from_str_octal(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn saturating_from_str_hex(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn wrapping_from_str(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn wrapping_from_str_binary(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn wrapping_from_str_octal(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn wrapping_from_str_hex(src: &str) -> Result<Self, ParseFixedError>
}
trait_delegate! {
fn overflowing_from_str(src: &str) -> Result<(Self, bool), ParseFixedError>
}
trait_delegate! {
fn overflowing_from_str_binary(src: &str) -> Result<(Self, bool), ParseFixedError>
}
trait_delegate! {
fn overflowing_from_str_octal(src: &str) -> Result<(Self, bool), ParseFixedError>
}
trait_delegate! {
fn overflowing_from_str_hex(src: &str) -> Result<(Self, bool), ParseFixedError>
}
trait_delegate! { fn int(self) -> Self }
trait_delegate! { fn frac(self) -> Self }
trait_delegate! { fn ceil(self) -> Self }
trait_delegate! { fn floor(self) -> Self }
trait_delegate! { fn round_to_zero(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_ones(self) -> u32 }
trait_delegate! { fn leading_zeros(self) -> u32 }
trait_delegate! { fn trailing_ones(self) -> u32 }
trait_delegate! { fn trailing_zeros(self) -> u32 }
trait_delegate! { fn int_log2(self) -> i32 }
trait_delegate! { fn int_log10(self) -> i32 }
trait_delegate! { fn checked_int_log2(self) -> Option<i32> }
trait_delegate! { fn checked_int_log10(self) -> Option<i32> }
trait_delegate! { fn rotate_left(self, n: u32) -> Self }
trait_delegate! { fn rotate_right(self, n: u32) -> Self }
trait_delegate! { fn div_euclid(self, rhs: Self) -> Self }
trait_delegate! { fn rem_euclid(self, rhs: Self) -> Self }
trait_delegate! { fn div_euclid_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn rem_euclid_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn checked_neg(self) -> Option<Self> }
trait_delegate! { fn checked_add(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_sub(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_mul(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_div(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_rem(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_div_euclid(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_rem_euclid(self, rhs: Self) -> Option<Self> }
trait_delegate! { fn checked_mul_int(self, rhs: Self::Bits) -> Option<Self> }
trait_delegate! { fn checked_div_int(self, rhs: Self::Bits) -> Option<Self> }
trait_delegate! { fn checked_rem_int(self, rhs: Self::Bits) -> Option<Self> }
trait_delegate! { fn checked_div_euclid_int(self, rhs: Self::Bits) -> Option<Self> }
trait_delegate! { fn checked_rem_euclid_int(self, rhs: Self::Bits) -> Option<Self> }
trait_delegate! { fn checked_shl(self, rhs: u32) -> Option<Self> }
trait_delegate! { fn checked_shr(self, rhs: u32) -> Option<Self> }
trait_delegate! { fn saturating_neg(self) -> Self }
trait_delegate! { fn saturating_add(self, rhs: Self) -> Self }
trait_delegate! { fn saturating_sub(self, rhs: Self) -> Self }
trait_delegate! { fn saturating_mul(self, rhs: Self) -> Self }
trait_delegate! { fn saturating_div(self, rhs: Self) -> Self }
trait_delegate! { fn saturating_div_euclid(self, rhs: Self) -> Self }
trait_delegate! { fn saturating_mul_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn wrapping_neg(self) -> Self }
trait_delegate! { fn wrapping_add(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_sub(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_mul(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_div(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_div_euclid(self, rhs: Self) -> Self }
trait_delegate! { fn wrapping_mul_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn wrapping_div_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn wrapping_div_euclid_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn wrapping_rem_euclid_int(self, rhs: Self::Bits) -> Self }
trait_delegate! { fn wrapping_shl(self, rhs: u32) -> Self }
trait_delegate! { fn wrapping_shr(self, rhs: u32) -> Self }
trait_delegate! { fn overflowing_neg(self) -> (Self, bool) }
trait_delegate! { fn overflowing_add(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_sub(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_mul(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_div(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) }
trait_delegate! { fn overflowing_mul_int(self, rhs: Self::Bits) -> (Self, bool) }
trait_delegate! { fn overflowing_div_int(self, rhs: Self::Bits) -> (Self, bool) }
trait_delegate! { fn overflowing_div_euclid_int(self, rhs: Self::Bits) -> (Self, bool) }
trait_delegate! { fn overflowing_rem_euclid_int(self, rhs: Self::Bits) -> (Self, bool) }
trait_delegate! { fn overflowing_shl(self, rhs: u32) -> (Self, bool) }
trait_delegate! { fn overflowing_shr(self, rhs: u32) -> (Self, bool) }
}
impl<Frac: $LeEqU> FromFixed for $Fixed<Frac> {
#[inline]
fn from_fixed<F: Fixed>(src: F) -> Self {
let (wrapped, overflow) = FromFixed::overflowing_from_fixed(src);
debug_assert!(!overflow, "{} overflows", src);
let _ = overflow;
wrapped
}
#[inline]
fn checked_from_fixed<F: Fixed>(src: F) -> Option<Self> {
match FromFixed::overflowing_from_fixed(src) {
(_, true) => None,
(wrapped, false) => Some(wrapped),
}
}
#[inline]
fn saturating_from_fixed<F: Fixed>(src: F) -> Self {
let conv = src.private_to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS);
if conv.overflow {
return if src < 0 { Self::MIN } else { Self::MAX };
}
let bits = if_signed_unsigned! {
$Signedness,
match conv.bits {
Widest::Unsigned(bits) => {
if (bits as $Bits) < 0 {
return Self::MAX;
}
bits as $Bits
}
Widest::Negative(bits) => bits as $Bits,
},
match conv.bits {
Widest::Unsigned(bits) => bits as $Bits,
Widest::Negative(_) => {
return Self::MIN;
}
},
};
Self::from_bits(bits)
}
#[inline]
fn wrapping_from_fixed<F: Fixed>(src: F) -> Self {
let (wrapped, _) = FromFixed::overflowing_from_fixed(src);
wrapped
}
#[inline]
fn overflowing_from_fixed<F: Fixed>(src: F) -> (Self, bool) {
let conv = src.private_to_fixed_helper(Self::FRAC_NBITS, Self::INT_NBITS);
let mut new_overflow = false;
let bits = if_signed_unsigned! {
$Signedness,
match conv.bits {
Widest::Unsigned(bits) => {
if (bits as $Bits) < 0 {
new_overflow = true;
}
bits as $Bits
}
Widest::Negative(bits) => bits as $Bits,
},
match conv.bits {
Widest::Unsigned(bits) => bits as $Bits,
Widest::Negative(bits) => {
new_overflow = true;
bits as $Bits
}
},
};
(Self::from_bits(bits), conv.overflow || new_overflow)
}
}
impl<Frac: $LeEqU> ToFixed for $Fixed<Frac> {
#[inline]
fn to_fixed<F: Fixed>(self) -> F {
FromFixed::from_fixed(self)
}
#[inline]
fn checked_to_fixed<F: Fixed>(self) -> Option<F> {
FromFixed::checked_from_fixed(self)
}
#[inline]
fn saturating_to_fixed<F: Fixed>(self) -> F {
FromFixed::saturating_from_fixed(self)
}
#[inline]
fn wrapping_to_fixed<F: Fixed>(self) -> F {
FromFixed::wrapping_from_fixed(self)
}
#[inline]
fn overflowing_to_fixed<F: Fixed>(self) -> (F, bool) {
FromFixed::overflowing_from_fixed(self)
}
}
if_signed! {
$Signedness;
impl<Frac: $LeEqU> FixedSigned for $Fixed<Frac> {
trait_delegate! { fn abs(self) -> Self }
trait_delegate! { fn signum(self) -> Self }
trait_delegate! { fn checked_abs(self) -> Option<Self> }
trait_delegate! { fn checked_signum(self) -> Option<Self> }
trait_delegate! { fn saturating_abs(self) -> Self }
trait_delegate! { fn saturating_signum(self) -> Self }
trait_delegate! { fn wrapping_abs(self) -> Self }
trait_delegate! { fn wrapping_signum(self) -> Self }
trait_delegate! { fn overflowing_abs(self) -> (Self, bool) }
trait_delegate! { fn overflowing_signum(self) -> (Self, bool) }
trait_delegate! { fn is_positive(self) -> bool }
trait_delegate! { fn is_negative(self) -> bool }
}
}
if_unsigned! {
$Signedness;
impl<Frac: $LeEqU> FixedUnsigned for $Fixed<Frac> {
trait_delegate! { fn is_power_of_two(self) -> bool }
trait_delegate! { fn next_power_of_two(self) -> Self }
trait_delegate! { fn checked_next_power_of_two(self) -> Option<Self> }
trait_delegate! { fn wrapping_next_power_of_two(self) -> Self }
}
}
};
}
impl_fixed! { FixedI8, LeEqU8, i8, Signed }
impl_fixed! { FixedI16, LeEqU16, i16, Signed }
impl_fixed! { FixedI32, LeEqU32, i32, Signed }
impl_fixed! { FixedI64, LeEqU64, i64, Signed }
impl_fixed! { FixedI128, LeEqU128, i128, Signed }
impl_fixed! { FixedU8, LeEqU8, u8, Unsigned }
impl_fixed! { FixedU16, LeEqU16, u16, Unsigned }
impl_fixed! { FixedU32, LeEqU32, u32, Unsigned }
impl_fixed! { FixedU64, LeEqU64, u64, Unsigned }
impl_fixed! { FixedU128, LeEqU128, u128, Unsigned }