@@ -4,9 +4,9 @@ use bigdecimal::{
4
4
BigDecimal , Signed , Zero , num_traits:: ToBytes ,
5
5
} ;
6
6
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 ;
10
10
const COEFFICIENT_MAX : i64 = 9_999_999 ; // 7 digits
11
11
const DEFAULT_CONSTR : u8 = 0x74 ;
12
12
@@ -30,6 +30,14 @@ impl TryFrom<f32> for Decimal32 {
30
30
}
31
31
}
32
32
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
+
33
41
#[ derive( thiserror:: Error , Debug , PartialEq ) ]
34
42
pub enum Decimal32ConversionError {
35
43
#[ error( "Failed to parse f32 value to Decimal32 value." ) ]
@@ -52,17 +60,15 @@ pub enum Decimal32ConversionError {
52
60
type ConversionError = Decimal32ConversionError ;
53
61
54
62
fn encode_to_bytes ( value : & BigDecimal ) -> Result < Vec < u8 > , Decimal32ConversionError > {
55
- if value. is_zero ( ) {
56
- return Ok ( [ 0 ; 4 ] . to_vec ( ) ) ;
57
- }
58
-
59
63
// start with empty bit array of 32 bits
60
- let result: u32 = 0 ;
61
-
62
-
64
+ let mut result: u32 = 0 ;
63
65
64
66
let ( mut coeff, mut exp) = value. as_bigint_and_exponent ( ) ;
65
67
68
+ result = set_sign_bit ( result, coeff. sign ( ) ) ?;
69
+ result = set_exponent_bits ( result, exp) ?;
70
+ result = set_significand_bits ( result, coeff) ?;
71
+
66
72
Ok ( result. to_be_bytes ( ) . to_vec ( ) )
67
73
}
68
74
@@ -80,13 +86,6 @@ fn set_sign_bit(mut result: u32, sign: Sign) -> Result<u32, ConversionError> {
80
86
}
81
87
}
82
88
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.
90
89
fn set_exponent_bits ( mut result : u32 , exp : i64 ) -> Result < u32 , ConversionError > {
91
90
if result != 0x8000_0000 && result != 0x0000_0000 {
92
91
return Err ( Decimal32ConversionError :: IllegalBaseValueForExponentSetting ) ;
@@ -103,6 +102,12 @@ fn set_exponent_bits(mut result: u32, exp: i64)-> Result<u32, ConversionError> {
103
102
}
104
103
}
105
104
105
+ fn set_significand_bits ( mut result : u32 , significand : BigInt ) -> Result < u32 , ConversionError > {
106
+
107
+
108
+ Ok ( result)
109
+ }
110
+
106
111
107
112
#[ cfg( test) ]
108
113
mod test {
@@ -132,18 +137,19 @@ mod test {
132
137
133
138
#[ test]
134
139
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 ) ) ;
137
142
}
138
143
139
144
#[ test]
140
145
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 ) ) ;
143
148
}
144
149
145
150
#[ test]
146
151
fn set_exponent_bits_works ( ) {
152
+ assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 127 ) . unwrap( ) ) , format!( "{:#b}" , 0x8C50_0000u32 ) ) ;
147
153
assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 96 ) . unwrap( ) ) , format!( "{:#b}" , 0x8C50_0000u32 ) ) ;
148
154
assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 64 ) . unwrap( ) ) , format!( "{:#b}" , 0x8A50_0000u32 ) ) ;
149
155
assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , 32 ) . unwrap( ) ) , format!( "{:#b}" , 0x8850_0000u32 ) ) ;
@@ -159,6 +165,7 @@ mod test {
159
165
assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -32 ) . unwrap( ) ) , format!( "{:#b}" , 0x8450_0000u32 ) ) ;
160
166
assert_eq ! ( format!( "{:#b}" , set_exponent_bits( 0x8000_0000 , -64 ) . unwrap( ) ) , format!( "{:#b}" , 0x8250_0000u32 ) ) ;
161
167
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 ) ) ;
162
169
}
163
170
164
171
}
0 commit comments