Skip to main content

fix/
util.rs

1use paste::paste;
2
3use crate::muldiv::MulDiv;
4use crate::typenum::{NInt, NonZero, Unsigned, U10};
5use crate::Fix;
6
7/// Domain specific extensions to the `Fix` type as it's used in this project.
8pub trait FixExt: Sized {
9    /// This precision's equivalent of 1.
10    const ONE: Self;
11}
12
13macro_rules! impl_fix_ext {
14    ($bits:ident) => {
15        paste! {
16            impl<U> FixExt for Fix<$bits, U10, NInt<U>>
17            where
18                U: Unsigned + NonZero,
19            {
20                const ONE: Self =
21                    Fix::constant((10 as $bits).pow(U::U32));
22            }
23        }
24    };
25}
26
27impl_fix_ext!(u8);
28impl_fix_ext!(u16);
29impl_fix_ext!(u32);
30impl_fix_ext!(u64);
31impl_fix_ext!(u128);
32impl_fix_ext!(usize);
33impl_fix_ext!(i8);
34impl_fix_ext!(i16);
35impl_fix_ext!(i32);
36impl_fix_ext!(i64);
37impl_fix_ext!(i128);
38impl_fix_ext!(isize);
39
40impl<Bits, Base, Exp> Fix<Bits, Base, Exp>
41where
42    Self: FixExt,
43{
44    /// This precision's equivalent of 1.
45    #[must_use]
46    pub const fn one() -> Self {
47        <Self as FixExt>::ONE
48    }
49}
50
51impl<Bits, Exp> Fix<Bits, U10, Exp>
52where
53    Self: FixExt,
54    Bits: MulDiv<Output = Bits>,
55{
56    /// Converts to another _Exp_, returning `None` on overflow.
57    ///
58    /// ```
59    /// use fix::prelude::*;
60    /// let source = UFix64::<N3>::new(5u64);
61    /// let target = source.checked_convert::<N6>();
62    /// assert_eq!(target, Some(UFix64::<N6>::new(5_000u64)));
63    /// ```
64    pub fn checked_convert<ToExp>(self) -> Option<Fix<Bits, U10, ToExp>>
65    where
66        Fix<Bits, U10, ToExp>: FixExt,
67    {
68        let target_one = Fix::<Bits, U10, ToExp>::one();
69        let source_one = Self::one();
70        target_one.mul_div_floor(self, source_one)
71    }
72}