1use crate::*;
2use bitvec::prelude::*;
3use fraction::{prelude::*, Num};
4
5pub trait IeeeBinary {
7 fn ieee_binary32() -> Self;
8 fn ieee_binary64() -> Self;
9}
10
11pub type Interpret = fn(&Components) -> Option<String>;
14
15fn ieee_interpret(comps: &Components) -> Option<String> {
17 match comps {
18 c if c.sign == Some(false) && c.exp.is_all_zero() && c.mant.is_all_zero() => {
19 Some("0".to_owned())
20 },
21 c if c.sign == Some(true) && c.exp.is_all_zero() && c.mant.is_all_zero() => {
22 Some("-0".to_owned())
23 },
24 c if c.sign == Some(false) && c.exp.is_all_one() && c.mant.is_all_zero() => {
25 Some("inf".to_owned())
26 },
27 c if c.sign == Some(true) && c.exp.is_all_one() && c.mant.is_all_zero() => {
28 Some("-inf".to_owned())
29 },
30 c if c.exp.is_all_one() && !c.mant.is_all_zero() && c.mant.iter().next().map(|b| *b) == Some(true) => {
31 Some("NaN".to_owned())
32 },
33 c if c.exp.is_all_one() && !c.mant.is_all_zero() && c.mant.iter().next().map(|b| *b) == Some(false) => {
34 Some("sNaN".to_owned())
35 },
36 _ => None,
37 }
38}
39
40impl IeeeBinary for Interpret {
41 fn ieee_binary32() -> Self {
42 ieee_interpret
43 }
44
45 fn ieee_binary64() -> Self {
46 ieee_interpret
47 }
48}
49
50pub type BitPattern = BitVec<usize, Msb0>;
51
52pub trait BitPatternExt where Self: Sized {
53 fn from_value<T>(val: T) -> Self
54 where
55 T: BitStore;
56
57 fn from_str(s: &str) -> Result<Self, error::Error>;
61
62 fn from_bin_str(s: &str) -> Self;
65
66 fn from_dec_str(s: &str) -> Self;
69
70 fn from_oct_str(s: &str) -> Self;
73
74 fn from_hex_str(s: &str) -> Self;
77
78 fn is_all_one(&self) -> bool;
80
81 fn is_all_zero(&self) -> bool;
83
84 fn to_bin_string(&self) -> String;
86
87 fn to_oct_string(&self) -> String;
89
90 fn to_dec_string(&self) -> String;
92
93 fn to_hex_string(&self) -> String;
95}
96
97impl BitPatternExt for BitPattern {
98 fn from_value<T>(val: T) -> Self
99 where
100 T: BitStore
101 {
102 val.view_bits::<Msb0>().iter().collect()
103 }
104
105 fn from_str(s: &str) -> Result<Self, error::Error> {
106 if s.len() < 3 {
107 return Err(error::Error::InvalidRadixPrefix);
108 }
109
110 match s[0..2].as_ref() {
111 "0b" => Ok(Self::from_bin_str(&s[2..])),
112 "0o" => Ok(Self::from_oct_str(&s[2..])),
113 "0d" => Ok(Self::from_dec_str(&s[2..])),
114 "0x" => Ok(Self::from_hex_str(&s[2..])),
115 _ => Err(error::Error::InvalidRadixPrefix),
116 }
117 }
118
119 fn from_bin_str(s: &str) -> Self {
120 s
121 .chars()
122 .filter(|c| c.is_digit(2))
123 .map(|c| c == '1')
124 .collect()
125 }
126
127 fn from_dec_str(s: &str) -> Self {
128 let s = s.chars().filter(|c| c.is_digit(10)).collect::<String>();
129
130 let mut int = BigUint::from_str_radix(&s, 10).unwrap();
131 let mut bits = String::new();
132
133 while int > BigUint::from(0u32) {
134 bits.push(if int.clone() % BigUint::from(2u32) == BigUint::from(1u32) { '1' } else { '0' });
135 int /= 2u32;
136 }
137
138 let bits = bits
139 .chars()
140 .rev()
141 .collect::<String>();
142
143 Self::from_bin_str(&bits)
144 }
145
146 fn from_oct_str(s: &str) -> Self {
147 s
148 .chars()
149 .filter(|c| c.is_digit(8))
150 .flat_map(|c| format!("{:3b}", c.to_digit(8).unwrap())
151 .chars()
152 .collect::<Vec<_>>()
153 )
154 .map(|c| c == '1')
155 .collect()
156 }
157
158 fn from_hex_str(s: &str) -> Self {
159 s
160 .chars()
161 .filter(|c| c.is_digit(16))
162 .flat_map(|c| format!("{:4b}", c.to_digit(16).unwrap())
163 .chars()
164 .collect::<Vec<_>>()
165 )
166 .map(|c| c == '1')
167 .collect()
168 }
169
170 fn is_all_one(&self) -> bool {
171 self.iter().all(|b| *b)
172 }
173
174 fn is_all_zero(&self) -> bool {
175 self.iter().all(|b| !*b)
176 }
177
178 fn to_bin_string(&self) -> String {
179 self
180 .iter()
181 .map(|b| if *b { '1' } else { '0' })
182 .collect()
183 }
184
185 fn to_oct_string(&self) -> String {
186 self
187 .as_bitslice()
188 .chunks(3)
189 .map(|c| format!("{:o}", c)
190 .chars()
191 .filter(|c| c.is_digit(8))
192 .collect::<String>()
193 )
194 .collect()
195 }
196
197 fn to_dec_string(&self) -> String {
198 self
199 .iter()
200 .fold(BigUint::from(0u32), |acc, b| acc * 2u32 + if *b { 1u32 } else { 0u32 })
201 .to_string()
202 }
203
204 fn to_hex_string(&self) -> String {
205 self
206 .as_bitslice()
207 .chunks(4)
208 .map(|c| format!("{:x}", c)
209 .chars()
210 .filter(|c| c.is_digit(16))
211 .collect::<String>()
212 )
213 .collect()
214 }
215}