fxp 0.1.0

Fixed-point numbers in Rust using const generics
Documentation
#[macro_export]
macro_rules! ifxp {
	($name:ident, $base:ty) => {

		#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Default, Debug)]
		pub struct $name<const EXPONENT: usize>($base);

		impl<const EXP: usize> $name<EXP>
		{
			fn precision<const EXPONENT: usize>(
				self,
			) -> $name<EXPONENT>
			{
				let diff = EXPONENT - EXP;
				$name::<EXPONENT>(self.0 >> diff)
			}
		}

		impl<const EXP1: usize, const EXP2: usize>
			ops::Add<$name<EXP2>> for $name<EXP1>
		where
			$name<{ max(EXP1, EXP2) }>: Sized,
		{
			type Output = $name<{ max(EXP1, EXP2) }>;

			fn add(self, rhs: $name<EXP2>) -> Self::Output
			{
				$name::<{ max(EXP1, EXP2) }>(
					self.precision::<{ max(EXP1, EXP2) }>().0
						+ rhs.precision::<{ max(EXP1, EXP2) }>().0,
				)
			}
		}

		impl<const EXP: usize> ops::AddAssign<$name<EXP>>
			for $name<EXP>
		{
			fn add_assign(&mut self, rhs: Self)
			{
				self.0 += rhs.0
			}
		}

		impl<const EXP1: usize, const EXP2: usize>
			ops::Div<$name<EXP2>> for $name<EXP1>
		where
			$name<{ EXP1 - EXP2 }>: Sized,
		{
			type Output = $name<{ EXP1 - EXP2 }>;

			fn div(self, rhs: $name<EXP2>) -> Self::Output
			{
				$name::<{ EXP1 - EXP2 }>(self.0 / rhs.0)
			}
		}

		impl<const EXP1: usize, const EXP2: usize>
			ops::Mul<$name<EXP2>> for $name<EXP1>
		where
			$name<{ EXP1 + EXP2 }>: Sized,
		{
			type Output = $name<{ EXP1 + EXP2 }>;

			fn mul(self, rhs: $name<EXP2>) -> Self::Output
			{
				$name::<{ EXP1 + EXP2 }>(self.0 * rhs.0)
			}
		}

		impl<const EXP: usize> ops::Neg for $name<EXP>
		{
			type Output = Self;

			fn neg(self) -> Self::Output
			{
				Self(-self.0)
			}
		}

		impl<const EXP1: usize, const EXP2: usize>
			ops::Sub<$name<EXP2>> for $name<EXP1>
		where
			$name<{ max(EXP1, EXP2) }>: Sized,
		{
			type Output = $name<{ max(EXP1, EXP2) }>;

			fn sub(self, rhs: $name<EXP2>) -> Self::Output
			{
				$name::<{ max(EXP1, EXP2) }>(
					self.precision::<{ max(EXP1, EXP2) }>().0
						- rhs.precision::<{ max(EXP1, EXP2) }>().0,
				)
			}
		}

		impl<const EXP: usize> ops::SubAssign<$name<EXP>>
			for $name<EXP>
		{
			fn sub_assign(&mut self, rhs: Self)
			{
				self.0 -= rhs.0
			}
		}
	};
}

#[macro_export]
macro_rules! ufxp {
	($name:ident, $base:ty) => {
		#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Default, Debug)]
		pub struct $name<const EXPONENT: usize>($base);

		impl<const EXP: usize> $name<EXP>
		{
			fn precision<const EXPONENT: usize>(
				self,
			) -> $name<EXPONENT>
			{
				let diff = EXPONENT - EXP;
				$name::<EXPONENT>(self.0 >> diff)
			}
		}

		impl<const EXP1: usize, const EXP2: usize>
			ops::Add<$name<EXP2>> for $name<EXP1>
		where
			$name<{ max(EXP1, EXP2) }>: Sized,
		{
			type Output = $name<{ max(EXP1, EXP2) }>;

			fn add(self, rhs: $name<EXP2>) -> Self::Output
			{
				$name::<{ max(EXP1, EXP2) }>(
					self.precision::<{ max(EXP1, EXP2) }>().0
						+ rhs.precision::<{ max(EXP1, EXP2) }>().0,
				)
			}
		}

		impl<const EXP: usize> ops::AddAssign<$name<EXP>>
			for $name<EXP>
		{
			fn add_assign(&mut self, rhs: Self)
			{
				self.0 += rhs.0
			}
		}

		impl<const EXP1: usize, const EXP2: usize>
			ops::Div<$name<EXP2>> for $name<EXP1>
		where
			$name<{ EXP1 - EXP2 }>: Sized,
		{
			type Output = $name<{ EXP1 - EXP2 }>;

			fn div(self, rhs: $name<EXP2>) -> Self::Output
			{
				$name::<{ EXP1 - EXP2 }>(self.0 / rhs.0)
			}
		}

		impl<const EXP1: usize, const EXP2: usize>
			ops::Mul<$name<EXP2>> for $name<EXP1>
		where
			$name<{ EXP1 + EXP2 }>: Sized,
		{
			type Output = $name<{ EXP1 + EXP2 }>;

			fn mul(self, rhs: $name<EXP2>) -> Self::Output
			{
				$name::<{ EXP1 + EXP2 }>(self.0 * rhs.0)
			}
		}

		impl<const EXP1: usize, const EXP2: usize>
			ops::Sub<$name<EXP2>> for $name<EXP1>
		where
			$name<{ max(EXP1, EXP2) }>: Sized,
		{
			type Output = $name<{ max(EXP1, EXP2) }>;

			fn sub(self, rhs: $name<EXP2>) -> Self::Output
			{
				$name::<{ max(EXP1, EXP2) }>(
					self.precision::<{ max(EXP1, EXP2) }>().0
						- rhs.precision::<{ max(EXP1, EXP2) }>().0,
				)
			}
		}

		impl<const EXP: usize> ops::SubAssign<$name<EXP>>
			for $name<EXP>
		{
			fn sub_assign(&mut self, rhs: Self)
			{
				self.0 -= rhs.0
			}
		}
	};
}