diff --git a/fixed_wide/Cargo.lock b/fixed_wide/Cargo.lock index d8b81fb..ff09daa 100644 --- a/fixed_wide/Cargo.lock +++ b/fixed_wide/Cargo.lock @@ -21,7 +21,6 @@ dependencies = [ "arrayvec", "bnum", "paste", - "typenum", ] [[package]] @@ -29,9 +28,3 @@ name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" diff --git a/fixed_wide/Cargo.toml b/fixed_wide/Cargo.toml index 6b39bd1..cc218bc 100644 --- a/fixed_wide/Cargo.toml +++ b/fixed_wide/Cargo.toml @@ -10,6 +10,5 @@ zeroes=["ratio","dep:arrayvec"] [dependencies] bnum = "0.11.0" -typenum = "1.17.0" arrayvec = { version = "0.7.6", optional = true } paste = "1.0.15" diff --git a/fixed_wide/src/fixed.rs b/fixed_wide/src/fixed.rs index a57135f..81494a3 100644 --- a/fixed_wide/src/fixed.rs +++ b/fixed_wide/src/fixed.rs @@ -1,35 +1,34 @@ use bnum::{BInt,cast::As}; -use typenum::{Sum,Unsigned}; #[derive(Clone,Copy,Debug,Hash)] -pub struct Fixed{ - pub(crate)bits:BInt<{CHUNKS}>, - pub(crate)frac:std::marker::PhantomData, +/// N is the number of u64s to use +/// F is the number of fractional bits (always N*32 lol) +pub struct Fixed{ + pub(crate)bits:BInt<{N}>, } -impl Fixed{ - pub const MAX:Self=Self::from_bits(BInt::::MAX); - pub const MIN:Self=Self::from_bits(BInt::::MIN); - pub const ZERO:Self=Self::from_bits(BInt::::ZERO); - pub const EPSILON:Self=Self::from_bits(BInt::::ONE); - pub const NEG_EPSILON:Self=Self::from_bits(BInt::::NEG_ONE); - pub const ONE:Self=Self::from_bits(BInt::::ONE.shl(Frac::U32)); - pub const TWO:Self=Self::from_bits(BInt::::TWO.shl(Frac::U32)); - pub const HALF:Self=Self::from_bits(BInt::::ONE.shl(Frac::U32-1)); - pub const NEG_ONE:Self=Self::from_bits(BInt::::NEG_ONE.shl(Frac::U32)); - pub const NEG_TWO:Self=Self::from_bits(BInt::::NEG_TWO.shl(Frac::U32)); - pub const NEG_HALF:Self=Self::from_bits(BInt::::NEG_ONE.shl(Frac::U32-1)); +impl Fixed{ + pub const MAX:Self=Self::from_bits(BInt::::MAX); + pub const MIN:Self=Self::from_bits(BInt::::MIN); + pub const ZERO:Self=Self::from_bits(BInt::::ZERO); + pub const EPSILON:Self=Self::from_bits(BInt::::ONE); + pub const NEG_EPSILON:Self=Self::from_bits(BInt::::NEG_ONE); + pub const ONE:Self=Self::from_bits(BInt::::ONE.shl(F as u32)); + pub const TWO:Self=Self::from_bits(BInt::::TWO.shl(F as u32)); + pub const HALF:Self=Self::from_bits(BInt::::ONE.shl(F as u32-1)); + pub const NEG_ONE:Self=Self::from_bits(BInt::::NEG_ONE.shl(F as u32)); + pub const NEG_TWO:Self=Self::from_bits(BInt::::NEG_TWO.shl(F as u32)); + pub const NEG_HALF:Self=Self::from_bits(BInt::::NEG_ONE.shl(F as u32-1)); } -impl Fixed{ +impl Fixed{ #[inline] - pub const fn from_bits(bits:BInt::)->Self{ + pub const fn from_bits(bits:BInt::)->Self{ Self{ bits, - frac:std::marker::PhantomData, } } #[inline] - pub const fn to_bits(self)->BInt{ + pub const fn to_bits(self)->BInt{ self.bits } #[inline] @@ -38,34 +37,34 @@ impl Fixed{ } } -impl From for Fixed +impl From for Fixed where - BInt:From + BInt:From { fn from(value:T)->Self{ - Self::from_bits(BInt::<{CHUNKS}>::from(value)<::from(value)< PartialEq for Fixed{ +impl PartialEq for Fixed{ fn eq(&self,other:&Self)->bool{ self.bits.eq(&other.bits) } } -impl Eq for Fixed{} +impl Eq for Fixed{} -impl PartialOrd for Fixed{ +impl PartialOrd for Fixed{ fn partial_cmp(&self,other:&Self)->Option{ self.bits.partial_cmp(&other.bits) } } -impl Ord for Fixed{ +impl Ord for Fixed{ fn cmp(&self,other:&Self)->std::cmp::Ordering{ self.bits.cmp(&other.bits) } } -impl std::ops::Neg for Fixed{ +impl std::ops::Neg for Fixed{ type Output=Self; fn neg(self)->Self{ Self::from_bits(self.bits.neg()) @@ -74,38 +73,38 @@ impl std::ops::Neg for Fixed{ macro_rules! impl_additive_operator { ( $struct: ident, $trait: ident, $method: ident, $output: ty ) => { - impl core::ops::$trait for $struct{ + impl core::ops::$trait for $struct{ type Output = $output; fn $method(self, other: Self) -> Self::Output { Self::from_bits(self.bits.$method(other.bits)) } } - impl core::ops::$trait for $struct + impl core::ops::$trait for $struct where - BInt:::From, + BInt:::From, { type Output = $output; fn $method(self, other: U) -> Self::Output { - Self::from_bits(self.bits.$method(BInt::::from(other)<::from(other).shl(F as u32))) } } }; } macro_rules! impl_additive_assign_operator { ( $struct: ident, $trait: ident, $method: ident ) => { - impl core::ops::$trait for $struct{ + impl core::ops::$trait for $struct{ fn $method(&mut self, other: Self) { self.bits.$method(other.bits); } } - impl core::ops::$trait for $struct + impl core::ops::$trait for $struct where - BInt:::From, + BInt:::From, { fn $method(&mut self, other: U) { - self.bits.$method(BInt::::from(other)<::from(other)< { - impl core::ops::$trait for $struct<$width,Frac>{ + impl core::ops::$trait for $struct<$width,F>{ type Output = $output; fn $method(self, other: Self) -> Self::Output { //this can be done better but that is a job for later let lhs=self.bits.as_::>(); let rhs=other.bits.as_::>(); - Self::from_bits(lhs.mul(rhs).shr(Frac::U32).as_()) + Self::from_bits(lhs.mul(rhs).shr(F as u32).as_()) } } }; } macro_rules! impl_multiply_assign_operator_const { ( $width:expr, $struct: ident, $trait: ident, $method: ident ) => { - impl core::ops::$trait for $struct<$width,Frac>{ + impl core::ops::$trait for $struct<$width,F>{ fn $method(&mut self, other: Self) { self.bits.$method(other.bits); } @@ -153,13 +152,13 @@ macro_rules! impl_multiply_assign_operator_const { macro_rules! impl_divide_operator_const { ( $width:expr, $struct: ident, $trait: ident, $method: ident, $output: ty ) => { - impl core::ops::$trait for $struct<$width,Frac>{ + impl core::ops::$trait for $struct<$width,F>{ type Output = $output; fn $method(self, other: Self) -> Self::Output { //this can be done better but that is a job for later - //this only needs to be $width+Frac::U32/64+1 but MUH CONST GENERICS!!!!! - let lhs=self.bits.as_::>().shl(Frac::U32); + //this only needs to be $width+F as u32/64+1 but MUH CONST GENERICS!!!!! + let lhs=self.bits.as_::>().shl(F as u32); let rhs=other.bits.as_::>(); Self::from_bits(lhs.div(rhs).as_()) } @@ -168,7 +167,7 @@ macro_rules! impl_divide_operator_const { } macro_rules! impl_divide_assign_operator_const { ( $width:expr, $struct: ident, $trait: ident, $method: ident ) => { - impl core::ops::$trait for $struct<$width,Frac>{ + impl core::ops::$trait for $struct<$width,F>{ fn $method(&mut self, other: Self) { self.bits.$method(other.bits); } @@ -178,26 +177,26 @@ macro_rules! impl_divide_assign_operator_const { macro_rules! impl_multiplicatave_operator { ( $struct: ident, $trait: ident, $method: ident, $output: ty ) => { - impl core::ops::$trait for $struct + impl core::ops::$trait for $struct where - BInt:::From+core::ops::$trait, + BInt:::From+core::ops::$trait, { type Output = $output; fn $method(self, other: U) -> Self::Output { - Self::from_bits(self.bits.$method(BInt::::from(other))) + Self::from_bits(self.bits.$method(BInt::::from(other))) } } }; } macro_rules! impl_multiplicatave_assign_operator { ( $struct: ident, $trait: ident, $method: ident ) => { - impl core::ops::$trait for $struct + impl core::ops::$trait for $struct where - BInt:::From+core::ops::$trait, + BInt:::From+core::ops::$trait, { fn $method(&mut self, other: U) { - self.bits.$method(BInt::::from(other)); + self.bits.$method(BInt::::from(other)); } } }; @@ -255,7 +254,7 @@ impl_multiplicatave_operator!( Fixed, Div, div, Self ); macro_rules! impl_shift_operator { ( $struct: ident, $trait: ident, $method: ident, $output: ty ) => { - impl core::ops::$trait for $struct{ + impl core::ops::$trait for $struct{ type Output = $output; fn $method(self, other: u32) -> Self::Output { @@ -266,7 +265,7 @@ macro_rules! impl_shift_operator { } macro_rules! impl_shift_assign_operator { ( $struct: ident, $trait: ident, $method: ident ) => { - impl core::ops::$trait for $struct{ + impl core::ops::$trait for $struct{ fn $method(&mut self, other: u32) { self.bits.$method(other); } @@ -283,13 +282,10 @@ impl_shift_operator!( Fixed, Shr, shr, Self ); // let b:I64F64 = a.wide_mul(a); macro_rules! impl_wide_mul{ ($lhs:expr,$rhs:expr)=>{ - impl Fixed<$lhs,A> + impl Fixed<$lhs,{$lhs*32}> { paste::item!{ - pub fn [](self,rhs:Fixed<$rhs,B>)->Fixed<{$lhs+$rhs},Sum> - where - A:std::ops::Add, - B:Unsigned,{ + pub fn [](self,rhs:Fixed<$rhs,{$rhs*32}>)->Fixed<{$lhs+$rhs},{($lhs+$rhs)*32}>{ Fixed::from_bits(self.bits.as_::>()*rhs.bits.as_::>()) } } @@ -316,15 +312,15 @@ impl_wide_mul_all!( (1,7),(2,7),(3,7),(4,7),(5,7),(6,7),(7,7),(8,7), (1,8),(2,8),(3,8),(4,8),(5,8),(6,8),(7,8),(8,8) ); -impl Fixed{ - pub fn resize_into(self)->Fixed{ +impl Fixed{ + pub fn resize_into(self)->Fixed{ Fixed::from_bits(self.bits.as_::>()) } } macro_rules! impl_const{ ($n:expr)=>{ - impl Fixed<$n,F>{ + impl Fixed<$n,{$n*32}>{ paste::item!{ pub fn sqrt_unchecked(self)->Self{ //1<>1 (sqrt-ish) //3. add on fractional offset //Voila - let used_bits=self.bits.bits() as i32-1-F::I32; - let max_shift=((used_bits>>1)+F::I32) as u32; + let used_bits=self.bits.bits() as i32-1-($n*32) as i32; + let max_shift=((used_bits>>1)+($n*32) as i32) as u32; let mut result=Self::ZERO; //multiply by one to make the types match (hack) diff --git a/fixed_wide/src/lib.rs b/fixed_wide/src/lib.rs index 049fd9d..eee0ec3 100644 --- a/fixed_wide/src/lib.rs +++ b/fixed_wide/src/lib.rs @@ -1,10 +1,6 @@ pub mod fixed; pub mod types; -pub mod typenum{ - pub use typenum::Unsigned; -} - #[cfg(feature="zeroes")] pub mod zeroes; #[cfg(feature="ratio")] diff --git a/fixed_wide/src/tests.rs b/fixed_wide/src/tests.rs index 1e92025..879a7fe 100644 --- a/fixed_wide/src/tests.rs +++ b/fixed_wide/src/tests.rs @@ -3,7 +3,7 @@ use crate::types::I32F32; #[test] fn test_wide_mul(){ let a=I32F32::ONE; - let aa=a.wide_mul(a); + let aa=a.wide_mul_1_1(a); assert_eq!(aa,crate::types::I64F64::ONE); } @@ -39,10 +39,10 @@ fn find_equiv_sqrt_via_f64(n:I32F32)->I32F32{ let r=I32F32::from_bits(bnum::BInt::<1>::from(i)); //mimic the behaviour of the algorithm, //return the result if it truncates to the exact answer - if (r+I32F32::EPSILON).wide_mul(r+I32F32::EPSILON)==n.wide_mul(I32F32::ONE){ + if (r+I32F32::EPSILON).wide_mul_1_1(r+I32F32::EPSILON)==n.wide_mul_1_1(I32F32::ONE){ return r+I32F32::EPSILON; } - if (r-I32F32::EPSILON).wide_mul(r-I32F32::EPSILON)==n.wide_mul(I32F32::ONE){ + if (r-I32F32::EPSILON).wide_mul_1_1(r-I32F32::EPSILON)==n.wide_mul_1_1(I32F32::ONE){ return r-I32F32::EPSILON; } return r; diff --git a/fixed_wide/src/types.rs b/fixed_wide/src/types.rs index 98cec10..8694435 100644 --- a/fixed_wide/src/types.rs +++ b/fixed_wide/src/types.rs @@ -1,4 +1,4 @@ -pub type I32F32=crate::fixed::Fixed<1,typenum::consts::U32>; -pub type I64F64=crate::fixed::Fixed<2,typenum::consts::U64>; -pub type I128F128=crate::fixed::Fixed<4,typenum::consts::U128>; -pub type I256F256=crate::fixed::Fixed<8,typenum::consts::U256>; +pub type I32F32=crate::fixed::Fixed<1,32>; +pub type I64F64=crate::fixed::Fixed<2,64>; +pub type I128F128=crate::fixed::Fixed<4,128>; +pub type I256F256=crate::fixed::Fixed<8,256>; diff --git a/fixed_wide/src/zeroes.rs b/fixed_wide/src/zeroes.rs index 8668dc5..16d211d 100644 --- a/fixed_wide/src/zeroes.rs +++ b/fixed_wide/src/zeroes.rs @@ -1,30 +1,27 @@ use crate::fixed::Fixed; use crate::ratio::Ratio; -use typenum::{Sum,Unsigned}; use arrayvec::ArrayVec; use std::cmp::Ordering; macro_rules! impl_zeroes{ ($n:expr)=>{ - impl Fixed<$n,F> - where - F:Unsigned+std::ops::Add, - ::Output:Unsigned, - { + impl Fixed<$n,{$n*32}>{ paste::item!{ #[inline] pub fn zeroes2(a0:Self,a1:Self,a2:Self)->ArrayVec,2>{ let a2pos=match a2.cmp(&Self::ZERO){ Ordering::Greater=>true, - Ordering::Equal=>return ArrayVec::from_iter($crate::zeroes::zeroes1(a0,a1).into_iter()), + Ordering::Equal=>return ArrayVec::from_iter(Self::zeroes1(a0,a1).into_iter()), Ordering::Less=>true, }; let radicand=a1.[](a1)-a2.[](a0)*4; - match radicand.cmp(&Fixed::<{$n*2},Sum>::ZERO){ + match radicand.cmp(&Fixed::<{$n*2},{$n*2*32}>::ZERO){ Ordering::Greater=>{ //start with f64 sqrt //failure case: 2^63 < sqrt(2^127) - let planar_radicand=radicand.sqrt(); + let planar_radicand_wide=radicand.sqrt(); + //lazy hack + let planar_radicand=Self::from_bits(bnum::cast::As::as_(planar_radicand_wide.bits.shr($n*32))); //TODO: one or two newtons //sort roots ascending and avoid taking the difference of large numbers match (a2pos,Self::ZERO