Skip to main content

fix/
util.rs

1use crate::muldiv::MulDiv;
2use crate::typenum::consts::Z0;
3use crate::typenum::{Integer, IsLess, B1, U10};
4use crate::{Fix, FromUnsigned, Pow};
5
6/// Domain specific extensions to the `Fix` type as it's used in this project.
7pub trait FixExt: Sized {
8    /// This precision's equivalent of 1.
9    fn one() -> Self;
10}
11
12impl<Bits, Exp> FixExt for Fix<Bits, U10, Exp>
13where
14    Bits: FromUnsigned + Pow,
15    Exp: Integer + IsLess<Z0, Output = B1>,
16{
17    fn one() -> Self {
18        let base = Bits::from_unsigned::<U10>();
19        Fix::new(base.pow(Exp::to_i32().unsigned_abs()))
20    }
21}
22
23impl<Bits, Exp> Fix<Bits, U10, Exp>
24where
25    Self: FixExt,
26    Bits: MulDiv<Output = Bits>,
27{
28    /// Converts to another _Exp_, returning `None` on overflow.
29    ///
30    /// ```
31    /// use fix::prelude::*;
32    /// let source = UFix64::<N3>::new(5u64);
33    /// let target = source.checked_convert::<N6>();
34    /// assert_eq!(target, Some(UFix64::<N6>::new(5_000u64)));
35    /// ```
36    pub fn checked_convert<ToExp>(self) -> Option<Fix<Bits, U10, ToExp>>
37    where
38        Fix<Bits, U10, ToExp>: FixExt,
39    {
40        let target_one = Fix::<Bits, U10, ToExp>::one();
41        let source_one = Self::one();
42        target_one.mul_div_floor(self, source_one)
43    }
44}