// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 /// A Fixed point, represented with the T underlying type, and shifted by so many bits #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Fixed(pub T); impl< T: Copy + core::ops::Shl + core::ops::Shr + core::ops::Div + core::ops::Add + core::ops::Rem, const SHIFT: usize, > Fixed { /// Create a fixed point from an integer value pub fn from_integer(value: T) -> Self { Self(value << SHIFT) } /// Get the integer part of the fixed point value pub fn truncate(self) -> T { self.0 >> SHIFT } pub fn from_fixed< T2: core::ops::Shl + core::ops::Shr + Into, const SHIFT2: usize, >( value: Fixed, ) -> Self { if SHIFT > SHIFT2 { let s: T = value.0.into(); Self(s << (SHIFT - SHIFT2)) } else { Self((value.0 >> (SHIFT2 - SHIFT)).into()) } } pub fn try_from_fixed< T2: core::ops::Shl + core::ops::Shr + TryInto, const SHIFT2: usize, >( value: Fixed, ) -> Result { Ok(if SHIFT > SHIFT2 { let s: T = value.0.try_into()?; Self(s << (SHIFT - SHIFT2)) } else { Self((value.0 >> (SHIFT2 - SHIFT)).try_into()?) }) } pub(crate) fn from_f32(value: f32) -> Option where T: num_traits::FromPrimitive, { Some(Self(T::from_f32(value * (1 << SHIFT) as f32)?)) } } impl, const SHIFT: usize> core::ops::Add for Fixed { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self(self.0.add(rhs.0)) } } impl, const SHIFT: usize> core::ops::Sub for Fixed { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self(self.0.sub(rhs.0)) } } impl core::ops::AddAssign for Fixed { fn add_assign(&mut self, rhs: Self) { self.0.add_assign(rhs.0) } } impl core::ops::SubAssign for Fixed { fn sub_assign(&mut self, rhs: Self) { self.0.sub_assign(rhs.0) } } impl, const SHIFT: usize> core::ops::Mul for Fixed { type Output = Self; fn mul(self, rhs: T) -> Self::Output { Self(self.0.mul(rhs)) } } impl, const SHIFT: usize> core::ops::Neg for Fixed { type Output = Self; fn neg(self) -> Self::Output { Self(-self.0) } } impl, const SHIFT: usize> core::ops::Div for Fixed { type Output = T; fn div(self, rhs: Self) -> Self::Output { self.0 / rhs.0 } } impl, const SHIFT: usize> core::ops::Rem for Fixed { type Output = Self; fn rem(self, rhs: Self) -> Self::Output { Self(self.0 % rhs.0) } }