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
24fn 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
101fn 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
426fn 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#[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, _ => sign * f64::from(4 + mant) * 2.0f64.powi(i32::from(exp) - 17),
462 }
463}
464
465fn 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, _ => sign * f64::from(8 + mant) * 2.0f64.powi(i32::from(exp) - 10),
475 }
476}
477
478fn 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
515fn 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}