Skip to content

Commit 6b0e913

Browse files
implemented decimal32 to binary conversion
1 parent 353535b commit 6b0e913

File tree

2 files changed

+67
-126
lines changed

2 files changed

+67
-126
lines changed

amqp-type/src/error.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ pub enum AppError {
88
DeserializationIllegalConstructorError(u8),
99
#[error("Iterator was empty or too short.")]
1010
IteratorEmptyOrTooShortError,
11-
#[error("Error while converting Decimal32.")]
12-
Decimal32ConversionError(#[from] crate::fixed_width::decimal32::Decimal32ConversionError),
13-
#[error("Error while converting Decimal64.")]
14-
Decimal64ConversionError(#[from] crate::fixed_width::decimal64::Decimal64ConversionError),
1511
#[error("Error while converting Decimal128.")]
1612
Decimal128ConversionError(#[from] crate::fixed_width::decimal128::Decimal128ConversionError),
1713
}
Lines changed: 67 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,171 +1,116 @@
1+
use std::hash::{Hash, Hasher};
2+
13
use crate::serde::encode::{Encode, Encoded};
2-
use bigdecimal::{
3-
num_bigint::{BigInt, Sign},
4-
BigDecimal, Signed, Zero, num_traits::ToBytes,
5-
};
6-
7-
const EXPONENT_BIAS: i64 = 127;
8-
const EXPONENT_MAX: i64 = 127;
9-
const EXPONENT_MIN: i64 = 1 - EXPONENT_MAX;
10-
const COEFFICIENT_MAX: i64 = 9_999_999; // 7 digits
4+
5+
// 7 digits
116
const DEFAULT_CONSTR: u8 = 0x74;
127

13-
#[derive(Hash, Eq, PartialEq)]
14-
pub struct Decimal32(BigDecimal);
8+
pub struct Decimal32(f32);
159

1610
impl Encode for Decimal32 {
1711
fn encode(&self) -> Encoded {
1812
Encoded::new_fixed(
1913
DEFAULT_CONSTR,
20-
encode_to_bytes(&self.0).unwrap(),
14+
encode_to_bytes(&self.0).to_be_bytes().to_vec(),
2115
)
2216
}
2317
}
2418

25-
impl TryFrom<f32> for Decimal32 {
26-
type Error = Decimal32ConversionError;
27-
28-
fn try_from(value: f32) -> Result<Self, Self::Error> {
29-
Ok(Decimal32(BigDecimal::try_from(value)?))
19+
impl Hash for Decimal32 {
20+
fn hash<H: Hasher>(&self, state: &mut H) {
21+
self.0.to_bits().hash(state)
3022
}
3123
}
3224

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")
25+
impl PartialEq for Decimal32 {
26+
fn eq(&self, other: &Self) -> bool {
27+
self.0.to_bits().eq(&other.0.to_bits())
3828
}
3929
}
4030

41-
#[derive(thiserror::Error, Debug, PartialEq)]
42-
pub enum Decimal32ConversionError {
43-
#[error("Failed to parse f32 value to Decimal32 value.")]
44-
ParseDecimal32Error(#[from] bigdecimal::ParseBigDecimalError),
45-
#[error("Coefficient is too large for Decimal32 representation.")]
46-
CoefficientTooLarge,
47-
#[error("Exponent overflowed in Decimal32 representation")]
48-
ExponentOverflow,
49-
#[error("Exponent underflowed in Decimal32 representation")]
50-
ExponentUnderflow,
51-
#[error("Failed to scale coefficient. Value cannot be fit into 32 bits.")]
52-
CoefficientScalingFailedError,
53-
#[error("The base value for setting the sign for converting the Decimal32 into bytes must be zero.")]
54-
SignSettingValueIsNotZero,
55-
#[error("The base value for setting the exponent was not 0x80000000 or 0x00000000.")]
56-
IllegalBaseValueForExponentSetting,
57-
58-
}
59-
60-
type ConversionError = Decimal32ConversionError;
61-
62-
fn encode_to_bytes(value: &BigDecimal) -> Result<Vec<u8>, Decimal32ConversionError> {
63-
// start with empty bit array of 32 bits
64-
let mut result: u32 = 0;
31+
impl Eq for Decimal32 {}
6532

66-
let (mut coeff, mut exp) = value.as_bigint_and_exponent();
67-
68-
result = set_sign_bit(result, coeff.sign())?;
69-
result = set_exponent_bits(result, exp)?;
70-
result = set_significand_bits(result, coeff)?;
71-
72-
Ok(result.to_be_bytes().to_vec())
73-
}
74-
75-
fn set_sign_bit(mut result: u32, sign: Sign) -> Result<u32, ConversionError> {
76-
if result != 0 {
77-
return Err(Decimal32ConversionError::SignSettingValueIsNotZero);
78-
}
79-
match sign {
80-
Sign::Minus => {
81-
result += 1; // set bit as least significant
82-
result <<= 31; // shift bit to sign bit location
83-
Ok(result)
84-
}
85-
_ => Ok(result)
33+
impl From<f32> for Decimal32 {
34+
fn from(value: f32) -> Self {
35+
Decimal32(value)
8636
}
8737
}
8838

89-
fn set_exponent_bits(mut result: u32, exp: i64)-> Result<u32, ConversionError> {
90-
if result != 0x8000_0000 && result != 0x0000_0000 {
91-
return Err(Decimal32ConversionError::IllegalBaseValueForExponentSetting);
92-
}
93-
match exp {
94-
_ if exp < EXPONENT_MIN => Err(Decimal32ConversionError::ExponentUnderflow),
95-
_ if exp > EXPONENT_MAX => Err(Decimal32ConversionError::ExponentOverflow),
96-
x => {
97-
let mut unsigned_exponent: u32 = (exp + EXPONENT_BIAS).try_into().unwrap();
98-
unsigned_exponent <<= 20;
99-
result = result | unsigned_exponent;
100-
Ok(result)
101-
}
102-
}
39+
fn encode_to_bytes(value: &f32) -> u32 {
40+
value.to_bits()
10341
}
10442

105-
fn set_significand_bits(mut result: u32, significand: BigInt) -> Result<u32, ConversionError> {
106-
107-
108-
Ok(result)
109-
}
110-
111-
11243
#[cfg(test)]
11344
mod test {
114-
11545
use super::*;
11646

11747
#[test]
11848
fn construct_decimal_32() {
119-
let val: Decimal32 = 32.0.try_into().unwrap();
49+
let val: Decimal32 = 32f32.into();
12050
assert_eq!(val.encode().constructor(), 0x74);
12151
}
12252

12353
#[test]
124-
fn set_sign_bit_works_for_positive_sign() {
125-
assert_eq!(set_sign_bit(0, Sign::Plus).unwrap().to_be_bytes(), [0x00, 0x00, 0x00, 0x00]);
54+
fn test_positive_number() {
55+
let decimal = 0.15625;
56+
let encoded = encode_to_bytes(&decimal);
57+
let expected = 0b00111110001000000000000000000000;
58+
assert_eq!(encoded, expected);
59+
}
60+
61+
#[test]
62+
fn test_negative_number() {
63+
let decimal = -0.15625;
64+
let encoded = encode_to_bytes(&decimal);
65+
let expected = 0b10111110001000000000000000000000;
66+
assert_eq!(encoded, expected);
12667
}
12768

12869
#[test]
129-
fn set_sign_bit_works_for_negative_sign() {
130-
assert_eq!(set_sign_bit(0, Sign::Minus).unwrap().to_be_bytes(), [0x80, 0x00, 0x00, 0x00]);
70+
fn test_large_number() {
71+
let decimal = 3.4028235e38; // Max value for f32
72+
let encoded = encode_to_bytes(&decimal);
73+
let expected = 0b01111111011111111111111111111111;
74+
assert_eq!(encoded, expected);
13175
}
132-
76+
13377
#[test]
134-
fn set_sign_bit_resturns_error_on_non_zero_base_number() {
135-
assert!(set_sign_bit(4, Sign::Minus).is_err());
78+
fn test_small_subnormal_number() {
79+
let decimal = 1E-45; // Smallest subnormal in f32
80+
let encoded = encode_to_bytes(&decimal);
81+
let expected = 0b00000000000000000000000000000001;
82+
assert_eq!(encoded, expected);
13683
}
13784

13885
#[test]
139-
fn set_exponent_bits_if_exponent_too_large_returns_err() {
140-
assert_eq!(set_exponent_bits(0x80000000, 128), Err(Decimal32ConversionError::ExponentOverflow));
141-
assert_eq!(set_exponent_bits(0x80000000, 139), Err(Decimal32ConversionError::ExponentOverflow));
86+
fn test_zero() {
87+
let decimal = 0f32;
88+
let encoded = encode_to_bytes(&decimal);
89+
let expected = 0b00000000000000000000000000000000;
90+
assert_eq!(encoded, expected);
14291
}
14392

14493
#[test]
145-
fn set_exponent_bits_if_exponent_too_small_returns_err() {
146-
assert_eq!(set_exponent_bits(0x80000000, -127), Err(Decimal32ConversionError::ExponentUnderflow));
147-
assert_eq!(set_exponent_bits(0x80000000, -300), Err(Decimal32ConversionError::ExponentUnderflow));
94+
fn test_one() {
95+
let decimal = 1f32;
96+
let encoded = encode_to_bytes(&decimal);
97+
let expected = 0b00111111100000000000000000000000;
98+
assert_eq!(encoded, expected);
14899
}
149-
100+
101+
#[test]
102+
fn test_infinity() {
103+
let decimal = f32::INFINITY; // A number too large for f32, should be infinity
104+
let encoded = encode_to_bytes(&decimal);
105+
let expected = 0b01111111100000000000000000000000; // Positive infinity in f32
106+
assert_eq!(encoded, expected);
107+
}
108+
150109
#[test]
151-
fn set_exponent_bits_works() {
152-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, 127).unwrap()), format!("{:#b}", 0x8C50_0000u32));
153-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, 96).unwrap()), format!("{:#b}", 0x8C50_0000u32));
154-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, 64).unwrap()), format!("{:#b}", 0x8A50_0000u32));
155-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, 32).unwrap()), format!("{:#b}", 0x8850_0000u32));
156-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, 16).unwrap()), format!("{:#b}", 0x8750_0000u32));
157-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, 8).unwrap()), format!("{:#b}", 0x86D0_0000u32));
158-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, 2).unwrap()), format!("{:#b}", 0x8670_0000u32));
159-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, 1).unwrap()), format!("{:#b}", 0x8660_0000u32));
160-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, 0).unwrap()), format!("{:#b}", 0x8650_0000u32));
161-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, -1).unwrap()), format!("{:#b}", 0x8640_0000u32));
162-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, -2).unwrap()), format!("{:#b}", 0x8630_0000u32));
163-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, -8).unwrap()), format!("{:#b}", 0x85C0_0000u32));
164-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, -16).unwrap()), format!("{:#b}", 0x8550_0000u32));
165-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, -32).unwrap()), format!("{:#b}", 0x8450_0000u32));
166-
assert_eq!(format!("{:#b}", set_exponent_bits(0x8000_0000, -64).unwrap()), format!("{:#b}", 0x8250_0000u32));
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));
110+
fn test_negative_infinity() {
111+
let decimal = f32::NEG_INFINITY; // A negative number too large for f32
112+
let encoded = encode_to_bytes(&decimal);
113+
let expected = 0b11111111100000000000000000000000; // Negative infinity in f32
114+
assert_eq!(encoded, expected);
169115
}
170-
171116
}

0 commit comments

Comments
 (0)