use bnum::cast::As; use bnum::BInt; use wide_traits::wide::WideMul; use typenum::{Sum,Unsigned}; use std::marker::PhantomData; #[derive(Clone,Copy,Debug,Hash)] pub struct Fixed<const CHUNKS:usize,Frac>{ bits:BInt<{CHUNKS}>, frac:PhantomData<Frac>, } impl<const CHUNKS:usize,FracDst:Unsigned,T> From<T> for Fixed<CHUNKS,FracDst> where BInt<CHUNKS>:From<T> { fn from(value:T)->Self{ Self{ bits:BInt::<{CHUNKS}>::from(value)<<FracDst::U32, frac:PhantomData, } } } impl<const CHUNKS:usize,Frac> PartialEq for Fixed<CHUNKS,Frac>{ fn eq(&self,other:&Self)->bool{ self.bits.eq(&other.bits) } } impl<const CHUNKS:usize,Frac> Eq for Fixed<CHUNKS,Frac>{} impl<const CHUNKS:usize,Frac> std::ops::Neg for Fixed<CHUNKS,Frac>{ type Output=Self; fn neg(self)->Self{ Self{ bits:self.bits.neg(), frac:PhantomData, } } } macro_rules! impl_operator { ( $struct: ident, $trait: ident, $method: ident, $output: ty ) => { impl<const CHUNKS:usize,Frac> core::ops::$trait<$struct<CHUNKS,Frac>> for $struct<CHUNKS,Frac>{ type Output = $output; fn $method(self, other: Self) -> Self::Output { Self { bits:self.bits.$method(other.bits), frac:PhantomData, } } } }; } macro_rules! impl_assign_operator { ( $struct: ident, $trait: ident, $method: ident ) => { impl<const CHUNKS:usize,Frac> core::ops::$trait<$struct<CHUNKS,Frac>> for $struct<CHUNKS,Frac>{ fn $method(&mut self, other: Self) { self.bits.$method(other.bits); } } }; } // Impl arithmetic pperators impl_assign_operator!( Fixed, AddAssign, add_assign ); impl_operator!( Fixed, Add, add, Self ); impl_assign_operator!( Fixed, SubAssign, sub_assign ); impl_operator!( Fixed, Sub, sub, Self ); impl_assign_operator!( Fixed, MulAssign, mul_assign ); impl_operator!( Fixed, Mul, mul, Self ); impl_assign_operator!( Fixed, DivAssign, div_assign ); impl_operator!( Fixed, Div, div, Self ); impl_assign_operator!( Fixed, RemAssign, rem_assign ); impl_operator!( Fixed, Rem, rem, Self ); // Impl bitwise operators impl_assign_operator!( Fixed, BitAndAssign, bitand_assign ); impl_operator!( Fixed, BitAnd, bitand, Self ); impl_assign_operator!( Fixed, BitOrAssign, bitor_assign ); impl_operator!( Fixed, BitOr, bitor, Self ); impl_assign_operator!( Fixed, BitXorAssign, bitxor_assign ); impl_operator!( Fixed, BitXor, bitxor, Self ); //going wider native macro_rules! impl_wide_mul { ($lhs: expr,$rhs: expr) => { impl<A,B> WideMul<Fixed<$rhs,B>> for Fixed<$lhs,A> where A:std::ops::Add<B>, B:Unsigned, { type Output=Fixed<{$lhs+$rhs},Sum<A,B>>; fn wide_mul(self,rhs:Fixed<$rhs,B>)->Self::Output{ Fixed{ bits:self.bits.as_::<BInt<{$lhs+$rhs}>>()*rhs.bits.as_::<BInt<{$lhs+$rhs}>>(), frac:PhantomData, } } } }; } //const generics sidestepped wahoo impl_wide_mul!(1,1);impl_wide_mul!(2,1);impl_wide_mul!(3,1);impl_wide_mul!(4,1);impl_wide_mul!(5,1);impl_wide_mul!(6,1);impl_wide_mul!(7,1);impl_wide_mul!(8,1); impl_wide_mul!(1,2);impl_wide_mul!(2,2);impl_wide_mul!(3,2);impl_wide_mul!(4,2);impl_wide_mul!(5,2);impl_wide_mul!(6,2);impl_wide_mul!(7,2);impl_wide_mul!(8,2); impl_wide_mul!(1,3);impl_wide_mul!(2,3);impl_wide_mul!(3,3);impl_wide_mul!(4,3);impl_wide_mul!(5,3);impl_wide_mul!(6,3);impl_wide_mul!(7,3);impl_wide_mul!(8,3); impl_wide_mul!(1,4);impl_wide_mul!(2,4);impl_wide_mul!(3,4);impl_wide_mul!(4,4);impl_wide_mul!(5,4);impl_wide_mul!(6,4);impl_wide_mul!(7,4);impl_wide_mul!(8,4); impl_wide_mul!(1,5);impl_wide_mul!(2,5);impl_wide_mul!(3,5);impl_wide_mul!(4,5);impl_wide_mul!(5,5);impl_wide_mul!(6,5);impl_wide_mul!(7,5);impl_wide_mul!(8,5); impl_wide_mul!(1,6);impl_wide_mul!(2,6);impl_wide_mul!(3,6);impl_wide_mul!(4,6);impl_wide_mul!(5,6);impl_wide_mul!(6,6);impl_wide_mul!(7,6);impl_wide_mul!(8,6); impl_wide_mul!(1,7);impl_wide_mul!(2,7);impl_wide_mul!(3,7);impl_wide_mul!(4,7);impl_wide_mul!(5,7);impl_wide_mul!(6,7);impl_wide_mul!(7,7);impl_wide_mul!(8,7); impl_wide_mul!(1,8);impl_wide_mul!(2,8);impl_wide_mul!(3,8);impl_wide_mul!(4,8);impl_wide_mul!(5,8);impl_wide_mul!(6,8);impl_wide_mul!(7,8);impl_wide_mul!(8,8);