@@ -4,9 +4,9 @@ use bigdecimal::{
44 BigDecimal , Signed , Zero , num_traits:: ToBytes ,
55} ;
66
7- const EXPONENT_BIAS : i64 = 101 ;
8- const EXPONENT_MAX : i64 = 96 ;
9- const EXPONENT_MIN : i64 = - 95 ;
7+ const EXPONENT_BIAS : i64 = 127 ;
8+ const EXPONENT_MAX : i64 = 127 ;
9+ const EXPONENT_MIN : i64 = 1 - EXPONENT_MAX ;
1010const COEFFICIENT_MAX : i64 = 9_999_999 ; // 7 digits
1111const DEFAULT_CONSTR : u8 = 0x74 ;
1212
@@ -30,6 +30,14 @@ impl TryFrom<f32> for Decimal32 {
3030 }
3131}
3232
33+ impl TryFrom < BigDecimal > for Decimal32 {
34+ type Error = ConversionError ;
35+
36+ fn try_from ( value : BigDecimal ) -> Result < Self , Self :: Error > {
37+ todo ! ( "implement conversion with error handling to only allow valid values according to IEEE 754" )
38+ }
39+ }
40+
3341#[ derive( thiserror:: Error , Debug , PartialEq ) ]
3442pub enum Decimal32ConversionError {
3543 #[ error( "Failed to parse f32 value to Decimal32 value." ) ]
@@ -52,17 +60,15 @@ pub enum Decimal32ConversionError {
5260type ConversionError = Decimal32ConversionError ;
5361
5462fn encode_to_bytes ( value : & BigDecimal ) -> Result < Vec < u8 > , Decimal32ConversionError > {
55- if value. is_zero ( ) {
56- return Ok ( [ 0 ; 4 ] . to_vec ( ) ) ;
57- }
58-
5963 // start with empty bit array of 32 bits
60- let result: u32 = 0 ;
61-
62-
64+ let mut result: u32 = 0 ;
6365
6466 let ( mut coeff, mut exp) = value. as_bigint_and_exponent ( ) ;
6567
68+ result = set_sign_bit ( result, coeff. sign ( ) ) ?;
69+ result = set_exponent_bits ( result, exp) ?;
70+ result = set_significand_bits ( result, coeff) ?;
71+
6672 Ok ( result. to_be_bytes ( ) . to_vec ( ) )
6773}
6874
@@ -80,13 +86,6 @@ fn set_sign_bit(mut result: u32, sign: Sign) -> Result<u32, ConversionError> {
8086 }
8187}
8288
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.
9089fn set_exponent_bits ( mut result : u32 , exp : i64 ) -> Result < u32 , ConversionError > {
9190 if result != 0x8000_0000 && result != 0x0000_0000 {
9291 return Err ( Decimal32ConversionError :: IllegalBaseValueForExponentSetting ) ;
@@ -103,6 +102,12 @@ fn set_exponent_bits(mut result: u32, exp: i64)-> Result<u32, ConversionError> {
103102 }
104103}
105104
105+ fn set_significand_bits ( mut result : u32 , significand : BigInt ) -> Result < u32 , ConversionError > {
106+
107+
108+ Ok ( result)
109+ }
110+
106111
107112#[ cfg( test) ]
108113mod test {
@@ -132,18 +137,19 @@ mod test {
132137
133138 #[ test]
134139 fn set_exponent_bits_if_exponent_too_large_returns_err ( ) {
135- assert_eq ! ( set_exponent_bits( 0x80000000 , 100 ) , Err ( Decimal32ConversionError :: ExponentOverflow ) ) ;
136- assert_eq ! ( set_exponent_bits( 0x80000000 , 97 ) , Err ( Decimal32ConversionError :: ExponentOverflow ) ) ;
140+ assert_eq ! ( set_exponent_bits( 0x80000000 , 128 ) , Err ( Decimal32ConversionError :: ExponentOverflow ) ) ;
141+ assert_eq ! ( set_exponent_bits( 0x80000000 , 139 ) , Err ( Decimal32ConversionError :: ExponentOverflow ) ) ;
137142 }
138143
139144 #[ test]
140145 fn set_exponent_bits_if_exponent_too_small_returns_err ( ) {
141- assert_eq ! ( set_exponent_bits( 0x80000000 , -100 ) , Err ( Decimal32ConversionError :: ExponentUnderflow ) ) ;
142- assert_eq ! ( set_exponent_bits( 0x80000000 , -96 ) , Err ( Decimal32ConversionError :: ExponentUnderflow ) ) ;
146+ assert_eq ! ( set_exponent_bits( 0x80000000 , -127 ) , Err ( Decimal32ConversionError :: ExponentUnderflow ) ) ;
147+ assert_eq ! ( set_exponent_bits( 0x80000000 , -300 ) , Err ( Decimal32ConversionError :: ExponentUnderflow ) ) ;
143148 }
144149
145150 #[ test]
146151 fn set_exponent_bits_works ( ) {
152+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 127 ) . unwrap( ) ) , format!( "{:#b}" , 0x8C50_0000u32 ) ) ;
147153 assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 96 ) . unwrap( ) ) , format!( "{:#b}" , 0x8C50_0000u32 ) ) ;
148154 assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 64 ) . unwrap( ) ) , format!( "{:#b}" , 0x8A50_0000u32 ) ) ;
149155 assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 32 ) . unwrap( ) ) , format!( "{:#b}" , 0x8850_0000u32 ) ) ;
@@ -159,6 +165,7 @@ mod test {
159165 assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -32 ) . unwrap( ) ) , format!( "{:#b}" , 0x8450_0000u32 ) ) ;
160166 assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -64 ) . unwrap( ) ) , format!( "{:#b}" , 0x8250_0000u32 ) ) ;
161167 assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -95 ) . unwrap( ) ) , format!( "{:#b}" , 0x8060_0000u32 ) ) ;
168+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -126 ) . unwrap( ) ) , format!( "{:#b}" , 0x8060_0000u32 ) ) ;
162169 }
163170
164171}
0 commit comments