1use crate::decimal::{Decimal, Fraction};
43
44mod arith;
45
46pub use crate::float::arith::Integral;
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
55pub enum Format {
56 Half,
58 BFloat16,
61 Single,
63 Double,
65 X87Extended,
68 Quad,
71 DoubleDouble,
84}
85
86const fn not_ieee() -> ! {
92 panic!(
93 "the double-double format is a pair of doubles rather than an IEEE encoding, so it has no \
94 single precision, no exponent range and no significand field to ask about"
95 )
96}
97
98impl Format {
99 #[must_use]
102 pub const fn name(self) -> &'static str {
103 match self {
104 Format::Half => "f16",
105 Format::BFloat16 => "bf16",
106 Format::Single => "f32",
107 Format::Double => "f64",
108 Format::X87Extended => "f80",
109 Format::Quad => "f128",
110 Format::DoubleDouble => "ppc-f128",
111 }
112 }
113
114 #[must_use]
116 pub fn from_name(name: &str) -> Option<Self> {
117 Some(match name {
118 "f16" => Format::Half,
119 "bf16" => Format::BFloat16,
120 "f32" => Format::Single,
121 "f64" => Format::Double,
122 "f80" => Format::X87Extended,
123 "f128" => Format::Quad,
124 "ppc-f128" => Format::DoubleDouble,
125 _ => return None,
126 })
127 }
128
129 #[must_use]
139 pub const fn is_ieee(self) -> bool {
140 !matches!(self, Format::DoubleDouble)
141 }
142
143 #[must_use]
149 pub const fn precision(self) -> u32 {
150 match self {
151 Format::Half => 11,
152 Format::BFloat16 => 8,
153 Format::Single => 24,
154 Format::Double => 53,
155 Format::X87Extended => 64,
156 Format::Quad => 113,
157 Format::DoubleDouble => not_ieee(),
158 }
159 }
160
161 #[must_use]
167 pub const fn max_exponent(self) -> i32 {
168 match self {
169 Format::Half => 15,
170 Format::BFloat16 | Format::Single => 127,
171 Format::Double => 1023,
172 Format::X87Extended | Format::Quad => 16383,
173 Format::DoubleDouble => not_ieee(),
174 }
175 }
176
177 #[must_use]
183 pub const fn min_exponent(self) -> i32 {
184 1 - self.max_exponent()
185 }
186
187 #[must_use]
194 pub const fn width(self) -> u32 {
195 match self {
196 Format::Half | Format::BFloat16 => 16,
197 Format::Single => 32,
198 Format::Double => 64,
199 Format::X87Extended => 80,
200 Format::Quad | Format::DoubleDouble => 128,
201 }
202 }
203
204 #[must_use]
210 pub const fn has_explicit_integer_bit(self) -> bool {
211 match self {
212 Format::X87Extended => true,
213 Format::Half | Format::BFloat16 | Format::Single | Format::Double | Format::Quad => {
214 false
215 }
216 Format::DoubleDouble => not_ieee(),
217 }
218 }
219
220 const fn exponent_bits(self) -> u32 {
222 self.width() - self.significand_bits() - 1
223 }
224
225 const fn significand_bits(self) -> u32 {
227 if self.has_explicit_integer_bit() { self.precision() } else { self.precision() - 1 }
228 }
229
230 const fn max_decimal_exponent(self) -> i32 {
236 (self.max_exponent() + 1) * 30103 / 100000 + 2
237 }
238
239 const fn min_decimal_exponent(self) -> i32 {
241 (self.min_exponent() - self.precision() as i32) * 30103 / 100000 - 2
242 }
243}
244
245#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
251pub struct Status(u8);
252
253impl Status {
254 pub const NONE: Status = Status(0);
256 pub const INEXACT: Status = Status(1);
258 pub const OVERFLOW: Status = Status(2);
260 pub const UNDERFLOW: Status = Status(4);
262 pub const INVALID: Status = Status(8);
264 pub const DIVIDE_BY_ZERO: Status = Status(16);
266
267 #[inline]
269 #[must_use]
270 pub const fn has(self, other: Status) -> bool {
271 self.0 & other.0 == other.0
272 }
273
274 #[inline]
276 #[must_use]
277 pub const fn with(self, other: Status) -> Status {
278 Status(self.0 | other.0)
279 }
280
281 #[inline]
283 #[must_use]
284 pub const fn is_none(self) -> bool {
285 self.0 == 0
286 }
287}
288
289#[derive(Debug, Clone, Copy, PartialEq, Eq)]
294pub enum ParseError {
295 NoDigits,
297 NoExponentDigits,
299 Invalid,
301}
302
303#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
305enum Category {
306 Zero,
307 Finite,
308 Infinite,
309 Nan,
310}
311
312#[derive(Debug, Clone, Copy, PartialEq, Eq)]
317pub struct Float {
318 format: Format,
319 category: Category,
320 sign: bool,
321 exponent: i32,
322 significand: u128,
323}
324
325const fn ieee(format: Format) -> Format {
331 if format.is_ieee() { format } else { not_ieee() }
332}
333
334impl Float {
335 #[must_use]
341 pub const fn zero(format: Format, sign: bool) -> Float {
342 Float { format: ieee(format), category: Category::Zero, sign, exponent: 0, significand: 0 }
343 }
344
345 #[must_use]
351 pub const fn infinity(format: Format, sign: bool) -> Float {
352 Float {
353 format: ieee(format),
354 category: Category::Infinite,
355 sign,
356 exponent: 0,
357 significand: 0,
358 }
359 }
360
361 #[must_use]
373 pub const fn smallest_normal(format: Format, sign: bool) -> Float {
374 Float {
375 format: ieee(format),
376 category: Category::Finite,
377 sign,
378 exponent: format.min_exponent(),
379 significand: 1u128 << (format.precision() - 1),
380 }
381 }
382
383 #[must_use]
396 pub const fn nan_with(format: Format, sign: bool, quiet: bool, payload: u128) -> Float {
397 let format = ieee(format);
398 let mut significand = payload & (Float::quiet_bit(format) - 1);
399 if quiet {
400 significand |= Float::quiet_bit(format);
401 } else if significand == 0 {
402 significand = Float::quiet_bit(format) >> 1;
403 }
404 Float {
405 format,
406 category: Category::Nan,
407 sign,
408 exponent: 0,
409 significand: significand | Float::leading_bit(format),
410 }
411 }
412
413 const fn quiet_bit(format: Format) -> u128 {
416 1u128 << (format.precision() - 2)
417 }
418
419 const fn leading_bit(format: Format) -> u128 {
422 if format.has_explicit_integer_bit() { 1u128 << (format.precision() - 1) } else { 0 }
423 }
424
425 #[must_use]
427 pub const fn format(self) -> Format {
428 self.format
429 }
430
431 #[must_use]
433 pub const fn is_negative(self) -> bool {
434 self.sign
435 }
436
437 #[must_use]
439 pub const fn is_zero(self) -> bool {
440 matches!(self.category, Category::Zero)
441 }
442
443 #[must_use]
445 pub const fn is_infinite(self) -> bool {
446 matches!(self.category, Category::Infinite)
447 }
448
449 #[must_use]
451 pub const fn is_finite(self) -> bool {
452 matches!(self.category, Category::Zero | Category::Finite)
453 }
454
455 #[must_use]
460 pub const fn is_normal(self) -> bool {
461 matches!(self.category, Category::Finite)
462 && self.significand >> (self.format.precision() - 1) != 0
463 }
464
465 pub fn parse(text: &str, format: Format) -> Result<(Float, Status), ParseError> {
483 let format = ieee(format);
484 let bytes = text.as_bytes();
485 let (sign, rest) = match bytes.first() {
486 Some(b'-') => (true, &bytes[1..]),
487 Some(b'+') => (false, &bytes[1..]),
488 _ => (false, bytes),
489 };
490 if rest.len() > 1 && rest[0] == b'0' && rest[1] | 32 == b'x' {
491 hexadecimal(&rest[2..], sign, format)
492 } else {
493 decimal(rest, sign, format)
494 }
495 }
496
497 #[must_use]
502 pub fn to_bits(self) -> u128 {
503 let format = self.format;
504 let significand_mask = (1u128 << format.significand_bits()) - 1;
505 let (exponent_field, significand_field) = match self.category {
506 Category::Zero => (0, 0),
507 Category::Infinite => (
508 (1u128 << format.exponent_bits()) - 1,
509 if format.has_explicit_integer_bit() {
510 1u128 << (format.precision() - 1)
511 } else {
512 0
513 },
514 ),
515 Category::Nan => ((1u128 << format.exponent_bits()) - 1, self.significand),
518 Category::Finite => {
519 let subnormal = self.significand >> (format.precision() - 1) == 0;
520 let field =
521 if subnormal { 0 } else { (self.exponent + format.max_exponent()) as u128 };
522 (field, self.significand & significand_mask)
523 }
524 };
525 let sign = u128::from(self.sign) << (format.width() - 1);
526 sign | (exponent_field << format.significand_bits()) | significand_field
527 }
528
529 #[must_use]
540 pub fn from_bits(format: Format, bits: u128) -> Float {
541 let format = ieee(format);
542 let significand_bits = format.significand_bits();
543 let sign = (bits >> (format.width() - 1)) & 1 == 1;
544 let exponent_field =
545 ((bits >> significand_bits) & ((1u128 << format.exponent_bits()) - 1)) as i32;
546 let stored = bits & ((1u128 << significand_bits) - 1);
547 if exponent_field == (1 << format.exponent_bits()) - 1 {
548 let fraction = stored & ((1u128 << (format.precision() - 1)) - 1);
551 if fraction == 0 {
552 return Float::infinity(format, sign);
553 }
554 return Float {
555 format,
556 category: Category::Nan,
557 sign,
558 exponent: 0,
559 significand: stored,
560 };
561 }
562 let implicit = if format.has_explicit_integer_bit() || exponent_field == 0 {
563 0
564 } else {
565 1u128 << (format.precision() - 1)
566 };
567 let significand = stored | implicit;
568 if significand == 0 {
569 return Float::zero(format, sign);
570 }
571 let exponent = if exponent_field == 0 {
572 format.min_exponent()
573 } else {
574 exponent_field - format.max_exponent()
575 };
576 Float { format, category: Category::Finite, sign, exponent, significand }
577 }
578
579 #[must_use]
596 pub fn to_hex(self) -> String {
597 let sign = if self.sign { "-" } else { "" };
598 match self.category {
599 Category::Nan => format!("{sign}nan"),
600 Category::Infinite => format!("{sign}0x1p+{}", self.format.max_exponent() + 1),
601 Category::Zero => format!("{sign}0x0p+0"),
602 Category::Finite => {
603 let mut significand = self.significand;
604 let mut exponent = self.exponent - (self.format.precision() as i32 - 1);
605 while significand & 0xf == 0 {
606 significand >>= 4;
607 exponent += 4;
608 }
609 format!("{sign}0x{significand:x}p{exponent:+}")
610 }
611 }
612 }
613}
614
615fn decimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
617 let mut digits = Vec::new();
618 let mut integer_digits = 0i32;
619 let mut seen_point = false;
620 let mut seen_digit = false;
621 let mut index = 0;
622 while index < bytes.len() {
623 match bytes[index] {
624 byte @ b'0'..=b'9' => {
625 digits.push(byte - b'0');
626 if !seen_point {
627 integer_digits += 1;
628 }
629 seen_digit = true;
630 }
631 b'\'' => {}
632 b'.' if !seen_point => seen_point = true,
633 b'e' | b'E' => break,
634 _ => return Err(ParseError::Invalid),
635 }
636 index += 1;
637 }
638 if !seen_digit {
639 return Err(ParseError::NoDigits);
640 }
641 let mut point = integer_digits;
642 if index < bytes.len() {
643 point = point.saturating_add(exponent_of(&bytes[index + 1..])?);
644 }
645 Ok(convert(Decimal::new(digits, point), sign, format))
646}
647
648fn hexadecimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
650 let mut significand: u128 = 0;
651 let mut exponent = 0i32;
652 let mut sticky = false;
653 let mut seen_point = false;
654 let mut seen_digit = false;
655 let mut index = 0;
656 while index < bytes.len() {
657 let byte = bytes[index];
658 let digit = match byte {
659 b'0'..=b'9' => byte - b'0',
660 b'a'..=b'f' => byte - b'a' + 10,
661 b'A'..=b'F' => byte - b'A' + 10,
662 b'\'' => {
663 index += 1;
664 continue;
665 }
666 b'.' if !seen_point => {
667 seen_point = true;
668 index += 1;
669 continue;
670 }
671 b'p' | b'P' => break,
672 _ => return Err(ParseError::Invalid),
673 };
674 seen_digit = true;
675 if significand.leading_zeros() >= 4 {
676 significand = (significand << 4) | u128::from(digit);
677 if seen_point {
678 exponent -= 4;
679 }
680 } else {
681 sticky |= digit != 0;
684 if !seen_point {
685 exponent += 4;
686 }
687 }
688 index += 1;
689 }
690 if !seen_digit {
691 return Err(ParseError::NoDigits);
692 }
693 if index < bytes.len() {
694 exponent = exponent.saturating_add(exponent_of(&bytes[index + 1..])?);
695 }
696 Ok(round(significand, exponent, sticky, sign, format))
697}
698
699fn exponent_of(bytes: &[u8]) -> Result<i32, ParseError> {
701 let (negative, digits) = match bytes.first() {
702 Some(b'-') => (true, &bytes[1..]),
703 Some(b'+') => (false, &bytes[1..]),
704 _ => (false, bytes),
705 };
706 if digits.is_empty() {
707 return Err(ParseError::NoExponentDigits);
708 }
709 let mut value = 0i32;
710 for &byte in digits {
711 if byte == b'\'' {
712 continue;
713 }
714 if !byte.is_ascii_digit() {
715 return Err(ParseError::Invalid);
716 }
717 value = value.saturating_mul(10).saturating_add(i32::from(byte - b'0'));
720 }
721 Ok(if negative { -value } else { value })
722}
723
724fn convert(mut value: Decimal, sign: bool, format: Format) -> (Float, Status) {
726 if value.is_zero() {
727 return (Float::zero(format, sign), Status::NONE);
728 }
729 if value.point() > format.max_decimal_exponent() {
730 return (Float::infinity(format, sign), Status::OVERFLOW.with(Status::INEXACT));
731 }
732 if value.point() < format.min_decimal_exponent() {
733 return (Float::zero(format, sign), Status::UNDERFLOW.with(Status::INEXACT));
734 }
735
736 let mut exponent = 0i32;
740 loop {
741 let point = value.point();
742 if point > 1 || (point == 1 && value.first_digit() >= 2) {
743 let step = binary_digits(point - 1).clamp(1, 60);
744 value.shift(-step);
745 exponent += step;
746 } else if point < 1 {
747 let step = (1 + binary_digits(-point)).clamp(1, 60);
748 value.shift(step);
749 exponent -= step;
750 } else {
751 break;
752 }
753 }
754
755 let precision = format.precision() as i32;
758 let scale = (exponent - precision + 1).max(format.min_exponent() - precision + 1);
759 value.shift(exponent - scale);
760 let (integer, fraction) = value.round_to_u128();
761 let rounded = match fraction {
762 Fraction::Zero | Fraction::BelowHalf => integer,
763 Fraction::Half => integer + (integer & 1),
764 Fraction::AboveHalf => integer + 1,
765 };
766 finish(rounded, scale, fraction != Fraction::Zero, sign, format)
767}
768
769const fn binary_digits(decimal: i32) -> i32 {
771 decimal * 33219 / 10000
772}
773
774fn round(
777 significand: u128,
778 exponent: i32,
779 sticky: bool,
780 sign: bool,
781 format: Format,
782) -> (Float, Status) {
783 if significand == 0 {
784 return (Float::zero(format, sign), Status::NONE);
785 }
786 let precision = format.precision() as i32;
787 let leading = (128 - significand.leading_zeros()) as i32;
788 let scale = (exponent + leading - precision).max(format.min_exponent() - precision + 1);
789 let mut sticky = sticky;
790 let (integer, half) = if scale <= exponent {
791 (significand << (exponent - scale), false)
792 } else {
793 let drop = (scale - exponent) as u32;
794 if drop >= 128 {
795 sticky = true;
796 (0, false)
797 } else {
798 let half = (significand >> (drop - 1)) & 1 == 1;
799 sticky |= drop > 1 && significand & ((1u128 << (drop - 1)) - 1) != 0;
800 (significand >> drop, half)
801 }
802 };
803 let rounded = if half && (sticky || integer & 1 == 1) { integer + 1 } else { integer };
804 finish(rounded, scale, half || sticky, sign, format)
805}
806
807fn finish(
810 significand: u128,
811 scale: i32,
812 inexact: bool,
813 sign: bool,
814 format: Format,
815) -> (Float, Status) {
816 let precision = format.precision();
817 let mut significand = significand;
818 let mut scale = scale;
819 if significand >> precision != 0 {
820 significand >>= 1;
822 scale += 1;
823 }
824 let mut status = if inexact { Status::INEXACT } else { Status::NONE };
825 if significand == 0 {
826 return (Float::zero(format, sign), status.with(Status::UNDERFLOW));
827 }
828 let exponent = scale + precision as i32 - 1;
829 if exponent > format.max_exponent() {
830 return (
831 Float::infinity(format, sign),
832 status.with(Status::OVERFLOW).with(Status::INEXACT),
833 );
834 }
835 let normal = significand >> (precision - 1) != 0;
836 if !normal && inexact {
837 status = status.with(Status::UNDERFLOW);
838 }
839 let exponent = if normal { exponent } else { format.min_exponent() };
840 (Float { format, category: Category::Finite, sign, exponent, significand }, status)
841}
842
843#[cfg(test)]
844mod tests {
845 use super::*;
846
847 fn double(text: &str) -> u128 {
849 Float::parse(text, Format::Double).expect("a number").0.to_bits()
850 }
851
852 fn single(text: &str) -> u128 {
854 Float::parse(text, Format::Single).expect("a number").0.to_bits()
855 }
856
857 #[test]
858 fn the_ordinary_numbers_land_where_the_host_would_put_them() {
859 for text in ["0", "1", "2", "0.5", "1.5", "3.14159", "2.718281828459045", "100", "1e10"] {
860 let host = text.parse::<f64>().expect("a number Rust reads too");
861 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
862 }
863 }
864
865 #[test]
866 fn a_number_that_needs_the_last_bit_rounded_gets_it_right() {
867 let hard = [
870 "0.1",
871 "0.3",
872 "2.2250738585072011e-308",
873 "2.2250738585072014e-308",
874 "1.7976931348623157e308",
875 "4.9406564584124654e-324",
876 "5e-324",
877 "8.98846567431158e307",
878 "9007199254740993",
879 "123456789012345678901234567890",
880 "1.000000000000000000000000000000000000000000000000000000000000000001",
881 "7.8459735791271921e65",
882 "3.518437208883201171875e13",
883 "0.500000000000000166533453693773481063544750213623046875",
884 ];
885 for text in hard {
886 let host = text.parse::<f64>().expect("a number Rust reads too");
887 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
888 }
889 }
890
891 #[test]
892 fn the_number_that_takes_seven_hundred_and_sixty_seven_digits() {
893 let text = concat!(
896 "2.47032822920623272088284396434110686182529901307162382",
897 "35378852574870103599108683372845652890455735483022221802",
898 "58573249056416711547735232764105795166208503595426876755",
899 "62317084535693494535245273750735013572761315046354601316",
900 "12127849863326369238975694273040488011871029093711789936",
901 "42245692702737764465109076580131048946378905599180391359",
902 "70011386455512221706120629864144453927884519445934871524",
903 "63344875888932891414823975864211858166195965106373837732",
904 "34435703331457550505022232309998195892058070506176382679",
905 "16323484472119097902806154870514036458498974142754747141",
906 "39683784321102080606305920253373777969877864922227306716",
907 "01324339457879181214233820577228206278891620001855078759",
908 "16278352090142077553206262229158550205643778244387017277",
909 "94459649305087139089301871550805125768938177360937844105",
910 "63661045147381814281647890691181239104545396303476425117",
911 "7562185422741845851144691421326303120484712594187004993e-324"
912 );
913 let host = text.parse::<f64>().expect("a number Rust reads too");
914 assert_eq!(double(text), u128::from(host.to_bits()));
915 }
916
917 #[test]
918 fn a_sweep_of_random_numbers_agrees_with_rust_in_every_bit() {
919 let mut state = 0x2545_f491_4f6c_dd1du64;
923 for _ in 0..4000 {
924 state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
925 let digits = state >> 11;
926 let exponent = (state % 600) as i32 - 300;
927 let text = format!("{digits}e{exponent}");
928 let host = text.parse::<f64>().expect("a number Rust reads too");
929 assert_eq!(double(&text), u128::from(host.to_bits()), "{text}");
930 let host = text.parse::<f32>().expect("a number Rust reads too");
931 assert_eq!(single(&text), u128::from(host.to_bits()), "{text} as a float");
932 }
933 }
934
935 #[test]
936 fn the_ends_of_the_range_are_an_infinity_and_a_zero() {
937 let (value, status) = Float::parse("1e400", Format::Double).expect("a number");
938 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
939 let (value, status) = Float::parse("1e-400", Format::Double).expect("a number");
940 assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
941 let (value, status) = Float::parse("1.7976931348623157e308", Format::Double).expect("one");
943 assert!(value.is_finite() && !status.has(Status::OVERFLOW));
944 let (value, _) = Float::parse("1.8e308", Format::Double).expect("a number");
945 assert!(value.is_infinite());
946 assert_eq!(double("2.4e-324"), u128::from((0f64).to_bits()));
948 assert_eq!(double("2.5e-324"), 1);
949 }
950
951 #[test]
952 fn a_number_that_is_exactly_what_was_written_says_so() {
953 assert!(Float::parse("1", Format::Double).expect("a number").1.is_none());
954 assert!(Float::parse("0.5", Format::Double).expect("a number").1.is_none());
955 assert!(Float::parse("0.1", Format::Double).expect("a number").1.has(Status::INEXACT));
956 let (_, status) = Float::parse("1e-320", Format::Double).expect("a number");
958 assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
959 }
960
961 #[test]
962 fn a_hexadecimal_constant_is_exact_and_needs_no_scaling() {
963 assert_eq!(double("0x1p0"), u128::from((1f64).to_bits()));
964 assert_eq!(double("0x1.8p1"), u128::from((3f64).to_bits()));
965 assert_eq!(double("0x1p-1074"), 1);
966 assert_eq!(double("0xa.bp-4"), u128::from((0.66796875f64).to_bits()));
967 assert_eq!(double("0X1.FFFFFFFFFFFFFP+1023"), u128::from(f64::MAX.to_bits()));
968 assert!(Float::parse("0x1p0", Format::Double).expect("a number").1.is_none());
969 let (_, status) = Float::parse("0x1.00000000000008p0", Format::Double).expect("a number");
971 assert!(status.has(Status::INEXACT));
972 assert_eq!(double("0x1.00000000000008p0"), u128::from((1f64).to_bits()));
973 assert_eq!(double("0x1.00000000000018p0"), u128::from((1f64).to_bits() + 2));
974 }
975
976 #[test]
977 fn digit_separators_are_not_part_of_the_number() {
978 assert_eq!(double("1'000.000'1"), double("1000.0001"));
979 assert_eq!(double("0x1'0p0"), double("16.0"));
980 assert_eq!(double("1e1'0"), double("1e10"));
981 }
982
983 #[test]
984 fn a_spelling_that_is_not_a_number_says_which_way_it_is_wrong() {
985 assert_eq!(Float::parse("", Format::Double), Err(ParseError::NoDigits));
986 assert_eq!(Float::parse(".", Format::Double), Err(ParseError::NoDigits));
987 assert_eq!(Float::parse("1e", Format::Double), Err(ParseError::NoExponentDigits));
988 assert_eq!(Float::parse("1e+", Format::Double), Err(ParseError::NoExponentDigits));
989 assert_eq!(Float::parse("0x1p", Format::Double), Err(ParseError::NoExponentDigits));
990 assert_eq!(Float::parse("0xp1", Format::Double), Err(ParseError::NoDigits));
991 assert_eq!(Float::parse("1x0", Format::Double), Err(ParseError::Invalid));
992 }
993
994 #[test]
995 fn a_sign_is_accepted_although_a_c_constant_never_has_one() {
996 let (value, _) = Float::parse("-1.5", Format::Double).expect("a number");
997 assert!(value.is_negative());
998 assert_eq!(value.to_bits(), u128::from((-1.5f64).to_bits()));
999 let (value, _) = Float::parse("-0.0", Format::Double).expect("a number");
1000 assert!(value.is_zero() && value.is_negative());
1001 assert_eq!(value.to_bits(), u128::from((-0.0f64).to_bits()));
1002 }
1003
1004 #[test]
1005 fn every_format_says_how_wide_its_fields_are() {
1006 for format in [
1007 Format::Half,
1008 Format::BFloat16,
1009 Format::Single,
1010 Format::Double,
1011 Format::X87Extended,
1012 Format::Quad,
1013 ] {
1014 assert_eq!(
1015 format.exponent_bits() + format.significand_bits() + 1,
1016 format.width(),
1017 "{format:?}"
1018 );
1019 assert_eq!(format.min_exponent(), 1 - format.max_exponent());
1020 }
1021 assert_eq!(Format::Half.exponent_bits(), 5);
1022 assert_eq!(Format::BFloat16.exponent_bits(), 8);
1023 assert_eq!(Format::Single.exponent_bits(), 8);
1024 assert_eq!(Format::Double.exponent_bits(), 11);
1025 assert_eq!(Format::X87Extended.exponent_bits(), 15);
1026 assert_eq!(Format::Quad.exponent_bits(), 15);
1027 }
1028
1029 #[test]
1030 fn a_number_survives_a_trip_through_its_encoding() {
1031 for format in [
1032 Format::Half,
1033 Format::BFloat16,
1034 Format::Single,
1035 Format::Double,
1036 Format::X87Extended,
1037 Format::Quad,
1038 ] {
1039 for text in ["0", "-0", "1", "-1.5", "3.14159", "1e-5", "65504", "0x1p-20"] {
1040 let (value, _) = Float::parse(text, format).expect("a number");
1041 let bits = value.to_bits();
1042 assert_eq!(Float::from_bits(format, bits).to_bits(), bits, "{text} in {format:?}");
1043 }
1044 assert_eq!(
1045 Float::from_bits(format, Float::infinity(format, false).to_bits()).to_bits(),
1046 Float::infinity(format, false).to_bits()
1047 );
1048 }
1049 }
1050
1051 #[test]
1052 fn a_hexadecimal_spelling_reads_back_as_the_number_it_came_from() {
1053 for format in [
1054 Format::Half,
1055 Format::BFloat16,
1056 Format::Single,
1057 Format::Double,
1058 Format::X87Extended,
1059 Format::Quad,
1060 ] {
1061 for text in [
1062 "0", "-0", "1", "-1", "0.5", "-1.5", "3.14159", "1e-5", "0x1p-20", "0.1", "255",
1063 "1e30",
1064 ] {
1065 let (value, _) = Float::parse(text, format).expect("a number");
1066 let spelling = value.to_hex();
1067 let (again, status) = Float::parse(&spelling, format).expect("a number");
1068 assert_eq!(again.to_bits(), value.to_bits(), "{text} as {spelling} in {format:?}");
1069 let rounded = status.has(Status::INEXACT) || status.has(Status::OVERFLOW);
1072 assert_eq!(rounded, !value.is_finite(), "{spelling} in {format:?}");
1073 }
1074 let tiny = Float::from_bits(format, 1);
1076 let (again, _) = Float::parse(&tiny.to_hex(), format).expect("a number");
1077 assert_eq!(again.to_bits(), tiny.to_bits(), "the smallest subnormal in {format:?}");
1078 let huge = Float::infinity(format, true);
1080 let (again, status) = Float::parse(&huge.to_hex(), format).expect("a number");
1081 assert!(again.is_infinite() && again.is_negative(), "{format:?}");
1082 assert!(status.has(Status::OVERFLOW));
1083 }
1084 }
1085
1086 #[test]
1087 fn a_round_number_gets_a_short_spelling() {
1088 let hex = |text: &str| Float::parse(text, Format::Double).expect("a number").0.to_hex();
1089 assert_eq!(hex("1"), "0x1p+0");
1090 assert_eq!(hex("-1"), "-0x1p+0");
1091 assert_eq!(hex("0"), "0x0p+0");
1092 assert_eq!(hex("-0"), "-0x0p+0");
1093 assert_eq!(hex("2"), "0x1p+1");
1094 assert_eq!(hex("0.5"), "0x1p-1");
1095 assert_eq!(hex("0.1"), "0x1999999999999ap-56");
1096 }
1097
1098 #[test]
1099 fn the_narrow_formats_round_where_they_are_supposed_to() {
1100 let (value, status) = Float::parse("65504", Format::Half).expect("a number");
1104 assert!(value.is_finite() && status.is_none());
1105 assert_eq!(value.to_bits(), 0x7bff);
1106 let (value, _) = Float::parse("65536", Format::Half).expect("a number");
1107 assert!(value.is_infinite());
1108 assert_eq!(Float::parse("1", Format::Half).expect("one").0.to_bits(), 0x3c00);
1109 assert_eq!(Float::parse("1", Format::BFloat16).expect("one").0.to_bits(), 0x3f80);
1110 assert_eq!(Float::parse("1e30", Format::BFloat16).expect("big").0.to_bits(), 0x714a);
1111 assert_eq!(Float::parse("0x1p-24", Format::Half).expect("tiny").0.to_bits(), 1);
1113 assert!(Float::parse("0x1p-26", Format::Half).expect("tinier").0.is_zero());
1114 }
1115
1116 #[test]
1117 fn the_x87_format_stores_the_bit_the_others_leave_implied() {
1118 let one = Float::parse("1", Format::X87Extended).expect("one").0;
1121 assert_eq!(one.to_bits(), 0x3fff_8000_0000_0000_0000);
1122 assert_eq!(
1123 Float::parse("2", Format::X87Extended).expect("two").0.to_bits(),
1124 0x4000_8000_0000_0000_0000
1125 );
1126 let (value, status) = Float::parse("9007199254740993", Format::X87Extended).expect("one");
1128 assert!(status.is_none());
1129 assert_eq!(value.to_bits(), 0x4034_8000_0000_0000_0400);
1130 assert_eq!(
1133 Float::parse("0.1", Format::X87Extended).expect("a tenth").0.to_bits(),
1134 0x3ffb_cccc_cccc_cccc_cccd
1135 );
1136 assert_eq!(Float::parse("1e-4950", Format::X87Extended).expect("tiny").0.to_bits(), 3);
1139 }
1140
1141 #[test]
1142 fn the_quad_format_has_a_hundred_and_thirteen_bits_of_it() {
1143 assert_eq!(
1144 Float::parse("1", Format::Quad).expect("one").0.to_bits(),
1145 0x3fff_0000_0000_0000_0000_0000_0000_0000
1146 );
1147 assert_eq!(
1149 Float::parse("0.1", Format::Quad).expect("a tenth").0.to_bits(),
1150 0x3ffb_9999_9999_9999_9999_9999_9999_999a
1151 );
1152 assert_eq!(
1154 Float::parse("3.14159", Format::Quad).expect("pi, roughly").0.to_bits(),
1155 0x4000_921f_9f01_b866_e43a_a79b_badc_0981
1156 );
1157 let (value, status) = Float::parse("1e5000", Format::Quad).expect("a number");
1158 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
1159 let (value, _) = Float::parse("1e-5000", Format::Quad).expect("a number");
1160 assert!(value.is_zero());
1161 }
1162
1163 #[test]
1166 fn a_nan_with_a_payload_has_the_bits_gcc_gives_it() {
1167 let double = |quiet, payload| Float::nan_with(Format::Double, false, quiet, payload);
1168 assert_eq!(double(true, 0).to_bits(), 0x7ff8_0000_0000_0000, "__builtin_nan(\"\")");
1169 assert_eq!(double(true, 1).to_bits(), 0x7ff8_0000_0000_0001, "__builtin_nan(\"0x1\")");
1170 assert_eq!(double(true, 8).to_bits(), 0x7ff8_0000_0000_0008, "__builtin_nan(\"010\")");
1171 assert_eq!(double(false, 0).to_bits(), 0x7ff4_0000_0000_0000, "__builtin_nans(\"\")");
1174 assert_eq!(double(false, 1).to_bits(), 0x7ff0_0000_0000_0001, "__builtin_nans(\"0x1\")");
1175 assert_eq!(double(true, 0xf_ffff_ffff_ffff).to_bits(), 0x7fff_ffff_ffff_ffff);
1177 assert_eq!(double(true, 1 << 52).to_bits(), 0x7ff8_0000_0000_0000);
1178 assert_eq!(
1179 Float::nan_with(Format::Single, false, true, 1).to_bits(),
1180 0x7fc0_0001,
1181 "__builtin_nanf(\"0x1\")"
1182 );
1183 assert_eq!(
1184 Float::nan_with(Format::Single, false, false, 0).to_bits(),
1185 0x7fa0_0000,
1186 "__builtin_nansf(\"\")"
1187 );
1188 assert_eq!(
1191 Float::nan_with(Format::X87Extended, false, true, 1).to_bits(),
1192 0x7fff_c000_0000_0000_0001,
1193 "__builtin_nanl(\"0x1\") on x86"
1194 );
1195 assert_eq!(
1196 Float::nan_with(Format::X87Extended, false, false, 0).to_bits(),
1197 0x7fff_a000_0000_0000_0000,
1198 "__builtin_nansl(\"\") on x86"
1199 );
1200 }
1201
1202 #[test]
1204 fn a_payload_comes_back_out_of_the_encoding_it_went_into() {
1205 for format in [Format::Half, Format::Single, Format::Double, Format::X87Extended] {
1206 for (quiet, payload) in [(true, 0), (true, 1), (false, 3), (true, 5)] {
1207 let nan = Float::nan_with(format, false, quiet, payload);
1208 assert!(nan.is_nan(), "{format:?}");
1209 assert_eq!(Float::from_bits(format, nan.to_bits()), nan, "{format:?} {payload}");
1210 }
1211 let nan = Float::nan_with(format, true, true, 7);
1213 assert!(nan.is_negative() && nan.negated().negated() == nan, "{format:?}");
1214 }
1215 }
1216
1217 #[test]
1220 fn the_smallest_normal_is_the_number_below_which_nothing_is_normal() {
1221 assert_eq!(
1222 Float::smallest_normal(Format::Single, false).to_bits(),
1223 u128::from(f32::MIN_POSITIVE.to_bits())
1224 );
1225 assert_eq!(
1226 Float::smallest_normal(Format::Double, false).to_bits(),
1227 u128::from(f64::MIN_POSITIVE.to_bits())
1228 );
1229 assert_eq!(
1232 Float::smallest_normal(Format::X87Extended, false).to_bits(),
1233 (1u128 << 64) | (1u128 << 63)
1234 );
1235 for format in [Format::Half, Format::BFloat16, Format::Single, Format::Double] {
1236 let normal = Float::smallest_normal(format, false);
1237 assert!(normal.is_finite() && !normal.is_zero(), "{format:?}");
1238 assert_eq!(Float::from_bits(format, normal.to_bits()), normal, "{format:?}");
1239 let below = Float::from_bits(format, normal.to_bits() - 1);
1242 assert_eq!(below.compare(normal), Some(std::cmp::Ordering::Less), "{format:?}");
1243 let negative = Float::smallest_normal(format, true);
1245 assert!(negative.is_negative() && negative.negated() == normal, "{format:?}");
1246 }
1247 }
1248
1249 const EVERY_FORMAT: [Format; 7] = [
1251 Format::Half,
1252 Format::BFloat16,
1253 Format::Single,
1254 Format::Double,
1255 Format::X87Extended,
1256 Format::Quad,
1257 Format::DoubleDouble,
1258 ];
1259
1260 #[test]
1261 fn the_double_double_is_the_one_format_that_is_not_an_ieee_encoding() {
1262 for format in EVERY_FORMAT {
1263 assert_eq!(format.is_ieee(), format != Format::DoubleDouble, "{format:?}");
1264 }
1265 }
1266
1267 #[test]
1268 fn every_format_has_a_name_that_reads_back_as_itself() {
1269 for format in EVERY_FORMAT {
1272 assert_eq!(Format::from_name(format.name()), Some(format), "{format:?}");
1273 }
1274 assert_eq!(Format::from_name("f128"), Some(Format::Quad));
1275 assert_eq!(Format::from_name("ppc-f128"), Some(Format::DoubleDouble));
1276 assert_eq!(Format::from_name("f256"), None);
1277 }
1278
1279 #[test]
1280 fn a_width_is_the_one_question_the_double_double_answers() {
1281 assert_eq!(Format::DoubleDouble.width(), 128);
1285 assert_eq!(Format::Quad.width(), Format::DoubleDouble.width());
1286 assert_ne!(Format::Quad, Format::DoubleDouble);
1287 }
1288
1289 #[test]
1290 #[should_panic(expected = "pair of doubles")]
1291 fn asking_a_double_double_for_a_precision_says_why_there_is_not_one() {
1292 let _ = Format::DoubleDouble.precision();
1293 }
1294
1295 #[test]
1296 #[should_panic(expected = "pair of doubles")]
1297 fn a_double_double_cannot_be_parsed_into() {
1298 let _ = Float::parse("1.0", Format::DoubleDouble);
1301 }
1302
1303 #[test]
1304 #[should_panic(expected = "pair of doubles")]
1305 fn a_double_double_cannot_be_read_out_of_its_bits_either() {
1306 let _ = Float::from_bits(Format::DoubleDouble, 0);
1307 }
1308
1309 #[test]
1310 #[should_panic(expected = "pair of doubles")]
1311 fn not_even_a_double_double_zero_can_be_made() {
1312 let _ = Float::zero(Format::DoubleDouble, false);
1316 }
1317}