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