2024-08-23 21:17:48 +00:00
|
|
|
use bnum::cast::As;
|
2024-08-23 20:42:44 +00:00
|
|
|
use bnum::types::{I256,I512};
|
2024-08-23 23:26:19 +00:00
|
|
|
use fixed::{FixedI64,FixedI128};
|
2024-08-23 22:45:01 +00:00
|
|
|
use typenum::{Sum,Unsigned};
|
2024-08-23 20:42:44 +00:00
|
|
|
|
2024-08-23 21:17:48 +00:00
|
|
|
#[derive(Clone,Copy,Debug)]
|
2024-08-23 20:42:44 +00:00
|
|
|
pub struct Fixed<Int,Frac>{
|
|
|
|
bits:Int,
|
2024-08-23 20:00:22 +00:00
|
|
|
phantom:std::marker::PhantomData<Frac>,
|
|
|
|
}
|
2024-08-23 20:42:44 +00:00
|
|
|
pub type FixedI256<Frac>=Fixed<I256,Frac>;
|
|
|
|
pub type FixedI512<Frac>=Fixed<I512,Frac>;
|
|
|
|
|
2024-08-23 21:17:48 +00:00
|
|
|
impl<Int:From<i128>+std::ops::Shl<u32,Output=Int>,FracDst:Unsigned> From<i128> for Fixed<Int,FracDst>{
|
|
|
|
fn from(value:i128)->Self{
|
|
|
|
Self{
|
|
|
|
bits:Int::from(value)<<FracDst::U32,
|
|
|
|
phantom:std::marker::PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Int:PartialEq,Frac> PartialEq for Fixed<Int,Frac>{
|
|
|
|
fn eq(&self,other:&Self)->bool{
|
|
|
|
self.bits==other.bits
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<Int:Eq,Frac> Eq for Fixed<Int,Frac>{}
|
|
|
|
|
2024-08-23 23:48:24 +00:00
|
|
|
impl<Int:std::ops::Add<Output=Int>,Frac> std::ops::Add for Fixed<Int,Frac>{
|
|
|
|
type Output=Self;
|
|
|
|
fn add(self,rhs:Self)->Self::Output{
|
|
|
|
Self{
|
|
|
|
bits:self.bits+rhs.bits,
|
|
|
|
phantom:std::marker::PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-23 21:17:48 +00:00
|
|
|
pub trait WideMul<Rhs=Self>{
|
|
|
|
type Output;
|
|
|
|
fn wide_mul(self,rhs:Rhs)->Self::Output;
|
|
|
|
}
|
|
|
|
|
|
|
|
//going wide from foreign fixed type
|
2024-08-23 23:26:19 +00:00
|
|
|
impl<A,B> WideMul<FixedI64<B>> for FixedI64<A>
|
|
|
|
where
|
|
|
|
A:std::ops::Add<B>,
|
|
|
|
B:Unsigned,
|
|
|
|
{
|
|
|
|
type Output=FixedI128<Sum<A,B>>;
|
|
|
|
fn wide_mul(self,rhs:FixedI64<B>)->Self::Output{
|
|
|
|
self.wide_mul(rhs)
|
|
|
|
}
|
|
|
|
}
|
2024-08-23 20:42:44 +00:00
|
|
|
impl<A,B> WideMul<FixedI128<B>> for FixedI128<A>
|
|
|
|
where
|
|
|
|
A:std::ops::Add<B>,
|
|
|
|
B:Unsigned,
|
|
|
|
{
|
|
|
|
type Output=FixedI256<Sum<A,B>>;
|
|
|
|
fn wide_mul(self,rhs:FixedI128<B>)->Self::Output{
|
|
|
|
FixedI256{
|
|
|
|
bits:I256::from(self.to_bits())*I256::from(rhs.to_bits()),
|
|
|
|
phantom:std::marker::PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-08-23 21:17:48 +00:00
|
|
|
//going wider native
|
|
|
|
impl<A,B> WideMul<FixedI256<B>> for FixedI256<A>
|
|
|
|
where
|
|
|
|
A:std::ops::Add<B>,
|
|
|
|
B:Unsigned,
|
|
|
|
{
|
|
|
|
type Output=FixedI512<Sum<A,B>>;
|
|
|
|
fn wide_mul(self,rhs:FixedI256<B>)->Self::Output{
|
|
|
|
FixedI512{
|
|
|
|
bits:self.bits.as_::<I512>()*rhs.bits.as_::<I512>(),
|
|
|
|
phantom:std::marker::PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|