1use crate::decimal::{Decimal, Fraction};
35
36mod arith;
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
40pub enum Format {
41 Half,
43 BFloat16,
46 Single,
48 Double,
50 X87Extended,
53 Quad,
56}
57
58impl Format {
59 #[must_use]
62 pub const fn name(self) -> &'static str {
63 match self {
64 Format::Half => "f16",
65 Format::BFloat16 => "bf16",
66 Format::Single => "f32",
67 Format::Double => "f64",
68 Format::X87Extended => "f80",
69 Format::Quad => "f128",
70 }
71 }
72
73 #[must_use]
75 pub fn from_name(name: &str) -> Option<Self> {
76 Some(match name {
77 "f16" => Format::Half,
78 "bf16" => Format::BFloat16,
79 "f32" => Format::Single,
80 "f64" => Format::Double,
81 "f80" => Format::X87Extended,
82 "f128" => Format::Quad,
83 _ => return None,
84 })
85 }
86
87 #[must_use]
89 pub const fn precision(self) -> u32 {
90 match self {
91 Format::Half => 11,
92 Format::BFloat16 => 8,
93 Format::Single => 24,
94 Format::Double => 53,
95 Format::X87Extended => 64,
96 Format::Quad => 113,
97 }
98 }
99
100 #[must_use]
102 pub const fn max_exponent(self) -> i32 {
103 match self {
104 Format::Half => 15,
105 Format::BFloat16 | Format::Single => 127,
106 Format::Double => 1023,
107 Format::X87Extended | Format::Quad => 16383,
108 }
109 }
110
111 #[must_use]
113 pub const fn min_exponent(self) -> i32 {
114 1 - self.max_exponent()
115 }
116
117 #[must_use]
120 pub const fn width(self) -> u32 {
121 match self {
122 Format::Half | Format::BFloat16 => 16,
123 Format::Single => 32,
124 Format::Double => 64,
125 Format::X87Extended => 80,
126 Format::Quad => 128,
127 }
128 }
129
130 #[must_use]
132 pub const fn has_explicit_integer_bit(self) -> bool {
133 matches!(self, Format::X87Extended)
134 }
135
136 const fn exponent_bits(self) -> u32 {
138 self.width() - self.significand_bits() - 1
139 }
140
141 const fn significand_bits(self) -> u32 {
143 if self.has_explicit_integer_bit() { self.precision() } else { self.precision() - 1 }
144 }
145
146 const fn max_decimal_exponent(self) -> i32 {
152 (self.max_exponent() + 1) * 30103 / 100000 + 2
153 }
154
155 const fn min_decimal_exponent(self) -> i32 {
157 (self.min_exponent() - self.precision() as i32) * 30103 / 100000 - 2
158 }
159}
160
161#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
167pub struct Status(u8);
168
169impl Status {
170 pub const NONE: Status = Status(0);
172 pub const INEXACT: Status = Status(1);
174 pub const OVERFLOW: Status = Status(2);
176 pub const UNDERFLOW: Status = Status(4);
178 pub const INVALID: Status = Status(8);
180 pub const DIVIDE_BY_ZERO: Status = Status(16);
182
183 #[inline]
185 #[must_use]
186 pub const fn has(self, other: Status) -> bool {
187 self.0 & other.0 == other.0
188 }
189
190 #[inline]
192 #[must_use]
193 pub const fn with(self, other: Status) -> Status {
194 Status(self.0 | other.0)
195 }
196
197 #[inline]
199 #[must_use]
200 pub const fn is_none(self) -> bool {
201 self.0 == 0
202 }
203}
204
205#[derive(Debug, Clone, Copy, PartialEq, Eq)]
210pub enum ParseError {
211 NoDigits,
213 NoExponentDigits,
215 Invalid,
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
221enum Category {
222 Zero,
223 Finite,
224 Infinite,
225 Nan,
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub struct Float {
234 format: Format,
235 category: Category,
236 sign: bool,
237 exponent: i32,
238 significand: u128,
239}
240
241impl Float {
242 #[must_use]
244 pub const fn zero(format: Format, sign: bool) -> Float {
245 Float { format, category: Category::Zero, sign, exponent: 0, significand: 0 }
246 }
247
248 #[must_use]
250 pub const fn infinity(format: Format, sign: bool) -> Float {
251 Float { format, category: Category::Infinite, sign, exponent: 0, significand: 0 }
252 }
253
254 #[must_use]
262 pub const fn smallest_normal(format: Format, sign: bool) -> Float {
263 Float {
264 format,
265 category: Category::Finite,
266 sign,
267 exponent: format.min_exponent(),
268 significand: 1u128 << (format.precision() - 1),
269 }
270 }
271
272 #[must_use]
281 pub const fn nan_with(format: Format, sign: bool, quiet: bool, payload: u128) -> Float {
282 let mut significand = payload & (Float::quiet_bit(format) - 1);
283 if quiet {
284 significand |= Float::quiet_bit(format);
285 } else if significand == 0 {
286 significand = Float::quiet_bit(format) >> 1;
287 }
288 Float {
289 format,
290 category: Category::Nan,
291 sign,
292 exponent: 0,
293 significand: significand | Float::leading_bit(format),
294 }
295 }
296
297 const fn quiet_bit(format: Format) -> u128 {
300 1u128 << (format.precision() - 2)
301 }
302
303 const fn leading_bit(format: Format) -> u128 {
306 if format.has_explicit_integer_bit() { 1u128 << (format.precision() - 1) } else { 0 }
307 }
308
309 #[must_use]
311 pub const fn format(self) -> Format {
312 self.format
313 }
314
315 #[must_use]
317 pub const fn is_negative(self) -> bool {
318 self.sign
319 }
320
321 #[must_use]
323 pub const fn is_zero(self) -> bool {
324 matches!(self.category, Category::Zero)
325 }
326
327 #[must_use]
329 pub const fn is_infinite(self) -> bool {
330 matches!(self.category, Category::Infinite)
331 }
332
333 #[must_use]
335 pub const fn is_finite(self) -> bool {
336 matches!(self.category, Category::Zero | Category::Finite)
337 }
338
339 #[must_use]
344 pub const fn is_normal(self) -> bool {
345 matches!(self.category, Category::Finite)
346 && self.significand >> (self.format.precision() - 1) != 0
347 }
348
349 pub fn parse(text: &str, format: Format) -> Result<(Float, Status), ParseError> {
361 let bytes = text.as_bytes();
362 let (sign, rest) = match bytes.first() {
363 Some(b'-') => (true, &bytes[1..]),
364 Some(b'+') => (false, &bytes[1..]),
365 _ => (false, bytes),
366 };
367 if rest.len() > 1 && rest[0] == b'0' && rest[1] | 32 == b'x' {
368 hexadecimal(&rest[2..], sign, format)
369 } else {
370 decimal(rest, sign, format)
371 }
372 }
373
374 #[must_use]
379 pub fn to_bits(self) -> u128 {
380 let format = self.format;
381 let significand_mask = (1u128 << format.significand_bits()) - 1;
382 let (exponent_field, significand_field) = match self.category {
383 Category::Zero => (0, 0),
384 Category::Infinite => (
385 (1u128 << format.exponent_bits()) - 1,
386 if format.has_explicit_integer_bit() {
387 1u128 << (format.precision() - 1)
388 } else {
389 0
390 },
391 ),
392 Category::Nan => ((1u128 << format.exponent_bits()) - 1, self.significand),
395 Category::Finite => {
396 let subnormal = self.significand >> (format.precision() - 1) == 0;
397 let field =
398 if subnormal { 0 } else { (self.exponent + format.max_exponent()) as u128 };
399 (field, self.significand & significand_mask)
400 }
401 };
402 let sign = u128::from(self.sign) << (format.width() - 1);
403 sign | (exponent_field << format.significand_bits()) | significand_field
404 }
405
406 #[must_use]
413 pub fn from_bits(format: Format, bits: u128) -> Float {
414 let significand_bits = format.significand_bits();
415 let sign = (bits >> (format.width() - 1)) & 1 == 1;
416 let exponent_field =
417 ((bits >> significand_bits) & ((1u128 << format.exponent_bits()) - 1)) as i32;
418 let stored = bits & ((1u128 << significand_bits) - 1);
419 if exponent_field == (1 << format.exponent_bits()) - 1 {
420 let fraction = stored & ((1u128 << (format.precision() - 1)) - 1);
423 if fraction == 0 {
424 return Float::infinity(format, sign);
425 }
426 return Float {
427 format,
428 category: Category::Nan,
429 sign,
430 exponent: 0,
431 significand: stored,
432 };
433 }
434 let implicit = if format.has_explicit_integer_bit() || exponent_field == 0 {
435 0
436 } else {
437 1u128 << (format.precision() - 1)
438 };
439 let significand = stored | implicit;
440 if significand == 0 {
441 return Float::zero(format, sign);
442 }
443 let exponent = if exponent_field == 0 {
444 format.min_exponent()
445 } else {
446 exponent_field - format.max_exponent()
447 };
448 Float { format, category: Category::Finite, sign, exponent, significand }
449 }
450
451 #[must_use]
468 pub fn to_hex(self) -> String {
469 let sign = if self.sign { "-" } else { "" };
470 match self.category {
471 Category::Nan => format!("{sign}nan"),
472 Category::Infinite => format!("{sign}0x1p+{}", self.format.max_exponent() + 1),
473 Category::Zero => format!("{sign}0x0p+0"),
474 Category::Finite => {
475 let mut significand = self.significand;
476 let mut exponent = self.exponent - (self.format.precision() as i32 - 1);
477 while significand & 0xf == 0 {
478 significand >>= 4;
479 exponent += 4;
480 }
481 format!("{sign}0x{significand:x}p{exponent:+}")
482 }
483 }
484 }
485}
486
487fn decimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
489 let mut digits = Vec::new();
490 let mut integer_digits = 0i32;
491 let mut seen_point = false;
492 let mut seen_digit = false;
493 let mut index = 0;
494 while index < bytes.len() {
495 match bytes[index] {
496 byte @ b'0'..=b'9' => {
497 digits.push(byte - b'0');
498 if !seen_point {
499 integer_digits += 1;
500 }
501 seen_digit = true;
502 }
503 b'\'' => {}
504 b'.' if !seen_point => seen_point = true,
505 b'e' | b'E' => break,
506 _ => return Err(ParseError::Invalid),
507 }
508 index += 1;
509 }
510 if !seen_digit {
511 return Err(ParseError::NoDigits);
512 }
513 let mut point = integer_digits;
514 if index < bytes.len() {
515 point = point.saturating_add(exponent_of(&bytes[index + 1..])?);
516 }
517 Ok(convert(Decimal::new(digits, point), sign, format))
518}
519
520fn hexadecimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
522 let mut significand: u128 = 0;
523 let mut exponent = 0i32;
524 let mut sticky = false;
525 let mut seen_point = false;
526 let mut seen_digit = false;
527 let mut index = 0;
528 while index < bytes.len() {
529 let byte = bytes[index];
530 let digit = match byte {
531 b'0'..=b'9' => byte - b'0',
532 b'a'..=b'f' => byte - b'a' + 10,
533 b'A'..=b'F' => byte - b'A' + 10,
534 b'\'' => {
535 index += 1;
536 continue;
537 }
538 b'.' if !seen_point => {
539 seen_point = true;
540 index += 1;
541 continue;
542 }
543 b'p' | b'P' => break,
544 _ => return Err(ParseError::Invalid),
545 };
546 seen_digit = true;
547 if significand.leading_zeros() >= 4 {
548 significand = (significand << 4) | u128::from(digit);
549 if seen_point {
550 exponent -= 4;
551 }
552 } else {
553 sticky |= digit != 0;
556 if !seen_point {
557 exponent += 4;
558 }
559 }
560 index += 1;
561 }
562 if !seen_digit {
563 return Err(ParseError::NoDigits);
564 }
565 if index < bytes.len() {
566 exponent = exponent.saturating_add(exponent_of(&bytes[index + 1..])?);
567 }
568 Ok(round(significand, exponent, sticky, sign, format))
569}
570
571fn exponent_of(bytes: &[u8]) -> Result<i32, ParseError> {
573 let (negative, digits) = match bytes.first() {
574 Some(b'-') => (true, &bytes[1..]),
575 Some(b'+') => (false, &bytes[1..]),
576 _ => (false, bytes),
577 };
578 if digits.is_empty() {
579 return Err(ParseError::NoExponentDigits);
580 }
581 let mut value = 0i32;
582 for &byte in digits {
583 if byte == b'\'' {
584 continue;
585 }
586 if !byte.is_ascii_digit() {
587 return Err(ParseError::Invalid);
588 }
589 value = value.saturating_mul(10).saturating_add(i32::from(byte - b'0'));
592 }
593 Ok(if negative { -value } else { value })
594}
595
596fn convert(mut value: Decimal, sign: bool, format: Format) -> (Float, Status) {
598 if value.is_zero() {
599 return (Float::zero(format, sign), Status::NONE);
600 }
601 if value.point() > format.max_decimal_exponent() {
602 return (Float::infinity(format, sign), Status::OVERFLOW.with(Status::INEXACT));
603 }
604 if value.point() < format.min_decimal_exponent() {
605 return (Float::zero(format, sign), Status::UNDERFLOW.with(Status::INEXACT));
606 }
607
608 let mut exponent = 0i32;
612 loop {
613 let point = value.point();
614 if point > 1 || (point == 1 && value.first_digit() >= 2) {
615 let step = binary_digits(point - 1).clamp(1, 60);
616 value.shift(-step);
617 exponent += step;
618 } else if point < 1 {
619 let step = (1 + binary_digits(-point)).clamp(1, 60);
620 value.shift(step);
621 exponent -= step;
622 } else {
623 break;
624 }
625 }
626
627 let precision = format.precision() as i32;
630 let scale = (exponent - precision + 1).max(format.min_exponent() - precision + 1);
631 value.shift(exponent - scale);
632 let (integer, fraction) = value.round_to_u128();
633 let rounded = match fraction {
634 Fraction::Zero | Fraction::BelowHalf => integer,
635 Fraction::Half => integer + (integer & 1),
636 Fraction::AboveHalf => integer + 1,
637 };
638 finish(rounded, scale, fraction != Fraction::Zero, sign, format)
639}
640
641const fn binary_digits(decimal: i32) -> i32 {
643 decimal * 33219 / 10000
644}
645
646fn round(
649 significand: u128,
650 exponent: i32,
651 sticky: bool,
652 sign: bool,
653 format: Format,
654) -> (Float, Status) {
655 if significand == 0 {
656 return (Float::zero(format, sign), Status::NONE);
657 }
658 let precision = format.precision() as i32;
659 let leading = (128 - significand.leading_zeros()) as i32;
660 let scale = (exponent + leading - precision).max(format.min_exponent() - precision + 1);
661 let mut sticky = sticky;
662 let (integer, half) = if scale <= exponent {
663 (significand << (exponent - scale), false)
664 } else {
665 let drop = (scale - exponent) as u32;
666 if drop >= 128 {
667 sticky = true;
668 (0, false)
669 } else {
670 let half = (significand >> (drop - 1)) & 1 == 1;
671 sticky |= drop > 1 && significand & ((1u128 << (drop - 1)) - 1) != 0;
672 (significand >> drop, half)
673 }
674 };
675 let rounded = if half && (sticky || integer & 1 == 1) { integer + 1 } else { integer };
676 finish(rounded, scale, half || sticky, sign, format)
677}
678
679fn finish(
682 significand: u128,
683 scale: i32,
684 inexact: bool,
685 sign: bool,
686 format: Format,
687) -> (Float, Status) {
688 let precision = format.precision();
689 let mut significand = significand;
690 let mut scale = scale;
691 if significand >> precision != 0 {
692 significand >>= 1;
694 scale += 1;
695 }
696 let mut status = if inexact { Status::INEXACT } else { Status::NONE };
697 if significand == 0 {
698 return (Float::zero(format, sign), status.with(Status::UNDERFLOW));
699 }
700 let exponent = scale + precision as i32 - 1;
701 if exponent > format.max_exponent() {
702 return (
703 Float::infinity(format, sign),
704 status.with(Status::OVERFLOW).with(Status::INEXACT),
705 );
706 }
707 let normal = significand >> (precision - 1) != 0;
708 if !normal && inexact {
709 status = status.with(Status::UNDERFLOW);
710 }
711 let exponent = if normal { exponent } else { format.min_exponent() };
712 (Float { format, category: Category::Finite, sign, exponent, significand }, status)
713}
714
715#[cfg(test)]
716mod tests {
717 use super::*;
718
719 fn double(text: &str) -> u128 {
721 Float::parse(text, Format::Double).expect("a number").0.to_bits()
722 }
723
724 fn single(text: &str) -> u128 {
726 Float::parse(text, Format::Single).expect("a number").0.to_bits()
727 }
728
729 #[test]
730 fn the_ordinary_numbers_land_where_the_host_would_put_them() {
731 for text in ["0", "1", "2", "0.5", "1.5", "3.14159", "2.718281828459045", "100", "1e10"] {
732 let host = text.parse::<f64>().expect("a number Rust reads too");
733 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
734 }
735 }
736
737 #[test]
738 fn a_number_that_needs_the_last_bit_rounded_gets_it_right() {
739 let hard = [
742 "0.1",
743 "0.3",
744 "2.2250738585072011e-308",
745 "2.2250738585072014e-308",
746 "1.7976931348623157e308",
747 "4.9406564584124654e-324",
748 "5e-324",
749 "8.98846567431158e307",
750 "9007199254740993",
751 "123456789012345678901234567890",
752 "1.000000000000000000000000000000000000000000000000000000000000000001",
753 "7.8459735791271921e65",
754 "3.518437208883201171875e13",
755 "0.500000000000000166533453693773481063544750213623046875",
756 ];
757 for text in hard {
758 let host = text.parse::<f64>().expect("a number Rust reads too");
759 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
760 }
761 }
762
763 #[test]
764 fn the_number_that_takes_seven_hundred_and_sixty_seven_digits() {
765 let text = concat!(
768 "2.47032822920623272088284396434110686182529901307162382",
769 "35378852574870103599108683372845652890455735483022221802",
770 "58573249056416711547735232764105795166208503595426876755",
771 "62317084535693494535245273750735013572761315046354601316",
772 "12127849863326369238975694273040488011871029093711789936",
773 "42245692702737764465109076580131048946378905599180391359",
774 "70011386455512221706120629864144453927884519445934871524",
775 "63344875888932891414823975864211858166195965106373837732",
776 "34435703331457550505022232309998195892058070506176382679",
777 "16323484472119097902806154870514036458498974142754747141",
778 "39683784321102080606305920253373777969877864922227306716",
779 "01324339457879181214233820577228206278891620001855078759",
780 "16278352090142077553206262229158550205643778244387017277",
781 "94459649305087139089301871550805125768938177360937844105",
782 "63661045147381814281647890691181239104545396303476425117",
783 "7562185422741845851144691421326303120484712594187004993e-324"
784 );
785 let host = text.parse::<f64>().expect("a number Rust reads too");
786 assert_eq!(double(text), u128::from(host.to_bits()));
787 }
788
789 #[test]
790 fn a_sweep_of_random_numbers_agrees_with_rust_in_every_bit() {
791 let mut state = 0x2545_f491_4f6c_dd1du64;
795 for _ in 0..4000 {
796 state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
797 let digits = state >> 11;
798 let exponent = (state % 600) as i32 - 300;
799 let text = format!("{digits}e{exponent}");
800 let host = text.parse::<f64>().expect("a number Rust reads too");
801 assert_eq!(double(&text), u128::from(host.to_bits()), "{text}");
802 let host = text.parse::<f32>().expect("a number Rust reads too");
803 assert_eq!(single(&text), u128::from(host.to_bits()), "{text} as a float");
804 }
805 }
806
807 #[test]
808 fn the_ends_of_the_range_are_an_infinity_and_a_zero() {
809 let (value, status) = Float::parse("1e400", Format::Double).expect("a number");
810 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
811 let (value, status) = Float::parse("1e-400", Format::Double).expect("a number");
812 assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
813 let (value, status) = Float::parse("1.7976931348623157e308", Format::Double).expect("one");
815 assert!(value.is_finite() && !status.has(Status::OVERFLOW));
816 let (value, _) = Float::parse("1.8e308", Format::Double).expect("a number");
817 assert!(value.is_infinite());
818 assert_eq!(double("2.4e-324"), u128::from((0f64).to_bits()));
820 assert_eq!(double("2.5e-324"), 1);
821 }
822
823 #[test]
824 fn a_number_that_is_exactly_what_was_written_says_so() {
825 assert!(Float::parse("1", Format::Double).expect("a number").1.is_none());
826 assert!(Float::parse("0.5", Format::Double).expect("a number").1.is_none());
827 assert!(Float::parse("0.1", Format::Double).expect("a number").1.has(Status::INEXACT));
828 let (_, status) = Float::parse("1e-320", Format::Double).expect("a number");
830 assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
831 }
832
833 #[test]
834 fn a_hexadecimal_constant_is_exact_and_needs_no_scaling() {
835 assert_eq!(double("0x1p0"), u128::from((1f64).to_bits()));
836 assert_eq!(double("0x1.8p1"), u128::from((3f64).to_bits()));
837 assert_eq!(double("0x1p-1074"), 1);
838 assert_eq!(double("0xa.bp-4"), u128::from((0.66796875f64).to_bits()));
839 assert_eq!(double("0X1.FFFFFFFFFFFFFP+1023"), u128::from(f64::MAX.to_bits()));
840 assert!(Float::parse("0x1p0", Format::Double).expect("a number").1.is_none());
841 let (_, status) = Float::parse("0x1.00000000000008p0", Format::Double).expect("a number");
843 assert!(status.has(Status::INEXACT));
844 assert_eq!(double("0x1.00000000000008p0"), u128::from((1f64).to_bits()));
845 assert_eq!(double("0x1.00000000000018p0"), u128::from((1f64).to_bits() + 2));
846 }
847
848 #[test]
849 fn digit_separators_are_not_part_of_the_number() {
850 assert_eq!(double("1'000.000'1"), double("1000.0001"));
851 assert_eq!(double("0x1'0p0"), double("16.0"));
852 assert_eq!(double("1e1'0"), double("1e10"));
853 }
854
855 #[test]
856 fn a_spelling_that_is_not_a_number_says_which_way_it_is_wrong() {
857 assert_eq!(Float::parse("", Format::Double), Err(ParseError::NoDigits));
858 assert_eq!(Float::parse(".", Format::Double), Err(ParseError::NoDigits));
859 assert_eq!(Float::parse("1e", Format::Double), Err(ParseError::NoExponentDigits));
860 assert_eq!(Float::parse("1e+", Format::Double), Err(ParseError::NoExponentDigits));
861 assert_eq!(Float::parse("0x1p", Format::Double), Err(ParseError::NoExponentDigits));
862 assert_eq!(Float::parse("0xp1", Format::Double), Err(ParseError::NoDigits));
863 assert_eq!(Float::parse("1x0", Format::Double), Err(ParseError::Invalid));
864 }
865
866 #[test]
867 fn a_sign_is_accepted_although_a_c_constant_never_has_one() {
868 let (value, _) = Float::parse("-1.5", Format::Double).expect("a number");
869 assert!(value.is_negative());
870 assert_eq!(value.to_bits(), u128::from((-1.5f64).to_bits()));
871 let (value, _) = Float::parse("-0.0", Format::Double).expect("a number");
872 assert!(value.is_zero() && value.is_negative());
873 assert_eq!(value.to_bits(), u128::from((-0.0f64).to_bits()));
874 }
875
876 #[test]
877 fn every_format_says_how_wide_its_fields_are() {
878 for format in [
879 Format::Half,
880 Format::BFloat16,
881 Format::Single,
882 Format::Double,
883 Format::X87Extended,
884 Format::Quad,
885 ] {
886 assert_eq!(
887 format.exponent_bits() + format.significand_bits() + 1,
888 format.width(),
889 "{format:?}"
890 );
891 assert_eq!(format.min_exponent(), 1 - format.max_exponent());
892 }
893 assert_eq!(Format::Half.exponent_bits(), 5);
894 assert_eq!(Format::BFloat16.exponent_bits(), 8);
895 assert_eq!(Format::Single.exponent_bits(), 8);
896 assert_eq!(Format::Double.exponent_bits(), 11);
897 assert_eq!(Format::X87Extended.exponent_bits(), 15);
898 assert_eq!(Format::Quad.exponent_bits(), 15);
899 }
900
901 #[test]
902 fn a_number_survives_a_trip_through_its_encoding() {
903 for format in [
904 Format::Half,
905 Format::BFloat16,
906 Format::Single,
907 Format::Double,
908 Format::X87Extended,
909 Format::Quad,
910 ] {
911 for text in ["0", "-0", "1", "-1.5", "3.14159", "1e-5", "65504", "0x1p-20"] {
912 let (value, _) = Float::parse(text, format).expect("a number");
913 let bits = value.to_bits();
914 assert_eq!(Float::from_bits(format, bits).to_bits(), bits, "{text} in {format:?}");
915 }
916 assert_eq!(
917 Float::from_bits(format, Float::infinity(format, false).to_bits()).to_bits(),
918 Float::infinity(format, false).to_bits()
919 );
920 }
921 }
922
923 #[test]
924 fn a_hexadecimal_spelling_reads_back_as_the_number_it_came_from() {
925 for format in [
926 Format::Half,
927 Format::BFloat16,
928 Format::Single,
929 Format::Double,
930 Format::X87Extended,
931 Format::Quad,
932 ] {
933 for text in [
934 "0", "-0", "1", "-1", "0.5", "-1.5", "3.14159", "1e-5", "0x1p-20", "0.1", "255",
935 "1e30",
936 ] {
937 let (value, _) = Float::parse(text, format).expect("a number");
938 let spelling = value.to_hex();
939 let (again, status) = Float::parse(&spelling, format).expect("a number");
940 assert_eq!(again.to_bits(), value.to_bits(), "{text} as {spelling} in {format:?}");
941 let rounded = status.has(Status::INEXACT) || status.has(Status::OVERFLOW);
944 assert_eq!(rounded, !value.is_finite(), "{spelling} in {format:?}");
945 }
946 let tiny = Float::from_bits(format, 1);
948 let (again, _) = Float::parse(&tiny.to_hex(), format).expect("a number");
949 assert_eq!(again.to_bits(), tiny.to_bits(), "the smallest subnormal in {format:?}");
950 let huge = Float::infinity(format, true);
952 let (again, status) = Float::parse(&huge.to_hex(), format).expect("a number");
953 assert!(again.is_infinite() && again.is_negative(), "{format:?}");
954 assert!(status.has(Status::OVERFLOW));
955 }
956 }
957
958 #[test]
959 fn a_round_number_gets_a_short_spelling() {
960 let hex = |text: &str| Float::parse(text, Format::Double).expect("a number").0.to_hex();
961 assert_eq!(hex("1"), "0x1p+0");
962 assert_eq!(hex("-1"), "-0x1p+0");
963 assert_eq!(hex("0"), "0x0p+0");
964 assert_eq!(hex("-0"), "-0x0p+0");
965 assert_eq!(hex("2"), "0x1p+1");
966 assert_eq!(hex("0.5"), "0x1p-1");
967 assert_eq!(hex("0.1"), "0x1999999999999ap-56");
968 }
969
970 #[test]
971 fn the_narrow_formats_round_where_they_are_supposed_to() {
972 let (value, status) = Float::parse("65504", Format::Half).expect("a number");
976 assert!(value.is_finite() && status.is_none());
977 assert_eq!(value.to_bits(), 0x7bff);
978 let (value, _) = Float::parse("65536", Format::Half).expect("a number");
979 assert!(value.is_infinite());
980 assert_eq!(Float::parse("1", Format::Half).expect("one").0.to_bits(), 0x3c00);
981 assert_eq!(Float::parse("1", Format::BFloat16).expect("one").0.to_bits(), 0x3f80);
982 assert_eq!(Float::parse("1e30", Format::BFloat16).expect("big").0.to_bits(), 0x714a);
983 assert_eq!(Float::parse("0x1p-24", Format::Half).expect("tiny").0.to_bits(), 1);
985 assert!(Float::parse("0x1p-26", Format::Half).expect("tinier").0.is_zero());
986 }
987
988 #[test]
989 fn the_x87_format_stores_the_bit_the_others_leave_implied() {
990 let one = Float::parse("1", Format::X87Extended).expect("one").0;
993 assert_eq!(one.to_bits(), 0x3fff_8000_0000_0000_0000);
994 assert_eq!(
995 Float::parse("2", Format::X87Extended).expect("two").0.to_bits(),
996 0x4000_8000_0000_0000_0000
997 );
998 let (value, status) = Float::parse("9007199254740993", Format::X87Extended).expect("one");
1000 assert!(status.is_none());
1001 assert_eq!(value.to_bits(), 0x4034_8000_0000_0000_0400);
1002 assert_eq!(
1005 Float::parse("0.1", Format::X87Extended).expect("a tenth").0.to_bits(),
1006 0x3ffb_cccc_cccc_cccc_cccd
1007 );
1008 assert_eq!(Float::parse("1e-4950", Format::X87Extended).expect("tiny").0.to_bits(), 3);
1011 }
1012
1013 #[test]
1014 fn the_quad_format_has_a_hundred_and_thirteen_bits_of_it() {
1015 assert_eq!(
1016 Float::parse("1", Format::Quad).expect("one").0.to_bits(),
1017 0x3fff_0000_0000_0000_0000_0000_0000_0000
1018 );
1019 assert_eq!(
1021 Float::parse("0.1", Format::Quad).expect("a tenth").0.to_bits(),
1022 0x3ffb_9999_9999_9999_9999_9999_9999_999a
1023 );
1024 assert_eq!(
1026 Float::parse("3.14159", Format::Quad).expect("pi, roughly").0.to_bits(),
1027 0x4000_921f_9f01_b866_e43a_a79b_badc_0981
1028 );
1029 let (value, status) = Float::parse("1e5000", Format::Quad).expect("a number");
1030 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
1031 let (value, _) = Float::parse("1e-5000", Format::Quad).expect("a number");
1032 assert!(value.is_zero());
1033 }
1034
1035 #[test]
1038 fn a_nan_with_a_payload_has_the_bits_gcc_gives_it() {
1039 let double = |quiet, payload| Float::nan_with(Format::Double, false, quiet, payload);
1040 assert_eq!(double(true, 0).to_bits(), 0x7ff8_0000_0000_0000, "__builtin_nan(\"\")");
1041 assert_eq!(double(true, 1).to_bits(), 0x7ff8_0000_0000_0001, "__builtin_nan(\"0x1\")");
1042 assert_eq!(double(true, 8).to_bits(), 0x7ff8_0000_0000_0008, "__builtin_nan(\"010\")");
1043 assert_eq!(double(false, 0).to_bits(), 0x7ff4_0000_0000_0000, "__builtin_nans(\"\")");
1046 assert_eq!(double(false, 1).to_bits(), 0x7ff0_0000_0000_0001, "__builtin_nans(\"0x1\")");
1047 assert_eq!(double(true, 0xf_ffff_ffff_ffff).to_bits(), 0x7fff_ffff_ffff_ffff);
1049 assert_eq!(double(true, 1 << 52).to_bits(), 0x7ff8_0000_0000_0000);
1050 assert_eq!(
1051 Float::nan_with(Format::Single, false, true, 1).to_bits(),
1052 0x7fc0_0001,
1053 "__builtin_nanf(\"0x1\")"
1054 );
1055 assert_eq!(
1056 Float::nan_with(Format::Single, false, false, 0).to_bits(),
1057 0x7fa0_0000,
1058 "__builtin_nansf(\"\")"
1059 );
1060 assert_eq!(
1063 Float::nan_with(Format::X87Extended, false, true, 1).to_bits(),
1064 0x7fff_c000_0000_0000_0001,
1065 "__builtin_nanl(\"0x1\") on x86"
1066 );
1067 assert_eq!(
1068 Float::nan_with(Format::X87Extended, false, false, 0).to_bits(),
1069 0x7fff_a000_0000_0000_0000,
1070 "__builtin_nansl(\"\") on x86"
1071 );
1072 }
1073
1074 #[test]
1076 fn a_payload_comes_back_out_of_the_encoding_it_went_into() {
1077 for format in [Format::Half, Format::Single, Format::Double, Format::X87Extended] {
1078 for (quiet, payload) in [(true, 0), (true, 1), (false, 3), (true, 5)] {
1079 let nan = Float::nan_with(format, false, quiet, payload);
1080 assert!(nan.is_nan(), "{format:?}");
1081 assert_eq!(Float::from_bits(format, nan.to_bits()), nan, "{format:?} {payload}");
1082 }
1083 let nan = Float::nan_with(format, true, true, 7);
1085 assert!(nan.is_negative() && nan.negated().negated() == nan, "{format:?}");
1086 }
1087 }
1088
1089 #[test]
1092 fn the_smallest_normal_is_the_number_below_which_nothing_is_normal() {
1093 assert_eq!(
1094 Float::smallest_normal(Format::Single, false).to_bits(),
1095 u128::from(f32::MIN_POSITIVE.to_bits())
1096 );
1097 assert_eq!(
1098 Float::smallest_normal(Format::Double, false).to_bits(),
1099 u128::from(f64::MIN_POSITIVE.to_bits())
1100 );
1101 assert_eq!(
1104 Float::smallest_normal(Format::X87Extended, false).to_bits(),
1105 (1u128 << 64) | (1u128 << 63)
1106 );
1107 for format in [Format::Half, Format::BFloat16, Format::Single, Format::Double] {
1108 let normal = Float::smallest_normal(format, false);
1109 assert!(normal.is_finite() && !normal.is_zero(), "{format:?}");
1110 assert_eq!(Float::from_bits(format, normal.to_bits()), normal, "{format:?}");
1111 let below = Float::from_bits(format, normal.to_bits() - 1);
1114 assert_eq!(below.compare(normal), Some(std::cmp::Ordering::Less), "{format:?}");
1115 let negative = Float::smallest_normal(format, true);
1117 assert!(negative.is_negative() && negative.negated() == normal, "{format:?}");
1118 }
1119 }
1120}