Skip to main content

libsurfer/translation/
numeric_translators.rs

1use crate::message::Message;
2use crate::translation::fixed_point::{big_uint_to_sfixed, big_uint_to_ufixed};
3use crate::variable_meta::VariableMetaExt;
4use crate::wave_container::{ScopeId, VarId};
5use eyre::Result;
6use half::{bf16, f16};
7use num::{BigUint, One};
8use softposit::{P8E0, P16E1, P32E2, Q8E0, Q16E1};
9use surfer_translation_types::{
10    BasicTranslator, NumericRange, TranslationResult, Translator, ValueKind, ValueRepr,
11    VariableInfo, VariableMeta, VariableValue, biguint_to_f64, parse_value_to_numeric,
12    translates_all_bit_types,
13};
14
15use super::{TranslationPreference, check_single_wordlength, integer_numeric_range};
16
17#[inline]
18fn shortest_float_representation<T: std::fmt::LowerExp + std::fmt::Display>(v: T) -> String {
19    let dec = format!("{v}");
20    let exp = format!("{v:e}");
21    if dec.len() > exp.len() { exp } else { dec }
22}
23
24/// If `value` is a biguint or consists only of 1 or 0, translates the value using
25/// `biguint_translator`. If `value` contains other values such as X, Z etc. the result
26/// is the corresponding `ValueKind`
27fn translate_numeric(
28    biguint_translator: impl Fn(&BigUint) -> String,
29    value: &VariableValue,
30) -> (String, ValueKind) {
31    match value.parse_biguint() {
32        Ok(v) => (biguint_translator(&v), ValueKind::Normal),
33        Err((v, k)) => (v, k),
34    }
35}
36
37pub struct UnsignedTranslator {}
38
39impl BasicTranslator<VarId, ScopeId> for UnsignedTranslator {
40    fn name(&self) -> String {
41        String::from("Unsigned")
42    }
43
44    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
45        translate_numeric(std::string::ToString::to_string, v)
46    }
47
48    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
49        Some(parse_value_to_numeric(value, biguint_to_f64))
50    }
51
52    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
53        if variable.has_unsigned_integer_type_name() {
54            Ok(TranslationPreference::Prefer)
55        } else {
56            translates_all_bit_types(variable)
57        }
58    }
59
60    fn basic_numeric_range(&self, num_bits: u32) -> Option<NumericRange> {
61        integer_numeric_range(num_bits, false)
62    }
63}
64
65pub struct SignedTranslator {}
66
67impl BasicTranslator<VarId, ScopeId> for SignedTranslator {
68    fn name(&self) -> String {
69        String::from("Signed")
70    }
71
72    fn basic_translate(&self, num_bits: u32, v: &VariableValue) -> (String, ValueKind) {
73        translate_numeric(|val| compute_signed_value(val, num_bits), v)
74    }
75
76    fn basic_translate_numeric(&self, num_bits: u32, value: &VariableValue) -> Option<f64> {
77        Some(parse_value_to_numeric(value, |v| {
78            let signweight = BigUint::one() << (num_bits - 1);
79            if v < &signweight {
80                biguint_to_f64(v)
81            } else {
82                let v2 = (&signweight << 1) - v;
83                -biguint_to_f64(&v2)
84            }
85        }))
86    }
87
88    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
89        if variable.is_integer_type() || variable.has_signed_integer_type_name() {
90            Ok(TranslationPreference::Prefer)
91        } else {
92            translates_all_bit_types(variable)
93        }
94    }
95
96    fn basic_numeric_range(&self, num_bits: u32) -> Option<NumericRange> {
97        integer_numeric_range(num_bits, true)
98    }
99}
100
101/// Computes the signed value string for a given `BigUint` and bit width.
102fn compute_signed_value(v: &BigUint, num_bits: u32) -> String {
103    let signweight = BigUint::one() << (num_bits - 1);
104    if v < &signweight {
105        v.to_string()
106    } else {
107        let v2 = (signweight << 1) - v;
108        format!("-{v2}")
109    }
110}
111
112pub struct SinglePrecisionTranslator {}
113
114impl BasicTranslator<VarId, ScopeId> for SinglePrecisionTranslator {
115    fn name(&self) -> String {
116        String::from("FP: 32-bit IEEE 754")
117    }
118
119    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
120        translate_numeric(
121            |v| {
122                shortest_float_representation(f32::from_bits(
123                    v.iter_u32_digits().next().unwrap_or(0),
124                ))
125            },
126            v,
127        )
128    }
129
130    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
131        Some(parse_value_to_numeric(value, |v| {
132            f64::from(f32::from_bits(v.iter_u32_digits().next().unwrap_or(0)))
133        }))
134    }
135
136    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
137        check_single_wordlength(variable.num_bits, 32)
138    }
139}
140
141pub struct DoublePrecisionTranslator {}
142
143impl BasicTranslator<VarId, ScopeId> for DoublePrecisionTranslator {
144    fn name(&self) -> String {
145        String::from("FP: 64-bit IEEE 754")
146    }
147    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
148        translate_numeric(
149            |v| {
150                shortest_float_representation(f64::from_bits(
151                    v.iter_u64_digits().next().unwrap_or(0),
152                ))
153            },
154            v,
155        )
156    }
157    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
158        Some(parse_value_to_numeric(value, |v| {
159            f64::from_bits(v.iter_u64_digits().next().unwrap_or(0))
160        }))
161    }
162    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
163        if variable.is_real() {
164            Ok(TranslationPreference::Prefer)
165        } else {
166            check_single_wordlength(variable.num_bits, 64)
167        }
168    }
169}
170
171#[cfg(feature = "f128")]
172pub struct QuadPrecisionTranslator {}
173
174#[cfg(feature = "f128")]
175impl BasicTranslator<VarId, ScopeId> for QuadPrecisionTranslator {
176    fn name(&self) -> String {
177        String::from("FP: 128-bit IEEE 754")
178    }
179    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
180        translate_numeric(
181            |v| {
182                let mut digits = v.iter_u64_digits();
183                let lsb = digits.next().unwrap_or(0);
184                let msb = if digits.len() > 0 {
185                    digits.next().unwrap_or(0)
186                } else {
187                    0
188                };
189                let val = lsb as u128 | (msb as u128) << 64;
190                f128::f128::from_bits(val).to_string()
191            },
192            v,
193        )
194    }
195    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
196        check_single_wordlength(variable.num_bits, 128)
197    }
198}
199
200pub struct HalfPrecisionTranslator {}
201
202impl BasicTranslator<VarId, ScopeId> for HalfPrecisionTranslator {
203    fn name(&self) -> String {
204        String::from("FP: 16-bit IEEE 754")
205    }
206    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
207        translate_numeric(
208            |v| {
209                shortest_float_representation(f16::from_bits(
210                    v.iter_u32_digits().next().unwrap_or(0) as u16,
211                ))
212            },
213            v,
214        )
215    }
216    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
217        Some(parse_value_to_numeric(value, |v| {
218            f64::from(f16::from_bits(
219                v.iter_u32_digits().next().unwrap_or(0) as u16
220            ))
221        }))
222    }
223    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
224        check_single_wordlength(variable.num_bits, 16)
225    }
226
227    fn basic_numeric_range(&self, _num_bits: u32) -> Option<NumericRange> {
228        Some(NumericRange {
229            min: f64::from(f16::MIN),
230            max: f64::from(f16::MAX),
231        })
232    }
233}
234
235pub struct BFloat16Translator {}
236
237impl BasicTranslator<VarId, ScopeId> for BFloat16Translator {
238    fn name(&self) -> String {
239        String::from("FP: bfloat16")
240    }
241    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
242        translate_numeric(
243            |v| {
244                shortest_float_representation(bf16::from_bits(
245                    v.iter_u32_digits().next().unwrap_or(0) as u16,
246                ))
247            },
248            v,
249        )
250    }
251    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
252        Some(parse_value_to_numeric(value, |v| {
253            f64::from(bf16::from_bits(
254                v.iter_u32_digits().next().unwrap_or(0) as u16
255            ))
256        }))
257    }
258    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
259        check_single_wordlength(variable.num_bits, 16)
260    }
261
262    fn basic_numeric_range(&self, _num_bits: u32) -> Option<NumericRange> {
263        Some(NumericRange {
264            min: f64::from(bf16::MIN),
265            max: f64::from(bf16::MAX),
266        })
267    }
268}
269
270pub struct Posit32Translator {}
271
272impl BasicTranslator<VarId, ScopeId> for Posit32Translator {
273    fn name(&self) -> String {
274        String::from("Posit: 32-bit (two exponent bits)")
275    }
276
277    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
278        translate_numeric(
279            |v| {
280                format!(
281                    "{p}",
282                    p = P32E2::from_bits(v.iter_u32_digits().next().unwrap_or(0))
283                )
284            },
285            v,
286        )
287    }
288
289    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
290        Some(parse_value_to_numeric(value, |v| {
291            P32E2::from_bits(v.iter_u32_digits().next().unwrap_or(0)).into()
292        }))
293    }
294
295    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
296        check_single_wordlength(variable.num_bits, 32)
297    }
298}
299
300pub struct Posit16Translator {}
301
302impl BasicTranslator<VarId, ScopeId> for Posit16Translator {
303    fn name(&self) -> String {
304        String::from("Posit: 16-bit (one exponent bit)")
305    }
306
307    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
308        translate_numeric(
309            |v| {
310                format!(
311                    "{p}",
312                    p = P16E1::from_bits(v.iter_u32_digits().next().unwrap_or(0) as u16)
313                )
314            },
315            v,
316        )
317    }
318
319    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
320        Some(parse_value_to_numeric(value, |v| {
321            P16E1::from_bits(v.iter_u32_digits().next().unwrap_or(0) as u16).into()
322        }))
323    }
324
325    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
326        check_single_wordlength(variable.num_bits, 16)
327    }
328}
329
330pub struct Posit8Translator {}
331
332impl BasicTranslator<VarId, ScopeId> for Posit8Translator {
333    fn name(&self) -> String {
334        String::from("Posit: 8-bit (no exponent bit)")
335    }
336
337    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
338        translate_numeric(
339            |v| {
340                format!(
341                    "{p}",
342                    p = P8E0::from_bits(v.iter_u32_digits().next().unwrap_or(0) as u8)
343                )
344            },
345            v,
346        )
347    }
348
349    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
350        Some(parse_value_to_numeric(value, |v| {
351            P8E0::from_bits(v.iter_u32_digits().next().unwrap_or(0) as u8).into()
352        }))
353    }
354
355    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
356        check_single_wordlength(variable.num_bits, 8)
357    }
358}
359
360pub struct PositQuire8Translator {}
361
362impl BasicTranslator<VarId, ScopeId> for PositQuire8Translator {
363    fn name(&self) -> String {
364        String::from("Posit: quire for 8-bit (no exponent bit)")
365    }
366
367    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
368        translate_numeric(
369            |v| {
370                format!(
371                    "{p}",
372                    p = Q8E0::from_bits(v.iter_u32_digits().next().unwrap_or(0))
373                )
374            },
375            v,
376        )
377    }
378
379    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
380        Some(parse_value_to_numeric(value, |v| {
381            let q = Q8E0::from_bits(v.iter_u32_digits().next().unwrap_or(0));
382            P8E0::from(q).into()
383        }))
384    }
385
386    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
387        check_single_wordlength(variable.num_bits, 32)
388    }
389}
390
391pub struct PositQuire16Translator {}
392
393impl BasicTranslator<VarId, ScopeId> for PositQuire16Translator {
394    fn name(&self) -> String {
395        String::from("Posit: quire for 16-bit (one exponent bit)")
396    }
397
398    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
399        translate_numeric(
400            |v| {
401                let mut digits = v.iter_u64_digits();
402                let lsb = digits.next().unwrap_or(0);
403                let msb = digits.next().unwrap_or(0);
404                let val = u128::from(lsb) | (u128::from(msb) << 64);
405                format!("{}", Q16E1::from_bits(val))
406            },
407            v,
408        )
409    }
410
411    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
412        Some(parse_value_to_numeric(value, |v| {
413            let mut digits = v.iter_u64_digits();
414            let lsb = digits.next().unwrap_or(0);
415            let msb = digits.next().unwrap_or(0);
416            let val = u128::from(lsb) | (u128::from(msb) << 64);
417            P16E1::from(Q16E1::from_bits(val)).into()
418        }))
419    }
420
421    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
422        check_single_wordlength(variable.num_bits, 128)
423    }
424}
425
426/// Format an f64 value as a string for FP8 display.
427///
428/// Handles special cases: NaN, infinity (with sign), and signed zero.
429/// Normal values use the shortest representation (decimal or scientific).
430fn format_fp8_value(v: f64) -> String {
431    if v.is_nan() {
432        "NaN".to_string()
433    } else if v.is_infinite() {
434        if v.is_sign_negative() {
435            "-∞".to_string()
436        } else {
437            "∞".to_string()
438        }
439    } else if v == 0.0 {
440        if v.is_sign_negative() {
441            "-0".to_string()
442        } else {
443            "0".to_string()
444        }
445    } else {
446        shortest_float_representation(v as f32)
447    }
448}
449
450/// Decode u8 as 8-bit float with five exponent bits and two mantissa bits, returning f64.
451#[allow(clippy::excessive_precision)]
452fn decode_e5m2_f64(v: u8) -> f64 {
453    let mant = v & 3;
454    let exp = (v >> 2) & 31;
455    let sign: f64 = if (v >> 7) != 0 { -1.0 } else { 1.0 };
456    match (exp, mant) {
457        (31, 0) => sign * f64::INFINITY,
458        (31, ..) => f64::NAN,
459        (0, 0) => sign * 0.0,
460        (0, ..) => sign * f64::from(mant) * 0.0000152587890625f64, // 2^-16
461        _ => sign * f64::from(4 + mant) * 2.0f64.powi(i32::from(exp) - 17),
462    }
463}
464
465/// Decode u8 as 8-bit float with four exponent bits and three mantissa bits, returning f64.
466fn decode_e4m3_f64(v: u8) -> f64 {
467    let mant = v & 7;
468    let exp = (v >> 3) & 15;
469    let sign: f64 = if (v >> 7) != 0 { -1.0 } else { 1.0 };
470    match (exp, mant) {
471        (15, 7) => f64::NAN,
472        (0, 0) => sign * 0.0,
473        (0, ..) => sign * f64::from(mant) * 0.001953125f64, // 2^-9
474        _ => sign * f64::from(8 + mant) * 2.0f64.powi(i32::from(exp) - 10),
475    }
476}
477
478/// Decode u8 as 8-bit float with five exponent bits and two mantissa bits.
479fn decode_e5m2(v: u8) -> String {
480    format_fp8_value(decode_e5m2_f64(v))
481}
482
483pub struct E5M2Translator {}
484
485impl BasicTranslator<VarId, ScopeId> for E5M2Translator {
486    fn name(&self) -> String {
487        String::from("FP: 8-bit (E5M2)")
488    }
489
490    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
491        translate_numeric(
492            |v| decode_e5m2(v.iter_u32_digits().next().unwrap_or(0) as u8),
493            v,
494        )
495    }
496
497    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
498        Some(parse_value_to_numeric(value, |v| {
499            decode_e5m2_f64(v.iter_u32_digits().next().unwrap_or(0) as u8)
500        }))
501    }
502
503    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
504        check_single_wordlength(variable.num_bits, 8)
505    }
506
507    fn basic_numeric_range(&self, _num_bits: u32) -> Option<NumericRange> {
508        Some(NumericRange {
509            min: -57344.0,
510            max: 57344.0,
511        })
512    }
513}
514
515/// Decode u8 as 8-bit float with four exponent bits and three mantissa bits.
516fn decode_e4m3(v: u8) -> String {
517    format_fp8_value(decode_e4m3_f64(v))
518}
519
520pub struct E4M3Translator {}
521
522impl BasicTranslator<VarId, ScopeId> for E4M3Translator {
523    fn name(&self) -> String {
524        String::from("FP: 8-bit (E4M3)")
525    }
526
527    fn basic_translate(&self, _: u32, v: &VariableValue) -> (String, ValueKind) {
528        translate_numeric(
529            |v| decode_e4m3(v.iter_u32_digits().next().unwrap_or(0) as u8),
530            v,
531        )
532    }
533
534    fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
535        Some(parse_value_to_numeric(value, |v| {
536            decode_e4m3_f64(v.iter_u32_digits().next().unwrap_or(0) as u8)
537        }))
538    }
539
540    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
541        check_single_wordlength(variable.num_bits, 8)
542    }
543
544    fn basic_numeric_range(&self, _num_bits: u32) -> Option<NumericRange> {
545        Some(NumericRange {
546            min: -448.0,
547            max: 448.0,
548        })
549    }
550}
551
552pub struct UnsignedFixedPointTranslator;
553
554impl Translator<VarId, ScopeId, Message> for UnsignedFixedPointTranslator {
555    fn name(&self) -> String {
556        "Unsigned fixed point".into()
557    }
558
559    fn translate(
560        &self,
561        variable: &VariableMeta<VarId, ScopeId>,
562        value: &VariableValue,
563    ) -> Result<TranslationResult> {
564        let (string, value_kind) = if let Some(idx) = &variable.index {
565            translate_numeric(|v| big_uint_to_ufixed(v, -idx.lsb), value)
566        } else {
567            translate_numeric(std::string::ToString::to_string, value)
568        };
569        Ok(TranslationResult {
570            kind: value_kind,
571            val: ValueRepr::String(string),
572            subfields: vec![],
573        })
574    }
575
576    fn variable_info(&self, _: &VariableMeta<VarId, ScopeId>) -> Result<VariableInfo> {
577        Ok(VariableInfo::Bits)
578    }
579
580    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
581        if variable.has_unsigned_fixedpoint_type_name() {
582            Ok(TranslationPreference::Prefer)
583        } else {
584            translates_all_bit_types(variable)
585        }
586    }
587}
588
589pub struct SignedFixedPointTranslator;
590
591impl Translator<VarId, ScopeId, Message> for SignedFixedPointTranslator {
592    fn name(&self) -> String {
593        "Signed fixed point".into()
594    }
595
596    fn translate(
597        &self,
598        variable: &VariableMeta<VarId, ScopeId>,
599        value: &VariableValue,
600    ) -> Result<TranslationResult> {
601        let (string, value_kind) = if let Some(idx) = &variable.index {
602            translate_numeric(
603                |v| big_uint_to_sfixed(v, u64::from(variable.num_bits.unwrap_or(0)), -idx.lsb),
604                value,
605            )
606        } else {
607            translate_numeric(std::string::ToString::to_string, value)
608        };
609        Ok(TranslationResult {
610            kind: value_kind,
611            val: ValueRepr::String(string),
612            subfields: vec![],
613        })
614    }
615
616    fn variable_info(&self, _: &VariableMeta<VarId, ScopeId>) -> Result<VariableInfo> {
617        Ok(VariableInfo::Bits)
618    }
619
620    fn translates(&self, variable: &VariableMeta<VarId, ScopeId>) -> Result<TranslationPreference> {
621        if variable.has_signed_fixedpoint_type_name() {
622            Ok(TranslationPreference::Prefer)
623        } else {
624            translates_all_bit_types(variable)
625        }
626    }
627}
628
629#[cfg(test)]
630mod test {
631    use super::*;
632    use surfer_translation_types::VariableValue;
633
634    #[test]
635    fn signed_translation_from_string() {
636        assert_eq!(
637            SignedTranslator {}
638                .basic_translate(5, &VariableValue::String("10000".to_string()))
639                .0,
640            "-16"
641        );
642
643        assert_eq!(
644            SignedTranslator {}
645                .basic_translate(5, &VariableValue::String("01000".to_string()))
646                .0,
647            "8"
648        );
649    }
650
651    #[test]
652    fn signed_translation_from_biguint() {
653        assert_eq!(
654            SignedTranslator {}
655                .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b10011u32)))
656                .0,
657            "-13"
658        );
659
660        assert_eq!(
661            SignedTranslator {}
662                .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b01000u32)))
663                .0,
664            "8"
665        );
666        assert_eq!(
667            SignedTranslator {}
668                .basic_translate(2, &VariableValue::BigUint(BigUint::from(0u32)))
669                .0,
670            "0"
671        );
672    }
673
674    #[test]
675    fn unsigned_translation_from_string() {
676        assert_eq!(
677            UnsignedTranslator {}
678                .basic_translate(5, &VariableValue::String("10000".to_string()))
679                .0,
680            "16"
681        );
682
683        assert_eq!(
684            UnsignedTranslator {}
685                .basic_translate(5, &VariableValue::String("01000".to_string()))
686                .0,
687            "8"
688        );
689    }
690
691    #[test]
692    fn unsigned_translation_from_biguint() {
693        assert_eq!(
694            UnsignedTranslator {}
695                .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b10011u32)))
696                .0,
697            "19"
698        );
699
700        assert_eq!(
701            UnsignedTranslator {}
702                .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b01000u32)))
703                .0,
704            "8"
705        );
706        assert_eq!(
707            UnsignedTranslator {}
708                .basic_translate(2, &VariableValue::BigUint(BigUint::from(0u32)))
709                .0,
710            "0"
711        );
712    }
713
714    #[test]
715    fn e4m3_translation_from_biguint() {
716        assert_eq!(
717            E4M3Translator {}
718                .basic_translate(8, &VariableValue::BigUint(BigUint::from(0b10001000u8)))
719                .0,
720            "-0.015625"
721        );
722    }
723
724    #[test]
725    fn e4m3_translation_from_string() {
726        assert_eq!(
727            E4M3Translator {}
728                .basic_translate(8, &VariableValue::String("11111111".to_string()))
729                .0,
730            "NaN"
731        );
732        assert_eq!(
733            E4M3Translator {}
734                .basic_translate(8, &VariableValue::String("00000011".to_string()))
735                .0,
736            "0.005859375"
737        );
738        assert_eq!(
739            E4M3Translator {}
740                .basic_translate(8, &VariableValue::String("10000000".to_string()))
741                .0,
742            "-0"
743        );
744        assert_eq!(
745            E4M3Translator {}
746                .basic_translate(8, &VariableValue::String("00000000".to_string()))
747                .0,
748            "0"
749        );
750        assert_eq!(
751            E4M3Translator {}
752                .basic_translate(8, &VariableValue::String("11110111".to_string()))
753                .0,
754            "-240"
755        );
756        assert_eq!(
757            E4M3Translator {}
758                .basic_translate(8, &VariableValue::String("01000000".to_string()))
759                .0,
760            "2"
761        );
762    }
763
764    #[test]
765    fn e5m2_translation_from_biguint() {
766        assert_eq!(
767            E5M2Translator {}
768                .basic_translate(8, &VariableValue::BigUint(BigUint::from(0b10000100u8)))
769                .0,
770            "-6.1035156e-5"
771        );
772        assert_eq!(
773            E5M2Translator {}
774                .basic_translate(8, &VariableValue::BigUint(BigUint::from(0b11111100u8)))
775                .0,
776            "-∞"
777        );
778    }
779
780    #[test]
781    fn e5m2_translation_from_string() {
782        assert_eq!(
783            E5M2Translator {}
784                .basic_translate(8, &VariableValue::String("11111111".to_string()))
785                .0,
786            "NaN"
787        );
788        assert_eq!(
789            E5M2Translator {}
790                .basic_translate(8, &VariableValue::String("00000011".to_string()))
791                .0,
792            "4.5776367e-5"
793        );
794        assert_eq!(
795            E5M2Translator {}
796                .basic_translate(8, &VariableValue::String("10000000".to_string()))
797                .0,
798            "-0"
799        );
800        assert_eq!(
801            E5M2Translator {}
802                .basic_translate(8, &VariableValue::String("00000000".to_string()))
803                .0,
804            "0"
805        );
806        assert_eq!(
807            E5M2Translator {}
808                .basic_translate(8, &VariableValue::String("11111011".to_string()))
809                .0,
810            "-57344"
811        );
812        assert_eq!(
813            E5M2Translator {}
814                .basic_translate(8, &VariableValue::String("01000000".to_string()))
815                .0,
816            "2"
817        );
818    }
819
820    #[test]
821    fn posit8_translation_from_biguint() {
822        assert_eq!(
823            Posit8Translator {}
824                .basic_translate(8, &VariableValue::BigUint(BigUint::from(0b10001000u8)))
825                .0,
826            "-8"
827        );
828        assert_eq!(
829            Posit8Translator {}
830                .basic_translate(8, &VariableValue::BigUint(BigUint::from(0u8)))
831                .0,
832            "0"
833        );
834    }
835
836    #[test]
837    fn posit8_translation_from_string() {
838        assert_eq!(
839            Posit8Translator {}
840                .basic_translate(8, &VariableValue::String("11111111".to_string()))
841                .0,
842            "-0.015625"
843        );
844        assert_eq!(
845            Posit8Translator {}
846                .basic_translate(8, &VariableValue::String("00000011".to_string()))
847                .0,
848            "0.046875"
849        );
850        assert_eq!(
851            Posit8Translator {}
852                .basic_translate(8, &VariableValue::String("10000000".to_string()))
853                .0,
854            "NaN"
855        );
856    }
857
858    #[test]
859    fn posit16_translation_from_biguint() {
860        assert_eq!(
861            Posit16Translator {}
862                .basic_translate(
863                    16,
864                    &VariableValue::BigUint(BigUint::from(0b1010101010001000u16))
865                )
866                .0,
867            "-2.68359375"
868        );
869        assert_eq!(
870            Posit16Translator {}
871                .basic_translate(16, &VariableValue::BigUint(BigUint::from(0u16)))
872                .0,
873            "0"
874        );
875    }
876
877    #[test]
878    fn posit16_translation_from_string() {
879        assert_eq!(
880            Posit16Translator {}
881                .basic_translate(16, &VariableValue::String("1111111111111111".to_string()))
882                .0,
883            "-0.000000003725290298461914"
884        );
885        assert_eq!(
886            Posit16Translator {}
887                .basic_translate(16, &VariableValue::String("0111000000000011".to_string()))
888                .0,
889            "16.046875"
890        );
891        assert_eq!(
892            Posit16Translator {}
893                .basic_translate(16, &VariableValue::String("1000000000000000".to_string()))
894                .0,
895            "NaN"
896        );
897    }
898
899    #[test]
900    fn posit32_translation_from_biguint() {
901        assert_eq!(
902            Posit32Translator {}
903                .basic_translate(
904                    32,
905                    &VariableValue::BigUint(BigUint::from(0b1010101010001000u16))
906                )
907                .0,
908            "0.0000000000000000023056236824262055"
909        );
910        assert_eq!(
911            Posit32Translator {}
912                .basic_translate(32, &VariableValue::BigUint(BigUint::from(0u32)))
913                .0,
914            "0"
915        );
916    }
917
918    #[test]
919    fn posit32_translation_from_string() {
920        assert_eq!(
921            Posit32Translator {}
922                .basic_translate(
923                    32,
924                    &VariableValue::String("10000111000000001111111111111111".to_string())
925                )
926                .0,
927            "-8176.000244140625"
928        );
929        assert_eq!(
930            Posit32Translator {}
931                .basic_translate(
932                    32,
933                    &VariableValue::String("01110000000000111000000000000000".to_string())
934                )
935                .0,
936            "257.75"
937        );
938    }
939
940    #[test]
941    fn quire8_translation_from_biguint() {
942        assert_eq!(
943            PositQuire8Translator {}
944                .basic_translate(
945                    32,
946                    &VariableValue::BigUint(BigUint::from(0b1010101010001000u16))
947                )
948                .0,
949            "10"
950        );
951        assert_eq!(
952            PositQuire8Translator {}
953                .basic_translate(32, &VariableValue::BigUint(BigUint::from(0u16)))
954                .0,
955            "0"
956        );
957    }
958
959    #[test]
960    fn quire8_translation_from_string() {
961        assert_eq!(
962            PositQuire8Translator {}
963                .basic_translate(
964                    32,
965                    &VariableValue::String("10000111000000001111111111111111".to_string())
966                )
967                .0,
968            "-64"
969        );
970        assert_eq!(
971            PositQuire8Translator {}
972                .basic_translate(
973                    32,
974                    &VariableValue::String("01110000000000111000000000000000".to_string())
975                )
976                .0,
977            "64"
978        );
979    }
980
981    #[test]
982    fn quire16_translation_from_biguint() {
983        assert_eq!(
984            PositQuire16Translator {}
985                .basic_translate(128, &VariableValue::BigUint(BigUint::from(0b10101010100010001010101010001000101010101000100010101010100010001010101010001000101010101000100010101010100010001010101010001000u128)))
986                .0,
987            "-268435456"
988        );
989        assert_eq!(
990            PositQuire16Translator {}
991                .basic_translate(128, &VariableValue::BigUint(BigUint::from(7u8)))
992                .0,
993            "0.000000003725290298461914"
994        );
995        assert_eq!(
996            PositQuire16Translator {}
997                .basic_translate(128, &VariableValue::BigUint(BigUint::from(0u8)))
998                .0,
999            "0"
1000        );
1001    }
1002
1003    #[test]
1004    fn quire16_translation_from_string() {
1005        assert_eq!(
1006            PositQuire16Translator {}
1007                .basic_translate(
1008                    128,
1009                    &VariableValue::String(
1010                        "1000011100000000111111111111111101110000000000111000000000000000"
1011                            .to_string()
1012                    )
1013                )
1014                .0,
1015            "135"
1016        );
1017        assert_eq!(
1018            PositQuire16Translator {}
1019                .basic_translate(
1020                    128,
1021                    &VariableValue::String("01110000000000111000000000000000".to_string())
1022                )
1023                .0,
1024            "0.000000029802322387695313"
1025        );
1026    }
1027
1028    #[test]
1029    fn bloat16_translation_from_string() {
1030        assert_eq!(
1031            BFloat16Translator {}
1032                .basic_translate(16, &VariableValue::String("0100100011100011".to_string()))
1033                .0,
1034            "464896"
1035        );
1036        assert_eq!(
1037            BFloat16Translator {}
1038                .basic_translate(16, &VariableValue::String("1000000000000000".to_string()))
1039                .0,
1040            "-0"
1041        );
1042        assert_eq!(
1043            BFloat16Translator {}
1044                .basic_translate(16, &VariableValue::String("1111111111111111".to_string()))
1045                .0,
1046            "NaN"
1047        );
1048        assert_eq!(
1049            BFloat16Translator {}
1050                .basic_translate(16, &VariableValue::String("01001z0011100011".to_string()))
1051                .0,
1052            "HIGHIMP"
1053        );
1054        assert_eq!(
1055            BFloat16Translator {}
1056                .basic_translate(16, &VariableValue::String("01001q0011100011".to_string()))
1057                .0,
1058            "UNKNOWN VALUES"
1059        );
1060        assert_eq!(
1061            BFloat16Translator {}
1062                .basic_translate(16, &VariableValue::String("01001-0011100011".to_string()))
1063                .0,
1064            "DON'T CARE"
1065        );
1066        assert_eq!(
1067            BFloat16Translator {}
1068                .basic_translate(16, &VariableValue::String("01001w0011100011".to_string()))
1069                .0,
1070            "UNDEF WEAK"
1071        );
1072        assert_eq!(
1073            BFloat16Translator {}
1074                .basic_translate(16, &VariableValue::String("01001h0011100011".to_string()))
1075                .0,
1076            "WEAK"
1077        );
1078        assert_eq!(
1079            BFloat16Translator {}
1080                .basic_translate(16, &VariableValue::String("01001u0011100011".to_string()))
1081                .0,
1082            "UNDEF"
1083        );
1084    }
1085
1086    #[test]
1087    fn bloat16_translation_from_bigunit() {
1088        assert_eq!(
1089            BFloat16Translator {}
1090                .basic_translate(
1091                    16,
1092                    &VariableValue::BigUint(BigUint::from(0b1010101010001000u16))
1093                )
1094                .0,
1095            "-2.4158453e-13"
1096        );
1097        assert_eq!(
1098            BFloat16Translator {}
1099                .basic_translate(
1100                    16,
1101                    &VariableValue::BigUint(BigUint::from(0b1000000000000000u16))
1102                )
1103                .0,
1104            "-0"
1105        );
1106        assert_eq!(
1107            BFloat16Translator {}
1108                .basic_translate(
1109                    16,
1110                    &VariableValue::BigUint(BigUint::from(0b0000000000000000u16))
1111                )
1112                .0,
1113            "0"
1114        );
1115        assert_eq!(
1116            BFloat16Translator {}
1117                .basic_translate(
1118                    16,
1119                    &VariableValue::BigUint(BigUint::from(0b1111111111111111u16))
1120                )
1121                .0,
1122            "NaN"
1123        );
1124    }
1125
1126    #[test]
1127    fn half_translation_from_biguint() {
1128        assert_eq!(
1129            HalfPrecisionTranslator {}
1130                .basic_translate(
1131                    16,
1132                    &VariableValue::BigUint(BigUint::from(0b1000000000000000u16))
1133                )
1134                .0,
1135            "-0"
1136        );
1137        assert_eq!(
1138            HalfPrecisionTranslator {}
1139                .basic_translate(
1140                    16,
1141                    &VariableValue::BigUint(BigUint::from(0b0000000000000000u16))
1142                )
1143                .0,
1144            "0"
1145        );
1146        assert_eq!(
1147            HalfPrecisionTranslator {}
1148                .basic_translate(
1149                    16,
1150                    &VariableValue::BigUint(BigUint::from(0b1111111111111111u16))
1151                )
1152                .0,
1153            "NaN"
1154        );
1155    }
1156
1157    #[test]
1158    fn half_translation_from_string() {
1159        assert_eq!(
1160            HalfPrecisionTranslator {}
1161                .basic_translate(16, &VariableValue::String("0100100011100011".to_string()))
1162                .0,
1163            "9.7734375"
1164        );
1165        assert_eq!(
1166            HalfPrecisionTranslator {}
1167                .basic_translate(16, &VariableValue::String("1000000000000000".to_string()))
1168                .0,
1169            "-0"
1170        );
1171        assert_eq!(
1172            HalfPrecisionTranslator {}
1173                .basic_translate(16, &VariableValue::String("1111111111111111".to_string()))
1174                .0,
1175            "NaN"
1176        );
1177    }
1178
1179    #[test]
1180    fn single_translation_from_bigunit() {
1181        assert_eq!(
1182            SinglePrecisionTranslator {}
1183                .basic_translate(
1184                    32,
1185                    &VariableValue::BigUint(BigUint::from(0b01010101010001001010101010001000u32))
1186                )
1187                .0,
1188            "1.3514794e13"
1189        );
1190        assert_eq!(
1191            SinglePrecisionTranslator {}
1192                .basic_translate(
1193                    32,
1194                    &VariableValue::BigUint(BigUint::from(0b10000000000000000000000000000000u32))
1195                )
1196                .0,
1197            "-0"
1198        );
1199        assert_eq!(
1200            SinglePrecisionTranslator {}
1201                .basic_translate(
1202                    32,
1203                    &VariableValue::BigUint(BigUint::from(0b00000000000000000000000000000000u32))
1204                )
1205                .0,
1206            "0"
1207        );
1208        assert_eq!(
1209            SinglePrecisionTranslator {}
1210                .basic_translate(
1211                    32,
1212                    &VariableValue::BigUint(BigUint::from(0b11111111111111111111111111111111u32))
1213                )
1214                .0,
1215            "NaN"
1216        );
1217    }
1218
1219    #[test]
1220    fn double_translation_from_bigunit() {
1221        assert_eq!(
1222            DoublePrecisionTranslator {}
1223                .basic_translate(
1224                    64,
1225                    &VariableValue::BigUint(BigUint::from(
1226                        0b0101010101000100101010101000100001010101010001001010101010001000u64
1227                    ))
1228                )
1229                .0,
1230            "5.785860578429741e102"
1231        );
1232        assert_eq!(
1233            DoublePrecisionTranslator {}
1234                .basic_translate(
1235                    64,
1236                    &VariableValue::BigUint(BigUint::from(
1237                        0b1000000000000000000000000000000000000000000000000000000000000000u64
1238                    ))
1239                )
1240                .0,
1241            "-0"
1242        );
1243        assert_eq!(
1244            DoublePrecisionTranslator {}
1245                .basic_translate(
1246                    64,
1247                    &VariableValue::BigUint(BigUint::from(
1248                        0b0000000000000000000000000000000000000000000000000000000000000000u64
1249                    ))
1250                )
1251                .0,
1252            "0"
1253        );
1254        assert_eq!(
1255            DoublePrecisionTranslator {}
1256                .basic_translate(
1257                    64,
1258                    &VariableValue::BigUint(BigUint::from(
1259                        0b1111111111111111111111111111111111111111111111111111111111111111u64
1260                    ))
1261                )
1262                .0,
1263            "NaN"
1264        );
1265    }
1266}