1use alloc::vec::Vec;
8use core::cmp::Ordering;
9use core::fmt::{self, Display, Formatter};
10use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Sub};
11use core::str::FromStr;
12use core::{i32, u32};
13#[cfg(feature = "enable-serde")]
14use serde_derive::{Deserialize, Serialize};
15
16pub trait IntoBytes {
19 fn into_bytes(self) -> Vec<u8>;
21}
22
23impl IntoBytes for u8 {
24 fn into_bytes(self) -> Vec<u8> {
25 vec![self]
26 }
27}
28
29impl IntoBytes for i8 {
30 fn into_bytes(self) -> Vec<u8> {
31 vec![self as u8]
32 }
33}
34
35impl IntoBytes for i16 {
36 fn into_bytes(self) -> Vec<u8> {
37 self.to_le_bytes().to_vec()
38 }
39}
40
41impl IntoBytes for i32 {
42 fn into_bytes(self) -> Vec<u8> {
43 self.to_le_bytes().to_vec()
44 }
45}
46
47impl IntoBytes for Vec<u8> {
48 fn into_bytes(self) -> Vec<u8> {
49 self
50 }
51}
52
53#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
58#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
59pub struct Imm64(i64);
60
61impl Imm64 {
62 pub fn new(x: i64) -> Self {
64 Self(x)
65 }
66
67 pub fn wrapping_neg(self) -> Self {
69 Self(self.0.wrapping_neg())
70 }
71
72 pub fn bits(&self) -> i64 {
74 self.0
75 }
76
77 #[must_use]
79 pub(crate) fn mask_to_width(&self, bit_width: u32) -> Self {
80 debug_assert!(bit_width.is_power_of_two());
81
82 if bit_width >= 64 {
83 return *self;
84 }
85
86 let bit_width = i64::from(bit_width);
87 let mask = (1 << bit_width) - 1;
88 let masked = self.0 & mask;
89 Imm64(masked)
90 }
91
92 #[must_use]
95 pub(crate) fn sign_extend_from_width(&self, bit_width: u32) -> Self {
96 debug_assert!(
97 bit_width.is_power_of_two(),
98 "{bit_width} is not a power of two"
99 );
100
101 if bit_width >= 64 {
102 return *self;
103 }
104
105 let bit_width = i64::from(bit_width);
106 let delta = 64 - bit_width;
107 let sign_extended = (self.0 << delta) >> delta;
108 Imm64(sign_extended)
109 }
110}
111
112impl From<Imm64> for i64 {
113 fn from(val: Imm64) -> i64 {
114 val.0
115 }
116}
117
118impl IntoBytes for Imm64 {
119 fn into_bytes(self) -> Vec<u8> {
120 self.0.to_le_bytes().to_vec()
121 }
122}
123
124impl From<i64> for Imm64 {
125 fn from(x: i64) -> Self {
126 Self(x)
127 }
128}
129
130impl Display for Imm64 {
131 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
132 let x = self.0;
133 if x < 10_000 {
134 write!(f, "{x}")
136 } else {
137 write_hex(x as u64, f)
138 }
139 }
140}
141
142fn parse_i64(s: &str) -> Result<i64, &'static str> {
144 let negative = s.starts_with('-');
145 let s2 = if negative || s.starts_with('+') {
146 &s[1..]
147 } else {
148 s
149 };
150
151 let mut value = parse_u64(s2)?;
152
153 if negative {
155 value = value.wrapping_neg();
156 if value as i64 > 0 {
158 return Err("Negative number too small");
159 }
160 }
161 Ok(value as i64)
162}
163
164impl FromStr for Imm64 {
165 type Err = &'static str;
166
167 fn from_str(s: &str) -> Result<Self, &'static str> {
169 parse_i64(s).map(Self::new)
170 }
171}
172
173#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
178#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
179pub struct Uimm64(u64);
180
181impl Uimm64 {
182 pub fn new(x: u64) -> Self {
184 Self(x)
185 }
186
187 pub fn wrapping_neg(self) -> Self {
189 Self(self.0.wrapping_neg())
190 }
191}
192
193impl From<Uimm64> for u64 {
194 fn from(val: Uimm64) -> u64 {
195 val.0
196 }
197}
198
199impl From<u64> for Uimm64 {
200 fn from(x: u64) -> Self {
201 Self(x)
202 }
203}
204
205fn write_hex(x: u64, f: &mut Formatter) -> fmt::Result {
212 let mut pos = (64 - x.leading_zeros() - 1) & 0xf0;
213 write!(f, "0x{:04x}", (x >> pos) & 0xffff)?;
214 while pos > 0 {
215 pos -= 16;
216 write!(f, "_{:04x}", (x >> pos) & 0xffff)?;
217 }
218 Ok(())
219}
220
221impl Display for Uimm64 {
222 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
223 let x = self.0;
224 if x < 10_000 {
225 write!(f, "{x}")
227 } else {
228 write_hex(x, f)
229 }
230 }
231}
232
233fn parse_u64(s: &str) -> Result<u64, &'static str> {
235 let mut value: u64 = 0;
236 let mut digits = 0;
237
238 if s.starts_with("-0x") {
239 return Err("Invalid character in hexadecimal number");
240 } else if let Some(num) = s.strip_prefix("0x") {
241 for ch in num.chars() {
243 match ch.to_digit(16) {
244 Some(digit) => {
245 digits += 1;
246 if digits > 16 {
247 return Err("Too many hexadecimal digits");
248 }
249 value = (value << 4) | u64::from(digit);
251 }
252 None => {
253 if ch != '_' {
255 return Err("Invalid character in hexadecimal number");
256 }
257 }
258 }
259 }
260 } else {
261 for ch in s.chars() {
263 match ch.to_digit(10) {
264 Some(digit) => {
265 digits += 1;
266 match value.checked_mul(10) {
267 None => return Err("Too large decimal number"),
268 Some(v) => value = v,
269 }
270 match value.checked_add(u64::from(digit)) {
271 None => return Err("Too large decimal number"),
272 Some(v) => value = v,
273 }
274 }
275 None => {
276 if ch != '_' {
278 return Err("Invalid character in decimal number");
279 }
280 }
281 }
282 }
283 }
284
285 if digits == 0 {
286 return Err("No digits in number");
287 }
288
289 Ok(value)
290}
291
292impl FromStr for Uimm64 {
293 type Err = &'static str;
294
295 fn from_str(s: &str) -> Result<Self, &'static str> {
297 parse_u64(s).map(Self::new)
298 }
299}
300
301pub type Uimm8 = u8;
305
306#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
310#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
311pub struct Uimm32(u32);
312
313impl From<Uimm32> for u32 {
314 fn from(val: Uimm32) -> u32 {
315 val.0
316 }
317}
318
319impl From<Uimm32> for u64 {
320 fn from(val: Uimm32) -> u64 {
321 val.0.into()
322 }
323}
324
325impl From<Uimm32> for i64 {
326 fn from(val: Uimm32) -> i64 {
327 i64::from(val.0)
328 }
329}
330
331impl From<u32> for Uimm32 {
332 fn from(x: u32) -> Self {
333 Self(x)
334 }
335}
336
337impl Display for Uimm32 {
338 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
339 if self.0 < 10_000 {
340 write!(f, "{}", self.0)
341 } else {
342 write_hex(u64::from(self.0), f)
343 }
344 }
345}
346
347impl FromStr for Uimm32 {
348 type Err = &'static str;
349
350 fn from_str(s: &str) -> Result<Self, &'static str> {
352 parse_i64(s).and_then(|x| {
353 if 0 <= x && x <= i64::from(u32::MAX) {
354 Ok(Self(x as u32))
355 } else {
356 Err("Uimm32 out of range")
357 }
358 })
359 }
360}
361
362#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
366#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
367pub struct V128Imm(pub [u8; 16]);
368
369impl V128Imm {
370 pub fn bytes(&self) -> impl Iterator<Item = &u8> {
372 self.0.iter()
373 }
374
375 pub fn to_vec(self) -> Vec<u8> {
377 self.0.to_vec()
378 }
379
380 pub fn as_slice(&self) -> &[u8] {
382 &self.0[..]
383 }
384}
385
386impl From<&[u8]> for V128Imm {
387 fn from(slice: &[u8]) -> Self {
388 assert_eq!(slice.len(), 16);
389 let mut buffer = [0; 16];
390 buffer.copy_from_slice(slice);
391 Self(buffer)
392 }
393}
394
395impl From<u128> for V128Imm {
396 fn from(val: u128) -> Self {
397 V128Imm(val.to_le_bytes())
398 }
399}
400
401#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
406#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
407pub struct Offset32(i32);
408
409impl Offset32 {
410 pub fn new(x: i32) -> Self {
412 Self(x)
413 }
414
415 pub fn try_from_i64(x: i64) -> Option<Self> {
417 let x = i32::try_from(x).ok()?;
418 Some(Self::new(x))
419 }
420
421 pub fn try_add_i64(self, x: i64) -> Option<Self> {
423 let x = i32::try_from(x).ok()?;
424 let ret = self.0.checked_add(x)?;
425 Some(Self::new(ret))
426 }
427}
428
429impl From<Offset32> for i32 {
430 fn from(val: Offset32) -> i32 {
431 val.0
432 }
433}
434
435impl From<Offset32> for i64 {
436 fn from(val: Offset32) -> i64 {
437 i64::from(val.0)
438 }
439}
440
441impl From<i32> for Offset32 {
442 fn from(x: i32) -> Self {
443 Self(x)
444 }
445}
446
447impl From<u8> for Offset32 {
448 fn from(val: u8) -> Offset32 {
449 Self(val.into())
450 }
451}
452
453impl Display for Offset32 {
454 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
455 if self.0 == 0 {
457 return Ok(());
458 }
459
460 write!(f, "{}", if self.0 < 0 { '-' } else { '+' })?;
462
463 let val = i64::from(self.0).abs();
464 if val < 10_000 {
465 write!(f, "{val}")
466 } else {
467 write_hex(val as u64, f)
468 }
469 }
470}
471
472impl FromStr for Offset32 {
473 type Err = &'static str;
474
475 fn from_str(s: &str) -> Result<Self, &'static str> {
477 if !(s.starts_with('-') || s.starts_with('+')) {
478 return Err("Offset must begin with sign");
479 }
480 parse_i64(s).and_then(|x| {
481 if i64::from(i32::MIN) <= x && x <= i64::from(i32::MAX) {
482 Ok(Self::new(x as i32))
483 } else {
484 Err("Offset out of range")
485 }
486 })
487 }
488}
489
490macro_rules! ignore {
492 ($($t:tt)*) => {};
493}
494
495macro_rules! ieee_float {
496 (
497 name = $name:ident,
498 bits = $bits:literal,
499 significand_bits = $significand_bits:literal,
500 bits_ty = $bits_ty:ident,
501 float_ty = $float_ty:ident,
502 $(as_float = $as_float:ident,)?
503 $(rust_type_not_stable = $rust_type_not_stable:ident,)?
504 ) => {
505 #[doc = concat!("binary", stringify!($bits))]
507 #[doc = stringify!($bits_ty)]
509 #[doc = stringify!($float_ty)]
513 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
521 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
522 #[repr(C)]
523 pub struct $name {
524 bits: $bits_ty
525 }
526
527 impl $name {
528 const BITS: u8 = $bits;
529 const SIGNIFICAND_BITS: u8 = $significand_bits;
530 const EXPONENT_BITS: u8 = Self::BITS - Self::SIGNIFICAND_BITS - 1;
531 const SIGN_MASK: $bits_ty = 1 << (Self::EXPONENT_BITS + Self::SIGNIFICAND_BITS);
532 const SIGNIFICAND_MASK: $bits_ty = $bits_ty::MAX >> (Self::EXPONENT_BITS + 1);
533 const EXPONENT_MASK: $bits_ty = !Self::SIGN_MASK & !Self::SIGNIFICAND_MASK;
534 pub const NAN: Self = Self::with_bits(Self::EXPONENT_MASK | (1 << (Self::SIGNIFICAND_BITS - 1)));
536
537 #[doc = concat!("`", stringify!($name), "`")]
539 pub const fn with_bits(bits: $bits_ty) -> Self {
541 Self { bits }
542 }
543
544 pub fn bits(self) -> $bits_ty {
546 self.bits
547 }
548
549 $(
550 #[doc = concat!("`", stringify!($name), "`")]
552 pub fn with_float(x: $float_ty) -> Self {
554 Self::with_bits(x.to_bits())
555 }
556
557 #[doc = concat!("`", stringify!($float_ty), "`.")]
559 pub fn $as_float(self) -> $float_ty {
560 $float_ty::from_bits(self.bits())
561 }
562 )?
563
564 pub fn abs(self) -> Self {
566 Self::with_bits(self.bits() & !Self::SIGN_MASK)
567 }
568
569 pub fn copysign(self, sign: Self) -> Self {
571 Self::with_bits((self.bits() & !Self::SIGN_MASK) | (sign.bits() & Self::SIGN_MASK))
572 }
573
574 pub fn minimum(self, other: Self) -> Self {
576 if self.is_nan() || other.is_nan() {
578 Self::NAN
579 } else if self.is_zero() && other.is_zero() {
580 if self.is_negative() {
581 self
582 } else {
583 other
584 }
585 } else if self <= other {
586 self
587 } else {
588 other
589 }
590 }
591
592 pub fn maximum(self, other: Self) -> Self {
594 if self.is_nan() || other.is_nan() {
596 Self::NAN
597 } else if self.is_zero() && other.is_zero() {
598 if self.is_positive() {
599 self
600 } else {
601 other
602 }
603 } else if self >= other {
604 self
605 } else {
606 other
607 }
608 }
609
610 #[doc = concat!("`", stringify!($name), "`")]
612 pub fn pow2<I: Into<i32>>(n: I) -> Self {
614 let n = n.into();
615 let w = Self::EXPONENT_BITS;
616 let t = Self::SIGNIFICAND_BITS;
617 let bias = (1 << (w - 1)) - 1;
618 let exponent = n + bias;
619 assert!(exponent > 0, "Underflow n={}", n);
620 assert!(exponent < (1 << w) + 1, "Overflow n={}", n);
621 Self::with_bits((exponent as $bits_ty) << t)
622 }
623
624 #[doc = concat!("`", stringify!($name), "`")]
626 #[doc = concat!("`", stringify!($float_ty), "`")]
628 pub fn fcvt_to_sint_negative_overflow<I: Into<i32>>(n: I) -> Self {
630 let n = n.into();
631 debug_assert!(n < i32::from(Self::BITS));
632 debug_assert!(i32::from(Self::SIGNIFICAND_BITS) + 1 - n < i32::from(Self::BITS));
633 Self::with_bits((1 << (Self::BITS - 1)) | Self::pow2(n - 1).bits() | (1 << (i32::from(Self::SIGNIFICAND_BITS) + 1 - n)))
634 }
635
636 #[doc = concat!("`", stringify!($name), "`,")]
638 pub fn is_nan(self) -> bool {
640 self.abs().bits() > Self::EXPONENT_MASK
641 }
642
643 pub fn is_positive(self) -> bool {
645 !self.is_negative()
646 }
647
648 pub fn is_negative(self) -> bool {
650 self.bits() & Self::SIGN_MASK == Self::SIGN_MASK
651 }
652
653 pub fn is_zero(self) -> bool {
655 self.abs().bits() == 0
656 }
657
658 pub fn non_nan(self) -> Option<Self> {
660 Some(self).filter(|f| !f.is_nan())
661 }
662
663 $(
664 pub fn sqrt(self) -> Self {
666 Self::with_float(self.$as_float().sqrt())
667 }
668
669 pub fn ceil(self) -> Self {
671 Self::with_float(self.$as_float().ceil())
672 }
673
674 pub fn floor(self) -> Self {
676 Self::with_float(self.$as_float().floor())
677 }
678
679 pub fn trunc(self) -> Self {
681 Self::with_float(self.$as_float().trunc())
682 }
683
684 pub fn round_ties_even(self) -> Self {
687 Self::with_float(self.$as_float().round_ties_even())
688 }
689 )?
690 }
691
692 impl PartialOrd for $name {
693 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
694 $(self.$as_float().partial_cmp(&rhs.$as_float()))?
695 $(
696 ignore!($rust_type_not_stable);
697 if self.is_nan() || rhs.is_nan() {
699 return None;
701 }
702 if self.is_zero() || rhs.is_zero() {
703 return Some(Ordering::Equal);
705 }
706 let lhs_positive = self.is_positive();
707 let rhs_positive = rhs.is_positive();
708 if lhs_positive != rhs_positive {
709 return lhs_positive.partial_cmp(&rhs_positive);
711 }
712 if lhs_positive {
714 self.bits().partial_cmp(&rhs.bits())
715 } else {
716 rhs.bits().partial_cmp(&self.bits())
718 }
719 )?
720 }
721 }
722
723 impl Display for $name {
724 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
725 format_float(u128::from(self.bits()), Self::EXPONENT_BITS, Self::SIGNIFICAND_BITS, f)
726 }
727 }
728
729 impl FromStr for $name {
730 type Err = &'static str;
731
732 fn from_str(s: &str) -> Result<Self, &'static str> {
733 match parse_float(s, Self::EXPONENT_BITS, Self::SIGNIFICAND_BITS) {
734 Ok(b) => Ok(Self::with_bits(b.try_into().unwrap())),
735 Err(s) => Err(s),
736 }
737 }
738 }
739
740 impl IntoBytes for $name {
741 fn into_bytes(self) -> Vec<u8> {
742 self.bits().to_le_bytes().to_vec()
743 }
744 }
745
746 impl Neg for $name {
747 type Output = Self;
748
749 fn neg(self) -> Self {
750 Self::with_bits(self.bits() ^ Self::SIGN_MASK)
751 }
752 }
753
754
755
756 $(
757 impl From<$float_ty> for $name {
758 fn from(x: $float_ty) -> Self {
759 Self::with_float(x)
760 }
761 }
762
763 impl Add for $name {
764 type Output = Self;
765
766 fn add(self, rhs: Self) -> Self {
767 Self::with_float(self.$as_float() + rhs.$as_float())
768 }
769 }
770
771 impl Sub for $name {
772 type Output = Self;
773
774 fn sub(self, rhs: Self) -> Self {
775 Self::with_float(self.$as_float() - rhs.$as_float())
776 }
777 }
778
779 impl Mul for $name {
780 type Output = Self;
781
782 fn mul(self, rhs: Self) -> Self {
783 Self::with_float(self.$as_float() * rhs.$as_float())
784 }
785 }
786
787 impl Div for $name {
788 type Output = Self;
789
790 fn div(self, rhs: Self) -> Self::Output {
791 Self::with_float(self.$as_float() / rhs.$as_float())
792 }
793 }
794 )?
795
796 impl BitAnd for $name {
797 type Output = Self;
798
799 fn bitand(self, rhs: Self) -> Self {
800 Self::with_bits(self.bits() & rhs.bits())
801 }
802 }
803
804 impl BitOr for $name {
805 type Output = Self;
806
807 fn bitor(self, rhs: Self) -> Self {
808 Self::with_bits(self.bits() | rhs.bits())
809 }
810 }
811
812 impl BitXor for $name {
813 type Output = Self;
814
815 fn bitxor(self, rhs: Self) -> Self {
816 Self::with_bits(self.bits() ^ rhs.bits())
817 }
818 }
819
820 impl Not for $name {
821 type Output = Self;
822
823 fn not(self) -> Self {
824 Self::with_bits(!self.bits())
825 }
826 }
827 };
828}
829
830ieee_float! {
831 name = Ieee16,
832 bits = 16,
833 significand_bits = 10,
834 bits_ty = u16,
835 float_ty = f16,
836 rust_type_not_stable = rust_type_not_stable,
837}
838
839ieee_float! {
840 name = Ieee32,
841 bits = 32,
842 significand_bits = 23,
843 bits_ty = u32,
844 float_ty = f32,
845 as_float = as_f32,
846}
847
848ieee_float! {
849 name = Ieee64,
850 bits = 64,
851 significand_bits = 52,
852 bits_ty = u64,
853 float_ty = f64,
854 as_float = as_f64,
855}
856
857ieee_float! {
858 name = Ieee128,
859 bits = 128,
860 significand_bits = 112,
861 bits_ty = u128,
862 float_ty = f128,
863 rust_type_not_stable = rust_type_not_stable,
864}
865
866fn format_float(bits: u128, w: u8, t: u8, f: &mut Formatter) -> fmt::Result {
877 debug_assert!(w > 0 && w <= 16, "Invalid exponent range");
878 debug_assert!(1 + w + t <= 128, "Too large IEEE format for u128");
879 debug_assert!((t + w + 1).is_power_of_two(), "Unexpected IEEE format size");
880
881 let max_e_bits = (1u128 << w) - 1;
882 let t_bits = bits & ((1u128 << t) - 1); let e_bits = (bits >> t) & max_e_bits; let sign_bit = (bits >> (w + t)) & 1;
885
886 let bias: i32 = (1 << (w - 1)) - 1;
887 let e = e_bits as i32 - bias; let emin = 1 - bias; let digits = (t + 3) / 4;
892 let left_t_bits = t_bits << (4 * digits - t);
894
895 if sign_bit != 0 {
897 write!(f, "-")?;
898 }
899
900 if e_bits == 0 {
901 if t_bits == 0 {
902 write!(f, "0.0")
904 } else {
905 write!(
907 f,
908 "0x0.{0:01$x}p{2}",
909 left_t_bits,
910 usize::from(digits),
911 emin
912 )
913 }
914 } else if e_bits == max_e_bits {
915 if sign_bit == 0 {
918 write!(f, "+")?;
919 }
920 if t_bits == 0 {
921 write!(f, "Inf")
923 } else {
924 let payload = t_bits & ((1 << (t - 1)) - 1);
926 if t_bits & (1 << (t - 1)) != 0 {
927 if payload != 0 {
929 write!(f, "NaN:0x{payload:x}")
930 } else {
931 write!(f, "NaN")
932 }
933 } else {
934 write!(f, "sNaN:0x{payload:x}")
936 }
937 }
938 } else {
939 write!(f, "0x1.{0:01$x}p{2}", left_t_bits, usize::from(digits), e)
941 }
942}
943
944fn parse_float(s: &str, w: u8, t: u8) -> Result<u128, &'static str> {
952 debug_assert!(w > 0 && w <= 16, "Invalid exponent range");
953 debug_assert!(1 + w + t <= 128, "Too large IEEE format for u128");
954 debug_assert!((t + w + 1).is_power_of_two(), "Unexpected IEEE format size");
955
956 let (sign_bit, s2) = if let Some(num) = s.strip_prefix('-') {
957 (1u128 << (t + w), num)
958 } else if let Some(num) = s.strip_prefix('+') {
959 (0, num)
960 } else {
961 (0, s)
962 };
963
964 if !s2.starts_with("0x") {
965 let max_e_bits = ((1u128 << w) - 1) << t;
966 let quiet_bit = 1u128 << (t - 1);
967
968 if s2 == "0.0" {
970 return Ok(sign_bit);
971 }
972
973 if s2 == "Inf" {
974 return Ok(sign_bit | max_e_bits);
976 }
977 if s2 == "NaN" {
978 return Ok(sign_bit | max_e_bits | quiet_bit);
980 }
981 if let Some(nan) = s2.strip_prefix("NaN:0x") {
982 return match u128::from_str_radix(nan, 16) {
984 Ok(payload) if payload < quiet_bit => {
985 Ok(sign_bit | max_e_bits | quiet_bit | payload)
986 }
987 _ => Err("Invalid NaN payload"),
988 };
989 }
990 if let Some(nan) = s2.strip_prefix("sNaN:0x") {
991 return match u128::from_str_radix(nan, 16) {
993 Ok(payload) if 0 < payload && payload < quiet_bit => {
994 Ok(sign_bit | max_e_bits | payload)
995 }
996 _ => Err("Invalid sNaN payload"),
997 };
998 }
999
1000 return Err("Float must be hexadecimal");
1001 }
1002 let s3 = &s2[2..];
1003
1004 let mut digits = 0u8;
1005 let mut digits_before_period: Option<u8> = None;
1006 let mut significand = 0u128;
1007 let mut exponent = 0i32;
1008
1009 for (idx, ch) in s3.char_indices() {
1010 match ch {
1011 '.' => {
1012 if digits_before_period != None {
1014 return Err("Multiple radix points");
1015 } else {
1016 digits_before_period = Some(digits);
1017 }
1018 }
1019 'p' => {
1020 let exp_str = &s3[1 + idx..];
1022 match exp_str.parse::<i16>() {
1023 Ok(e) => {
1024 exponent = i32::from(e);
1025 break;
1026 }
1027 Err(_) => return Err("Bad exponent"),
1028 }
1029 }
1030 _ => match ch.to_digit(16) {
1031 Some(digit) => {
1032 digits += 1;
1033 if digits > 32 {
1034 return Err("Too many digits");
1035 }
1036 significand = (significand << 4) | u128::from(digit);
1037 }
1038 None => return Err("Invalid character"),
1039 },
1040 }
1041 }
1042
1043 if digits == 0 {
1044 return Err("No digits");
1045 }
1046
1047 if significand == 0 {
1048 return Ok(sign_bit);
1050 }
1051
1052 match digits_before_period {
1054 None => {} Some(d) => exponent -= 4 * i32::from(digits - d),
1056 };
1057
1058 let significant_bits = (128 - significand.leading_zeros()) as u8;
1060 if significant_bits > t + 1 {
1061 let adjust = significant_bits - (t + 1);
1062 if significand & ((1u128 << adjust) - 1) != 0 {
1063 return Err("Too many significant bits");
1064 }
1065 significand >>= adjust;
1067 exponent += i32::from(adjust);
1068 } else {
1069 let adjust = t + 1 - significant_bits;
1070 significand <<= adjust;
1071 exponent -= i32::from(adjust);
1072 }
1073 debug_assert_eq!(significand >> t, 1);
1074
1075 let t_bits = significand & ((1 << t) - 1);
1077
1078 let max_exp = (1i32 << w) - 2;
1079 let bias: i32 = (1 << (w - 1)) - 1;
1080 exponent += bias + i32::from(t);
1081
1082 if exponent > max_exp {
1083 Err("Magnitude too large")
1084 } else if exponent > 0 {
1085 let e_bits = (exponent as u128) << t;
1087 Ok(sign_bit | e_bits | t_bits)
1088 } else if 1 - exponent <= i32::from(t) {
1089 let adjust = 1 - exponent;
1092 if significand & ((1u128 << adjust) - 1) != 0 {
1093 Err("Subnormal underflow")
1094 } else {
1095 significand >>= adjust;
1096 Ok(sign_bit | significand)
1097 }
1098 } else {
1099 Err("Magnitude too small")
1100 }
1101}
1102
1103#[cfg(test)]
1104mod tests {
1105 use super::*;
1106 use alloc::string::ToString;
1107 use core::{f32, f64};
1108
1109 #[test]
1110 fn format_imm64() {
1111 assert_eq!(Imm64(0).to_string(), "0");
1112 assert_eq!(Imm64(9999).to_string(), "9999");
1113 assert_eq!(Imm64(10000).to_string(), "0x2710");
1114 assert_eq!(Imm64(-9999).to_string(), "-9999");
1115 assert_eq!(Imm64(-10000).to_string(), "-10000");
1116 assert_eq!(Imm64(0xffff).to_string(), "0xffff");
1117 assert_eq!(Imm64(0x10000).to_string(), "0x0001_0000");
1118 }
1119
1120 #[test]
1121 fn format_uimm64() {
1122 assert_eq!(Uimm64(0).to_string(), "0");
1123 assert_eq!(Uimm64(9999).to_string(), "9999");
1124 assert_eq!(Uimm64(10000).to_string(), "0x2710");
1125 assert_eq!(Uimm64(-9999i64 as u64).to_string(), "0xffff_ffff_ffff_d8f1");
1126 assert_eq!(
1127 Uimm64(-10000i64 as u64).to_string(),
1128 "0xffff_ffff_ffff_d8f0"
1129 );
1130 assert_eq!(Uimm64(0xffff).to_string(), "0xffff");
1131 assert_eq!(Uimm64(0x10000).to_string(), "0x0001_0000");
1132 }
1133
1134 #[track_caller]
1136 fn parse_ok<T: FromStr + Display>(text: &str, want: &str)
1137 where
1138 <T as FromStr>::Err: Display,
1139 {
1140 match text.parse::<T>() {
1141 Err(s) => panic!("\"{text}\".parse() error: {s}"),
1142 Ok(x) => assert_eq!(x.to_string(), want),
1143 }
1144 }
1145
1146 fn parse_err<T: FromStr + Display>(text: &str, msg: &str)
1148 where
1149 <T as FromStr>::Err: Display,
1150 {
1151 match text.parse::<T>() {
1152 Err(s) => assert_eq!(s.to_string(), msg),
1153 Ok(x) => panic!("Wanted Err({msg}), but got {x}"),
1154 }
1155 }
1156
1157 #[test]
1158 fn parse_imm64() {
1159 parse_ok::<Imm64>("0", "0");
1160 parse_ok::<Imm64>("1", "1");
1161 parse_ok::<Imm64>("-0", "0");
1162 parse_ok::<Imm64>("-1", "-1");
1163 parse_ok::<Imm64>("0x0", "0");
1164 parse_ok::<Imm64>("0xf", "15");
1165 parse_ok::<Imm64>("-0x9", "-9");
1166
1167 parse_ok::<Imm64>("0xffffffff_ffffffff", "-1");
1169 parse_ok::<Imm64>("0x80000000_00000000", "-9223372036854775808");
1170 parse_ok::<Imm64>("-0x80000000_00000000", "-9223372036854775808");
1171 parse_err::<Imm64>("-0x80000000_00000001", "Negative number too small");
1172 parse_ok::<Imm64>("18446744073709551615", "-1");
1173 parse_ok::<Imm64>("-9223372036854775808", "-9223372036854775808");
1174 parse_err::<Imm64>("18446744073709551616", "Too large decimal number");
1176 parse_err::<Imm64>("184467440737095516100", "Too large decimal number");
1177 parse_err::<Imm64>("-9223372036854775809", "Negative number too small");
1178
1179 parse_ok::<Imm64>("0_0", "0");
1181 parse_ok::<Imm64>("-_10_0", "-100");
1182 parse_ok::<Imm64>("_10_", "10");
1183 parse_ok::<Imm64>("0x97_88_bb", "0x0097_88bb");
1184 parse_ok::<Imm64>("0x_97_", "151");
1185
1186 parse_err::<Imm64>("", "No digits in number");
1187 parse_err::<Imm64>("-", "No digits in number");
1188 parse_err::<Imm64>("_", "No digits in number");
1189 parse_err::<Imm64>("0x", "No digits in number");
1190 parse_err::<Imm64>("0x_", "No digits in number");
1191 parse_err::<Imm64>("-0x", "No digits in number");
1192 parse_err::<Imm64>(" ", "Invalid character in decimal number");
1193 parse_err::<Imm64>("0 ", "Invalid character in decimal number");
1194 parse_err::<Imm64>(" 0", "Invalid character in decimal number");
1195 parse_err::<Imm64>("--", "Invalid character in decimal number");
1196 parse_err::<Imm64>("-0x-", "Invalid character in hexadecimal number");
1197 parse_err::<Imm64>("abc", "Invalid character in decimal number");
1198 parse_err::<Imm64>("-abc", "Invalid character in decimal number");
1199
1200 parse_err::<Imm64>("0x0_0000_0000_0000_0000", "Too many hexadecimal digits");
1202 }
1203
1204 #[test]
1205 fn parse_uimm64() {
1206 parse_ok::<Uimm64>("0", "0");
1207 parse_ok::<Uimm64>("1", "1");
1208 parse_ok::<Uimm64>("0x0", "0");
1209 parse_ok::<Uimm64>("0xf", "15");
1210 parse_ok::<Uimm64>("0xffffffff_fffffff7", "0xffff_ffff_ffff_fff7");
1211
1212 parse_ok::<Uimm64>("0xffffffff_ffffffff", "0xffff_ffff_ffff_ffff");
1214 parse_ok::<Uimm64>("0x80000000_00000000", "0x8000_0000_0000_0000");
1215 parse_ok::<Uimm64>("18446744073709551615", "0xffff_ffff_ffff_ffff");
1216 parse_err::<Uimm64>("18446744073709551616", "Too large decimal number");
1218 parse_err::<Uimm64>("184467440737095516100", "Too large decimal number");
1219
1220 parse_ok::<Uimm64>("0_0", "0");
1222 parse_ok::<Uimm64>("_10_", "10");
1223 parse_ok::<Uimm64>("0x97_88_bb", "0x0097_88bb");
1224 parse_ok::<Uimm64>("0x_97_", "151");
1225
1226 parse_err::<Uimm64>("", "No digits in number");
1227 parse_err::<Uimm64>("_", "No digits in number");
1228 parse_err::<Uimm64>("0x", "No digits in number");
1229 parse_err::<Uimm64>("0x_", "No digits in number");
1230 parse_err::<Uimm64>("-", "Invalid character in decimal number");
1231 parse_err::<Uimm64>("-0x", "Invalid character in hexadecimal number");
1232 parse_err::<Uimm64>(" ", "Invalid character in decimal number");
1233 parse_err::<Uimm64>("0 ", "Invalid character in decimal number");
1234 parse_err::<Uimm64>(" 0", "Invalid character in decimal number");
1235 parse_err::<Uimm64>("--", "Invalid character in decimal number");
1236 parse_err::<Uimm64>("-0x-", "Invalid character in hexadecimal number");
1237 parse_err::<Uimm64>("-0", "Invalid character in decimal number");
1238 parse_err::<Uimm64>("-1", "Invalid character in decimal number");
1239 parse_err::<Uimm64>("abc", "Invalid character in decimal number");
1240 parse_err::<Uimm64>("-abc", "Invalid character in decimal number");
1241
1242 parse_err::<Uimm64>("0x0_0000_0000_0000_0000", "Too many hexadecimal digits");
1244 }
1245
1246 #[test]
1247 fn format_offset32() {
1248 assert_eq!(Offset32(0).to_string(), "");
1249 assert_eq!(Offset32(1).to_string(), "+1");
1250 assert_eq!(Offset32(-1).to_string(), "-1");
1251 assert_eq!(Offset32(9999).to_string(), "+9999");
1252 assert_eq!(Offset32(10000).to_string(), "+0x2710");
1253 assert_eq!(Offset32(-9999).to_string(), "-9999");
1254 assert_eq!(Offset32(-10000).to_string(), "-0x2710");
1255 assert_eq!(Offset32(0xffff).to_string(), "+0xffff");
1256 assert_eq!(Offset32(0x10000).to_string(), "+0x0001_0000");
1257 }
1258
1259 #[test]
1260 fn parse_offset32() {
1261 parse_ok::<Offset32>("+0", "");
1262 parse_ok::<Offset32>("+1", "+1");
1263 parse_ok::<Offset32>("-0", "");
1264 parse_ok::<Offset32>("-1", "-1");
1265 parse_ok::<Offset32>("+0x0", "");
1266 parse_ok::<Offset32>("+0xf", "+15");
1267 parse_ok::<Offset32>("-0x9", "-9");
1268 parse_ok::<Offset32>("-0x8000_0000", "-0x8000_0000");
1269
1270 parse_err::<Offset32>("+0x8000_0000", "Offset out of range");
1271 }
1272
1273 #[test]
1274 fn format_ieee16() {
1275 assert_eq!(Ieee16::with_bits(0).to_string(), "0.0"); assert_eq!(Ieee16::with_bits(0x8000).to_string(), "-0.0"); assert_eq!(Ieee16::with_bits(0x3c00).to_string(), "0x1.000p0"); assert_eq!(Ieee16::with_bits(0x3e00).to_string(), "0x1.800p0"); assert_eq!(Ieee16::with_bits(0x3800).to_string(), "0x1.000p-1"); assert_eq!(
1281 Ieee16::with_bits(0x1400).to_string(), "0x1.000p-10"
1283 );
1284 assert_eq!(
1285 Ieee16::with_bits(0xfbff).to_string(), "-0x1.ffcp15"
1287 );
1288 assert_eq!(
1289 Ieee16::with_bits(0x7bff).to_string(), "0x1.ffcp15"
1291 );
1292 assert_eq!(
1294 Ieee16::with_bits(0x0400).to_string(), "0x1.000p-14"
1296 );
1297 assert_eq!(
1299 Ieee16::with_bits(0x0200).to_string(), "0x0.800p-14"
1301 );
1302 assert_eq!(
1303 Ieee16::with_bits(0x0001).to_string(), "0x0.004p-14"
1305 );
1306 assert_eq!(
1307 Ieee16::with_bits(0x7c00).to_string(), "+Inf"
1309 );
1310 assert_eq!(
1311 Ieee16::with_bits(0xfc00).to_string(), "-Inf"
1313 );
1314 assert_eq!(
1315 Ieee16::with_bits(0x7e00).to_string(), "+NaN"
1317 );
1318 assert_eq!(
1319 Ieee16::with_bits(0xfe00).to_string(), "-NaN"
1321 );
1322 assert_eq!(Ieee16::with_bits(0x7e01).to_string(), "+NaN:0x1");
1324 assert_eq!(Ieee16::with_bits(0x7f01).to_string(), "+NaN:0x101");
1325 assert_eq!(Ieee16::with_bits(0x7c01).to_string(), "+sNaN:0x1");
1327 assert_eq!(Ieee16::with_bits(0x7d01).to_string(), "+sNaN:0x101");
1328 }
1329
1330 #[test]
1331 fn parse_ieee16() {
1332 parse_ok::<Ieee16>("0.0", "0.0");
1333 parse_ok::<Ieee16>("+0.0", "0.0");
1334 parse_ok::<Ieee16>("-0.0", "-0.0");
1335 parse_ok::<Ieee16>("0x0", "0.0");
1336 parse_ok::<Ieee16>("0x0.0", "0.0");
1337 parse_ok::<Ieee16>("0x.0", "0.0");
1338 parse_ok::<Ieee16>("0x0.", "0.0");
1339 parse_ok::<Ieee16>("0x1", "0x1.000p0");
1340 parse_ok::<Ieee16>("+0x1", "0x1.000p0");
1341 parse_ok::<Ieee16>("-0x1", "-0x1.000p0");
1342 parse_ok::<Ieee16>("0x10", "0x1.000p4");
1343 parse_ok::<Ieee16>("0x10.0", "0x1.000p4");
1344 parse_err::<Ieee16>("0.", "Float must be hexadecimal");
1345 parse_err::<Ieee16>(".0", "Float must be hexadecimal");
1346 parse_err::<Ieee16>("0", "Float must be hexadecimal");
1347 parse_err::<Ieee16>("-0", "Float must be hexadecimal");
1348 parse_err::<Ieee16>(".", "Float must be hexadecimal");
1349 parse_err::<Ieee16>("", "Float must be hexadecimal");
1350 parse_err::<Ieee16>("-", "Float must be hexadecimal");
1351 parse_err::<Ieee16>("0x", "No digits");
1352 parse_err::<Ieee16>("0x..", "Multiple radix points");
1353
1354 parse_ok::<Ieee16>("0x0.ffe", "0x1.ffcp-1");
1356 parse_ok::<Ieee16>("0x1.ffc", "0x1.ffcp0");
1357 parse_ok::<Ieee16>("0x3.ff8", "0x1.ffcp1");
1358 parse_ok::<Ieee16>("0x7.ff", "0x1.ffcp2");
1359 parse_ok::<Ieee16>("0xf.fe", "0x1.ffcp3");
1360 parse_err::<Ieee16>("0x1.ffe", "Too many significant bits");
1361 parse_err::<Ieee16>("0x1.ffc00000000000000000000000000000", "Too many digits");
1362
1363 parse_ok::<Ieee16>("0x1p3", "0x1.000p3");
1365 parse_ok::<Ieee16>("0x1p-3", "0x1.000p-3");
1366 parse_ok::<Ieee16>("0x1.0p3", "0x1.000p3");
1367 parse_ok::<Ieee16>("0x2.0p3", "0x1.000p4");
1368 parse_ok::<Ieee16>("0x1.0p15", "0x1.000p15");
1369 parse_ok::<Ieee16>("0x1.0p-14", "0x1.000p-14");
1370 parse_ok::<Ieee16>("0x0.1p-10", "0x1.000p-14");
1371 parse_err::<Ieee16>("0x2.0p15", "Magnitude too large");
1372
1373 parse_ok::<Ieee16>("0x1.0p-15", "0x0.800p-14");
1375 parse_ok::<Ieee16>("0x1.0p-24", "0x0.004p-14");
1376 parse_ok::<Ieee16>("0x0.004p-14", "0x0.004p-14");
1377 parse_err::<Ieee16>("0x0.102p-14", "Subnormal underflow");
1378 parse_err::<Ieee16>("0x1.8p-24", "Subnormal underflow");
1379 parse_err::<Ieee16>("0x1.0p-25", "Magnitude too small");
1380
1381 parse_ok::<Ieee16>("Inf", "+Inf");
1383 parse_ok::<Ieee16>("+Inf", "+Inf");
1384 parse_ok::<Ieee16>("-Inf", "-Inf");
1385 parse_ok::<Ieee16>("NaN", "+NaN");
1386 parse_ok::<Ieee16>("+NaN", "+NaN");
1387 parse_ok::<Ieee16>("-NaN", "-NaN");
1388 parse_ok::<Ieee16>("NaN:0x0", "+NaN");
1389 parse_err::<Ieee16>("NaN:", "Float must be hexadecimal");
1390 parse_err::<Ieee16>("NaN:0", "Float must be hexadecimal");
1391 parse_err::<Ieee16>("NaN:0x", "Invalid NaN payload");
1392 parse_ok::<Ieee16>("NaN:0x001", "+NaN:0x1");
1393 parse_ok::<Ieee16>("NaN:0x101", "+NaN:0x101");
1394 parse_err::<Ieee16>("NaN:0x301", "Invalid NaN payload");
1395 parse_ok::<Ieee16>("sNaN:0x1", "+sNaN:0x1");
1396 parse_err::<Ieee16>("sNaN:0x0", "Invalid sNaN payload");
1397 parse_ok::<Ieee16>("sNaN:0x101", "+sNaN:0x101");
1398 parse_err::<Ieee16>("sNaN:0x301", "Invalid sNaN payload");
1399 }
1400
1401 #[test]
1402 fn pow2_ieee16() {
1403 assert_eq!(Ieee16::pow2(0).to_string(), "0x1.000p0");
1404 assert_eq!(Ieee16::pow2(1).to_string(), "0x1.000p1");
1405 assert_eq!(Ieee16::pow2(-1).to_string(), "0x1.000p-1");
1406 assert_eq!(Ieee16::pow2(15).to_string(), "0x1.000p15");
1407 assert_eq!(Ieee16::pow2(-14).to_string(), "0x1.000p-14");
1408
1409 assert_eq!((-Ieee16::pow2(1)).to_string(), "-0x1.000p1");
1410 }
1411
1412 #[test]
1413 fn fcvt_to_sint_negative_overflow_ieee16() {
1414 let n = 8;
1421 assert_eq!(
1422 "-0x1.020p7",
1423 Ieee16::fcvt_to_sint_negative_overflow(n).to_string()
1424 );
1425 }
1426
1427 #[test]
1428 fn format_ieee32() {
1429 assert_eq!(Ieee32::with_float(0.0).to_string(), "0.0");
1430 assert_eq!(Ieee32::with_float(-0.0).to_string(), "-0.0");
1431 assert_eq!(Ieee32::with_float(1.0).to_string(), "0x1.000000p0");
1432 assert_eq!(Ieee32::with_float(1.5).to_string(), "0x1.800000p0");
1433 assert_eq!(Ieee32::with_float(0.5).to_string(), "0x1.000000p-1");
1434 assert_eq!(
1435 Ieee32::with_float(f32::EPSILON).to_string(),
1436 "0x1.000000p-23"
1437 );
1438 assert_eq!(Ieee32::with_float(f32::MIN).to_string(), "-0x1.fffffep127");
1439 assert_eq!(Ieee32::with_float(f32::MAX).to_string(), "0x1.fffffep127");
1440 assert_eq!(
1442 Ieee32::with_float(f32::MIN_POSITIVE).to_string(),
1443 "0x1.000000p-126"
1444 );
1445 assert_eq!(
1447 Ieee32::with_float(f32::MIN_POSITIVE / 2.0).to_string(),
1448 "0x0.800000p-126"
1449 );
1450 assert_eq!(
1451 Ieee32::with_float(f32::MIN_POSITIVE * f32::EPSILON).to_string(),
1452 "0x0.000002p-126"
1453 );
1454 assert_eq!(Ieee32::with_float(f32::INFINITY).to_string(), "+Inf");
1455 assert_eq!(Ieee32::with_float(f32::NEG_INFINITY).to_string(), "-Inf");
1456 assert_eq!(Ieee32::with_float(f32::NAN).to_string(), "+NaN");
1457 assert_eq!(Ieee32::with_float(-f32::NAN).to_string(), "-NaN");
1458 assert_eq!(Ieee32::with_bits(0x7fc00001).to_string(), "+NaN:0x1");
1460 assert_eq!(Ieee32::with_bits(0x7ff00001).to_string(), "+NaN:0x300001");
1461 assert_eq!(Ieee32::with_bits(0x7f800001).to_string(), "+sNaN:0x1");
1463 assert_eq!(Ieee32::with_bits(0x7fa00001).to_string(), "+sNaN:0x200001");
1464 }
1465
1466 #[test]
1467 fn parse_ieee32() {
1468 parse_ok::<Ieee32>("0.0", "0.0");
1469 parse_ok::<Ieee32>("+0.0", "0.0");
1470 parse_ok::<Ieee32>("-0.0", "-0.0");
1471 parse_ok::<Ieee32>("0x0", "0.0");
1472 parse_ok::<Ieee32>("0x0.0", "0.0");
1473 parse_ok::<Ieee32>("0x.0", "0.0");
1474 parse_ok::<Ieee32>("0x0.", "0.0");
1475 parse_ok::<Ieee32>("0x1", "0x1.000000p0");
1476 parse_ok::<Ieee32>("+0x1", "0x1.000000p0");
1477 parse_ok::<Ieee32>("-0x1", "-0x1.000000p0");
1478 parse_ok::<Ieee32>("0x10", "0x1.000000p4");
1479 parse_ok::<Ieee32>("0x10.0", "0x1.000000p4");
1480 parse_err::<Ieee32>("0.", "Float must be hexadecimal");
1481 parse_err::<Ieee32>(".0", "Float must be hexadecimal");
1482 parse_err::<Ieee32>("0", "Float must be hexadecimal");
1483 parse_err::<Ieee32>("-0", "Float must be hexadecimal");
1484 parse_err::<Ieee32>(".", "Float must be hexadecimal");
1485 parse_err::<Ieee32>("", "Float must be hexadecimal");
1486 parse_err::<Ieee32>("-", "Float must be hexadecimal");
1487 parse_err::<Ieee32>("0x", "No digits");
1488 parse_err::<Ieee32>("0x..", "Multiple radix points");
1489
1490 parse_ok::<Ieee32>("0x0.ffffff", "0x1.fffffep-1");
1492 parse_ok::<Ieee32>("0x1.fffffe", "0x1.fffffep0");
1493 parse_ok::<Ieee32>("0x3.fffffc", "0x1.fffffep1");
1494 parse_ok::<Ieee32>("0x7.fffff8", "0x1.fffffep2");
1495 parse_ok::<Ieee32>("0xf.fffff0", "0x1.fffffep3");
1496 parse_err::<Ieee32>("0x1.ffffff", "Too many significant bits");
1497 parse_err::<Ieee32>("0x1.fffffe00000000000000000000000000", "Too many digits");
1498
1499 parse_ok::<Ieee32>("0x1p3", "0x1.000000p3");
1501 parse_ok::<Ieee32>("0x1p-3", "0x1.000000p-3");
1502 parse_ok::<Ieee32>("0x1.0p3", "0x1.000000p3");
1503 parse_ok::<Ieee32>("0x2.0p3", "0x1.000000p4");
1504 parse_ok::<Ieee32>("0x1.0p127", "0x1.000000p127");
1505 parse_ok::<Ieee32>("0x1.0p-126", "0x1.000000p-126");
1506 parse_ok::<Ieee32>("0x0.1p-122", "0x1.000000p-126");
1507 parse_err::<Ieee32>("0x2.0p127", "Magnitude too large");
1508
1509 parse_ok::<Ieee32>("0x1.0p-127", "0x0.800000p-126");
1511 parse_ok::<Ieee32>("0x1.0p-149", "0x0.000002p-126");
1512 parse_ok::<Ieee32>("0x0.000002p-126", "0x0.000002p-126");
1513 parse_err::<Ieee32>("0x0.100001p-126", "Subnormal underflow");
1514 parse_err::<Ieee32>("0x1.8p-149", "Subnormal underflow");
1515 parse_err::<Ieee32>("0x1.0p-150", "Magnitude too small");
1516
1517 parse_ok::<Ieee32>("Inf", "+Inf");
1519 parse_ok::<Ieee32>("+Inf", "+Inf");
1520 parse_ok::<Ieee32>("-Inf", "-Inf");
1521 parse_ok::<Ieee32>("NaN", "+NaN");
1522 parse_ok::<Ieee32>("+NaN", "+NaN");
1523 parse_ok::<Ieee32>("-NaN", "-NaN");
1524 parse_ok::<Ieee32>("NaN:0x0", "+NaN");
1525 parse_err::<Ieee32>("NaN:", "Float must be hexadecimal");
1526 parse_err::<Ieee32>("NaN:0", "Float must be hexadecimal");
1527 parse_err::<Ieee32>("NaN:0x", "Invalid NaN payload");
1528 parse_ok::<Ieee32>("NaN:0x000001", "+NaN:0x1");
1529 parse_ok::<Ieee32>("NaN:0x300001", "+NaN:0x300001");
1530 parse_err::<Ieee32>("NaN:0x400001", "Invalid NaN payload");
1531 parse_ok::<Ieee32>("sNaN:0x1", "+sNaN:0x1");
1532 parse_err::<Ieee32>("sNaN:0x0", "Invalid sNaN payload");
1533 parse_ok::<Ieee32>("sNaN:0x200001", "+sNaN:0x200001");
1534 parse_err::<Ieee32>("sNaN:0x400001", "Invalid sNaN payload");
1535 }
1536
1537 #[test]
1538 fn pow2_ieee32() {
1539 assert_eq!(Ieee32::pow2(0).to_string(), "0x1.000000p0");
1540 assert_eq!(Ieee32::pow2(1).to_string(), "0x1.000000p1");
1541 assert_eq!(Ieee32::pow2(-1).to_string(), "0x1.000000p-1");
1542 assert_eq!(Ieee32::pow2(127).to_string(), "0x1.000000p127");
1543 assert_eq!(Ieee32::pow2(-126).to_string(), "0x1.000000p-126");
1544
1545 assert_eq!((-Ieee32::pow2(1)).to_string(), "-0x1.000000p1");
1546 }
1547
1548 #[test]
1549 fn fcvt_to_sint_negative_overflow_ieee32() {
1550 for n in [8, 16] {
1551 assert_eq!(
1552 -((1u32 << (n - 1)) as f32) - 1.0,
1553 Ieee32::fcvt_to_sint_negative_overflow(n).as_f32(),
1554 "n = {n}"
1555 );
1556 }
1557 }
1558
1559 #[test]
1560 fn format_ieee64() {
1561 assert_eq!(Ieee64::with_float(0.0).to_string(), "0.0");
1562 assert_eq!(Ieee64::with_float(-0.0).to_string(), "-0.0");
1563 assert_eq!(Ieee64::with_float(1.0).to_string(), "0x1.0000000000000p0");
1564 assert_eq!(Ieee64::with_float(1.5).to_string(), "0x1.8000000000000p0");
1565 assert_eq!(Ieee64::with_float(0.5).to_string(), "0x1.0000000000000p-1");
1566 assert_eq!(
1567 Ieee64::with_float(f64::EPSILON).to_string(),
1568 "0x1.0000000000000p-52"
1569 );
1570 assert_eq!(
1571 Ieee64::with_float(f64::MIN).to_string(),
1572 "-0x1.fffffffffffffp1023"
1573 );
1574 assert_eq!(
1575 Ieee64::with_float(f64::MAX).to_string(),
1576 "0x1.fffffffffffffp1023"
1577 );
1578 assert_eq!(
1580 Ieee64::with_float(f64::MIN_POSITIVE).to_string(),
1581 "0x1.0000000000000p-1022"
1582 );
1583 assert_eq!(
1585 Ieee64::with_float(f64::MIN_POSITIVE / 2.0).to_string(),
1586 "0x0.8000000000000p-1022"
1587 );
1588 assert_eq!(
1589 Ieee64::with_float(f64::MIN_POSITIVE * f64::EPSILON).to_string(),
1590 "0x0.0000000000001p-1022"
1591 );
1592 assert_eq!(Ieee64::with_float(f64::INFINITY).to_string(), "+Inf");
1593 assert_eq!(Ieee64::with_float(f64::NEG_INFINITY).to_string(), "-Inf");
1594 assert_eq!(Ieee64::with_float(f64::NAN).to_string(), "+NaN");
1595 assert_eq!(Ieee64::with_float(-f64::NAN).to_string(), "-NaN");
1596 assert_eq!(
1598 Ieee64::with_bits(0x7ff8000000000001).to_string(),
1599 "+NaN:0x1"
1600 );
1601 assert_eq!(
1602 Ieee64::with_bits(0x7ffc000000000001).to_string(),
1603 "+NaN:0x4000000000001"
1604 );
1605 assert_eq!(
1607 Ieee64::with_bits(0x7ff0000000000001).to_string(),
1608 "+sNaN:0x1"
1609 );
1610 assert_eq!(
1611 Ieee64::with_bits(0x7ff4000000000001).to_string(),
1612 "+sNaN:0x4000000000001"
1613 );
1614 }
1615
1616 #[test]
1617 fn parse_ieee64() {
1618 parse_ok::<Ieee64>("0.0", "0.0");
1619 parse_ok::<Ieee64>("-0.0", "-0.0");
1620 parse_ok::<Ieee64>("0x0", "0.0");
1621 parse_ok::<Ieee64>("0x0.0", "0.0");
1622 parse_ok::<Ieee64>("0x.0", "0.0");
1623 parse_ok::<Ieee64>("0x0.", "0.0");
1624 parse_ok::<Ieee64>("0x1", "0x1.0000000000000p0");
1625 parse_ok::<Ieee64>("-0x1", "-0x1.0000000000000p0");
1626 parse_ok::<Ieee64>("0x10", "0x1.0000000000000p4");
1627 parse_ok::<Ieee64>("0x10.0", "0x1.0000000000000p4");
1628 parse_err::<Ieee64>("0.", "Float must be hexadecimal");
1629 parse_err::<Ieee64>(".0", "Float must be hexadecimal");
1630 parse_err::<Ieee64>("0", "Float must be hexadecimal");
1631 parse_err::<Ieee64>("-0", "Float must be hexadecimal");
1632 parse_err::<Ieee64>(".", "Float must be hexadecimal");
1633 parse_err::<Ieee64>("", "Float must be hexadecimal");
1634 parse_err::<Ieee64>("-", "Float must be hexadecimal");
1635 parse_err::<Ieee64>("0x", "No digits");
1636 parse_err::<Ieee64>("0x..", "Multiple radix points");
1637
1638 parse_ok::<Ieee64>("0x0.fffffffffffff8", "0x1.fffffffffffffp-1");
1640 parse_ok::<Ieee64>("0x1.fffffffffffff", "0x1.fffffffffffffp0");
1641 parse_ok::<Ieee64>("0x3.ffffffffffffe", "0x1.fffffffffffffp1");
1642 parse_ok::<Ieee64>("0x7.ffffffffffffc", "0x1.fffffffffffffp2");
1643 parse_ok::<Ieee64>("0xf.ffffffffffff8", "0x1.fffffffffffffp3");
1644 parse_err::<Ieee64>("0x3.fffffffffffff", "Too many significant bits");
1645 parse_err::<Ieee64>("0x001.fffffe000000000000000000000000", "Too many digits");
1646
1647 parse_ok::<Ieee64>("0x1p3", "0x1.0000000000000p3");
1649 parse_ok::<Ieee64>("0x1p-3", "0x1.0000000000000p-3");
1650 parse_ok::<Ieee64>("0x1.0p3", "0x1.0000000000000p3");
1651 parse_ok::<Ieee64>("0x2.0p3", "0x1.0000000000000p4");
1652 parse_ok::<Ieee64>("0x1.0p1023", "0x1.0000000000000p1023");
1653 parse_ok::<Ieee64>("0x1.0p-1022", "0x1.0000000000000p-1022");
1654 parse_ok::<Ieee64>("0x0.1p-1018", "0x1.0000000000000p-1022");
1655 parse_err::<Ieee64>("0x2.0p1023", "Magnitude too large");
1656
1657 parse_ok::<Ieee64>("0x1.0p-1023", "0x0.8000000000000p-1022");
1659 parse_ok::<Ieee64>("0x1.0p-1074", "0x0.0000000000001p-1022");
1660 parse_ok::<Ieee64>("0x0.0000000000001p-1022", "0x0.0000000000001p-1022");
1661 parse_err::<Ieee64>("0x0.10000000000008p-1022", "Subnormal underflow");
1662 parse_err::<Ieee64>("0x1.8p-1074", "Subnormal underflow");
1663 parse_err::<Ieee64>("0x1.0p-1075", "Magnitude too small");
1664
1665 parse_ok::<Ieee64>("Inf", "+Inf");
1667 parse_ok::<Ieee64>("-Inf", "-Inf");
1668 parse_ok::<Ieee64>("NaN", "+NaN");
1669 parse_ok::<Ieee64>("-NaN", "-NaN");
1670 parse_ok::<Ieee64>("NaN:0x0", "+NaN");
1671 parse_err::<Ieee64>("NaN:", "Float must be hexadecimal");
1672 parse_err::<Ieee64>("NaN:0", "Float must be hexadecimal");
1673 parse_err::<Ieee64>("NaN:0x", "Invalid NaN payload");
1674 parse_ok::<Ieee64>("NaN:0x000001", "+NaN:0x1");
1675 parse_ok::<Ieee64>("NaN:0x4000000000001", "+NaN:0x4000000000001");
1676 parse_err::<Ieee64>("NaN:0x8000000000001", "Invalid NaN payload");
1677 parse_ok::<Ieee64>("sNaN:0x1", "+sNaN:0x1");
1678 parse_err::<Ieee64>("sNaN:0x0", "Invalid sNaN payload");
1679 parse_ok::<Ieee64>("sNaN:0x4000000000001", "+sNaN:0x4000000000001");
1680 parse_err::<Ieee64>("sNaN:0x8000000000001", "Invalid sNaN payload");
1681 }
1682
1683 #[test]
1684 fn pow2_ieee64() {
1685 assert_eq!(Ieee64::pow2(0).to_string(), "0x1.0000000000000p0");
1686 assert_eq!(Ieee64::pow2(1).to_string(), "0x1.0000000000000p1");
1687 assert_eq!(Ieee64::pow2(-1).to_string(), "0x1.0000000000000p-1");
1688 assert_eq!(Ieee64::pow2(1023).to_string(), "0x1.0000000000000p1023");
1689 assert_eq!(Ieee64::pow2(-1022).to_string(), "0x1.0000000000000p-1022");
1690
1691 assert_eq!((-Ieee64::pow2(1)).to_string(), "-0x1.0000000000000p1");
1692 }
1693
1694 #[test]
1695 fn fcvt_to_sint_negative_overflow_ieee64() {
1696 for n in [8, 16, 32] {
1697 assert_eq!(
1698 -((1u64 << (n - 1)) as f64) - 1.0,
1699 Ieee64::fcvt_to_sint_negative_overflow(n).as_f64(),
1700 "n = {n}"
1701 );
1702 }
1703 }
1704
1705 #[test]
1706 fn format_ieee128() {
1707 assert_eq!(
1708 Ieee128::with_bits(0x00000000000000000000000000000000).to_string(), "0.0"
1710 );
1711 assert_eq!(
1712 Ieee128::with_bits(0x80000000000000000000000000000000).to_string(), "-0.0"
1714 );
1715 assert_eq!(
1716 Ieee128::with_bits(0x3fff0000000000000000000000000000).to_string(), "0x1.0000000000000000000000000000p0"
1718 );
1719 assert_eq!(
1720 Ieee128::with_bits(0x3fff8000000000000000000000000000).to_string(), "0x1.8000000000000000000000000000p0"
1722 );
1723 assert_eq!(
1724 Ieee128::with_bits(0x3ffe0000000000000000000000000000).to_string(), "0x1.0000000000000000000000000000p-1"
1726 );
1727 assert_eq!(
1728 Ieee128::with_bits(0x3f8f0000000000000000000000000000).to_string(), "0x1.0000000000000000000000000000p-112"
1730 );
1731 assert_eq!(
1732 Ieee128::with_bits(0xfffeffffffffffffffffffffffffffff).to_string(), "-0x1.ffffffffffffffffffffffffffffp16383"
1734 );
1735 assert_eq!(
1736 Ieee128::with_bits(0x7ffeffffffffffffffffffffffffffff).to_string(), "0x1.ffffffffffffffffffffffffffffp16383"
1738 );
1739 assert_eq!(
1741 Ieee128::with_bits(0x00010000000000000000000000000000).to_string(), "0x1.0000000000000000000000000000p-16382"
1743 );
1744 assert_eq!(
1746 Ieee128::with_bits(0x00008000000000000000000000000000).to_string(), "0x0.8000000000000000000000000000p-16382"
1748 );
1749 assert_eq!(
1750 Ieee128::with_bits(0x00000000000000000000000000000001).to_string(), "0x0.0000000000000000000000000001p-16382"
1752 );
1753 assert_eq!(
1754 Ieee128::with_bits(0x7fff0000000000000000000000000000).to_string(), "+Inf"
1756 );
1757 assert_eq!(
1758 Ieee128::with_bits(0xffff0000000000000000000000000000).to_string(), "-Inf"
1760 );
1761 assert_eq!(
1762 Ieee128::with_bits(0x7fff8000000000000000000000000000).to_string(), "+NaN"
1764 );
1765 assert_eq!(
1766 Ieee128::with_bits(0xffff8000000000000000000000000000).to_string(), "-NaN"
1768 );
1769 assert_eq!(
1771 Ieee128::with_bits(0x7fff8000000000000000000000000001).to_string(),
1772 "+NaN:0x1"
1773 );
1774 assert_eq!(
1775 Ieee128::with_bits(0x7fffc000000000000000000000000001).to_string(),
1776 "+NaN:0x4000000000000000000000000001"
1777 );
1778 assert_eq!(
1780 Ieee128::with_bits(0x7fff0000000000000000000000000001).to_string(),
1781 "+sNaN:0x1"
1782 );
1783 assert_eq!(
1784 Ieee128::with_bits(0x7fff4000000000000000000000000001).to_string(),
1785 "+sNaN:0x4000000000000000000000000001"
1786 );
1787 }
1788
1789 #[test]
1790 fn parse_ieee128() {
1791 parse_ok::<Ieee128>("0.0", "0.0");
1792 parse_ok::<Ieee128>("-0.0", "-0.0");
1793 parse_ok::<Ieee128>("0x0", "0.0");
1794 parse_ok::<Ieee128>("0x0.0", "0.0");
1795 parse_ok::<Ieee128>("0x.0", "0.0");
1796 parse_ok::<Ieee128>("0x0.", "0.0");
1797 parse_ok::<Ieee128>("0x1", "0x1.0000000000000000000000000000p0");
1798 parse_ok::<Ieee128>("-0x1", "-0x1.0000000000000000000000000000p0");
1799 parse_ok::<Ieee128>("0x10", "0x1.0000000000000000000000000000p4");
1800 parse_ok::<Ieee128>("0x10.0", "0x1.0000000000000000000000000000p4");
1801 parse_err::<Ieee128>("0.", "Float must be hexadecimal");
1802 parse_err::<Ieee128>(".0", "Float must be hexadecimal");
1803 parse_err::<Ieee128>("0", "Float must be hexadecimal");
1804 parse_err::<Ieee128>("-0", "Float must be hexadecimal");
1805 parse_err::<Ieee128>(".", "Float must be hexadecimal");
1806 parse_err::<Ieee128>("", "Float must be hexadecimal");
1807 parse_err::<Ieee128>("-", "Float must be hexadecimal");
1808 parse_err::<Ieee128>("0x", "No digits");
1809 parse_err::<Ieee128>("0x..", "Multiple radix points");
1810
1811 parse_ok::<Ieee128>(
1813 "0x0.ffffffffffffffffffffffffffff8",
1814 "0x1.ffffffffffffffffffffffffffffp-1",
1815 );
1816 parse_ok::<Ieee128>(
1817 "0x1.ffffffffffffffffffffffffffff",
1818 "0x1.ffffffffffffffffffffffffffffp0",
1819 );
1820 parse_ok::<Ieee128>(
1821 "0x3.fffffffffffffffffffffffffffe",
1822 "0x1.ffffffffffffffffffffffffffffp1",
1823 );
1824 parse_ok::<Ieee128>(
1825 "0x7.fffffffffffffffffffffffffffc",
1826 "0x1.ffffffffffffffffffffffffffffp2",
1827 );
1828 parse_ok::<Ieee128>(
1829 "0xf.fffffffffffffffffffffffffff8",
1830 "0x1.ffffffffffffffffffffffffffffp3",
1831 );
1832 parse_err::<Ieee128>(
1833 "0x3.ffffffffffffffffffffffffffff",
1834 "Too many significant bits",
1835 );
1836 parse_err::<Ieee128>("0x001.fffffe000000000000000000000000", "Too many digits");
1837
1838 parse_ok::<Ieee128>("0x1p3", "0x1.0000000000000000000000000000p3");
1840 parse_ok::<Ieee128>("0x1p-3", "0x1.0000000000000000000000000000p-3");
1841 parse_ok::<Ieee128>("0x1.0p3", "0x1.0000000000000000000000000000p3");
1842 parse_ok::<Ieee128>("0x2.0p3", "0x1.0000000000000000000000000000p4");
1843 parse_ok::<Ieee128>("0x1.0p16383", "0x1.0000000000000000000000000000p16383");
1844 parse_ok::<Ieee128>("0x1.0p-16382", "0x1.0000000000000000000000000000p-16382");
1845 parse_ok::<Ieee128>("0x0.1p-16378", "0x1.0000000000000000000000000000p-16382");
1846 parse_err::<Ieee128>("0x2.0p16383", "Magnitude too large");
1847
1848 parse_ok::<Ieee128>("0x1.0p-16383", "0x0.8000000000000000000000000000p-16382");
1850 parse_ok::<Ieee128>("0x1.0p-16494", "0x0.0000000000000000000000000001p-16382");
1851 parse_ok::<Ieee128>(
1852 "0x0.0000000000000000000000000001p-16382",
1853 "0x0.0000000000000000000000000001p-16382",
1854 );
1855 parse_err::<Ieee128>(
1856 "0x0.10000000000000000000000000008p-16382",
1857 "Subnormal underflow",
1858 );
1859 parse_err::<Ieee128>("0x1.8p-16494", "Subnormal underflow");
1860 parse_err::<Ieee128>("0x1.0p-16495", "Magnitude too small");
1861
1862 parse_ok::<Ieee128>("Inf", "+Inf");
1864 parse_ok::<Ieee128>("-Inf", "-Inf");
1865 parse_ok::<Ieee128>("NaN", "+NaN");
1866 parse_ok::<Ieee128>("-NaN", "-NaN");
1867 parse_ok::<Ieee128>("NaN:0x0", "+NaN");
1868 parse_err::<Ieee128>("NaN:", "Float must be hexadecimal");
1869 parse_err::<Ieee128>("NaN:0", "Float must be hexadecimal");
1870 parse_err::<Ieee128>("NaN:0x", "Invalid NaN payload");
1871 parse_ok::<Ieee128>("NaN:0x000001", "+NaN:0x1");
1872 parse_ok::<Ieee128>(
1873 "NaN:0x4000000000000000000000000001",
1874 "+NaN:0x4000000000000000000000000001",
1875 );
1876 parse_err::<Ieee128>("NaN:0x8000000000000000000000000001", "Invalid NaN payload");
1877 parse_ok::<Ieee128>("sNaN:0x1", "+sNaN:0x1");
1878 parse_err::<Ieee128>("sNaN:0x0", "Invalid sNaN payload");
1879 parse_ok::<Ieee128>(
1880 "sNaN:0x4000000000000000000000000001",
1881 "+sNaN:0x4000000000000000000000000001",
1882 );
1883 parse_err::<Ieee128>(
1884 "sNaN:0x8000000000000000000000000001",
1885 "Invalid sNaN payload",
1886 );
1887 }
1888
1889 #[test]
1890 fn pow2_ieee128() {
1891 assert_eq!(
1892 Ieee128::pow2(0).to_string(),
1893 "0x1.0000000000000000000000000000p0"
1894 );
1895 assert_eq!(
1896 Ieee128::pow2(1).to_string(),
1897 "0x1.0000000000000000000000000000p1"
1898 );
1899 assert_eq!(
1900 Ieee128::pow2(-1).to_string(),
1901 "0x1.0000000000000000000000000000p-1"
1902 );
1903 assert_eq!(
1904 Ieee128::pow2(16383).to_string(),
1905 "0x1.0000000000000000000000000000p16383"
1906 );
1907 assert_eq!(
1908 Ieee128::pow2(-16382).to_string(),
1909 "0x1.0000000000000000000000000000p-16382"
1910 );
1911
1912 assert_eq!(
1913 (-Ieee128::pow2(1)).to_string(),
1914 "-0x1.0000000000000000000000000000p1"
1915 );
1916 }
1917
1918 #[test]
1919 fn fcvt_to_sint_negative_overflow_ieee128() {
1920 for (n, expected) in [
1929 (8, "-0x1.0200000000000000000000000000p7"),
1930 (16, "-0x1.0002000000000000000000000000p15"),
1931 (32, "-0x1.0000000200000000000000000000p31"),
1932 (64, "-0x1.0000000000000002000000000000p63"),
1933 ] {
1934 assert_eq!(
1935 expected,
1936 Ieee128::fcvt_to_sint_negative_overflow(n).to_string(),
1937 "n = {n}"
1938 );
1939 }
1940 }
1941}