diff --git a/fixed_wide/Cargo.toml b/fixed_wide/Cargo.toml index cc218bc..ab20a56 100644 --- a/fixed_wide/Cargo.toml +++ b/fixed_wide/Cargo.toml @@ -4,8 +4,9 @@ version = "0.1.0" edition = "2021" [features] -default=["zeroes"] +default=["zeroes","wide-mul"] ratio=[] +wide-mul=[] zeroes=["ratio","dep:arrayvec"] [dependencies] diff --git a/fixed_wide/src/fixed.rs b/fixed_wide/src/fixed.rs index c8b1969..79f7579 100644 --- a/fixed_wide/src/fixed.rs +++ b/fixed_wide/src/fixed.rs @@ -1,6 +1,7 @@ use bnum::{BInt,cast::As}; #[derive(Clone,Copy,Debug,Hash)] +/// A Fixed point number for which multiply operations widen the bits in the output. (when the wide-mul feature is enabled) /// N is the number of u64s to use /// F is the number of fractional bits (always N*32 lol) pub struct Fixed{ @@ -139,6 +140,10 @@ impl_additive_operator!( Fixed, BitOr, bitor, Self ); impl_additive_assign_operator!( Fixed, BitXorAssign, bitxor_assign ); impl_additive_operator!( Fixed, BitXor, bitxor, Self ); +// non-wide operators. The result is the same width as the inputs. + +// This macro is not used in the default configuration. +#[allow(unused_macros)] macro_rules! impl_multiplicative_operator_not_const_generic { ( ($struct: ident, $trait: ident, $method: ident, $output: ty ), $width:expr ) => { impl core::ops::$trait for $struct<$width,F>{ @@ -175,6 +180,7 @@ macro_rules! impl_multiply_operator_not_const_generic { } } } + #[cfg(not(feature="wide-mul"))] impl_multiplicative_operator_not_const_generic!(($struct, $trait, $method, $output ), $width); } } @@ -191,6 +197,7 @@ macro_rules! impl_divide_operator_not_const_generic { } } } + #[cfg(all(not(feature="wide-mul"),not(feature="ratio")))] impl_multiplicative_operator_not_const_generic!(($struct, $trait, $method, $output ), $width); }; } @@ -248,6 +255,13 @@ impl_multiplicative_assign_operator!( Fixed, MulAssign, mul_assign ); impl_multiplicative_operator!( Fixed, Mul, mul, Self ); impl_multiplicative_assign_operator!( Fixed, DivAssign, div_assign ); impl_multiplicative_operator!( Fixed, Div, div, Self ); +#[cfg(feature="ratio")] +impl core::ops::Div> for Fixed{ + type Output=crate::ratio::Ratio,Fixed>; + fn div(self, other: Fixed)->Self::Output{ + crate::ratio::Ratio::new(self,other) + } +} macro_rules! impl_shift_operator { ( $struct: ident, $trait: ident, $method: ident, $output: ty ) => { @@ -274,6 +288,30 @@ impl_shift_operator!( Fixed, Shl, shl, Self ); impl_shift_assign_operator!( Fixed, ShrAssign, shr_assign ); impl_shift_operator!( Fixed, Shr, shr, Self ); +// wide operators. The result width is the sum of the input widths, i.e. none of the multiplication + +macro_rules! impl_wide_operators{ + ($lhs:expr,$rhs:expr)=>{ + impl core::ops::Mul> for Fixed<$lhs,{$lhs*32}>{ + type Output=Fixed<{$lhs+$rhs},{($lhs+$rhs)*32}>; + fn mul(self, other: Fixed<$rhs,{$rhs*32}>)->Self::Output{ + paste::item!{ + self.[](other) + } + } + } + #[cfg(not(feature="ratio"))] + impl core::ops::Div> for Fixed<$lhs,{$lhs*32}>{ + type Output=Fixed<{$lhs+$rhs},{($lhs+$rhs)*32}>; + fn div(self, other: Fixed<$rhs,{$rhs*32}>)->Self::Output{ + paste::item!{ + self.[](other) + } + } + } + } +} + // WIDE MUL: multiply into a wider type // let a = I32F32::ONE; // let b:I64F64 = a.wide_mul(a); @@ -301,6 +339,8 @@ macro_rules! impl_wide_not_const_generic{ } } } + #[cfg(feature="wide-mul")] + impl_wide_operators!($lhs,$rhs); }; } diff --git a/fixed_wide/src/tests.rs b/fixed_wide/src/tests.rs index 43fa2ab..2f9aaa6 100644 --- a/fixed_wide/src/tests.rs +++ b/fixed_wide/src/tests.rs @@ -65,7 +65,7 @@ fn test_sqrt_zero(){ #[test] fn test_sqrt_low(){ let a=I32F32::HALF; - let b=a*a; + let b=a.fixed_mul(a); assert_eq!(b.sqrt(),a); } fn find_equiv_sqrt_via_f64(n:I32F32)->I32F32{