1#[derive(Debug)]
2pub struct ComputeMantissaBits;
3
4impl ComputeMantissaBits {
5 pub fn round_up(bits: &mut Vec<u8>) -> Result<Vec<u8>, String> {
6 let mut is_overflow: bool = true;
7 let mut i = bits.len() - 1;
8
9 loop {
10 if let Some(b) = bits.get_mut(i) {
11 if *b == 1 {
12 *b = 0;
13 } else {
14 *b = 1;
15 is_overflow = false;
16 break;
17 }
18 } else {
19 return Err("unable to round up, no bit to compare".to_string());
20 }
21 if i == 0 {
22 break;
23 }
24 i -= 1;
25 }
26 if is_overflow {
27 return Err("unable to round up, overflow".to_string());
28 }
29 Ok(bits.to_owned())
30 }
31
32 pub fn compute(input: Vec<u8>, length: usize) -> Result<Vec<u8>, String> {
33 let mut bits = input.get(0..length).unwrap().to_vec();
34 let guard_bit: u8 = *input.get(length).unwrap_or(&0);
35 let round_bit: u8 = *input.get(length + 1).unwrap_or(&0);
36 let sticky_bits: Vec<u8> = input.get(length + 2..).unwrap_or(&Vec::new()).to_vec();
37 let mut is_round_up = false;
38 if guard_bit == 1 {
39 if round_bit == 1 {
40 is_round_up = true;
41 } else if round_bit == 0 {
42 if sticky_bits
43 .clone()
44 .into_iter()
45 .filter(|v| *v == 1)
46 .collect::<Vec<u8>>()
47 .len()
48 > 0
49 {
50 is_round_up = true;
51 } else {
52 if let Some(last_bit) = bits.last() {
53 if *last_bit == 1 {
54 is_round_up = true;
55 }
56 }
57 }
58 }
59 }
60 if is_round_up {
61 bits = Self::round_up(&mut bits)?;
62 }
63 Ok(bits)
64 }
65}
66
67#[derive(Debug, Clone)]
68pub struct SplitFloat;
69impl SplitFloat {
70 pub fn f32(input: f32) -> Result<(u8, u32, f32), String> {
71 let sign: u8 = if input.is_sign_negative() { 1 } else { 0 };
72 let value: String = input.to_string().replace("-", "");
73 let vsplitted: Vec<&str> = if !value.contains(".") {
74 vec![&"0", &"0"]
75 } else {
76 value.split(".").collect()
77 };
78 let integer_part: u32 = if let Some(v) = vsplitted.get(0) {
79 match v.parse::<u32>() {
80 Ok(v) => v,
81 Err(error) => return Err(error.to_string()),
82 }
83 } else {
84 return Err("invalid floating integer part value".to_string());
85 };
86 let fractional_part: f32 = if let Some(v) = vsplitted.get(1) {
87 match format!("0.{}", v).parse::<f32>() {
88 Ok(v) => v,
89 Err(error) => return Err(error.to_string()),
90 }
91 } else {
92 return Err("invalid floating fractional part value".to_string());
93 };
94 Ok((sign, integer_part, fractional_part))
95 }
96 pub fn f64(input: f64) -> Result<(u8, u64, f64), String> {
97 let sign: u8 = if input.is_sign_negative() { 1 } else { 0 };
98 let value: String = input.to_string().replace("-", "");
99 let vsplitted: Vec<&str> = if !value.contains(".") {
100 vec![&"0", &"0"]
101 } else {
102 value.split(".").collect()
103 };
104 let integer_part: u64 = if let Some(v) = vsplitted.get(0) {
105 match v.parse::<u64>() {
106 Ok(v) => v,
107 Err(error) => return Err(error.to_string()),
108 }
109 } else {
110 return Err("invalid floating integer part value".to_string());
111 };
112 let fractional_part: f64 = if let Some(v) = vsplitted.get(1) {
113 match format!("0.{}", v).parse::<f64>() {
114 Ok(v) => v,
115 Err(error) => return Err(error.to_string()),
116 }
117 } else {
118 return Err("invalid floating fractional part value".to_string());
119 };
120 Ok((sign, integer_part, fractional_part))
121 }
122}