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