Skip to content

Commit 353535b

Browse files
continued on decimal32
1 parent f536781 commit 353535b

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

amqp-type/src/fixed_width/decimal32.rs

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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;
1010
const COEFFICIENT_MAX: i64 = 9_999_999; // 7 digits
1111
const 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)]
3442
pub enum Decimal32ConversionError {
3543
#[error("Failed to parse f32 value to Decimal32 value.")]
@@ -52,17 +60,15 @@ pub enum Decimal32ConversionError {
5260
type ConversionError = Decimal32ConversionError;
5361

5462
fn 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.
9089
fn 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)]
108113
mod 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

Comments
 (0)