1use alloc::vec::Vec;
8use core::cmp::Ordering;
9use core::convert::TryFrom;
10use core::fmt::{self, Display, Formatter};
11use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Sub};
12use core::str::FromStr;
13use core::{i32, u32};
14#[cfg(feature = "enable-serde")]
15use serde::{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 pub fn sign_extend_from_width(&mut self, bit_width: u32) {
81 debug_assert!(bit_width.is_power_of_two());
82
83 if bit_width >= 64 {
84 return;
85 }
86
87 let bit_width = i64::from(bit_width);
88 let delta = 64 - bit_width;
89 let sign_extended = (self.0 << delta) >> delta;
90 *self = Imm64(sign_extended);
91 }
92}
93
94impl From<Imm64> for i64 {
95 fn from(val: Imm64) -> i64 {
96 val.0
97 }
98}
99
100impl IntoBytes for Imm64 {
101 fn into_bytes(self) -> Vec<u8> {
102 self.0.to_le_bytes().to_vec()
103 }
104}
105
106impl From<i64> for Imm64 {
107 fn from(x: i64) -> Self {
108 Self(x)
109 }
110}
111
112impl Display for Imm64 {
113 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
114 let x = self.0;
115 if -10_000 < x && x < 10_000 {
116 write!(f, "{}", x)
118 } else {
119 write_hex(x as u64, f)
120 }
121 }
122}
123
124fn parse_i64(s: &str) -> Result<i64, &'static str> {
126 let negative = s.starts_with('-');
127 let s2 = if negative || s.starts_with('+') {
128 &s[1..]
129 } else {
130 s
131 };
132
133 let mut value = parse_u64(s2)?;
134
135 if negative {
137 value = value.wrapping_neg();
138 if value as i64 > 0 {
140 return Err("Negative number too small");
141 }
142 }
143 Ok(value as i64)
144}
145
146impl FromStr for Imm64 {
147 type Err = &'static str;
148
149 fn from_str(s: &str) -> Result<Self, &'static str> {
151 parse_i64(s).map(Self::new)
152 }
153}
154
155#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
160#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
161pub struct Uimm64(u64);
162
163impl Uimm64 {
164 pub fn new(x: u64) -> Self {
166 Self(x)
167 }
168
169 pub fn wrapping_neg(self) -> Self {
171 Self(self.0.wrapping_neg())
172 }
173}
174
175impl From<Uimm64> for u64 {
176 fn from(val: Uimm64) -> u64 {
177 val.0
178 }
179}
180
181impl From<u64> for Uimm64 {
182 fn from(x: u64) -> Self {
183 Self(x)
184 }
185}
186
187fn write_hex(x: u64, f: &mut Formatter) -> fmt::Result {
194 let mut pos = (64 - x.leading_zeros() - 1) & 0xf0;
195 write!(f, "0x{:04x}", (x >> pos) & 0xffff)?;
196 while pos > 0 {
197 pos -= 16;
198 write!(f, "_{:04x}", (x >> pos) & 0xffff)?;
199 }
200 Ok(())
201}
202
203impl Display for Uimm64 {
204 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
205 let x = self.0;
206 if x < 10_000 {
207 write!(f, "{}", x)
209 } else {
210 write_hex(x, f)
211 }
212 }
213}
214
215fn parse_u64(s: &str) -> Result<u64, &'static str> {
217 let mut value: u64 = 0;
218 let mut digits = 0;
219
220 if s.starts_with("-0x") {
221 return Err("Invalid character in hexadecimal number");
222 } else if s.starts_with("0x") {
223 for ch in s[2..].chars() {
225 match ch.to_digit(16) {
226 Some(digit) => {
227 digits += 1;
228 if digits > 16 {
229 return Err("Too many hexadecimal digits");
230 }
231 value = (value << 4) | u64::from(digit);
233 }
234 None => {
235 if ch != '_' {
237 return Err("Invalid character in hexadecimal number");
238 }
239 }
240 }
241 }
242 } else {
243 for ch in s.chars() {
245 match ch.to_digit(16) {
246 Some(digit) => {
247 digits += 1;
248 match value.checked_mul(10) {
249 None => return Err("Too large decimal number"),
250 Some(v) => value = v,
251 }
252 match value.checked_add(u64::from(digit)) {
253 None => return Err("Too large decimal number"),
254 Some(v) => value = v,
255 }
256 }
257 None => {
258 if ch != '_' {
260 return Err("Invalid character in decimal number");
261 }
262 }
263 }
264 }
265 }
266
267 if digits == 0 {
268 return Err("No digits in number");
269 }
270
271 Ok(value)
272}
273
274impl FromStr for Uimm64 {
275 type Err = &'static str;
276
277 fn from_str(s: &str) -> Result<Self, &'static str> {
279 parse_u64(s).map(Self::new)
280 }
281}
282
283pub type Uimm8 = u8;
287
288#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
292#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
293pub struct Uimm32(u32);
294
295impl From<Uimm32> for u32 {
296 fn from(val: Uimm32) -> u32 {
297 val.0
298 }
299}
300
301impl From<Uimm32> for u64 {
302 fn from(val: Uimm32) -> u64 {
303 val.0.into()
304 }
305}
306
307impl From<Uimm32> for i64 {
308 fn from(val: Uimm32) -> i64 {
309 i64::from(val.0)
310 }
311}
312
313impl From<u32> for Uimm32 {
314 fn from(x: u32) -> Self {
315 Self(x)
316 }
317}
318
319impl Display for Uimm32 {
320 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
321 if self.0 < 10_000 {
322 write!(f, "{}", self.0)
323 } else {
324 write_hex(u64::from(self.0), f)
325 }
326 }
327}
328
329impl FromStr for Uimm32 {
330 type Err = &'static str;
331
332 fn from_str(s: &str) -> Result<Self, &'static str> {
334 parse_i64(s).and_then(|x| {
335 if 0 <= x && x <= i64::from(u32::MAX) {
336 Ok(Self(x as u32))
337 } else {
338 Err("Uimm32 out of range")
339 }
340 })
341 }
342}
343
344#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
348#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
349pub struct V128Imm(pub [u8; 16]);
350
351impl V128Imm {
352 pub fn bytes(&self) -> impl Iterator<Item = &u8> {
354 self.0.iter()
355 }
356
357 pub fn to_vec(self) -> Vec<u8> {
359 self.0.to_vec()
360 }
361
362 pub fn as_slice(&self) -> &[u8] {
364 &self.0[..]
365 }
366}
367
368impl From<&[u8]> for V128Imm {
369 fn from(slice: &[u8]) -> Self {
370 assert_eq!(slice.len(), 16);
371 let mut buffer = [0; 16];
372 buffer.copy_from_slice(slice);
373 Self(buffer)
374 }
375}
376
377impl From<u128> for V128Imm {
378 fn from(val: u128) -> Self {
379 V128Imm(val.to_le_bytes())
380 }
381}
382
383#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
388#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
389pub struct Offset32(i32);
390
391impl Offset32 {
392 pub fn new(x: i32) -> Self {
394 Self(x)
395 }
396
397 pub fn try_from_i64(x: i64) -> Option<Self> {
399 let x = i32::try_from(x).ok()?;
400 Some(Self::new(x))
401 }
402
403 pub fn try_add_i64(self, x: i64) -> Option<Self> {
405 let x = i32::try_from(x).ok()?;
406 let ret = self.0.checked_add(x)?;
407 Some(Self::new(ret))
408 }
409}
410
411impl From<Offset32> for i32 {
412 fn from(val: Offset32) -> i32 {
413 val.0
414 }
415}
416
417impl From<Offset32> for i64 {
418 fn from(val: Offset32) -> i64 {
419 i64::from(val.0)
420 }
421}
422
423impl From<i32> for Offset32 {
424 fn from(x: i32) -> Self {
425 Self(x)
426 }
427}
428
429impl From<u8> for Offset32 {
430 fn from(val: u8) -> Offset32 {
431 Self(val.into())
432 }
433}
434
435impl Display for Offset32 {
436 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
437 if self.0 == 0 {
439 return Ok(());
440 }
441
442 write!(f, "{}", if self.0 < 0 { '-' } else { '+' })?;
444
445 let val = i64::from(self.0).abs();
446 if val < 10_000 {
447 write!(f, "{}", val)
448 } else {
449 write_hex(val as u64, f)
450 }
451 }
452}
453
454impl FromStr for Offset32 {
455 type Err = &'static str;
456
457 fn from_str(s: &str) -> Result<Self, &'static str> {
459 if !(s.starts_with('-') || s.starts_with('+')) {
460 return Err("Offset must begin with sign");
461 }
462 parse_i64(s).and_then(|x| {
463 if i64::from(i32::MIN) <= x && x <= i64::from(i32::MAX) {
464 Ok(Self::new(x as i32))
465 } else {
466 Err("Offset out of range")
467 }
468 })
469 }
470}
471
472#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
483#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
484#[repr(C)]
485pub struct Ieee32(u32);
486
487#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
498#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
499#[repr(C)]
500pub struct Ieee64(u64);
501
502fn format_float(bits: u64, w: u8, t: u8, f: &mut Formatter) -> fmt::Result {
513 debug_assert!(w > 0 && w <= 16, "Invalid exponent range");
514 debug_assert!(1 + w + t <= 64, "Too large IEEE format for u64");
515 debug_assert!((t + w + 1).is_power_of_two(), "Unexpected IEEE format size");
516
517 let max_e_bits = (1u64 << w) - 1;
518 let t_bits = bits & ((1u64 << t) - 1); let e_bits = (bits >> t) & max_e_bits; let sign_bit = (bits >> (w + t)) & 1;
521
522 let bias: i32 = (1 << (w - 1)) - 1;
523 let e = e_bits as i32 - bias; let emin = 1 - bias; let digits = (t + 3) / 4;
528 let left_t_bits = t_bits << (4 * digits - t);
530
531 if sign_bit != 0 {
533 write!(f, "-")?;
534 }
535
536 if e_bits == 0 {
537 if t_bits == 0 {
538 write!(f, "0.0")
540 } else {
541 write!(
543 f,
544 "0x0.{0:01$x}p{2}",
545 left_t_bits,
546 usize::from(digits),
547 emin
548 )
549 }
550 } else if e_bits == max_e_bits {
551 if sign_bit == 0 {
554 write!(f, "+")?;
555 }
556 if t_bits == 0 {
557 write!(f, "Inf")
559 } else {
560 let payload = t_bits & ((1 << (t - 1)) - 1);
562 if t_bits & (1 << (t - 1)) != 0 {
563 if payload != 0 {
565 write!(f, "NaN:0x{:x}", payload)
566 } else {
567 write!(f, "NaN")
568 }
569 } else {
570 write!(f, "sNaN:0x{:x}", payload)
572 }
573 }
574 } else {
575 write!(f, "0x1.{0:01$x}p{2}", left_t_bits, usize::from(digits), e)
577 }
578}
579
580fn parse_float(s: &str, w: u8, t: u8) -> Result<u64, &'static str> {
588 debug_assert!(w > 0 && w <= 16, "Invalid exponent range");
589 debug_assert!(1 + w + t <= 64, "Too large IEEE format for u64");
590 debug_assert!((t + w + 1).is_power_of_two(), "Unexpected IEEE format size");
591
592 let (sign_bit, s2) = if s.starts_with('-') {
593 (1u64 << (t + w), &s[1..])
594 } else if s.starts_with('+') {
595 (0, &s[1..])
596 } else {
597 (0, s)
598 };
599
600 if !s2.starts_with("0x") {
601 let max_e_bits = ((1u64 << w) - 1) << t;
602 let quiet_bit = 1u64 << (t - 1);
603
604 if s2 == "0.0" {
606 return Ok(sign_bit);
607 }
608
609 if s2 == "Inf" {
610 return Ok(sign_bit | max_e_bits);
612 }
613 if s2 == "NaN" {
614 return Ok(sign_bit | max_e_bits | quiet_bit);
616 }
617 if s2.starts_with("NaN:0x") {
618 return match u64::from_str_radix(&s2[6..], 16) {
620 Ok(payload) if payload < quiet_bit => {
621 Ok(sign_bit | max_e_bits | quiet_bit | payload)
622 }
623 _ => Err("Invalid NaN payload"),
624 };
625 }
626 if s2.starts_with("sNaN:0x") {
627 return match u64::from_str_radix(&s2[7..], 16) {
629 Ok(payload) if 0 < payload && payload < quiet_bit => {
630 Ok(sign_bit | max_e_bits | payload)
631 }
632 _ => Err("Invalid sNaN payload"),
633 };
634 }
635
636 return Err("Float must be hexadecimal");
637 }
638 let s3 = &s2[2..];
639
640 let mut digits = 0u8;
641 let mut digits_before_period: Option<u8> = None;
642 let mut significand = 0u64;
643 let mut exponent = 0i32;
644
645 for (idx, ch) in s3.char_indices() {
646 match ch {
647 '.' => {
648 if digits_before_period != None {
650 return Err("Multiple radix points");
651 } else {
652 digits_before_period = Some(digits);
653 }
654 }
655 'p' => {
656 let exp_str = &s3[1 + idx..];
658 match exp_str.parse::<i16>() {
659 Ok(e) => {
660 exponent = i32::from(e);
661 break;
662 }
663 Err(_) => return Err("Bad exponent"),
664 }
665 }
666 _ => match ch.to_digit(16) {
667 Some(digit) => {
668 digits += 1;
669 if digits > 16 {
670 return Err("Too many digits");
671 }
672 significand = (significand << 4) | u64::from(digit);
673 }
674 None => return Err("Invalid character"),
675 },
676 }
677 }
678
679 if digits == 0 {
680 return Err("No digits");
681 }
682
683 if significand == 0 {
684 return Ok(sign_bit);
686 }
687
688 match digits_before_period {
690 None => {} Some(d) => exponent -= 4 * i32::from(digits - d),
692 };
693
694 let significant_bits = (64 - significand.leading_zeros()) as u8;
696 if significant_bits > t + 1 {
697 let adjust = significant_bits - (t + 1);
698 if significand & ((1u64 << adjust) - 1) != 0 {
699 return Err("Too many significant bits");
700 }
701 significand >>= adjust;
703 exponent += i32::from(adjust);
704 } else {
705 let adjust = t + 1 - significant_bits;
706 significand <<= adjust;
707 exponent -= i32::from(adjust);
708 }
709 debug_assert_eq!(significand >> t, 1);
710
711 let t_bits = significand & ((1 << t) - 1);
713
714 let max_exp = (1i32 << w) - 2;
715 let bias: i32 = (1 << (w - 1)) - 1;
716 exponent += bias + i32::from(t);
717
718 if exponent > max_exp {
719 Err("Magnitude too large")
720 } else if exponent > 0 {
721 let e_bits = (exponent as u64) << t;
723 Ok(sign_bit | e_bits | t_bits)
724 } else if 1 - exponent <= i32::from(t) {
725 let adjust = 1 - exponent;
728 if significand & ((1u64 << adjust) - 1) != 0 {
729 Err("Subnormal underflow")
730 } else {
731 significand >>= adjust;
732 Ok(sign_bit | significand)
733 }
734 } else {
735 Err("Magnitude too small")
736 }
737}
738
739impl Ieee32 {
740 pub fn with_bits(x: u32) -> Self {
742 Self(x)
743 }
744
745 pub fn pow2<I: Into<i32>>(n: I) -> Self {
747 let n = n.into();
748 let w = 8;
749 let t = 23;
750 let bias = (1 << (w - 1)) - 1;
751 let exponent = (n + bias) as u32;
752 assert!(exponent > 0, "Underflow n={}", n);
753 assert!(exponent < (1 << w) + 1, "Overflow n={}", n);
754 Self(exponent << t)
755 }
756
757 pub fn fcvt_to_sint_negative_overflow<I: Into<i32>>(n: I) -> Self {
760 let n = n.into();
761 debug_assert!(n < 32);
762 debug_assert!(23 + 1 - n < 32);
763 Self::with_bits((1u32 << (32 - 1)) | Self::pow2(n - 1).0 | (1u32 << (23 + 1 - n)))
764 }
765
766 pub fn neg(self) -> Self {
768 Self(self.0 ^ (1 << 31))
769 }
770
771 pub fn with_float(x: f32) -> Self {
773 Self(x.to_bits())
774 }
775
776 pub fn bits(self) -> u32 {
778 self.0
779 }
780
781 pub fn is_nan(&self) -> bool {
783 self.as_f32().is_nan()
784 }
785
786 pub fn as_f32(self) -> f32 {
788 f32::from_bits(self.0)
789 }
790
791 pub fn sqrt(self) -> Self {
793 Self::with_float(self.as_f32().sqrt())
794 }
795
796 pub fn abs(self) -> Self {
798 Self::with_float(self.as_f32().abs())
799 }
800
801 pub fn copysign(self, sign: Self) -> Self {
803 Self::with_float(self.as_f32().copysign(sign.as_f32()))
804 }
805
806 pub fn is_negative(&self) -> bool {
808 self.as_f32().is_sign_negative()
809 }
810
811 pub fn is_zero(&self) -> bool {
813 self.as_f32() == 0.0
814 }
815
816 pub fn ceil(self) -> Self {
818 Self::with_float(self.as_f32().ceil())
819 }
820
821 pub fn floor(self) -> Self {
823 Self::with_float(self.as_f32().floor())
824 }
825
826 pub fn trunc(self) -> Self {
828 Self::with_float(self.as_f32().trunc())
829 }
830
831 pub fn round_ties_even(self) -> Self {
834 let toint_32: f32 = 1.0 / f32::EPSILON;
837
838 let f = self.as_f32();
839 let e = self.0 >> 23 & 0xff;
840 if e >= 0x7f_u32 + 23 {
841 self
842 } else {
843 Self::with_float((f.abs() + toint_32 - toint_32).copysign(f))
844 }
845 }
846}
847
848impl PartialOrd for Ieee32 {
849 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
850 self.as_f32().partial_cmp(&other.as_f32())
851 }
852}
853
854impl Display for Ieee32 {
855 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
856 let bits: u32 = self.0;
857 format_float(u64::from(bits), 8, 23, f)
858 }
859}
860
861impl FromStr for Ieee32 {
862 type Err = &'static str;
863
864 fn from_str(s: &str) -> Result<Self, &'static str> {
865 match parse_float(s, 8, 23) {
866 Ok(b) => Ok(Self(b as u32)),
867 Err(s) => Err(s),
868 }
869 }
870}
871
872impl From<f32> for Ieee32 {
873 fn from(x: f32) -> Self {
874 Self::with_float(x)
875 }
876}
877
878impl IntoBytes for Ieee32 {
879 fn into_bytes(self) -> Vec<u8> {
880 self.0.to_le_bytes().to_vec()
881 }
882}
883
884impl Neg for Ieee32 {
885 type Output = Ieee32;
886
887 fn neg(self) -> Self::Output {
888 Self::with_float(self.as_f32().neg())
889 }
890}
891
892impl Add for Ieee32 {
893 type Output = Ieee32;
894
895 fn add(self, rhs: Self) -> Self::Output {
896 Self::with_float(self.as_f32() + rhs.as_f32())
897 }
898}
899
900impl Sub for Ieee32 {
901 type Output = Ieee32;
902
903 fn sub(self, rhs: Self) -> Self::Output {
904 Self::with_float(self.as_f32() - rhs.as_f32())
905 }
906}
907
908impl Mul for Ieee32 {
909 type Output = Ieee32;
910
911 fn mul(self, rhs: Self) -> Self::Output {
912 Self::with_float(self.as_f32() * rhs.as_f32())
913 }
914}
915
916impl Div for Ieee32 {
917 type Output = Ieee32;
918
919 fn div(self, rhs: Self) -> Self::Output {
920 Self::with_float(self.as_f32() / rhs.as_f32())
921 }
922}
923
924impl BitAnd for Ieee32 {
925 type Output = Ieee32;
926
927 fn bitand(self, rhs: Self) -> Self::Output {
928 Self::with_bits(self.bits() & rhs.bits())
929 }
930}
931
932impl BitOr for Ieee32 {
933 type Output = Ieee32;
934
935 fn bitor(self, rhs: Self) -> Self::Output {
936 Self::with_bits(self.bits() | rhs.bits())
937 }
938}
939
940impl BitXor for Ieee32 {
941 type Output = Ieee32;
942
943 fn bitxor(self, rhs: Self) -> Self::Output {
944 Self::with_bits(self.bits() ^ rhs.bits())
945 }
946}
947
948impl Not for Ieee32 {
949 type Output = Ieee32;
950
951 fn not(self) -> Self::Output {
952 Self::with_bits(!self.bits())
953 }
954}
955
956impl Ieee64 {
957 pub fn with_bits(x: u64) -> Self {
959 Self(x)
960 }
961
962 pub fn pow2<I: Into<i64>>(n: I) -> Self {
964 let n = n.into();
965 let w = 11;
966 let t = 52;
967 let bias = (1 << (w - 1)) - 1;
968 let exponent = (n + bias) as u64;
969 assert!(exponent > 0, "Underflow n={}", n);
970 assert!(exponent < (1 << w) + 1, "Overflow n={}", n);
971 Self(exponent << t)
972 }
973
974 pub fn fcvt_to_sint_negative_overflow<I: Into<i64>>(n: I) -> Self {
977 let n = n.into();
978 debug_assert!(n < 64);
979 debug_assert!(52 + 1 - n < 64);
980 Self::with_bits((1u64 << (64 - 1)) | Self::pow2(n - 1).0 | (1u64 << (52 + 1 - n)))
981 }
982
983 pub fn neg(self) -> Self {
985 Self(self.0 ^ (1 << 63))
986 }
987
988 pub fn with_float(x: f64) -> Self {
990 Self(x.to_bits())
991 }
992
993 pub fn bits(self) -> u64 {
995 self.0
996 }
997
998 pub fn is_nan(&self) -> bool {
1001 self.as_f64().is_nan()
1002 }
1003
1004 pub fn as_f64(self) -> f64 {
1006 f64::from_bits(self.0)
1007 }
1008
1009 pub fn sqrt(self) -> Self {
1011 Self::with_float(self.as_f64().sqrt())
1012 }
1013
1014 pub fn abs(self) -> Self {
1016 Self::with_float(self.as_f64().abs())
1017 }
1018
1019 pub fn copysign(self, sign: Self) -> Self {
1021 Self::with_float(self.as_f64().copysign(sign.as_f64()))
1022 }
1023
1024 pub fn is_negative(&self) -> bool {
1026 self.as_f64().is_sign_negative()
1027 }
1028
1029 pub fn is_zero(&self) -> bool {
1031 self.as_f64() == 0.0
1032 }
1033
1034 pub fn ceil(self) -> Self {
1036 Self::with_float(self.as_f64().ceil())
1037 }
1038
1039 pub fn floor(self) -> Self {
1041 Self::with_float(self.as_f64().floor())
1042 }
1043
1044 pub fn trunc(self) -> Self {
1046 Self::with_float(self.as_f64().trunc())
1047 }
1048
1049 pub fn round_ties_even(self) -> Self {
1052 let toint_64: f64 = 1.0 / f64::EPSILON;
1055
1056 let f = self.as_f64();
1057 let e = self.0 >> 52 & 0x7ff_u64;
1058 if e >= 0x3ff_u64 + 52 {
1059 self
1060 } else {
1061 Self::with_float((f.abs() + toint_64 - toint_64).copysign(f))
1062 }
1063 }
1064}
1065
1066impl PartialOrd for Ieee64 {
1067 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1068 self.as_f64().partial_cmp(&other.as_f64())
1069 }
1070}
1071
1072impl Display for Ieee64 {
1073 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1074 let bits: u64 = self.0;
1075 format_float(bits, 11, 52, f)
1076 }
1077}
1078
1079impl FromStr for Ieee64 {
1080 type Err = &'static str;
1081
1082 fn from_str(s: &str) -> Result<Self, &'static str> {
1083 match parse_float(s, 11, 52) {
1084 Ok(b) => Ok(Self(b)),
1085 Err(s) => Err(s),
1086 }
1087 }
1088}
1089
1090impl From<f64> for Ieee64 {
1091 fn from(x: f64) -> Self {
1092 Self::with_float(x)
1093 }
1094}
1095
1096impl From<u64> for Ieee64 {
1097 fn from(x: u64) -> Self {
1098 Self::with_float(f64::from_bits(x))
1099 }
1100}
1101
1102impl IntoBytes for Ieee64 {
1103 fn into_bytes(self) -> Vec<u8> {
1104 self.0.to_le_bytes().to_vec()
1105 }
1106}
1107
1108impl Neg for Ieee64 {
1109 type Output = Ieee64;
1110
1111 fn neg(self) -> Self::Output {
1112 Self::with_float(self.as_f64().neg())
1113 }
1114}
1115
1116impl Add for Ieee64 {
1117 type Output = Ieee64;
1118
1119 fn add(self, rhs: Self) -> Self::Output {
1120 Self::with_float(self.as_f64() + rhs.as_f64())
1121 }
1122}
1123
1124impl Sub for Ieee64 {
1125 type Output = Ieee64;
1126
1127 fn sub(self, rhs: Self) -> Self::Output {
1128 Self::with_float(self.as_f64() - rhs.as_f64())
1129 }
1130}
1131
1132impl Mul for Ieee64 {
1133 type Output = Ieee64;
1134
1135 fn mul(self, rhs: Self) -> Self::Output {
1136 Self::with_float(self.as_f64() * rhs.as_f64())
1137 }
1138}
1139
1140impl Div for Ieee64 {
1141 type Output = Ieee64;
1142
1143 fn div(self, rhs: Self) -> Self::Output {
1144 Self::with_float(self.as_f64() / rhs.as_f64())
1145 }
1146}
1147
1148impl BitAnd for Ieee64 {
1149 type Output = Ieee64;
1150
1151 fn bitand(self, rhs: Self) -> Self::Output {
1152 Self::with_bits(self.bits() & rhs.bits())
1153 }
1154}
1155
1156impl BitOr for Ieee64 {
1157 type Output = Ieee64;
1158
1159 fn bitor(self, rhs: Self) -> Self::Output {
1160 Self::with_bits(self.bits() | rhs.bits())
1161 }
1162}
1163
1164impl BitXor for Ieee64 {
1165 type Output = Ieee64;
1166
1167 fn bitxor(self, rhs: Self) -> Self::Output {
1168 Self::with_bits(self.bits() ^ rhs.bits())
1169 }
1170}
1171
1172impl Not for Ieee64 {
1173 type Output = Ieee64;
1174
1175 fn not(self) -> Self::Output {
1176 Self::with_bits(!self.bits())
1177 }
1178}
1179
1180#[cfg(test)]
1181mod tests {
1182 use super::*;
1183 use alloc::string::ToString;
1184 use core::fmt::Display;
1185 use core::mem;
1186 use core::str::FromStr;
1187 use core::{f32, f64};
1188
1189 #[test]
1190 fn format_imm64() {
1191 assert_eq!(Imm64(0).to_string(), "0");
1192 assert_eq!(Imm64(9999).to_string(), "9999");
1193 assert_eq!(Imm64(10000).to_string(), "0x2710");
1194 assert_eq!(Imm64(-9999).to_string(), "-9999");
1195 assert_eq!(Imm64(-10000).to_string(), "0xffff_ffff_ffff_d8f0");
1196 assert_eq!(Imm64(0xffff).to_string(), "0xffff");
1197 assert_eq!(Imm64(0x10000).to_string(), "0x0001_0000");
1198 }
1199
1200 #[test]
1201 fn format_uimm64() {
1202 assert_eq!(Uimm64(0).to_string(), "0");
1203 assert_eq!(Uimm64(9999).to_string(), "9999");
1204 assert_eq!(Uimm64(10000).to_string(), "0x2710");
1205 assert_eq!(Uimm64(-9999i64 as u64).to_string(), "0xffff_ffff_ffff_d8f1");
1206 assert_eq!(
1207 Uimm64(-10000i64 as u64).to_string(),
1208 "0xffff_ffff_ffff_d8f0"
1209 );
1210 assert_eq!(Uimm64(0xffff).to_string(), "0xffff");
1211 assert_eq!(Uimm64(0x10000).to_string(), "0x0001_0000");
1212 }
1213
1214 fn parse_ok<T: FromStr + Display>(text: &str, want: &str)
1216 where
1217 <T as FromStr>::Err: Display,
1218 {
1219 match text.parse::<T>() {
1220 Err(s) => panic!("\"{}\".parse() error: {}", text, s),
1221 Ok(x) => assert_eq!(x.to_string(), want),
1222 }
1223 }
1224
1225 fn parse_err<T: FromStr + Display>(text: &str, msg: &str)
1227 where
1228 <T as FromStr>::Err: Display,
1229 {
1230 match text.parse::<T>() {
1231 Err(s) => assert_eq!(s.to_string(), msg),
1232 Ok(x) => panic!("Wanted Err({}), but got {}", msg, x),
1233 }
1234 }
1235
1236 #[test]
1237 fn parse_imm64() {
1238 parse_ok::<Imm64>("0", "0");
1239 parse_ok::<Imm64>("1", "1");
1240 parse_ok::<Imm64>("-0", "0");
1241 parse_ok::<Imm64>("-1", "-1");
1242 parse_ok::<Imm64>("0x0", "0");
1243 parse_ok::<Imm64>("0xf", "15");
1244 parse_ok::<Imm64>("-0x9", "-9");
1245
1246 parse_ok::<Imm64>("0xffffffff_ffffffff", "-1");
1248 parse_ok::<Imm64>("0x80000000_00000000", "0x8000_0000_0000_0000");
1249 parse_ok::<Imm64>("-0x80000000_00000000", "0x8000_0000_0000_0000");
1250 parse_err::<Imm64>("-0x80000000_00000001", "Negative number too small");
1251 parse_ok::<Imm64>("18446744073709551615", "-1");
1252 parse_ok::<Imm64>("-9223372036854775808", "0x8000_0000_0000_0000");
1253 parse_err::<Imm64>("18446744073709551616", "Too large decimal number");
1255 parse_err::<Imm64>("184467440737095516100", "Too large decimal number");
1256 parse_err::<Imm64>("-9223372036854775809", "Negative number too small");
1257
1258 parse_ok::<Imm64>("0_0", "0");
1260 parse_ok::<Imm64>("-_10_0", "-100");
1261 parse_ok::<Imm64>("_10_", "10");
1262 parse_ok::<Imm64>("0x97_88_bb", "0x0097_88bb");
1263 parse_ok::<Imm64>("0x_97_", "151");
1264
1265 parse_err::<Imm64>("", "No digits in number");
1266 parse_err::<Imm64>("-", "No digits in number");
1267 parse_err::<Imm64>("_", "No digits in number");
1268 parse_err::<Imm64>("0x", "No digits in number");
1269 parse_err::<Imm64>("0x_", "No digits in number");
1270 parse_err::<Imm64>("-0x", "No digits in number");
1271 parse_err::<Imm64>(" ", "Invalid character in decimal number");
1272 parse_err::<Imm64>("0 ", "Invalid character in decimal number");
1273 parse_err::<Imm64>(" 0", "Invalid character in decimal number");
1274 parse_err::<Imm64>("--", "Invalid character in decimal number");
1275 parse_err::<Imm64>("-0x-", "Invalid character in hexadecimal number");
1276
1277 parse_err::<Imm64>("0x0_0000_0000_0000_0000", "Too many hexadecimal digits");
1279 }
1280
1281 #[test]
1282 fn parse_uimm64() {
1283 parse_ok::<Uimm64>("0", "0");
1284 parse_ok::<Uimm64>("1", "1");
1285 parse_ok::<Uimm64>("0x0", "0");
1286 parse_ok::<Uimm64>("0xf", "15");
1287 parse_ok::<Uimm64>("0xffffffff_fffffff7", "0xffff_ffff_ffff_fff7");
1288
1289 parse_ok::<Uimm64>("0xffffffff_ffffffff", "0xffff_ffff_ffff_ffff");
1291 parse_ok::<Uimm64>("0x80000000_00000000", "0x8000_0000_0000_0000");
1292 parse_ok::<Uimm64>("18446744073709551615", "0xffff_ffff_ffff_ffff");
1293 parse_err::<Uimm64>("18446744073709551616", "Too large decimal number");
1295 parse_err::<Uimm64>("184467440737095516100", "Too large decimal number");
1296
1297 parse_ok::<Uimm64>("0_0", "0");
1299 parse_ok::<Uimm64>("_10_", "10");
1300 parse_ok::<Uimm64>("0x97_88_bb", "0x0097_88bb");
1301 parse_ok::<Uimm64>("0x_97_", "151");
1302
1303 parse_err::<Uimm64>("", "No digits in number");
1304 parse_err::<Uimm64>("_", "No digits in number");
1305 parse_err::<Uimm64>("0x", "No digits in number");
1306 parse_err::<Uimm64>("0x_", "No digits in number");
1307 parse_err::<Uimm64>("-", "Invalid character in decimal number");
1308 parse_err::<Uimm64>("-0x", "Invalid character in hexadecimal number");
1309 parse_err::<Uimm64>(" ", "Invalid character in decimal number");
1310 parse_err::<Uimm64>("0 ", "Invalid character in decimal number");
1311 parse_err::<Uimm64>(" 0", "Invalid character in decimal number");
1312 parse_err::<Uimm64>("--", "Invalid character in decimal number");
1313 parse_err::<Uimm64>("-0x-", "Invalid character in hexadecimal number");
1314 parse_err::<Uimm64>("-0", "Invalid character in decimal number");
1315 parse_err::<Uimm64>("-1", "Invalid character in decimal number");
1316
1317 parse_err::<Uimm64>("0x0_0000_0000_0000_0000", "Too many hexadecimal digits");
1319 }
1320
1321 #[test]
1322 fn format_offset32() {
1323 assert_eq!(Offset32(0).to_string(), "");
1324 assert_eq!(Offset32(1).to_string(), "+1");
1325 assert_eq!(Offset32(-1).to_string(), "-1");
1326 assert_eq!(Offset32(9999).to_string(), "+9999");
1327 assert_eq!(Offset32(10000).to_string(), "+0x2710");
1328 assert_eq!(Offset32(-9999).to_string(), "-9999");
1329 assert_eq!(Offset32(-10000).to_string(), "-0x2710");
1330 assert_eq!(Offset32(0xffff).to_string(), "+0xffff");
1331 assert_eq!(Offset32(0x10000).to_string(), "+0x0001_0000");
1332 }
1333
1334 #[test]
1335 fn parse_offset32() {
1336 parse_ok::<Offset32>("+0", "");
1337 parse_ok::<Offset32>("+1", "+1");
1338 parse_ok::<Offset32>("-0", "");
1339 parse_ok::<Offset32>("-1", "-1");
1340 parse_ok::<Offset32>("+0x0", "");
1341 parse_ok::<Offset32>("+0xf", "+15");
1342 parse_ok::<Offset32>("-0x9", "-9");
1343 parse_ok::<Offset32>("-0x8000_0000", "-0x8000_0000");
1344
1345 parse_err::<Offset32>("+0x8000_0000", "Offset out of range");
1346 }
1347
1348 #[test]
1349 fn format_ieee32() {
1350 assert_eq!(Ieee32::with_float(0.0).to_string(), "0.0");
1351 assert_eq!(Ieee32::with_float(-0.0).to_string(), "-0.0");
1352 assert_eq!(Ieee32::with_float(1.0).to_string(), "0x1.000000p0");
1353 assert_eq!(Ieee32::with_float(1.5).to_string(), "0x1.800000p0");
1354 assert_eq!(Ieee32::with_float(0.5).to_string(), "0x1.000000p-1");
1355 assert_eq!(
1356 Ieee32::with_float(f32::EPSILON).to_string(),
1357 "0x1.000000p-23"
1358 );
1359 assert_eq!(Ieee32::with_float(f32::MIN).to_string(), "-0x1.fffffep127");
1360 assert_eq!(Ieee32::with_float(f32::MAX).to_string(), "0x1.fffffep127");
1361 assert_eq!(
1363 Ieee32::with_float(f32::MIN_POSITIVE).to_string(),
1364 "0x1.000000p-126"
1365 );
1366 assert_eq!(
1368 Ieee32::with_float(f32::MIN_POSITIVE / 2.0).to_string(),
1369 "0x0.800000p-126"
1370 );
1371 assert_eq!(
1372 Ieee32::with_float(f32::MIN_POSITIVE * f32::EPSILON).to_string(),
1373 "0x0.000002p-126"
1374 );
1375 assert_eq!(Ieee32::with_float(f32::INFINITY).to_string(), "+Inf");
1376 assert_eq!(Ieee32::with_float(f32::NEG_INFINITY).to_string(), "-Inf");
1377 assert_eq!(Ieee32::with_float(f32::NAN).to_string(), "+NaN");
1378 assert_eq!(Ieee32::with_float(-f32::NAN).to_string(), "-NaN");
1379 assert_eq!(Ieee32(0x7fc00001).to_string(), "+NaN:0x1");
1381 assert_eq!(Ieee32(0x7ff00001).to_string(), "+NaN:0x300001");
1382 assert_eq!(Ieee32(0x7f800001).to_string(), "+sNaN:0x1");
1384 assert_eq!(Ieee32(0x7fa00001).to_string(), "+sNaN:0x200001");
1385 }
1386
1387 #[test]
1388 fn parse_ieee32() {
1389 parse_ok::<Ieee32>("0.0", "0.0");
1390 parse_ok::<Ieee32>("+0.0", "0.0");
1391 parse_ok::<Ieee32>("-0.0", "-0.0");
1392 parse_ok::<Ieee32>("0x0", "0.0");
1393 parse_ok::<Ieee32>("0x0.0", "0.0");
1394 parse_ok::<Ieee32>("0x.0", "0.0");
1395 parse_ok::<Ieee32>("0x0.", "0.0");
1396 parse_ok::<Ieee32>("0x1", "0x1.000000p0");
1397 parse_ok::<Ieee32>("+0x1", "0x1.000000p0");
1398 parse_ok::<Ieee32>("-0x1", "-0x1.000000p0");
1399 parse_ok::<Ieee32>("0x10", "0x1.000000p4");
1400 parse_ok::<Ieee32>("0x10.0", "0x1.000000p4");
1401 parse_err::<Ieee32>("0.", "Float must be hexadecimal");
1402 parse_err::<Ieee32>(".0", "Float must be hexadecimal");
1403 parse_err::<Ieee32>("0", "Float must be hexadecimal");
1404 parse_err::<Ieee32>("-0", "Float must be hexadecimal");
1405 parse_err::<Ieee32>(".", "Float must be hexadecimal");
1406 parse_err::<Ieee32>("", "Float must be hexadecimal");
1407 parse_err::<Ieee32>("-", "Float must be hexadecimal");
1408 parse_err::<Ieee32>("0x", "No digits");
1409 parse_err::<Ieee32>("0x..", "Multiple radix points");
1410
1411 parse_ok::<Ieee32>("0x0.ffffff", "0x1.fffffep-1");
1413 parse_ok::<Ieee32>("0x1.fffffe", "0x1.fffffep0");
1414 parse_ok::<Ieee32>("0x3.fffffc", "0x1.fffffep1");
1415 parse_ok::<Ieee32>("0x7.fffff8", "0x1.fffffep2");
1416 parse_ok::<Ieee32>("0xf.fffff0", "0x1.fffffep3");
1417 parse_err::<Ieee32>("0x1.ffffff", "Too many significant bits");
1418 parse_err::<Ieee32>("0x1.fffffe0000000000", "Too many digits");
1419
1420 parse_ok::<Ieee32>("0x1p3", "0x1.000000p3");
1422 parse_ok::<Ieee32>("0x1p-3", "0x1.000000p-3");
1423 parse_ok::<Ieee32>("0x1.0p3", "0x1.000000p3");
1424 parse_ok::<Ieee32>("0x2.0p3", "0x1.000000p4");
1425 parse_ok::<Ieee32>("0x1.0p127", "0x1.000000p127");
1426 parse_ok::<Ieee32>("0x1.0p-126", "0x1.000000p-126");
1427 parse_ok::<Ieee32>("0x0.1p-122", "0x1.000000p-126");
1428 parse_err::<Ieee32>("0x2.0p127", "Magnitude too large");
1429
1430 parse_ok::<Ieee32>("0x1.0p-127", "0x0.800000p-126");
1432 parse_ok::<Ieee32>("0x1.0p-149", "0x0.000002p-126");
1433 parse_ok::<Ieee32>("0x0.000002p-126", "0x0.000002p-126");
1434 parse_err::<Ieee32>("0x0.100001p-126", "Subnormal underflow");
1435 parse_err::<Ieee32>("0x1.8p-149", "Subnormal underflow");
1436 parse_err::<Ieee32>("0x1.0p-150", "Magnitude too small");
1437
1438 parse_ok::<Ieee32>("Inf", "+Inf");
1440 parse_ok::<Ieee32>("+Inf", "+Inf");
1441 parse_ok::<Ieee32>("-Inf", "-Inf");
1442 parse_ok::<Ieee32>("NaN", "+NaN");
1443 parse_ok::<Ieee32>("+NaN", "+NaN");
1444 parse_ok::<Ieee32>("-NaN", "-NaN");
1445 parse_ok::<Ieee32>("NaN:0x0", "+NaN");
1446 parse_err::<Ieee32>("NaN:", "Float must be hexadecimal");
1447 parse_err::<Ieee32>("NaN:0", "Float must be hexadecimal");
1448 parse_err::<Ieee32>("NaN:0x", "Invalid NaN payload");
1449 parse_ok::<Ieee32>("NaN:0x000001", "+NaN:0x1");
1450 parse_ok::<Ieee32>("NaN:0x300001", "+NaN:0x300001");
1451 parse_err::<Ieee32>("NaN:0x400001", "Invalid NaN payload");
1452 parse_ok::<Ieee32>("sNaN:0x1", "+sNaN:0x1");
1453 parse_err::<Ieee32>("sNaN:0x0", "Invalid sNaN payload");
1454 parse_ok::<Ieee32>("sNaN:0x200001", "+sNaN:0x200001");
1455 parse_err::<Ieee32>("sNaN:0x400001", "Invalid sNaN payload");
1456 }
1457
1458 #[test]
1459 fn pow2_ieee32() {
1460 assert_eq!(Ieee32::pow2(0).to_string(), "0x1.000000p0");
1461 assert_eq!(Ieee32::pow2(1).to_string(), "0x1.000000p1");
1462 assert_eq!(Ieee32::pow2(-1).to_string(), "0x1.000000p-1");
1463 assert_eq!(Ieee32::pow2(127).to_string(), "0x1.000000p127");
1464 assert_eq!(Ieee32::pow2(-126).to_string(), "0x1.000000p-126");
1465
1466 assert_eq!(Ieee32::pow2(1).neg().to_string(), "-0x1.000000p1");
1467 }
1468
1469 #[test]
1470 fn fcvt_to_sint_negative_overflow_ieee32() {
1471 for n in &[8, 16] {
1472 assert_eq!(-((1u32 << (n - 1)) as f32) - 1.0, unsafe {
1473 mem::transmute(Ieee32::fcvt_to_sint_negative_overflow(*n))
1474 });
1475 }
1476 }
1477
1478 #[test]
1479 fn format_ieee64() {
1480 assert_eq!(Ieee64::with_float(0.0).to_string(), "0.0");
1481 assert_eq!(Ieee64::with_float(-0.0).to_string(), "-0.0");
1482 assert_eq!(Ieee64::with_float(1.0).to_string(), "0x1.0000000000000p0");
1483 assert_eq!(Ieee64::with_float(1.5).to_string(), "0x1.8000000000000p0");
1484 assert_eq!(Ieee64::with_float(0.5).to_string(), "0x1.0000000000000p-1");
1485 assert_eq!(
1486 Ieee64::with_float(f64::EPSILON).to_string(),
1487 "0x1.0000000000000p-52"
1488 );
1489 assert_eq!(
1490 Ieee64::with_float(f64::MIN).to_string(),
1491 "-0x1.fffffffffffffp1023"
1492 );
1493 assert_eq!(
1494 Ieee64::with_float(f64::MAX).to_string(),
1495 "0x1.fffffffffffffp1023"
1496 );
1497 assert_eq!(
1499 Ieee64::with_float(f64::MIN_POSITIVE).to_string(),
1500 "0x1.0000000000000p-1022"
1501 );
1502 assert_eq!(
1504 Ieee64::with_float(f64::MIN_POSITIVE / 2.0).to_string(),
1505 "0x0.8000000000000p-1022"
1506 );
1507 assert_eq!(
1508 Ieee64::with_float(f64::MIN_POSITIVE * f64::EPSILON).to_string(),
1509 "0x0.0000000000001p-1022"
1510 );
1511 assert_eq!(Ieee64::with_float(f64::INFINITY).to_string(), "+Inf");
1512 assert_eq!(Ieee64::with_float(f64::NEG_INFINITY).to_string(), "-Inf");
1513 assert_eq!(Ieee64::with_float(f64::NAN).to_string(), "+NaN");
1514 assert_eq!(Ieee64::with_float(-f64::NAN).to_string(), "-NaN");
1515 assert_eq!(Ieee64(0x7ff8000000000001).to_string(), "+NaN:0x1");
1517 assert_eq!(
1518 Ieee64(0x7ffc000000000001).to_string(),
1519 "+NaN:0x4000000000001"
1520 );
1521 assert_eq!(Ieee64(0x7ff0000000000001).to_string(), "+sNaN:0x1");
1523 assert_eq!(
1524 Ieee64(0x7ff4000000000001).to_string(),
1525 "+sNaN:0x4000000000001"
1526 );
1527 }
1528
1529 #[test]
1530 fn parse_ieee64() {
1531 parse_ok::<Ieee64>("0.0", "0.0");
1532 parse_ok::<Ieee64>("-0.0", "-0.0");
1533 parse_ok::<Ieee64>("0x0", "0.0");
1534 parse_ok::<Ieee64>("0x0.0", "0.0");
1535 parse_ok::<Ieee64>("0x.0", "0.0");
1536 parse_ok::<Ieee64>("0x0.", "0.0");
1537 parse_ok::<Ieee64>("0x1", "0x1.0000000000000p0");
1538 parse_ok::<Ieee64>("-0x1", "-0x1.0000000000000p0");
1539 parse_ok::<Ieee64>("0x10", "0x1.0000000000000p4");
1540 parse_ok::<Ieee64>("0x10.0", "0x1.0000000000000p4");
1541 parse_err::<Ieee64>("0.", "Float must be hexadecimal");
1542 parse_err::<Ieee64>(".0", "Float must be hexadecimal");
1543 parse_err::<Ieee64>("0", "Float must be hexadecimal");
1544 parse_err::<Ieee64>("-0", "Float must be hexadecimal");
1545 parse_err::<Ieee64>(".", "Float must be hexadecimal");
1546 parse_err::<Ieee64>("", "Float must be hexadecimal");
1547 parse_err::<Ieee64>("-", "Float must be hexadecimal");
1548 parse_err::<Ieee64>("0x", "No digits");
1549 parse_err::<Ieee64>("0x..", "Multiple radix points");
1550
1551 parse_ok::<Ieee64>("0x0.fffffffffffff8", "0x1.fffffffffffffp-1");
1553 parse_ok::<Ieee64>("0x1.fffffffffffff", "0x1.fffffffffffffp0");
1554 parse_ok::<Ieee64>("0x3.ffffffffffffe", "0x1.fffffffffffffp1");
1555 parse_ok::<Ieee64>("0x7.ffffffffffffc", "0x1.fffffffffffffp2");
1556 parse_ok::<Ieee64>("0xf.ffffffffffff8", "0x1.fffffffffffffp3");
1557 parse_err::<Ieee64>("0x3.fffffffffffff", "Too many significant bits");
1558 parse_err::<Ieee64>("0x001.fffffe00000000", "Too many digits");
1559
1560 parse_ok::<Ieee64>("0x1p3", "0x1.0000000000000p3");
1562 parse_ok::<Ieee64>("0x1p-3", "0x1.0000000000000p-3");
1563 parse_ok::<Ieee64>("0x1.0p3", "0x1.0000000000000p3");
1564 parse_ok::<Ieee64>("0x2.0p3", "0x1.0000000000000p4");
1565 parse_ok::<Ieee64>("0x1.0p1023", "0x1.0000000000000p1023");
1566 parse_ok::<Ieee64>("0x1.0p-1022", "0x1.0000000000000p-1022");
1567 parse_ok::<Ieee64>("0x0.1p-1018", "0x1.0000000000000p-1022");
1568 parse_err::<Ieee64>("0x2.0p1023", "Magnitude too large");
1569
1570 parse_ok::<Ieee64>("0x1.0p-1023", "0x0.8000000000000p-1022");
1572 parse_ok::<Ieee64>("0x1.0p-1074", "0x0.0000000000001p-1022");
1573 parse_ok::<Ieee64>("0x0.0000000000001p-1022", "0x0.0000000000001p-1022");
1574 parse_err::<Ieee64>("0x0.10000000000008p-1022", "Subnormal underflow");
1575 parse_err::<Ieee64>("0x1.8p-1074", "Subnormal underflow");
1576 parse_err::<Ieee64>("0x1.0p-1075", "Magnitude too small");
1577
1578 parse_ok::<Ieee64>("Inf", "+Inf");
1580 parse_ok::<Ieee64>("-Inf", "-Inf");
1581 parse_ok::<Ieee64>("NaN", "+NaN");
1582 parse_ok::<Ieee64>("-NaN", "-NaN");
1583 parse_ok::<Ieee64>("NaN:0x0", "+NaN");
1584 parse_err::<Ieee64>("NaN:", "Float must be hexadecimal");
1585 parse_err::<Ieee64>("NaN:0", "Float must be hexadecimal");
1586 parse_err::<Ieee64>("NaN:0x", "Invalid NaN payload");
1587 parse_ok::<Ieee64>("NaN:0x000001", "+NaN:0x1");
1588 parse_ok::<Ieee64>("NaN:0x4000000000001", "+NaN:0x4000000000001");
1589 parse_err::<Ieee64>("NaN:0x8000000000001", "Invalid NaN payload");
1590 parse_ok::<Ieee64>("sNaN:0x1", "+sNaN:0x1");
1591 parse_err::<Ieee64>("sNaN:0x0", "Invalid sNaN payload");
1592 parse_ok::<Ieee64>("sNaN:0x4000000000001", "+sNaN:0x4000000000001");
1593 parse_err::<Ieee64>("sNaN:0x8000000000001", "Invalid sNaN payload");
1594 }
1595
1596 #[test]
1597 fn pow2_ieee64() {
1598 assert_eq!(Ieee64::pow2(0).to_string(), "0x1.0000000000000p0");
1599 assert_eq!(Ieee64::pow2(1).to_string(), "0x1.0000000000000p1");
1600 assert_eq!(Ieee64::pow2(-1).to_string(), "0x1.0000000000000p-1");
1601 assert_eq!(Ieee64::pow2(1023).to_string(), "0x1.0000000000000p1023");
1602 assert_eq!(Ieee64::pow2(-1022).to_string(), "0x1.0000000000000p-1022");
1603
1604 assert_eq!(Ieee64::pow2(1).neg().to_string(), "-0x1.0000000000000p1");
1605 }
1606
1607 #[test]
1608 fn fcvt_to_sint_negative_overflow_ieee64() {
1609 for n in &[8, 16, 32] {
1610 assert_eq!(-((1u64 << (n - 1)) as f64) - 1.0, unsafe {
1611 mem::transmute(Ieee64::fcvt_to_sint_negative_overflow(*n))
1612 });
1613 }
1614 }
1615}