From 031cd6e77182ea80c9452ca9ccc42418747fab69 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Tue, 17 Sep 2024 14:47:14 -0700 Subject: [PATCH] float builder (debug version) --- fixed_wide/src/fixed.rs | 73 ++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/fixed_wide/src/fixed.rs b/fixed_wide/src/fixed.rs index 84667bc..bcee486 100644 --- a/fixed_wide/src/fixed.rs +++ b/fixed_wide/src/fixed.rs @@ -138,31 +138,72 @@ impl<const N:usize,const F:usize> std::iter::Sum for Fixed<N,F>{ } } +const fn signed_shift(lhs:u64,rhs:i32)->u64{ + if rhs.is_negative(){ + lhs>>-rhs + }else{ + lhs<<rhs + } +} macro_rules! impl_into_float { - ( $output: ty ) => { + ( $output: ty, $unsigned:ty, $exponent_bits:expr, $mantissa_bits:expr ) => { impl<const N:usize,const F:usize> Into<$output> for Fixed<N,F>{ #[inline] fn into(self)->$output{ - let mut total=0.0; - let bits=self.bits.to_bits(); - let digits=bits.digits(); - for (i,digit) in digits[0..N-1].iter().enumerate(){ - // (i*64-F) as i32 will interpret the highest order bit as a sign bit but whatever - total+=(*digit as $output)*(2.0 as $output).powi((i*64-F) as i32); + const DIGIT_SHIFT:u32=6;//Log2[64] + // SBBB BBBB + // 1001 1110 0000 0000 + let sign=if self.bits.is_negative(){(1 as $unsigned)<<(<$unsigned>::BITS-1)}else{0}; + println!("sign={sign}"); + let unsigned=self.bits.unsigned_abs(); + println!("unsigned={unsigned}"); + let most_significant_bit=unsigned.bits(); + println!("most_significant_bit={most_significant_bit}"); + let exp=if unsigned.is_zero(){ + 0 + }else{ + let msb=most_significant_bit as $unsigned; + println!("msb={msb}"); + let _127=((1 as $unsigned)<<($exponent_bits-1))-1; + println!("_127={_127}"); + let msb_offset=msb+_127-1-F as $unsigned; + println!("msb_offset={msb_offset}"); + msb_offset<<($mantissa_bits-1) + }; + println!("exp={exp:#034b}"); + let digits=unsigned.digits(); + println!("digits={digits:?}"); + let digit_index=most_significant_bit>>DIGIT_SHIFT; + println!("digit_index={digit_index}"); + let digit=digits[digit_index as usize]; + println!("digit={digit:#034b}"); + //How many bits does the mantissa take from this digit + let take_bits=most_significant_bit-(digit_index<<DIGIT_SHIFT); + println!("take_bits={take_bits}"); + let rest_of_mantissa=$mantissa_bits as i32-(take_bits as i32); + println!("rest_of_mantissa={rest_of_mantissa}"); + let mut unmasked_mant=signed_shift(digit,rest_of_mantissa) as $unsigned; + println!("umnt={unmasked_mant:#034b}"); + if 0<rest_of_mantissa&&digit_index!=0{ + //take the next digit down and shove some of its bits onto the bottom of the mantissa + let digit=digits[digit_index as usize-1]; + let take_bits=most_significant_bit-((digit_index-1)<<DIGIT_SHIFT); + let rest_of_mantissa=$mantissa_bits as i32-(take_bits as i32); + let unmasked_mant2=signed_shift(digit,rest_of_mantissa) as $unsigned; + println!("unmasked_mant2={unmasked_mant2:#034b}"); + unmasked_mant|=unmasked_mant2; } - //most significant digit holds the sign bit - //assume we are using a number with at least 1 digit... - total+=((*digits.last().unwrap() as i64).abs() as $output)*(2.0 as $output).powi(((N-1)*64-F) as i32); - if self.bits.is_negative(){ - total=-total; - } - total + let mant=unmasked_mant&((1 as $unsigned)<<($mantissa_bits-1))-1; + println!("mant={mant:#034b}"); + let bits=sign|exp|mant; + println!("bits={bits:#034b}"); + <$output>::from_bits(bits) } } } } -impl_into_float!(f32); -impl_into_float!(f64); +impl_into_float!(f32,u32,8,24); +impl_into_float!(f64,u64,11,53); impl<const N:usize,const F:usize> core::fmt::Display for Fixed<N,F>{ #[inline]