@@ -44,6 +44,9 @@ pub enum Decimal32ConversionError {
4444 CoefficientScalingFailedError ,
4545 #[ error( "The base value for setting the sign for converting the Decimal32 into bytes must be zero." ) ]
4646 SignSettingValueIsNotZero ,
47+ #[ error( "The base value for setting the exponent was not 0x80000000 or 0x00000000." ) ]
48+ IllegalBaseValueForExponentSetting ,
49+
4750}
4851
4952type ConversionError = Decimal32ConversionError ;
@@ -77,11 +80,24 @@ fn set_sign_bit(mut result: u32, sign: Sign) -> Result<u32, ConversionError> {
7780 }
7881}
7982
83+ /// the wikipedia article at https://en.wikipedia.org/wiki/Decimal32_floating-point_format
84+ /// describes decoding a decimal32. in this case we are encoding and thus have to think the other way around
85+ /// if the significant's MSB is 0 then left shift significand by 1 (leading zero becomes implicit)
86+ /// and exponent mus start with bits 00, 01 or 10.
87+ /// if significand's 3 MSB are 100, left shift it by 3 to make the 100 implicit
88+ /// and insert 11 after the sign bit and right shift exponent field by 2 to preserve
89+ /// the two added bits.
8090fn set_exponent_bits ( mut result : u32 , exp : i64 ) -> Result < u32 , ConversionError > {
91+ if result != 0x8000_0000 && result != 0x0000_0000 {
92+ return Err ( Decimal32ConversionError :: IllegalBaseValueForExponentSetting ) ;
93+ }
8194 match exp {
8295 _ if exp < EXPONENT_MIN => Err ( Decimal32ConversionError :: ExponentUnderflow ) ,
8396 _ if exp > EXPONENT_MAX => Err ( Decimal32ConversionError :: ExponentOverflow ) ,
8497 x => {
98+ let mut unsigned_exponent: u32 = ( exp + EXPONENT_BIAS ) . try_into ( ) . unwrap ( ) ;
99+ unsigned_exponent <<= 20 ;
100+ result = result | unsigned_exponent;
85101 Ok ( result)
86102 }
87103 }
@@ -128,22 +144,21 @@ mod test {
128144
129145 #[ test]
130146 fn set_exponent_bits_works ( ) {
131- assert_eq ! ( set_exponent_bits( 0x80000000 , 1 ) . unwrap( ) , 0x86600000 ) ;
132- assert_eq ! ( set_exponent_bits( 0x80000000 , 2 ) . unwrap( ) , 0x86700000 ) ;
133- assert_eq ! ( set_exponent_bits( 0x80000000 , 8 ) . unwrap( ) , 0x86D00000 ) ;
134- assert_eq ! ( set_exponent_bits( 0x80000000 , 16 ) . unwrap( ) , 0x87500000 ) ;
135- assert_eq ! ( set_exponent_bits( 0x80000000 , 32 ) . unwrap( ) , 0x88500000 ) ;
136- assert_eq ! ( set_exponent_bits( 0x80000000 , 64 ) . unwrap( ) , 0x8A500000 ) ;
137- assert_eq ! ( set_exponent_bits( 0x80000000 , 96 ) . unwrap( ) , 0x8C500000 ) ;
138- assert_eq ! ( set_exponent_bits( 0x80000000 , 0 ) . unwrap( ) , 0x86500000 ) ;
139- assert_eq ! ( set_exponent_bits( 0x80000000 , -1 ) . unwrap( ) , 0x86400000 ) ;
140- // TODO continue here
141- assert_eq ! ( set_exponent_bits( 0x80000000 , -2 ) . unwrap( ) , 0x86600000 ) ;
142- assert_eq ! ( set_exponent_bits( 0x80000000 , -8 ) . unwrap( ) , 0x86600000 ) ;
143- assert_eq ! ( set_exponent_bits( 0x80000000 , -16 ) . unwrap( ) , 0x86600000 ) ;
144- assert_eq ! ( set_exponent_bits( 0x80000000 , -32 ) . unwrap( ) , 0x86600000 ) ;
145- assert_eq ! ( set_exponent_bits( 0x80000000 , -64 ) . unwrap( ) , 0x86600000 ) ;
146- assert_eq ! ( set_exponent_bits( 0x80000000 , -95 ) . unwrap( ) , 0x86600000 ) ;
147+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 96 ) . unwrap( ) ) , format!( "{:#b}" , 0x8C50_0000u32 ) ) ;
148+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 64 ) . unwrap( ) ) , format!( "{:#b}" , 0x8A50_0000u32 ) ) ;
149+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 32 ) . unwrap( ) ) , format!( "{:#b}" , 0x8850_0000u32 ) ) ;
150+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 16 ) . unwrap( ) ) , format!( "{:#b}" , 0x8750_0000u32 ) ) ;
151+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 8 ) . unwrap( ) ) , format!( "{:#b}" , 0x86D0_0000u32 ) ) ;
152+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 2 ) . unwrap( ) ) , format!( "{:#b}" , 0x8670_0000u32 ) ) ;
153+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 1 ) . unwrap( ) ) , format!( "{:#b}" , 0x8660_0000u32 ) ) ;
154+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 0 ) . unwrap( ) ) , format!( "{:#b}" , 0x8650_0000u32 ) ) ;
155+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -1 ) . unwrap( ) ) , format!( "{:#b}" , 0x8640_0000u32 ) ) ;
156+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -2 ) . unwrap( ) ) , format!( "{:#b}" , 0x8630_0000u32 ) ) ;
157+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -8 ) . unwrap( ) ) , format!( "{:#b}" , 0x85C0_0000u32 ) ) ;
158+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -16 ) . unwrap( ) ) , format!( "{:#b}" , 0x8550_0000u32 ) ) ;
159+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -32 ) . unwrap( ) ) , format!( "{:#b}" , 0x8450_0000u32 ) ) ;
160+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -64 ) . unwrap( ) ) , format!( "{:#b}" , 0x8250_0000u32 ) ) ;
161+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -95 ) . unwrap( ) ) , format!( "{:#b}" , 0x8060_0000u32 ) ) ;
147162 }
148163
149164}
0 commit comments