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