libsurfer/translation/
numeric_translators.rs

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