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