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 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 #[must_use]
114 pub fn zero_extend_from_width(&self, bit_width: u32) -> Self {
115 debug_assert!(
116 bit_width.is_power_of_two(),
117 "{bit_width} is not a power of two"
118 );
119
120 if bit_width >= 64 {
121 return *self;
122 }
123
124 let bit_width = u64::from(bit_width);
125 let delta = 64 - bit_width;
126 let zero_extended = (self.0.cast_unsigned() << delta) >> delta;
127 Imm64(zero_extended.cast_signed())
128 }
129}
130
131impl From<Imm64> for i64 {
132 fn from(val: Imm64) -> i64 {
133 val.0
134 }
135}
136
137impl IntoBytes for Imm64 {
138 fn into_bytes(self) -> Vec<u8> {
139 self.0.to_le_bytes().to_vec()
140 }
141}
142
143impl From<i64> for Imm64 {
144 fn from(x: i64) -> Self {
145 Self(x)
146 }
147}
148
149impl Display for Imm64 {
150 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
151 let x = self.0;
152 if x < 10_000 {
153 write!(f, "{x}")
155 } else {
156 write_hex(x as u64, f)
157 }
158 }
159}
160
161fn parse_i64(s: &str) -> Result<i64, &'static str> {
163 let negative = s.starts_with('-');
164 let s2 = if negative || s.starts_with('+') {
165 &s[1..]
166 } else {
167 s
168 };
169
170 let mut value = parse_u64(s2)?;
171
172 if negative {
174 value = value.wrapping_neg();
175 if value as i64 > 0 {
177 return Err("Negative number too small");
178 }
179 }
180 Ok(value as i64)
181}
182
183impl FromStr for Imm64 {
184 type Err = &'static str;
185
186 fn from_str(s: &str) -> Result<Self, &'static str> {
188 parse_i64(s).map(Self::new)
189 }
190}
191
192#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
197#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
198pub struct Uimm64(u64);
199
200impl Uimm64 {
201 pub fn new(x: u64) -> Self {
203 Self(x)
204 }
205
206 pub fn wrapping_neg(self) -> Self {
208 Self(self.0.wrapping_neg())
209 }
210}
211
212impl From<Uimm64> for u64 {
213 fn from(val: Uimm64) -> u64 {
214 val.0
215 }
216}
217
218impl From<u64> for Uimm64 {
219 fn from(x: u64) -> Self {
220 Self(x)
221 }
222}
223
224fn write_hex(x: u64, f: &mut Formatter) -> fmt::Result {
231 let mut pos = (64 - x.leading_zeros() - 1) & 0xf0;
232 write!(f, "0x{:04x}", (x >> pos) & 0xffff)?;
233 while pos > 0 {
234 pos -= 16;
235 write!(f, "_{:04x}", (x >> pos) & 0xffff)?;
236 }
237 Ok(())
238}
239
240impl Display for Uimm64 {
241 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
242 let x = self.0;
243 if x < 10_000 {
244 write!(f, "{x}")
246 } else {
247 write_hex(x, f)
248 }
249 }
250}
251
252fn parse_u64(s: &str) -> Result<u64, &'static str> {
254 let mut value: u64 = 0;
255 let mut digits = 0;
256
257 if s.starts_with("-0x") {
258 return Err("Invalid character in hexadecimal number");
259 } else if let Some(num) = s.strip_prefix("0x") {
260 for ch in num.chars() {
262 match ch.to_digit(16) {
263 Some(digit) => {
264 digits += 1;
265 if digits > 16 {
266 return Err("Too many hexadecimal digits");
267 }
268 value = (value << 4) | u64::from(digit);
270 }
271 None => {
272 if ch != '_' {
274 return Err("Invalid character in hexadecimal number");
275 }
276 }
277 }
278 }
279 } else {
280 for ch in s.chars() {
282 match ch.to_digit(10) {
283 Some(digit) => {
284 digits += 1;
285 match value.checked_mul(10) {
286 None => return Err("Too large decimal number"),
287 Some(v) => value = v,
288 }
289 match value.checked_add(u64::from(digit)) {
290 None => return Err("Too large decimal number"),
291 Some(v) => value = v,
292 }
293 }
294 None => {
295 if ch != '_' {
297 return Err("Invalid character in decimal number");
298 }
299 }
300 }
301 }
302 }
303
304 if digits == 0 {
305 return Err("No digits in number");
306 }
307
308 Ok(value)
309}
310
311impl FromStr for Uimm64 {
312 type Err = &'static str;
313
314 fn from_str(s: &str) -> Result<Self, &'static str> {
316 parse_u64(s).map(Self::new)
317 }
318}
319
320pub type Uimm8 = u8;
324
325#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
329#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
330pub struct Uimm32(u32);
331
332impl From<Uimm32> for u32 {
333 fn from(val: Uimm32) -> u32 {
334 val.0
335 }
336}
337
338impl From<Uimm32> for u64 {
339 fn from(val: Uimm32) -> u64 {
340 val.0.into()
341 }
342}
343
344impl From<Uimm32> for i64 {
345 fn from(val: Uimm32) -> i64 {
346 i64::from(val.0)
347 }
348}
349
350impl From<u32> for Uimm32 {
351 fn from(x: u32) -> Self {
352 Self(x)
353 }
354}
355
356impl Display for Uimm32 {
357 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
358 if self.0 < 10_000 {
359 write!(f, "{}", self.0)
360 } else {
361 write_hex(u64::from(self.0), f)
362 }
363 }
364}
365
366impl FromStr for Uimm32 {
367 type Err = &'static str;
368
369 fn from_str(s: &str) -> Result<Self, &'static str> {
371 parse_i64(s).and_then(|x| {
372 if 0 <= x && x <= i64::from(u32::MAX) {
373 Ok(Self(x as u32))
374 } else {
375 Err("Uimm32 out of range")
376 }
377 })
378 }
379}
380
381#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
385#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
386pub struct V128Imm(pub [u8; 16]);
387
388impl V128Imm {
389 pub fn bytes(&self) -> impl Iterator<Item = &u8> {
391 self.0.iter()
392 }
393
394 pub fn to_vec(self) -> Vec<u8> {
396 self.0.to_vec()
397 }
398
399 pub fn as_slice(&self) -> &[u8] {
401 &self.0[..]
402 }
403}
404
405impl From<&[u8]> for V128Imm {
406 fn from(slice: &[u8]) -> Self {
407 assert_eq!(slice.len(), 16);
408 let mut buffer = [0; 16];
409 buffer.copy_from_slice(slice);
410 Self(buffer)
411 }
412}
413
414impl From<u128> for V128Imm {
415 fn from(val: u128) -> Self {
416 V128Imm(val.to_le_bytes())
417 }
418}
419
420#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
425#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
426pub struct Offset32(i32);
427
428impl Offset32 {
429 pub fn new(x: i32) -> Self {
431 Self(x)
432 }
433
434 pub fn try_from_i64(x: i64) -> Option<Self> {
436 let x = i32::try_from(x).ok()?;
437 Some(Self::new(x))
438 }
439
440 pub fn try_add_i64(self, x: i64) -> Option<Self> {
442 let x = i32::try_from(x).ok()?;
443 let ret = self.0.checked_add(x)?;
444 Some(Self::new(ret))
445 }
446}
447
448impl From<Offset32> for i32 {
449 fn from(val: Offset32) -> i32 {
450 val.0
451 }
452}
453
454impl From<Offset32> for i64 {
455 fn from(val: Offset32) -> i64 {
456 i64::from(val.0)
457 }
458}
459
460impl From<i32> for Offset32 {
461 fn from(x: i32) -> Self {
462 Self(x)
463 }
464}
465
466impl From<u8> for Offset32 {
467 fn from(val: u8) -> Offset32 {
468 Self(val.into())
469 }
470}
471
472impl Display for Offset32 {
473 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
474 if self.0 == 0 {
476 return Ok(());
477 }
478
479 write!(f, "{}", if self.0 < 0 { '-' } else { '+' })?;
481
482 let val = i64::from(self.0).abs();
483 if val < 10_000 {
484 write!(f, "{val}")
485 } else {
486 write_hex(val as u64, f)
487 }
488 }
489}
490
491impl FromStr for Offset32 {
492 type Err = &'static str;
493
494 fn from_str(s: &str) -> Result<Self, &'static str> {
496 if !(s.starts_with('-') || s.starts_with('+')) {
497 return Err("Offset must begin with sign");
498 }
499 parse_i64(s).and_then(|x| {
500 if i64::from(i32::MIN) <= x && x <= i64::from(i32::MAX) {
501 Ok(Self::new(x as i32))
502 } else {
503 Err("Offset out of range")
504 }
505 })
506 }
507}
508
509macro_rules! ignore {
511 ($($t:tt)*) => {};
512}
513
514macro_rules! ieee_float {
515 (
516 name = $name:ident,
517 bits = $bits:literal,
518 significand_bits = $significand_bits:literal,
519 bits_ty = $bits_ty:ident,
520 float_ty = $float_ty:ident,
521 $(as_float = $as_float:ident,)?
522 $(rust_type_not_stable = $rust_type_not_stable:ident,)?
523 ) => {
524 #[doc = concat!("binary", stringify!($bits))]
526 #[doc = stringify!($bits_ty)]
528 #[doc = stringify!($float_ty)]
532 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
540 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
541 #[repr(C)]
542 pub struct $name {
543 bits: $bits_ty
544 }
545
546 impl $name {
547 const BITS: u8 = $bits;
548 const SIGNIFICAND_BITS: u8 = $significand_bits;
549 const EXPONENT_BITS: u8 = Self::BITS - Self::SIGNIFICAND_BITS - 1;
550 const SIGN_MASK: $bits_ty = 1 << (Self::EXPONENT_BITS + Self::SIGNIFICAND_BITS);
551 const SIGNIFICAND_MASK: $bits_ty = $bits_ty::MAX >> (Self::EXPONENT_BITS + 1);
552 const EXPONENT_MASK: $bits_ty = !Self::SIGN_MASK & !Self::SIGNIFICAND_MASK;
553 pub const NAN: Self = Self::with_bits(Self::EXPONENT_MASK | (1 << (Self::SIGNIFICAND_BITS - 1)));
555
556 #[doc = concat!("`", stringify!($name), "`")]
558 pub const fn with_bits(bits: $bits_ty) -> Self {
560 Self { bits }
561 }
562
563 pub fn bits(self) -> $bits_ty {
565 self.bits
566 }
567
568 $(
569 #[doc = concat!("`", stringify!($name), "`")]
571 pub fn with_float(x: $float_ty) -> Self {
573 Self::with_bits(x.to_bits())
574 }
575
576 #[doc = concat!("`", stringify!($float_ty), "`.")]
578 pub fn $as_float(self) -> $float_ty {
579 $float_ty::from_bits(self.bits())
580 }
581 )?
582
583 pub fn abs(self) -> Self {
585 Self::with_bits(self.bits() & !Self::SIGN_MASK)
586 }
587
588 pub fn copysign(self, sign: Self) -> Self {
590 Self::with_bits((self.bits() & !Self::SIGN_MASK) | (sign.bits() & Self::SIGN_MASK))
591 }
592
593 pub fn minimum(self, other: Self) -> Self {
595 if self.is_nan() || other.is_nan() {
597 Self::NAN
598 } else if self.is_zero() && other.is_zero() {
599 if self.is_negative() {
600 self
601 } else {
602 other
603 }
604 } else if self <= other {
605 self
606 } else {
607 other
608 }
609 }
610
611 pub fn maximum(self, other: Self) -> Self {
613 if self.is_nan() || other.is_nan() {
615 Self::NAN
616 } else if self.is_zero() && other.is_zero() {
617 if self.is_positive() {
618 self
619 } else {
620 other
621 }
622 } else if self >= other {
623 self
624 } else {
625 other
626 }
627 }
628
629 #[doc = concat!("`", stringify!($name), "`")]
631 pub fn pow2<I: Into<i32>>(n: I) -> Self {
633 let n = n.into();
634 let w = Self::EXPONENT_BITS;
635 let t = Self::SIGNIFICAND_BITS;
636 let bias = (1 << (w - 1)) - 1;
637 let exponent = n + bias;
638 assert!(exponent > 0, "Underflow n={}", n);
639 assert!(exponent < (1 << w) + 1, "Overflow n={}", n);
640 Self::with_bits((exponent as $bits_ty) << t)
641 }
642
643 #[doc = concat!("`", stringify!($name), "`")]
645 #[doc = concat!("`", stringify!($float_ty), "`")]
647 pub fn fcvt_to_sint_negative_overflow<I: Into<i32>>(n: I) -> Self {
649 let n = n.into();
650 debug_assert!(n < i32::from(Self::BITS));
651 debug_assert!(i32::from(Self::SIGNIFICAND_BITS) + 1 - n < i32::from(Self::BITS));
652 Self::with_bits((1 << (Self::BITS - 1)) | Self::pow2(n - 1).bits() | (1 << (i32::from(Self::SIGNIFICAND_BITS) + 1 - n)))
653 }
654
655 #[doc = concat!("`", stringify!($name), "`,")]
657 pub fn is_nan(self) -> bool {
659 self.abs().bits() > Self::EXPONENT_MASK
660 }
661
662 pub fn is_positive(self) -> bool {
664 !self.is_negative()
665 }
666
667 pub fn is_negative(self) -> bool {
669 self.bits() & Self::SIGN_MASK == Self::SIGN_MASK
670 }
671
672 pub fn is_zero(self) -> bool {
674 self.abs().bits() == 0
675 }
676
677 pub fn non_nan(self) -> Option<Self> {
679 Some(self).filter(|f| !f.is_nan())
680 }
681
682 $(
683 pub fn sqrt(self) -> Self {
685 Self::with_float(self.$as_float().sqrt())
686 }
687
688 pub fn ceil(self) -> Self {
690 Self::with_float(self.$as_float().ceil())
691 }
692
693 pub fn floor(self) -> Self {
695 Self::with_float(self.$as_float().floor())
696 }
697
698 pub fn trunc(self) -> Self {
700 Self::with_float(self.$as_float().trunc())
701 }
702
703 pub fn round_ties_even(self) -> Self {
706 Self::with_float(self.$as_float().round_ties_even())
707 }
708 )?
709 }
710
711 impl PartialOrd for $name {
712 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
713 $(self.$as_float().partial_cmp(&rhs.$as_float()))?
714 $(
715 ignore!($rust_type_not_stable);
716 if self.is_nan() || rhs.is_nan() {
718 return None;
720 }
721 if self.is_zero() || rhs.is_zero() {
722 return Some(Ordering::Equal);
724 }
725 let lhs_positive = self.is_positive();
726 let rhs_positive = rhs.is_positive();
727 if lhs_positive != rhs_positive {
728 return lhs_positive.partial_cmp(&rhs_positive);
730 }
731 if lhs_positive {
733 self.bits().partial_cmp(&rhs.bits())
734 } else {
735 rhs.bits().partial_cmp(&self.bits())
737 }
738 )?
739 }
740 }
741
742 impl Display for $name {
743 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
744 format_float(u128::from(self.bits()), Self::EXPONENT_BITS, Self::SIGNIFICAND_BITS, f)
745 }
746 }
747
748 impl FromStr for $name {
749 type Err = &'static str;
750
751 fn from_str(s: &str) -> Result<Self, &'static str> {
752 match parse_float(s, Self::EXPONENT_BITS, Self::SIGNIFICAND_BITS) {
753 Ok(b) => Ok(Self::with_bits(b.try_into().unwrap())),
754 Err(s) => Err(s),
755 }
756 }
757 }
758
759 impl IntoBytes for $name {
760 fn into_bytes(self) -> Vec<u8> {
761 self.bits().to_le_bytes().to_vec()
762 }
763 }
764
765 impl Neg for $name {
766 type Output = Self;
767
768 fn neg(self) -> Self {
769 Self::with_bits(self.bits() ^ Self::SIGN_MASK)
770 }
771 }
772
773
774
775 $(
776 impl From<$float_ty> for $name {
777 fn from(x: $float_ty) -> Self {
778 Self::with_float(x)
779 }
780 }
781
782 impl Add for $name {
783 type Output = Self;
784
785 fn add(self, rhs: Self) -> Self {
786 Self::with_float(self.$as_float() + rhs.$as_float())
787 }
788 }
789
790 impl Sub for $name {
791 type Output = Self;
792
793 fn sub(self, rhs: Self) -> Self {
794 Self::with_float(self.$as_float() - rhs.$as_float())
795 }
796 }
797
798 impl Mul for $name {
799 type Output = Self;
800
801 fn mul(self, rhs: Self) -> Self {
802 Self::with_float(self.$as_float() * rhs.$as_float())
803 }
804 }
805
806 impl Div for $name {
807 type Output = Self;
808
809 fn div(self, rhs: Self) -> Self::Output {
810 Self::with_float(self.$as_float() / rhs.$as_float())
811 }
812 }
813 )?
814
815 impl BitAnd for $name {
816 type Output = Self;
817
818 fn bitand(self, rhs: Self) -> Self {
819 Self::with_bits(self.bits() & rhs.bits())
820 }
821 }
822
823 impl BitOr for $name {
824 type Output = Self;
825
826 fn bitor(self, rhs: Self) -> Self {
827 Self::with_bits(self.bits() | rhs.bits())
828 }
829 }
830
831 impl BitXor for $name {
832 type Output = Self;
833
834 fn bitxor(self, rhs: Self) -> Self {
835 Self::with_bits(self.bits() ^ rhs.bits())
836 }
837 }
838
839 impl Not for $name {
840 type Output = Self;
841
842 fn not(self) -> Self {
843 Self::with_bits(!self.bits())
844 }
845 }
846 };
847}
848
849ieee_float! {
850 name = Ieee16,
851 bits = 16,
852 significand_bits = 10,
853 bits_ty = u16,
854 float_ty = f16,
855 rust_type_not_stable = rust_type_not_stable,
856}
857
858ieee_float! {
859 name = Ieee32,
860 bits = 32,
861 significand_bits = 23,
862 bits_ty = u32,
863 float_ty = f32,
864 as_float = as_f32,
865}
866
867ieee_float! {
868 name = Ieee64,
869 bits = 64,
870 significand_bits = 52,
871 bits_ty = u64,
872 float_ty = f64,
873 as_float = as_f64,
874}
875
876ieee_float! {
877 name = Ieee128,
878 bits = 128,
879 significand_bits = 112,
880 bits_ty = u128,
881 float_ty = f128,
882 rust_type_not_stable = rust_type_not_stable,
883}
884
885fn format_float(bits: u128, w: u8, t: u8, f: &mut Formatter) -> fmt::Result {
896 debug_assert!(w > 0 && w <= 16, "Invalid exponent range");
897 debug_assert!(1 + w + t <= 128, "Too large IEEE format for u128");
898 debug_assert!((t + w + 1).is_power_of_two(), "Unexpected IEEE format size");
899
900 let max_e_bits = (1u128 << w) - 1;
901 let t_bits = bits & ((1u128 << t) - 1); let e_bits = (bits >> t) & max_e_bits; let sign_bit = (bits >> (w + t)) & 1;
904
905 let bias: i32 = (1 << (w - 1)) - 1;
906 let e = e_bits as i32 - bias; let emin = 1 - bias; let digits = (t + 3) / 4;
911 let left_t_bits = t_bits << (4 * digits - t);
913
914 if sign_bit != 0 {
916 write!(f, "-")?;
917 }
918
919 if e_bits == 0 {
920 if t_bits == 0 {
921 write!(f, "0.0")
923 } else {
924 write!(
926 f,
927 "0x0.{0:01$x}p{2}",
928 left_t_bits,
929 usize::from(digits),
930 emin
931 )
932 }
933 } else if e_bits == max_e_bits {
934 if sign_bit == 0 {
937 write!(f, "+")?;
938 }
939 if t_bits == 0 {
940 write!(f, "Inf")
942 } else {
943 let payload = t_bits & ((1 << (t - 1)) - 1);
945 if t_bits & (1 << (t - 1)) != 0 {
946 if payload != 0 {
948 write!(f, "NaN:0x{payload:x}")
949 } else {
950 write!(f, "NaN")
951 }
952 } else {
953 write!(f, "sNaN:0x{payload:x}")
955 }
956 }
957 } else {
958 write!(f, "0x1.{0:01$x}p{2}", left_t_bits, usize::from(digits), e)
960 }
961}
962
963fn parse_float(s: &str, w: u8, t: u8) -> Result<u128, &'static str> {
971 debug_assert!(w > 0 && w <= 16, "Invalid exponent range");
972 debug_assert!(1 + w + t <= 128, "Too large IEEE format for u128");
973 debug_assert!((t + w + 1).is_power_of_two(), "Unexpected IEEE format size");
974
975 let (sign_bit, s2) = if let Some(num) = s.strip_prefix('-') {
976 (1u128 << (t + w), num)
977 } else if let Some(num) = s.strip_prefix('+') {
978 (0, num)
979 } else {
980 (0, s)
981 };
982
983 if !s2.starts_with("0x") {
984 let max_e_bits = ((1u128 << w) - 1) << t;
985 let quiet_bit = 1u128 << (t - 1);
986
987 if s2 == "0.0" {
989 return Ok(sign_bit);
990 }
991
992 if s2 == "Inf" {
993 return Ok(sign_bit | max_e_bits);
995 }
996 if s2 == "NaN" {
997 return Ok(sign_bit | max_e_bits | quiet_bit);
999 }
1000 if let Some(nan) = s2.strip_prefix("NaN:0x") {
1001 return match u128::from_str_radix(nan, 16) {
1003 Ok(payload) if payload < quiet_bit => {
1004 Ok(sign_bit | max_e_bits | quiet_bit | payload)
1005 }
1006 _ => Err("Invalid NaN payload"),
1007 };
1008 }
1009 if let Some(nan) = s2.strip_prefix("sNaN:0x") {
1010 return match u128::from_str_radix(nan, 16) {
1012 Ok(payload) if 0 < payload && payload < quiet_bit => {
1013 Ok(sign_bit | max_e_bits | payload)
1014 }
1015 _ => Err("Invalid sNaN payload"),
1016 };
1017 }
1018
1019 return Err("Float must be hexadecimal");
1020 }
1021 let s3 = &s2[2..];
1022
1023 let mut digits = 0u8;
1024 let mut digits_before_period: Option<u8> = None;
1025 let mut significand = 0u128;
1026 let mut exponent = 0i32;
1027
1028 for (idx, ch) in s3.char_indices() {
1029 match ch {
1030 '.' => {
1031 if digits_before_period != None {
1033 return Err("Multiple radix points");
1034 } else {
1035 digits_before_period = Some(digits);
1036 }
1037 }
1038 'p' => {
1039 let exp_str = &s3[1 + idx..];
1041 match exp_str.parse::<i16>() {
1042 Ok(e) => {
1043 exponent = i32::from(e);
1044 break;
1045 }
1046 Err(_) => return Err("Bad exponent"),
1047 }
1048 }
1049 _ => match ch.to_digit(16) {
1050 Some(digit) => {
1051 digits += 1;
1052 if digits > 32 {
1053 return Err("Too many digits");
1054 }
1055 significand = (significand << 4) | u128::from(digit);
1056 }
1057 None => return Err("Invalid character"),
1058 },
1059 }
1060 }
1061
1062 if digits == 0 {
1063 return Err("No digits");
1064 }
1065
1066 if significand == 0 {
1067 return Ok(sign_bit);
1069 }
1070
1071 match digits_before_period {
1073 None => {} Some(d) => exponent -= 4 * i32::from(digits - d),
1075 };
1076
1077 let significant_bits = (128 - significand.leading_zeros()) as u8;
1079 if significant_bits > t + 1 {
1080 let adjust = significant_bits - (t + 1);
1081 if significand & ((1u128 << adjust) - 1) != 0 {
1082 return Err("Too many significant bits");
1083 }
1084 significand >>= adjust;
1086 exponent += i32::from(adjust);
1087 } else {
1088 let adjust = t + 1 - significant_bits;
1089 significand <<= adjust;
1090 exponent -= i32::from(adjust);
1091 }
1092 debug_assert_eq!(significand >> t, 1);
1093
1094 let t_bits = significand & ((1 << t) - 1);
1096
1097 let max_exp = (1i32 << w) - 2;
1098 let bias: i32 = (1 << (w - 1)) - 1;
1099 exponent += bias + i32::from(t);
1100
1101 if exponent > max_exp {
1102 Err("Magnitude too large")
1103 } else if exponent > 0 {
1104 let e_bits = (exponent as u128) << t;
1106 Ok(sign_bit | e_bits | t_bits)
1107 } else if 1 - exponent <= i32::from(t) {
1108 let adjust = 1 - exponent;
1111 if significand & ((1u128 << adjust) - 1) != 0 {
1112 Err("Subnormal underflow")
1113 } else {
1114 significand >>= adjust;
1115 Ok(sign_bit | significand)
1116 }
1117 } else {
1118 Err("Magnitude too small")
1119 }
1120}
1121
1122#[cfg(test)]
1123mod tests {
1124 use super::*;
1125 use alloc::string::ToString;
1126 use core::{f32, f64};
1127
1128 #[test]
1129 fn format_imm64() {
1130 assert_eq!(Imm64(0).to_string(), "0");
1131 assert_eq!(Imm64(9999).to_string(), "9999");
1132 assert_eq!(Imm64(10000).to_string(), "0x2710");
1133 assert_eq!(Imm64(-9999).to_string(), "-9999");
1134 assert_eq!(Imm64(-10000).to_string(), "-10000");
1135 assert_eq!(Imm64(0xffff).to_string(), "0xffff");
1136 assert_eq!(Imm64(0x10000).to_string(), "0x0001_0000");
1137 }
1138
1139 #[test]
1140 fn format_uimm64() {
1141 assert_eq!(Uimm64(0).to_string(), "0");
1142 assert_eq!(Uimm64(9999).to_string(), "9999");
1143 assert_eq!(Uimm64(10000).to_string(), "0x2710");
1144 assert_eq!(Uimm64(-9999i64 as u64).to_string(), "0xffff_ffff_ffff_d8f1");
1145 assert_eq!(
1146 Uimm64(-10000i64 as u64).to_string(),
1147 "0xffff_ffff_ffff_d8f0"
1148 );
1149 assert_eq!(Uimm64(0xffff).to_string(), "0xffff");
1150 assert_eq!(Uimm64(0x10000).to_string(), "0x0001_0000");
1151 }
1152
1153 #[track_caller]
1155 fn parse_ok<T: FromStr + Display>(text: &str, want: &str)
1156 where
1157 <T as FromStr>::Err: Display,
1158 {
1159 match text.parse::<T>() {
1160 Err(s) => panic!("\"{text}\".parse() error: {s}"),
1161 Ok(x) => assert_eq!(x.to_string(), want),
1162 }
1163 }
1164
1165 fn parse_err<T: FromStr + Display>(text: &str, msg: &str)
1167 where
1168 <T as FromStr>::Err: Display,
1169 {
1170 match text.parse::<T>() {
1171 Err(s) => assert_eq!(s.to_string(), msg),
1172 Ok(x) => panic!("Wanted Err({msg}), but got {x}"),
1173 }
1174 }
1175
1176 #[test]
1177 fn parse_imm64() {
1178 parse_ok::<Imm64>("0", "0");
1179 parse_ok::<Imm64>("1", "1");
1180 parse_ok::<Imm64>("-0", "0");
1181 parse_ok::<Imm64>("-1", "-1");
1182 parse_ok::<Imm64>("0x0", "0");
1183 parse_ok::<Imm64>("0xf", "15");
1184 parse_ok::<Imm64>("-0x9", "-9");
1185
1186 parse_ok::<Imm64>("0xffffffff_ffffffff", "-1");
1188 parse_ok::<Imm64>("0x80000000_00000000", "-9223372036854775808");
1189 parse_ok::<Imm64>("-0x80000000_00000000", "-9223372036854775808");
1190 parse_err::<Imm64>("-0x80000000_00000001", "Negative number too small");
1191 parse_ok::<Imm64>("18446744073709551615", "-1");
1192 parse_ok::<Imm64>("-9223372036854775808", "-9223372036854775808");
1193 parse_err::<Imm64>("18446744073709551616", "Too large decimal number");
1195 parse_err::<Imm64>("184467440737095516100", "Too large decimal number");
1196 parse_err::<Imm64>("-9223372036854775809", "Negative number too small");
1197
1198 parse_ok::<Imm64>("0_0", "0");
1200 parse_ok::<Imm64>("-_10_0", "-100");
1201 parse_ok::<Imm64>("_10_", "10");
1202 parse_ok::<Imm64>("0x97_88_bb", "0x0097_88bb");
1203 parse_ok::<Imm64>("0x_97_", "151");
1204
1205 parse_err::<Imm64>("", "No digits in number");
1206 parse_err::<Imm64>("-", "No digits in number");
1207 parse_err::<Imm64>("_", "No digits in number");
1208 parse_err::<Imm64>("0x", "No digits in number");
1209 parse_err::<Imm64>("0x_", "No digits in number");
1210 parse_err::<Imm64>("-0x", "No digits in number");
1211 parse_err::<Imm64>(" ", "Invalid character in decimal number");
1212 parse_err::<Imm64>("0 ", "Invalid character in decimal number");
1213 parse_err::<Imm64>(" 0", "Invalid character in decimal number");
1214 parse_err::<Imm64>("--", "Invalid character in decimal number");
1215 parse_err::<Imm64>("-0x-", "Invalid character in hexadecimal number");
1216 parse_err::<Imm64>("abc", "Invalid character in decimal number");
1217 parse_err::<Imm64>("-abc", "Invalid character in decimal number");
1218
1219 parse_err::<Imm64>("0x0_0000_0000_0000_0000", "Too many hexadecimal digits");
1221 }
1222
1223 #[test]
1224 fn parse_uimm64() {
1225 parse_ok::<Uimm64>("0", "0");
1226 parse_ok::<Uimm64>("1", "1");
1227 parse_ok::<Uimm64>("0x0", "0");
1228 parse_ok::<Uimm64>("0xf", "15");
1229 parse_ok::<Uimm64>("0xffffffff_fffffff7", "0xffff_ffff_ffff_fff7");
1230
1231 parse_ok::<Uimm64>("0xffffffff_ffffffff", "0xffff_ffff_ffff_ffff");
1233 parse_ok::<Uimm64>("0x80000000_00000000", "0x8000_0000_0000_0000");
1234 parse_ok::<Uimm64>("18446744073709551615", "0xffff_ffff_ffff_ffff");
1235 parse_err::<Uimm64>("18446744073709551616", "Too large decimal number");
1237 parse_err::<Uimm64>("184467440737095516100", "Too large decimal number");
1238
1239 parse_ok::<Uimm64>("0_0", "0");
1241 parse_ok::<Uimm64>("_10_", "10");
1242 parse_ok::<Uimm64>("0x97_88_bb", "0x0097_88bb");
1243 parse_ok::<Uimm64>("0x_97_", "151");
1244
1245 parse_err::<Uimm64>("", "No digits in number");
1246 parse_err::<Uimm64>("_", "No digits in number");
1247 parse_err::<Uimm64>("0x", "No digits in number");
1248 parse_err::<Uimm64>("0x_", "No digits in number");
1249 parse_err::<Uimm64>("-", "Invalid character in decimal number");
1250 parse_err::<Uimm64>("-0x", "Invalid character in hexadecimal number");
1251 parse_err::<Uimm64>(" ", "Invalid character in decimal number");
1252 parse_err::<Uimm64>("0 ", "Invalid character in decimal number");
1253 parse_err::<Uimm64>(" 0", "Invalid character in decimal number");
1254 parse_err::<Uimm64>("--", "Invalid character in decimal number");
1255 parse_err::<Uimm64>("-0x-", "Invalid character in hexadecimal number");
1256 parse_err::<Uimm64>("-0", "Invalid character in decimal number");
1257 parse_err::<Uimm64>("-1", "Invalid character in decimal number");
1258 parse_err::<Uimm64>("abc", "Invalid character in decimal number");
1259 parse_err::<Uimm64>("-abc", "Invalid character in decimal number");
1260
1261 parse_err::<Uimm64>("0x0_0000_0000_0000_0000", "Too many hexadecimal digits");
1263 }
1264
1265 #[test]
1266 fn format_offset32() {
1267 assert_eq!(Offset32(0).to_string(), "");
1268 assert_eq!(Offset32(1).to_string(), "+1");
1269 assert_eq!(Offset32(-1).to_string(), "-1");
1270 assert_eq!(Offset32(9999).to_string(), "+9999");
1271 assert_eq!(Offset32(10000).to_string(), "+0x2710");
1272 assert_eq!(Offset32(-9999).to_string(), "-9999");
1273 assert_eq!(Offset32(-10000).to_string(), "-0x2710");
1274 assert_eq!(Offset32(0xffff).to_string(), "+0xffff");
1275 assert_eq!(Offset32(0x10000).to_string(), "+0x0001_0000");
1276 }
1277
1278 #[test]
1279 fn parse_offset32() {
1280 parse_ok::<Offset32>("+0", "");
1281 parse_ok::<Offset32>("+1", "+1");
1282 parse_ok::<Offset32>("-0", "");
1283 parse_ok::<Offset32>("-1", "-1");
1284 parse_ok::<Offset32>("+0x0", "");
1285 parse_ok::<Offset32>("+0xf", "+15");
1286 parse_ok::<Offset32>("-0x9", "-9");
1287 parse_ok::<Offset32>("-0x8000_0000", "-0x8000_0000");
1288
1289 parse_err::<Offset32>("+0x8000_0000", "Offset out of range");
1290 }
1291
1292 #[test]
1293 fn format_ieee16() {
1294 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!(
1300 Ieee16::with_bits(0x1400).to_string(), "0x1.000p-10"
1302 );
1303 assert_eq!(
1304 Ieee16::with_bits(0xfbff).to_string(), "-0x1.ffcp15"
1306 );
1307 assert_eq!(
1308 Ieee16::with_bits(0x7bff).to_string(), "0x1.ffcp15"
1310 );
1311 assert_eq!(
1313 Ieee16::with_bits(0x0400).to_string(), "0x1.000p-14"
1315 );
1316 assert_eq!(
1318 Ieee16::with_bits(0x0200).to_string(), "0x0.800p-14"
1320 );
1321 assert_eq!(
1322 Ieee16::with_bits(0x0001).to_string(), "0x0.004p-14"
1324 );
1325 assert_eq!(
1326 Ieee16::with_bits(0x7c00).to_string(), "+Inf"
1328 );
1329 assert_eq!(
1330 Ieee16::with_bits(0xfc00).to_string(), "-Inf"
1332 );
1333 assert_eq!(
1334 Ieee16::with_bits(0x7e00).to_string(), "+NaN"
1336 );
1337 assert_eq!(
1338 Ieee16::with_bits(0xfe00).to_string(), "-NaN"
1340 );
1341 assert_eq!(Ieee16::with_bits(0x7e01).to_string(), "+NaN:0x1");
1343 assert_eq!(Ieee16::with_bits(0x7f01).to_string(), "+NaN:0x101");
1344 assert_eq!(Ieee16::with_bits(0x7c01).to_string(), "+sNaN:0x1");
1346 assert_eq!(Ieee16::with_bits(0x7d01).to_string(), "+sNaN:0x101");
1347 }
1348
1349 #[test]
1350 fn parse_ieee16() {
1351 parse_ok::<Ieee16>("0.0", "0.0");
1352 parse_ok::<Ieee16>("+0.0", "0.0");
1353 parse_ok::<Ieee16>("-0.0", "-0.0");
1354 parse_ok::<Ieee16>("0x0", "0.0");
1355 parse_ok::<Ieee16>("0x0.0", "0.0");
1356 parse_ok::<Ieee16>("0x.0", "0.0");
1357 parse_ok::<Ieee16>("0x0.", "0.0");
1358 parse_ok::<Ieee16>("0x1", "0x1.000p0");
1359 parse_ok::<Ieee16>("+0x1", "0x1.000p0");
1360 parse_ok::<Ieee16>("-0x1", "-0x1.000p0");
1361 parse_ok::<Ieee16>("0x10", "0x1.000p4");
1362 parse_ok::<Ieee16>("0x10.0", "0x1.000p4");
1363 parse_err::<Ieee16>("0.", "Float must be hexadecimal");
1364 parse_err::<Ieee16>(".0", "Float must be hexadecimal");
1365 parse_err::<Ieee16>("0", "Float must be hexadecimal");
1366 parse_err::<Ieee16>("-0", "Float must be hexadecimal");
1367 parse_err::<Ieee16>(".", "Float must be hexadecimal");
1368 parse_err::<Ieee16>("", "Float must be hexadecimal");
1369 parse_err::<Ieee16>("-", "Float must be hexadecimal");
1370 parse_err::<Ieee16>("0x", "No digits");
1371 parse_err::<Ieee16>("0x..", "Multiple radix points");
1372
1373 parse_ok::<Ieee16>("0x0.ffe", "0x1.ffcp-1");
1375 parse_ok::<Ieee16>("0x1.ffc", "0x1.ffcp0");
1376 parse_ok::<Ieee16>("0x3.ff8", "0x1.ffcp1");
1377 parse_ok::<Ieee16>("0x7.ff", "0x1.ffcp2");
1378 parse_ok::<Ieee16>("0xf.fe", "0x1.ffcp3");
1379 parse_err::<Ieee16>("0x1.ffe", "Too many significant bits");
1380 parse_err::<Ieee16>("0x1.ffc00000000000000000000000000000", "Too many digits");
1381
1382 parse_ok::<Ieee16>("0x1p3", "0x1.000p3");
1384 parse_ok::<Ieee16>("0x1p-3", "0x1.000p-3");
1385 parse_ok::<Ieee16>("0x1.0p3", "0x1.000p3");
1386 parse_ok::<Ieee16>("0x2.0p3", "0x1.000p4");
1387 parse_ok::<Ieee16>("0x1.0p15", "0x1.000p15");
1388 parse_ok::<Ieee16>("0x1.0p-14", "0x1.000p-14");
1389 parse_ok::<Ieee16>("0x0.1p-10", "0x1.000p-14");
1390 parse_err::<Ieee16>("0x2.0p15", "Magnitude too large");
1391
1392 parse_ok::<Ieee16>("0x1.0p-15", "0x0.800p-14");
1394 parse_ok::<Ieee16>("0x1.0p-24", "0x0.004p-14");
1395 parse_ok::<Ieee16>("0x0.004p-14", "0x0.004p-14");
1396 parse_err::<Ieee16>("0x0.102p-14", "Subnormal underflow");
1397 parse_err::<Ieee16>("0x1.8p-24", "Subnormal underflow");
1398 parse_err::<Ieee16>("0x1.0p-25", "Magnitude too small");
1399
1400 parse_ok::<Ieee16>("Inf", "+Inf");
1402 parse_ok::<Ieee16>("+Inf", "+Inf");
1403 parse_ok::<Ieee16>("-Inf", "-Inf");
1404 parse_ok::<Ieee16>("NaN", "+NaN");
1405 parse_ok::<Ieee16>("+NaN", "+NaN");
1406 parse_ok::<Ieee16>("-NaN", "-NaN");
1407 parse_ok::<Ieee16>("NaN:0x0", "+NaN");
1408 parse_err::<Ieee16>("NaN:", "Float must be hexadecimal");
1409 parse_err::<Ieee16>("NaN:0", "Float must be hexadecimal");
1410 parse_err::<Ieee16>("NaN:0x", "Invalid NaN payload");
1411 parse_ok::<Ieee16>("NaN:0x001", "+NaN:0x1");
1412 parse_ok::<Ieee16>("NaN:0x101", "+NaN:0x101");
1413 parse_err::<Ieee16>("NaN:0x301", "Invalid NaN payload");
1414 parse_ok::<Ieee16>("sNaN:0x1", "+sNaN:0x1");
1415 parse_err::<Ieee16>("sNaN:0x0", "Invalid sNaN payload");
1416 parse_ok::<Ieee16>("sNaN:0x101", "+sNaN:0x101");
1417 parse_err::<Ieee16>("sNaN:0x301", "Invalid sNaN payload");
1418 }
1419
1420 #[test]
1421 fn pow2_ieee16() {
1422 assert_eq!(Ieee16::pow2(0).to_string(), "0x1.000p0");
1423 assert_eq!(Ieee16::pow2(1).to_string(), "0x1.000p1");
1424 assert_eq!(Ieee16::pow2(-1).to_string(), "0x1.000p-1");
1425 assert_eq!(Ieee16::pow2(15).to_string(), "0x1.000p15");
1426 assert_eq!(Ieee16::pow2(-14).to_string(), "0x1.000p-14");
1427
1428 assert_eq!((-Ieee16::pow2(1)).to_string(), "-0x1.000p1");
1429 }
1430
1431 #[test]
1432 fn fcvt_to_sint_negative_overflow_ieee16() {
1433 let n = 8;
1440 assert_eq!(
1441 "-0x1.020p7",
1442 Ieee16::fcvt_to_sint_negative_overflow(n).to_string()
1443 );
1444 }
1445
1446 #[test]
1447 fn format_ieee32() {
1448 assert_eq!(Ieee32::with_float(0.0).to_string(), "0.0");
1449 assert_eq!(Ieee32::with_float(-0.0).to_string(), "-0.0");
1450 assert_eq!(Ieee32::with_float(1.0).to_string(), "0x1.000000p0");
1451 assert_eq!(Ieee32::with_float(1.5).to_string(), "0x1.800000p0");
1452 assert_eq!(Ieee32::with_float(0.5).to_string(), "0x1.000000p-1");
1453 assert_eq!(
1454 Ieee32::with_float(f32::EPSILON).to_string(),
1455 "0x1.000000p-23"
1456 );
1457 assert_eq!(Ieee32::with_float(f32::MIN).to_string(), "-0x1.fffffep127");
1458 assert_eq!(Ieee32::with_float(f32::MAX).to_string(), "0x1.fffffep127");
1459 assert_eq!(
1461 Ieee32::with_float(f32::MIN_POSITIVE).to_string(),
1462 "0x1.000000p-126"
1463 );
1464 assert_eq!(
1466 Ieee32::with_float(f32::MIN_POSITIVE / 2.0).to_string(),
1467 "0x0.800000p-126"
1468 );
1469 assert_eq!(
1470 Ieee32::with_float(f32::MIN_POSITIVE * f32::EPSILON).to_string(),
1471 "0x0.000002p-126"
1472 );
1473 assert_eq!(Ieee32::with_float(f32::INFINITY).to_string(), "+Inf");
1474 assert_eq!(Ieee32::with_float(f32::NEG_INFINITY).to_string(), "-Inf");
1475 assert_eq!(Ieee32::with_float(f32::NAN).to_string(), "+NaN");
1476 assert_eq!(Ieee32::with_float(-f32::NAN).to_string(), "-NaN");
1477 assert_eq!(Ieee32::with_bits(0x7fc00001).to_string(), "+NaN:0x1");
1479 assert_eq!(Ieee32::with_bits(0x7ff00001).to_string(), "+NaN:0x300001");
1480 assert_eq!(Ieee32::with_bits(0x7f800001).to_string(), "+sNaN:0x1");
1482 assert_eq!(Ieee32::with_bits(0x7fa00001).to_string(), "+sNaN:0x200001");
1483 }
1484
1485 #[test]
1486 fn parse_ieee32() {
1487 parse_ok::<Ieee32>("0.0", "0.0");
1488 parse_ok::<Ieee32>("+0.0", "0.0");
1489 parse_ok::<Ieee32>("-0.0", "-0.0");
1490 parse_ok::<Ieee32>("0x0", "0.0");
1491 parse_ok::<Ieee32>("0x0.0", "0.0");
1492 parse_ok::<Ieee32>("0x.0", "0.0");
1493 parse_ok::<Ieee32>("0x0.", "0.0");
1494 parse_ok::<Ieee32>("0x1", "0x1.000000p0");
1495 parse_ok::<Ieee32>("+0x1", "0x1.000000p0");
1496 parse_ok::<Ieee32>("-0x1", "-0x1.000000p0");
1497 parse_ok::<Ieee32>("0x10", "0x1.000000p4");
1498 parse_ok::<Ieee32>("0x10.0", "0x1.000000p4");
1499 parse_err::<Ieee32>("0.", "Float must be hexadecimal");
1500 parse_err::<Ieee32>(".0", "Float must be hexadecimal");
1501 parse_err::<Ieee32>("0", "Float must be hexadecimal");
1502 parse_err::<Ieee32>("-0", "Float must be hexadecimal");
1503 parse_err::<Ieee32>(".", "Float must be hexadecimal");
1504 parse_err::<Ieee32>("", "Float must be hexadecimal");
1505 parse_err::<Ieee32>("-", "Float must be hexadecimal");
1506 parse_err::<Ieee32>("0x", "No digits");
1507 parse_err::<Ieee32>("0x..", "Multiple radix points");
1508
1509 parse_ok::<Ieee32>("0x0.ffffff", "0x1.fffffep-1");
1511 parse_ok::<Ieee32>("0x1.fffffe", "0x1.fffffep0");
1512 parse_ok::<Ieee32>("0x3.fffffc", "0x1.fffffep1");
1513 parse_ok::<Ieee32>("0x7.fffff8", "0x1.fffffep2");
1514 parse_ok::<Ieee32>("0xf.fffff0", "0x1.fffffep3");
1515 parse_err::<Ieee32>("0x1.ffffff", "Too many significant bits");
1516 parse_err::<Ieee32>("0x1.fffffe00000000000000000000000000", "Too many digits");
1517
1518 parse_ok::<Ieee32>("0x1p3", "0x1.000000p3");
1520 parse_ok::<Ieee32>("0x1p-3", "0x1.000000p-3");
1521 parse_ok::<Ieee32>("0x1.0p3", "0x1.000000p3");
1522 parse_ok::<Ieee32>("0x2.0p3", "0x1.000000p4");
1523 parse_ok::<Ieee32>("0x1.0p127", "0x1.000000p127");
1524 parse_ok::<Ieee32>("0x1.0p-126", "0x1.000000p-126");
1525 parse_ok::<Ieee32>("0x0.1p-122", "0x1.000000p-126");
1526 parse_err::<Ieee32>("0x2.0p127", "Magnitude too large");
1527
1528 parse_ok::<Ieee32>("0x1.0p-127", "0x0.800000p-126");
1530 parse_ok::<Ieee32>("0x1.0p-149", "0x0.000002p-126");
1531 parse_ok::<Ieee32>("0x0.000002p-126", "0x0.000002p-126");
1532 parse_err::<Ieee32>("0x0.100001p-126", "Subnormal underflow");
1533 parse_err::<Ieee32>("0x1.8p-149", "Subnormal underflow");
1534 parse_err::<Ieee32>("0x1.0p-150", "Magnitude too small");
1535
1536 parse_ok::<Ieee32>("Inf", "+Inf");
1538 parse_ok::<Ieee32>("+Inf", "+Inf");
1539 parse_ok::<Ieee32>("-Inf", "-Inf");
1540 parse_ok::<Ieee32>("NaN", "+NaN");
1541 parse_ok::<Ieee32>("+NaN", "+NaN");
1542 parse_ok::<Ieee32>("-NaN", "-NaN");
1543 parse_ok::<Ieee32>("NaN:0x0", "+NaN");
1544 parse_err::<Ieee32>("NaN:", "Float must be hexadecimal");
1545 parse_err::<Ieee32>("NaN:0", "Float must be hexadecimal");
1546 parse_err::<Ieee32>("NaN:0x", "Invalid NaN payload");
1547 parse_ok::<Ieee32>("NaN:0x000001", "+NaN:0x1");
1548 parse_ok::<Ieee32>("NaN:0x300001", "+NaN:0x300001");
1549 parse_err::<Ieee32>("NaN:0x400001", "Invalid NaN payload");
1550 parse_ok::<Ieee32>("sNaN:0x1", "+sNaN:0x1");
1551 parse_err::<Ieee32>("sNaN:0x0", "Invalid sNaN payload");
1552 parse_ok::<Ieee32>("sNaN:0x200001", "+sNaN:0x200001");
1553 parse_err::<Ieee32>("sNaN:0x400001", "Invalid sNaN payload");
1554 }
1555
1556 #[test]
1557 fn pow2_ieee32() {
1558 assert_eq!(Ieee32::pow2(0).to_string(), "0x1.000000p0");
1559 assert_eq!(Ieee32::pow2(1).to_string(), "0x1.000000p1");
1560 assert_eq!(Ieee32::pow2(-1).to_string(), "0x1.000000p-1");
1561 assert_eq!(Ieee32::pow2(127).to_string(), "0x1.000000p127");
1562 assert_eq!(Ieee32::pow2(-126).to_string(), "0x1.000000p-126");
1563
1564 assert_eq!((-Ieee32::pow2(1)).to_string(), "-0x1.000000p1");
1565 }
1566
1567 #[test]
1568 fn fcvt_to_sint_negative_overflow_ieee32() {
1569 for n in [8, 16] {
1570 assert_eq!(
1571 -((1u32 << (n - 1)) as f32) - 1.0,
1572 Ieee32::fcvt_to_sint_negative_overflow(n).as_f32(),
1573 "n = {n}"
1574 );
1575 }
1576 }
1577
1578 #[test]
1579 fn format_ieee64() {
1580 assert_eq!(Ieee64::with_float(0.0).to_string(), "0.0");
1581 assert_eq!(Ieee64::with_float(-0.0).to_string(), "-0.0");
1582 assert_eq!(Ieee64::with_float(1.0).to_string(), "0x1.0000000000000p0");
1583 assert_eq!(Ieee64::with_float(1.5).to_string(), "0x1.8000000000000p0");
1584 assert_eq!(Ieee64::with_float(0.5).to_string(), "0x1.0000000000000p-1");
1585 assert_eq!(
1586 Ieee64::with_float(f64::EPSILON).to_string(),
1587 "0x1.0000000000000p-52"
1588 );
1589 assert_eq!(
1590 Ieee64::with_float(f64::MIN).to_string(),
1591 "-0x1.fffffffffffffp1023"
1592 );
1593 assert_eq!(
1594 Ieee64::with_float(f64::MAX).to_string(),
1595 "0x1.fffffffffffffp1023"
1596 );
1597 assert_eq!(
1599 Ieee64::with_float(f64::MIN_POSITIVE).to_string(),
1600 "0x1.0000000000000p-1022"
1601 );
1602 assert_eq!(
1604 Ieee64::with_float(f64::MIN_POSITIVE / 2.0).to_string(),
1605 "0x0.8000000000000p-1022"
1606 );
1607 assert_eq!(
1608 Ieee64::with_float(f64::MIN_POSITIVE * f64::EPSILON).to_string(),
1609 "0x0.0000000000001p-1022"
1610 );
1611 assert_eq!(Ieee64::with_float(f64::INFINITY).to_string(), "+Inf");
1612 assert_eq!(Ieee64::with_float(f64::NEG_INFINITY).to_string(), "-Inf");
1613 assert_eq!(Ieee64::with_float(f64::NAN).to_string(), "+NaN");
1614 assert_eq!(Ieee64::with_float(-f64::NAN).to_string(), "-NaN");
1615 assert_eq!(
1617 Ieee64::with_bits(0x7ff8000000000001).to_string(),
1618 "+NaN:0x1"
1619 );
1620 assert_eq!(
1621 Ieee64::with_bits(0x7ffc000000000001).to_string(),
1622 "+NaN:0x4000000000001"
1623 );
1624 assert_eq!(
1626 Ieee64::with_bits(0x7ff0000000000001).to_string(),
1627 "+sNaN:0x1"
1628 );
1629 assert_eq!(
1630 Ieee64::with_bits(0x7ff4000000000001).to_string(),
1631 "+sNaN:0x4000000000001"
1632 );
1633 }
1634
1635 #[test]
1636 fn parse_ieee64() {
1637 parse_ok::<Ieee64>("0.0", "0.0");
1638 parse_ok::<Ieee64>("-0.0", "-0.0");
1639 parse_ok::<Ieee64>("0x0", "0.0");
1640 parse_ok::<Ieee64>("0x0.0", "0.0");
1641 parse_ok::<Ieee64>("0x.0", "0.0");
1642 parse_ok::<Ieee64>("0x0.", "0.0");
1643 parse_ok::<Ieee64>("0x1", "0x1.0000000000000p0");
1644 parse_ok::<Ieee64>("-0x1", "-0x1.0000000000000p0");
1645 parse_ok::<Ieee64>("0x10", "0x1.0000000000000p4");
1646 parse_ok::<Ieee64>("0x10.0", "0x1.0000000000000p4");
1647 parse_err::<Ieee64>("0.", "Float must be hexadecimal");
1648 parse_err::<Ieee64>(".0", "Float must be hexadecimal");
1649 parse_err::<Ieee64>("0", "Float must be hexadecimal");
1650 parse_err::<Ieee64>("-0", "Float must be hexadecimal");
1651 parse_err::<Ieee64>(".", "Float must be hexadecimal");
1652 parse_err::<Ieee64>("", "Float must be hexadecimal");
1653 parse_err::<Ieee64>("-", "Float must be hexadecimal");
1654 parse_err::<Ieee64>("0x", "No digits");
1655 parse_err::<Ieee64>("0x..", "Multiple radix points");
1656
1657 parse_ok::<Ieee64>("0x0.fffffffffffff8", "0x1.fffffffffffffp-1");
1659 parse_ok::<Ieee64>("0x1.fffffffffffff", "0x1.fffffffffffffp0");
1660 parse_ok::<Ieee64>("0x3.ffffffffffffe", "0x1.fffffffffffffp1");
1661 parse_ok::<Ieee64>("0x7.ffffffffffffc", "0x1.fffffffffffffp2");
1662 parse_ok::<Ieee64>("0xf.ffffffffffff8", "0x1.fffffffffffffp3");
1663 parse_err::<Ieee64>("0x3.fffffffffffff", "Too many significant bits");
1664 parse_err::<Ieee64>("0x001.fffffe000000000000000000000000", "Too many digits");
1665
1666 parse_ok::<Ieee64>("0x1p3", "0x1.0000000000000p3");
1668 parse_ok::<Ieee64>("0x1p-3", "0x1.0000000000000p-3");
1669 parse_ok::<Ieee64>("0x1.0p3", "0x1.0000000000000p3");
1670 parse_ok::<Ieee64>("0x2.0p3", "0x1.0000000000000p4");
1671 parse_ok::<Ieee64>("0x1.0p1023", "0x1.0000000000000p1023");
1672 parse_ok::<Ieee64>("0x1.0p-1022", "0x1.0000000000000p-1022");
1673 parse_ok::<Ieee64>("0x0.1p-1018", "0x1.0000000000000p-1022");
1674 parse_err::<Ieee64>("0x2.0p1023", "Magnitude too large");
1675
1676 parse_ok::<Ieee64>("0x1.0p-1023", "0x0.8000000000000p-1022");
1678 parse_ok::<Ieee64>("0x1.0p-1074", "0x0.0000000000001p-1022");
1679 parse_ok::<Ieee64>("0x0.0000000000001p-1022", "0x0.0000000000001p-1022");
1680 parse_err::<Ieee64>("0x0.10000000000008p-1022", "Subnormal underflow");
1681 parse_err::<Ieee64>("0x1.8p-1074", "Subnormal underflow");
1682 parse_err::<Ieee64>("0x1.0p-1075", "Magnitude too small");
1683
1684 parse_ok::<Ieee64>("Inf", "+Inf");
1686 parse_ok::<Ieee64>("-Inf", "-Inf");
1687 parse_ok::<Ieee64>("NaN", "+NaN");
1688 parse_ok::<Ieee64>("-NaN", "-NaN");
1689 parse_ok::<Ieee64>("NaN:0x0", "+NaN");
1690 parse_err::<Ieee64>("NaN:", "Float must be hexadecimal");
1691 parse_err::<Ieee64>("NaN:0", "Float must be hexadecimal");
1692 parse_err::<Ieee64>("NaN:0x", "Invalid NaN payload");
1693 parse_ok::<Ieee64>("NaN:0x000001", "+NaN:0x1");
1694 parse_ok::<Ieee64>("NaN:0x4000000000001", "+NaN:0x4000000000001");
1695 parse_err::<Ieee64>("NaN:0x8000000000001", "Invalid NaN payload");
1696 parse_ok::<Ieee64>("sNaN:0x1", "+sNaN:0x1");
1697 parse_err::<Ieee64>("sNaN:0x0", "Invalid sNaN payload");
1698 parse_ok::<Ieee64>("sNaN:0x4000000000001", "+sNaN:0x4000000000001");
1699 parse_err::<Ieee64>("sNaN:0x8000000000001", "Invalid sNaN payload");
1700 }
1701
1702 #[test]
1703 fn pow2_ieee64() {
1704 assert_eq!(Ieee64::pow2(0).to_string(), "0x1.0000000000000p0");
1705 assert_eq!(Ieee64::pow2(1).to_string(), "0x1.0000000000000p1");
1706 assert_eq!(Ieee64::pow2(-1).to_string(), "0x1.0000000000000p-1");
1707 assert_eq!(Ieee64::pow2(1023).to_string(), "0x1.0000000000000p1023");
1708 assert_eq!(Ieee64::pow2(-1022).to_string(), "0x1.0000000000000p-1022");
1709
1710 assert_eq!((-Ieee64::pow2(1)).to_string(), "-0x1.0000000000000p1");
1711 }
1712
1713 #[test]
1714 fn fcvt_to_sint_negative_overflow_ieee64() {
1715 for n in [8, 16, 32] {
1716 assert_eq!(
1717 -((1u64 << (n - 1)) as f64) - 1.0,
1718 Ieee64::fcvt_to_sint_negative_overflow(n).as_f64(),
1719 "n = {n}"
1720 );
1721 }
1722 }
1723
1724 #[test]
1725 fn format_ieee128() {
1726 assert_eq!(
1727 Ieee128::with_bits(0x00000000000000000000000000000000).to_string(), "0.0"
1729 );
1730 assert_eq!(
1731 Ieee128::with_bits(0x80000000000000000000000000000000).to_string(), "-0.0"
1733 );
1734 assert_eq!(
1735 Ieee128::with_bits(0x3fff0000000000000000000000000000).to_string(), "0x1.0000000000000000000000000000p0"
1737 );
1738 assert_eq!(
1739 Ieee128::with_bits(0x3fff8000000000000000000000000000).to_string(), "0x1.8000000000000000000000000000p0"
1741 );
1742 assert_eq!(
1743 Ieee128::with_bits(0x3ffe0000000000000000000000000000).to_string(), "0x1.0000000000000000000000000000p-1"
1745 );
1746 assert_eq!(
1747 Ieee128::with_bits(0x3f8f0000000000000000000000000000).to_string(), "0x1.0000000000000000000000000000p-112"
1749 );
1750 assert_eq!(
1751 Ieee128::with_bits(0xfffeffffffffffffffffffffffffffff).to_string(), "-0x1.ffffffffffffffffffffffffffffp16383"
1753 );
1754 assert_eq!(
1755 Ieee128::with_bits(0x7ffeffffffffffffffffffffffffffff).to_string(), "0x1.ffffffffffffffffffffffffffffp16383"
1757 );
1758 assert_eq!(
1760 Ieee128::with_bits(0x00010000000000000000000000000000).to_string(), "0x1.0000000000000000000000000000p-16382"
1762 );
1763 assert_eq!(
1765 Ieee128::with_bits(0x00008000000000000000000000000000).to_string(), "0x0.8000000000000000000000000000p-16382"
1767 );
1768 assert_eq!(
1769 Ieee128::with_bits(0x00000000000000000000000000000001).to_string(), "0x0.0000000000000000000000000001p-16382"
1771 );
1772 assert_eq!(
1773 Ieee128::with_bits(0x7fff0000000000000000000000000000).to_string(), "+Inf"
1775 );
1776 assert_eq!(
1777 Ieee128::with_bits(0xffff0000000000000000000000000000).to_string(), "-Inf"
1779 );
1780 assert_eq!(
1781 Ieee128::with_bits(0x7fff8000000000000000000000000000).to_string(), "+NaN"
1783 );
1784 assert_eq!(
1785 Ieee128::with_bits(0xffff8000000000000000000000000000).to_string(), "-NaN"
1787 );
1788 assert_eq!(
1790 Ieee128::with_bits(0x7fff8000000000000000000000000001).to_string(),
1791 "+NaN:0x1"
1792 );
1793 assert_eq!(
1794 Ieee128::with_bits(0x7fffc000000000000000000000000001).to_string(),
1795 "+NaN:0x4000000000000000000000000001"
1796 );
1797 assert_eq!(
1799 Ieee128::with_bits(0x7fff0000000000000000000000000001).to_string(),
1800 "+sNaN:0x1"
1801 );
1802 assert_eq!(
1803 Ieee128::with_bits(0x7fff4000000000000000000000000001).to_string(),
1804 "+sNaN:0x4000000000000000000000000001"
1805 );
1806 }
1807
1808 #[test]
1809 fn parse_ieee128() {
1810 parse_ok::<Ieee128>("0.0", "0.0");
1811 parse_ok::<Ieee128>("-0.0", "-0.0");
1812 parse_ok::<Ieee128>("0x0", "0.0");
1813 parse_ok::<Ieee128>("0x0.0", "0.0");
1814 parse_ok::<Ieee128>("0x.0", "0.0");
1815 parse_ok::<Ieee128>("0x0.", "0.0");
1816 parse_ok::<Ieee128>("0x1", "0x1.0000000000000000000000000000p0");
1817 parse_ok::<Ieee128>("-0x1", "-0x1.0000000000000000000000000000p0");
1818 parse_ok::<Ieee128>("0x10", "0x1.0000000000000000000000000000p4");
1819 parse_ok::<Ieee128>("0x10.0", "0x1.0000000000000000000000000000p4");
1820 parse_err::<Ieee128>("0.", "Float must be hexadecimal");
1821 parse_err::<Ieee128>(".0", "Float must be hexadecimal");
1822 parse_err::<Ieee128>("0", "Float must be hexadecimal");
1823 parse_err::<Ieee128>("-0", "Float must be hexadecimal");
1824 parse_err::<Ieee128>(".", "Float must be hexadecimal");
1825 parse_err::<Ieee128>("", "Float must be hexadecimal");
1826 parse_err::<Ieee128>("-", "Float must be hexadecimal");
1827 parse_err::<Ieee128>("0x", "No digits");
1828 parse_err::<Ieee128>("0x..", "Multiple radix points");
1829
1830 parse_ok::<Ieee128>(
1832 "0x0.ffffffffffffffffffffffffffff8",
1833 "0x1.ffffffffffffffffffffffffffffp-1",
1834 );
1835 parse_ok::<Ieee128>(
1836 "0x1.ffffffffffffffffffffffffffff",
1837 "0x1.ffffffffffffffffffffffffffffp0",
1838 );
1839 parse_ok::<Ieee128>(
1840 "0x3.fffffffffffffffffffffffffffe",
1841 "0x1.ffffffffffffffffffffffffffffp1",
1842 );
1843 parse_ok::<Ieee128>(
1844 "0x7.fffffffffffffffffffffffffffc",
1845 "0x1.ffffffffffffffffffffffffffffp2",
1846 );
1847 parse_ok::<Ieee128>(
1848 "0xf.fffffffffffffffffffffffffff8",
1849 "0x1.ffffffffffffffffffffffffffffp3",
1850 );
1851 parse_err::<Ieee128>(
1852 "0x3.ffffffffffffffffffffffffffff",
1853 "Too many significant bits",
1854 );
1855 parse_err::<Ieee128>("0x001.fffffe000000000000000000000000", "Too many digits");
1856
1857 parse_ok::<Ieee128>("0x1p3", "0x1.0000000000000000000000000000p3");
1859 parse_ok::<Ieee128>("0x1p-3", "0x1.0000000000000000000000000000p-3");
1860 parse_ok::<Ieee128>("0x1.0p3", "0x1.0000000000000000000000000000p3");
1861 parse_ok::<Ieee128>("0x2.0p3", "0x1.0000000000000000000000000000p4");
1862 parse_ok::<Ieee128>("0x1.0p16383", "0x1.0000000000000000000000000000p16383");
1863 parse_ok::<Ieee128>("0x1.0p-16382", "0x1.0000000000000000000000000000p-16382");
1864 parse_ok::<Ieee128>("0x0.1p-16378", "0x1.0000000000000000000000000000p-16382");
1865 parse_err::<Ieee128>("0x2.0p16383", "Magnitude too large");
1866
1867 parse_ok::<Ieee128>("0x1.0p-16383", "0x0.8000000000000000000000000000p-16382");
1869 parse_ok::<Ieee128>("0x1.0p-16494", "0x0.0000000000000000000000000001p-16382");
1870 parse_ok::<Ieee128>(
1871 "0x0.0000000000000000000000000001p-16382",
1872 "0x0.0000000000000000000000000001p-16382",
1873 );
1874 parse_err::<Ieee128>(
1875 "0x0.10000000000000000000000000008p-16382",
1876 "Subnormal underflow",
1877 );
1878 parse_err::<Ieee128>("0x1.8p-16494", "Subnormal underflow");
1879 parse_err::<Ieee128>("0x1.0p-16495", "Magnitude too small");
1880
1881 parse_ok::<Ieee128>("Inf", "+Inf");
1883 parse_ok::<Ieee128>("-Inf", "-Inf");
1884 parse_ok::<Ieee128>("NaN", "+NaN");
1885 parse_ok::<Ieee128>("-NaN", "-NaN");
1886 parse_ok::<Ieee128>("NaN:0x0", "+NaN");
1887 parse_err::<Ieee128>("NaN:", "Float must be hexadecimal");
1888 parse_err::<Ieee128>("NaN:0", "Float must be hexadecimal");
1889 parse_err::<Ieee128>("NaN:0x", "Invalid NaN payload");
1890 parse_ok::<Ieee128>("NaN:0x000001", "+NaN:0x1");
1891 parse_ok::<Ieee128>(
1892 "NaN:0x4000000000000000000000000001",
1893 "+NaN:0x4000000000000000000000000001",
1894 );
1895 parse_err::<Ieee128>("NaN:0x8000000000000000000000000001", "Invalid NaN payload");
1896 parse_ok::<Ieee128>("sNaN:0x1", "+sNaN:0x1");
1897 parse_err::<Ieee128>("sNaN:0x0", "Invalid sNaN payload");
1898 parse_ok::<Ieee128>(
1899 "sNaN:0x4000000000000000000000000001",
1900 "+sNaN:0x4000000000000000000000000001",
1901 );
1902 parse_err::<Ieee128>(
1903 "sNaN:0x8000000000000000000000000001",
1904 "Invalid sNaN payload",
1905 );
1906 }
1907
1908 #[test]
1909 fn pow2_ieee128() {
1910 assert_eq!(
1911 Ieee128::pow2(0).to_string(),
1912 "0x1.0000000000000000000000000000p0"
1913 );
1914 assert_eq!(
1915 Ieee128::pow2(1).to_string(),
1916 "0x1.0000000000000000000000000000p1"
1917 );
1918 assert_eq!(
1919 Ieee128::pow2(-1).to_string(),
1920 "0x1.0000000000000000000000000000p-1"
1921 );
1922 assert_eq!(
1923 Ieee128::pow2(16383).to_string(),
1924 "0x1.0000000000000000000000000000p16383"
1925 );
1926 assert_eq!(
1927 Ieee128::pow2(-16382).to_string(),
1928 "0x1.0000000000000000000000000000p-16382"
1929 );
1930
1931 assert_eq!(
1932 (-Ieee128::pow2(1)).to_string(),
1933 "-0x1.0000000000000000000000000000p1"
1934 );
1935 }
1936
1937 #[test]
1938 fn fcvt_to_sint_negative_overflow_ieee128() {
1939 for (n, expected) in [
1948 (8, "-0x1.0200000000000000000000000000p7"),
1949 (16, "-0x1.0002000000000000000000000000p15"),
1950 (32, "-0x1.0000000200000000000000000000p31"),
1951 (64, "-0x1.0000000000000002000000000000p63"),
1952 ] {
1953 assert_eq!(
1954 expected,
1955 Ieee128::fcvt_to_sint_negative_overflow(n).to_string(),
1956 "n = {n}"
1957 );
1958 }
1959 }
1960}