ieee_754/
lib.rs

1pub mod helper;
2pub mod ieee754;
3
4use crate::ieee754::{IEEE754_32bit, IEEE754_64bit, ValidationError};
5
6#[derive(Debug)]
7pub struct IEEE754;
8
9impl IEEE754 {
10    pub fn to_hex(binary: Vec<u8>) -> Result<String, String> {
11        let mut hex = String::new();
12        for b in binary.chunks(4) {
13            let byte_str: String = b
14                .into_iter()
15                .map(|v| v.to_string())
16                .collect::<Vec<String>>()
17                .concat();
18
19            match u8::from_str_radix(&byte_str, 2) {
20                Ok(v) => {
21                    hex.push_str(&format!("{:X}", v));
22                }
23                Err(error) => return Err(error.to_string()),
24            }
25        }
26        Ok(hex)
27    }
28
29    pub fn to_32bit_hex(value: f32) -> Result<String, String> {
30        let binary: Vec<u8> = IEEE754_32bit::get_binary(value)?;
31        let hex: String = IEEE754::to_hex(binary)?;
32        Ok(hex)
33    }
34
35    pub fn to_64bit_hex(value: f64) -> Result<String, String> {
36        let binary: Vec<u8> = IEEE754_64bit::get_binary(value)?;
37        let hex: String = IEEE754::to_hex(binary)?;
38        Ok(hex)
39    }
40
41    pub fn to_binary(values: Vec<u32>) -> Result<Vec<u8>, ValidationError> {
42        let mut binaries: Vec<u8> = Vec::new();
43        if values.is_empty() {
44            return Err(ValidationError::EmptyValues);
45        }
46        for v in values.iter() {
47            for x in &mut format!("{:08b}", v).chars() {
48                match u8::from_str_radix(&x.to_string(), 2) {
49                    Ok(value) => binaries.push(value),
50                    Err(_) => return Err(ValidationError::ParseError),
51                }
52            }
53        }
54        Ok(binaries)
55    }
56
57    fn get_sign_bit(binaries: &[u8]) -> Result<i8, ValidationError> {
58        if binaries.is_empty() {
59            return Err(ValidationError::EmptySignBit);
60        }
61        match binaries.first() {
62            Some(value) => Ok(if value == &0 { 1 } else { -1 }),
63            None => Err(ValidationError::InvalidSignBit),
64        }
65    }
66
67    pub fn to_64bit_float(values: Vec<u32>) -> Result<f64, ValidationError> {
68        let binaries: Vec<u8> = Self::to_binary(values)?;
69        let sign_bit: i8 = Self::get_sign_bit(&binaries)?;
70
71        // Exponent
72        match binaries.get(1..12) {
73            Some(exponent_binaries) => {
74                // Mantissa
75                match binaries.get(12..) {
76                    Some(mantissa_binaries) => {
77                        IEEE754_64bit::validate(exponent_binaries, mantissa_binaries)?;
78                        let exponent: i32 = IEEE754_64bit::get_exponent(exponent_binaries)?;
79                        let value: f64 = IEEE754_64bit::get_mantissa(mantissa_binaries, exponent)?;
80                        match sign_bit {
81                            1 => Ok(value),
82                            -1 => Ok(-(value)),
83                            _ => Err(ValidationError::InvalidSignBit),
84                        }
85                    }
86                    None => Err(ValidationError::InvalidMantissa),
87                }
88            }
89            None => Err(ValidationError::InvalidExponent),
90        }
91    }
92    pub fn to_32bit_float(values: Vec<u32>) -> Result<f32, ValidationError> {
93        let binaries: Vec<u8> = Self::to_binary(values)?;
94        let sign_bit: i8 = Self::get_sign_bit(&binaries)?;
95
96        // Exponent
97        match binaries.get(1..9) {
98            Some(exponent_binaries) => {
99                // Mantissa
100                match binaries.get(9..) {
101                    Some(mantissa_binaries) => {
102                        IEEE754_32bit::validate(exponent_binaries, mantissa_binaries)?;
103                        let exponent: i32 = IEEE754_32bit::get_exponent(exponent_binaries)?;
104                        let value: f32 = IEEE754_32bit::get_mantissa(mantissa_binaries, exponent)?;
105                        match sign_bit {
106                            1 => Ok(value),
107                            -1 => Ok(-(value)),
108                            _ => Err(ValidationError::InvalidSignBit),
109                        }
110                    }
111
112                    None => Err(ValidationError::InvalidMantissa),
113                }
114            }
115            None => Err(ValidationError::InvalidExponent),
116        }
117    }
118}
119#[cfg(test)]
120mod tests {
121    use super::*;
122    use crate::helper::ComputeMantissaBits;
123    use std::f64;
124
125    #[test]
126    fn test_compute_mantissa_bits_computation() {
127        assert_eq!(
128            ComputeMantissaBits::compute(
129                "10101010101010101010101 0 0"
130                    .chars()
131                    .filter(|&c| c != ' ')
132                    .map(|c| c.to_digit(10).unwrap() as u8)
133                    .collect::<Vec<u8>>(),
134                23
135            )
136            .unwrap(),
137            "10101010101010101010101"
138                .chars()
139                .map(|c| c.to_digit(10).unwrap() as u8)
140                .collect::<Vec<u8>>()
141        );
142        assert_eq!(
143            ComputeMantissaBits::compute(
144                "10101010101010101010101 1 0"
145                    .chars()
146                    .filter(|&c| c != ' ')
147                    .map(|c| c.to_digit(10).unwrap() as u8)
148                    .collect::<Vec<u8>>(),
149                23
150            )
151            .unwrap(),
152            "10101010101010101010110"
153                .chars()
154                .map(|c| c.to_digit(10).unwrap() as u8)
155                .collect::<Vec<u8>>()
156        );
157
158        assert!(ComputeMantissaBits::compute(
159            "11111111111111111111111 1 0"
160                .chars()
161                .filter(|&c| c != ' ')
162                .map(|c| c.to_digit(10).unwrap() as u8)
163                .collect::<Vec<u8>>(),
164            23
165        )
166        .is_err());
167
168        assert_eq!(
169            ComputeMantissaBits::compute(
170                "00000000000000000000000 1 0"
171                    .chars()
172                    .filter(|&c| c != ' ')
173                    .map(|c| c.to_digit(10).unwrap() as u8)
174                    .collect::<Vec<u8>>(),
175                23
176            )
177            .unwrap(),
178            "00000000000000000000000"
179                .chars()
180                .map(|c| c.to_digit(10).unwrap() as u8)
181                .collect::<Vec<u8>>(),
182        );
183
184        assert_eq!(
185            ComputeMantissaBits::compute(
186                "01111111111111111111111 1"
187                    .chars()
188                    .filter(|&c| c != ' ')
189                    .map(|c| c.to_digit(10).unwrap() as u8)
190                    .collect::<Vec<u8>>(),
191                23
192            )
193            .unwrap(),
194            "10000000000000000000000"
195                .chars()
196                .map(|c| c.to_digit(10).unwrap() as u8)
197                .collect::<Vec<u8>>(),
198        );
199
200        assert!(ComputeMantissaBits::compute(
201            "11111111111111111111111 1"
202                .chars()
203                .filter(|&c| c != ' ')
204                .map(|c| c.to_digit(10).unwrap() as u8)
205                .collect::<Vec<u8>>(),
206            23
207        )
208        .is_err());
209    }
210
211    #[test]
212    fn test_32bit() {
213        // 0.0
214        let values = vec![0x00, 0x00, 0x00, 0x00];
215        let output = IEEE754::to_32bit_float(values.clone());
216        println!("Input: {:x?}", values);
217        println!("Expected Output: {}", 0.0);
218        assert_eq!(0.0, output.unwrap());
219
220        // -0.0
221        let values = vec![0x80, 0x00, 0x00, 0x00];
222        let output = IEEE754::to_32bit_float(values.clone());
223        println!("Input: {:x?}", values);
224        println!("Expected Output: {}", -0.0);
225        assert_eq!(-0.0, output.unwrap());
226
227        // -2.7182817
228        let values = vec![0xc0, 0x2d, 0xf8, 0x54];
229        let output = IEEE754::to_32bit_float(values.clone());
230        println!("Input: {:x?}", values);
231        println!("Expected Output: {}", -2.7182817);
232        assert_eq!(-2.7182817, output.unwrap());
233
234        // Infinity (Positive)
235        let values = vec![0x7f, 0x80, 0x00, 0x00];
236        let output = IEEE754::to_32bit_float(values.clone());
237        println!("Input: {:x?}", values);
238        println!("Expected Output: Error(Infinity)");
239        assert!(output.is_err());
240
241        // Infinity (Negative)
242        let values = vec![0xff, 0x80, 0x00, 0x00];
243        let output = IEEE754::to_32bit_float(values.clone());
244        println!("Input: {:x?}", values);
245        println!("Expected Output: Error(Infinity)");
246        assert!(output.is_err());
247
248        // NaN
249        let values = vec![0x7f, 0xc0, 0x00, 0x00];
250        let output = IEEE754::to_32bit_float(values.clone());
251        println!("Input: {:x?}", values);
252        println!("Expected Output: Error(NaN)");
253        assert!(output.is_err());
254    }
255
256    #[test]
257    fn test_64bit_to_hex() {
258        let values = 10.001;
259        let output = IEEE754::to_64bit_hex(values.clone());
260        println!("Input: {:x?}", values);
261        println!("Expected Output: 40240083126E978D");
262        assert_eq!(output.unwrap(), "40240083126E978D");
263
264        let values = -85.125;
265        let output = IEEE754::to_64bit_hex(values.clone());
266        println!("Input: {:x?}", values);
267        println!("Expected Output: C055480000000000");
268        assert_eq!(output.unwrap(), "C055480000000000");
269
270        let values = 0.0;
271        let output = IEEE754::to_64bit_hex(values.clone());
272        println!("Input: {:x?}", values);
273        println!("Expected Output: 0000000000000000");
274        assert_eq!(output.unwrap(), "0000000000000000");
275
276        let values = -33.33333333;
277        let output = IEEE754::to_64bit_hex(values.clone());
278        println!("Input: {:x?}", values);
279        println!("Expected Output: C040AAAAAAA38226");
280        assert_eq!(output.unwrap(), "C040AAAAAAA38226");
281
282        let values = -333.33333333;
283        let output = IEEE754::to_64bit_hex(values.clone());
284        println!("Input: {:x?}", values);
285        println!("Expected Output: C074D55555547045");
286        assert_eq!(output.unwrap(), "C074D55555547045");
287
288        let values = 333.33333333;
289        let output = IEEE754::to_64bit_hex(values.clone());
290        println!("Input: {:x?}", values);
291        println!("Expected Output: 4074D55555547045");
292        assert_eq!(output.unwrap(), "4074D55555547045");
293    }
294
295    #[test]
296    fn test_32bit_to_hex() {
297        let values = 10.001;
298        let output = IEEE754::to_32bit_hex(values.clone());
299        println!("Input: {:x?}", values);
300        println!("Expected Output: 41200419");
301        assert_eq!(output.unwrap(), "41200419");
302
303        let values = -85.125;
304        let output = IEEE754::to_32bit_hex(values.clone());
305        println!("Input: {:x?}", values);
306        println!("Expected Output: C2AA4000");
307        assert_eq!(output.unwrap(), "C2AA4000");
308
309        let values = 0.0;
310        let output = IEEE754::to_32bit_hex(values.clone());
311        println!("Input: {:x?}", values);
312        println!("Expected Output: 00000000");
313        assert_eq!(output.unwrap(), "00000000");
314
315        let values = -33.33333333;
316        let output = IEEE754::to_32bit_hex(values.clone());
317        println!("Input: {:x?}", values);
318        println!("Expected Output: C2055555");
319        assert_eq!(output.unwrap(), "C2055555");
320
321        let values = -333.33333333;
322        let output = IEEE754::to_32bit_hex(values.clone());
323        println!("Input: {:x?}", values);
324        println!("Expected Output: C3A6AAAB");
325        assert_eq!(output.unwrap(), "C3A6AAAB");
326
327        let values = 333.33333333;
328        let output = IEEE754::to_32bit_hex(values.clone());
329        println!("Input: {:x?}", values);
330        println!("Expected Output: 43A6AAAB");
331        assert_eq!(output.unwrap(), "43A6AAAB");
332    }
333
334    #[test]
335    fn test_64bit() {
336        // -74.74597276138431
337        let values = vec![0xc0, 0x52, 0xaf, 0xbe, 0x4, 0x89, 0x76, 0x8e];
338        let output = IEEE754::to_64bit_float(values.clone());
339        println!("Input: {:x?}", values);
340        println!("Expected Output: {}", -74.74597276138431);
341        assert_eq!(-74.74597276138431, output.unwrap());
342
343        // -3.125
344        let values = vec![0xc0, 0x09, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
345        let output = IEEE754::to_64bit_float(values.clone());
346        println!("Input: {:x?}", values);
347        println!("Expected Output: {}", -3.125);
348        assert_eq!(-3.125, output.unwrap());
349
350        // Infinity
351        let values = vec![0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
352        let output = IEEE754::to_64bit_float(values.clone());
353        println!("Input: {:x?}", values);
354        println!("Expected Output: Error");
355        assert!(output.is_err());
356
357        // -Infinity
358        let values = vec![0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
359        let output = IEEE754::to_64bit_float(values.clone());
360        println!("Input: {:x?}", values);
361        println!("Expected Output: Error");
362        assert!(output.is_err());
363
364        // Quiet NaN
365        // InProgress
366        let values = vec![0x7f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
367        let output = IEEE754::to_64bit_float(values.clone());
368        println!("Input: {:x?}", values);
369        println!("Expected Output: Error");
370        assert!(output.is_err());
371
372        // Signal NaN
373        let values = vec![0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
374        let output = IEEE754::to_64bit_float(values.clone());
375        println!("Input: {:x?}", values);
376        println!("Expected Output: Error");
377        assert!(output.is_err());
378
379        // 0.0
380        let values = vec![0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
381        let output = IEEE754::to_64bit_float(values.clone());
382        println!("Input: {:x?}", values);
383        println!("Expected Output: {}", 0.0);
384        assert_eq!(0.0, output.unwrap());
385
386        // 3.141592653589793
387        let values = vec![0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18];
388        let output = IEEE754::to_64bit_float(values.clone());
389        println!("Input: {:x?}", values);
390        println!("Expected Output: {}", f64::consts::PI);
391        assert_eq!(f64::consts::PI, output.unwrap());
392
393        // 2.718281828459045
394        let values = vec![0x40, 0x05, 0xbf, 0x0a, 0x8b, 0x14, 0x57, 0x69];
395        let output = IEEE754::to_64bit_float(values.clone());
396        println!("Input: {:x?}", values);
397        println!("Expected Output: {}", f64::consts::E);
398        assert_eq!(f64::consts::E, output.unwrap());
399    }
400}