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]
61 pub const fn precision(self) -> u32 {
62 match self {
63 Format::Half => 11,
64 Format::BFloat16 => 8,
65 Format::Single => 24,
66 Format::Double => 53,
67 Format::X87Extended => 64,
68 Format::Quad => 113,
69 }
70 }
71
72 #[must_use]
74 pub const fn max_exponent(self) -> i32 {
75 match self {
76 Format::Half => 15,
77 Format::BFloat16 | Format::Single => 127,
78 Format::Double => 1023,
79 Format::X87Extended | Format::Quad => 16383,
80 }
81 }
82
83 #[must_use]
85 pub const fn min_exponent(self) -> i32 {
86 1 - self.max_exponent()
87 }
88
89 #[must_use]
92 pub const fn width(self) -> u32 {
93 match self {
94 Format::Half | Format::BFloat16 => 16,
95 Format::Single => 32,
96 Format::Double => 64,
97 Format::X87Extended => 80,
98 Format::Quad => 128,
99 }
100 }
101
102 #[must_use]
104 pub const fn has_explicit_integer_bit(self) -> bool {
105 matches!(self, Format::X87Extended)
106 }
107
108 const fn exponent_bits(self) -> u32 {
110 self.width() - self.significand_bits() - 1
111 }
112
113 const fn significand_bits(self) -> u32 {
115 if self.has_explicit_integer_bit() { self.precision() } else { self.precision() - 1 }
116 }
117
118 const fn max_decimal_exponent(self) -> i32 {
124 (self.max_exponent() + 1) * 30103 / 100000 + 2
125 }
126
127 const fn min_decimal_exponent(self) -> i32 {
129 (self.min_exponent() - self.precision() as i32) * 30103 / 100000 - 2
130 }
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
139pub struct Status(u8);
140
141impl Status {
142 pub const NONE: Status = Status(0);
144 pub const INEXACT: Status = Status(1);
146 pub const OVERFLOW: Status = Status(2);
148 pub const UNDERFLOW: Status = Status(4);
150 pub const INVALID: Status = Status(8);
152 pub const DIVIDE_BY_ZERO: Status = Status(16);
154
155 #[inline]
157 #[must_use]
158 pub const fn has(self, other: Status) -> bool {
159 self.0 & other.0 == other.0
160 }
161
162 #[inline]
164 #[must_use]
165 pub const fn with(self, other: Status) -> Status {
166 Status(self.0 | other.0)
167 }
168
169 #[inline]
171 #[must_use]
172 pub const fn is_none(self) -> bool {
173 self.0 == 0
174 }
175}
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
182pub enum ParseError {
183 NoDigits,
185 NoExponentDigits,
187 Invalid,
189}
190
191#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
193enum Category {
194 Zero,
195 Finite,
196 Infinite,
197 Nan,
198}
199
200#[derive(Debug, Clone, Copy, PartialEq, Eq)]
205pub struct Float {
206 format: Format,
207 category: Category,
208 sign: bool,
209 exponent: i32,
210 significand: u128,
211}
212
213impl Float {
214 #[must_use]
216 pub const fn zero(format: Format, sign: bool) -> Float {
217 Float { format, category: Category::Zero, sign, exponent: 0, significand: 0 }
218 }
219
220 #[must_use]
222 pub const fn infinity(format: Format, sign: bool) -> Float {
223 Float { format, category: Category::Infinite, sign, exponent: 0, significand: 0 }
224 }
225
226 #[must_use]
228 pub const fn format(self) -> Format {
229 self.format
230 }
231
232 #[must_use]
234 pub const fn is_negative(self) -> bool {
235 self.sign
236 }
237
238 #[must_use]
240 pub const fn is_zero(self) -> bool {
241 matches!(self.category, Category::Zero)
242 }
243
244 #[must_use]
246 pub const fn is_infinite(self) -> bool {
247 matches!(self.category, Category::Infinite)
248 }
249
250 #[must_use]
252 pub const fn is_finite(self) -> bool {
253 matches!(self.category, Category::Zero | Category::Finite)
254 }
255
256 pub fn parse(text: &str, format: Format) -> Result<(Float, Status), ParseError> {
268 let bytes = text.as_bytes();
269 let (sign, rest) = match bytes.first() {
270 Some(b'-') => (true, &bytes[1..]),
271 Some(b'+') => (false, &bytes[1..]),
272 _ => (false, bytes),
273 };
274 if rest.len() > 1 && rest[0] == b'0' && rest[1] | 32 == b'x' {
275 hexadecimal(&rest[2..], sign, format)
276 } else {
277 decimal(rest, sign, format)
278 }
279 }
280
281 #[must_use]
286 pub fn to_bits(self) -> u128 {
287 let format = self.format;
288 let significand_mask = (1u128 << format.significand_bits()) - 1;
289 let (exponent_field, significand_field) = match self.category {
290 Category::Zero => (0, 0),
291 Category::Infinite => (
292 (1u128 << format.exponent_bits()) - 1,
293 if format.has_explicit_integer_bit() {
294 1u128 << (format.precision() - 1)
295 } else {
296 0
297 },
298 ),
299 Category::Nan => {
302 let quiet = 1u128 << (format.precision() - 2);
303 let leading = if format.has_explicit_integer_bit() {
304 1u128 << (format.precision() - 1)
305 } else {
306 0
307 };
308 ((1u128 << format.exponent_bits()) - 1, quiet | leading)
309 }
310 Category::Finite => {
311 let subnormal = self.significand >> (format.precision() - 1) == 0;
312 let field =
313 if subnormal { 0 } else { (self.exponent + format.max_exponent()) as u128 };
314 (field, self.significand & significand_mask)
315 }
316 };
317 let sign = u128::from(self.sign) << (format.width() - 1);
318 sign | (exponent_field << format.significand_bits()) | significand_field
319 }
320
321 #[must_use]
328 pub fn from_bits(format: Format, bits: u128) -> Float {
329 let significand_bits = format.significand_bits();
330 let sign = (bits >> (format.width() - 1)) & 1 == 1;
331 let exponent_field =
332 ((bits >> significand_bits) & ((1u128 << format.exponent_bits()) - 1)) as i32;
333 let stored = bits & ((1u128 << significand_bits) - 1);
334 if exponent_field == (1 << format.exponent_bits()) - 1 {
335 let fraction = stored & ((1u128 << (format.precision() - 1)) - 1);
338 if fraction == 0 {
339 return Float::infinity(format, sign);
340 }
341 return Float { sign, ..Float::nan(format) };
342 }
343 let implicit = if format.has_explicit_integer_bit() || exponent_field == 0 {
344 0
345 } else {
346 1u128 << (format.precision() - 1)
347 };
348 let significand = stored | implicit;
349 if significand == 0 {
350 return Float::zero(format, sign);
351 }
352 let exponent = if exponent_field == 0 {
353 format.min_exponent()
354 } else {
355 exponent_field - format.max_exponent()
356 };
357 Float { format, category: Category::Finite, sign, exponent, significand }
358 }
359
360 #[must_use]
377 pub fn to_hex(self) -> String {
378 let sign = if self.sign { "-" } else { "" };
379 match self.category {
380 Category::Nan => format!("{sign}nan"),
381 Category::Infinite => format!("{sign}0x1p+{}", self.format.max_exponent() + 1),
382 Category::Zero => format!("{sign}0x0p+0"),
383 Category::Finite => {
384 let mut significand = self.significand;
385 let mut exponent = self.exponent - (self.format.precision() as i32 - 1);
386 while significand & 0xf == 0 {
387 significand >>= 4;
388 exponent += 4;
389 }
390 format!("{sign}0x{significand:x}p{exponent:+}")
391 }
392 }
393 }
394}
395
396fn decimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
398 let mut digits = Vec::new();
399 let mut integer_digits = 0i32;
400 let mut seen_point = false;
401 let mut seen_digit = false;
402 let mut index = 0;
403 while index < bytes.len() {
404 match bytes[index] {
405 byte @ b'0'..=b'9' => {
406 digits.push(byte - b'0');
407 if !seen_point {
408 integer_digits += 1;
409 }
410 seen_digit = true;
411 }
412 b'\'' => {}
413 b'.' if !seen_point => seen_point = true,
414 b'e' | b'E' => break,
415 _ => return Err(ParseError::Invalid),
416 }
417 index += 1;
418 }
419 if !seen_digit {
420 return Err(ParseError::NoDigits);
421 }
422 let mut point = integer_digits;
423 if index < bytes.len() {
424 point = point.saturating_add(exponent_of(&bytes[index + 1..])?);
425 }
426 Ok(convert(Decimal::new(digits, point), sign, format))
427}
428
429fn hexadecimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
431 let mut significand: u128 = 0;
432 let mut exponent = 0i32;
433 let mut sticky = false;
434 let mut seen_point = false;
435 let mut seen_digit = false;
436 let mut index = 0;
437 while index < bytes.len() {
438 let byte = bytes[index];
439 let digit = match byte {
440 b'0'..=b'9' => byte - b'0',
441 b'a'..=b'f' => byte - b'a' + 10,
442 b'A'..=b'F' => byte - b'A' + 10,
443 b'\'' => {
444 index += 1;
445 continue;
446 }
447 b'.' if !seen_point => {
448 seen_point = true;
449 index += 1;
450 continue;
451 }
452 b'p' | b'P' => break,
453 _ => return Err(ParseError::Invalid),
454 };
455 seen_digit = true;
456 if significand.leading_zeros() >= 4 {
457 significand = (significand << 4) | u128::from(digit);
458 if seen_point {
459 exponent -= 4;
460 }
461 } else {
462 sticky |= digit != 0;
465 if !seen_point {
466 exponent += 4;
467 }
468 }
469 index += 1;
470 }
471 if !seen_digit {
472 return Err(ParseError::NoDigits);
473 }
474 if index < bytes.len() {
475 exponent = exponent.saturating_add(exponent_of(&bytes[index + 1..])?);
476 }
477 Ok(round(significand, exponent, sticky, sign, format))
478}
479
480fn exponent_of(bytes: &[u8]) -> Result<i32, ParseError> {
482 let (negative, digits) = match bytes.first() {
483 Some(b'-') => (true, &bytes[1..]),
484 Some(b'+') => (false, &bytes[1..]),
485 _ => (false, bytes),
486 };
487 if digits.is_empty() {
488 return Err(ParseError::NoExponentDigits);
489 }
490 let mut value = 0i32;
491 for &byte in digits {
492 if byte == b'\'' {
493 continue;
494 }
495 if !byte.is_ascii_digit() {
496 return Err(ParseError::Invalid);
497 }
498 value = value.saturating_mul(10).saturating_add(i32::from(byte - b'0'));
501 }
502 Ok(if negative { -value } else { value })
503}
504
505fn convert(mut value: Decimal, sign: bool, format: Format) -> (Float, Status) {
507 if value.is_zero() {
508 return (Float::zero(format, sign), Status::NONE);
509 }
510 if value.point() > format.max_decimal_exponent() {
511 return (Float::infinity(format, sign), Status::OVERFLOW.with(Status::INEXACT));
512 }
513 if value.point() < format.min_decimal_exponent() {
514 return (Float::zero(format, sign), Status::UNDERFLOW.with(Status::INEXACT));
515 }
516
517 let mut exponent = 0i32;
521 loop {
522 let point = value.point();
523 if point > 1 || (point == 1 && value.first_digit() >= 2) {
524 let step = binary_digits(point - 1).clamp(1, 60);
525 value.shift(-step);
526 exponent += step;
527 } else if point < 1 {
528 let step = (1 + binary_digits(-point)).clamp(1, 60);
529 value.shift(step);
530 exponent -= step;
531 } else {
532 break;
533 }
534 }
535
536 let precision = format.precision() as i32;
539 let scale = (exponent - precision + 1).max(format.min_exponent() - precision + 1);
540 value.shift(exponent - scale);
541 let (integer, fraction) = value.round_to_u128();
542 let rounded = match fraction {
543 Fraction::Zero | Fraction::BelowHalf => integer,
544 Fraction::Half => integer + (integer & 1),
545 Fraction::AboveHalf => integer + 1,
546 };
547 finish(rounded, scale, fraction != Fraction::Zero, sign, format)
548}
549
550const fn binary_digits(decimal: i32) -> i32 {
552 decimal * 33219 / 10000
553}
554
555fn round(
558 significand: u128,
559 exponent: i32,
560 sticky: bool,
561 sign: bool,
562 format: Format,
563) -> (Float, Status) {
564 if significand == 0 {
565 return (Float::zero(format, sign), Status::NONE);
566 }
567 let precision = format.precision() as i32;
568 let leading = (128 - significand.leading_zeros()) as i32;
569 let scale = (exponent + leading - precision).max(format.min_exponent() - precision + 1);
570 let mut sticky = sticky;
571 let (integer, half) = if scale <= exponent {
572 (significand << (exponent - scale), false)
573 } else {
574 let drop = (scale - exponent) as u32;
575 if drop >= 128 {
576 sticky = true;
577 (0, false)
578 } else {
579 let half = (significand >> (drop - 1)) & 1 == 1;
580 sticky |= drop > 1 && significand & ((1u128 << (drop - 1)) - 1) != 0;
581 (significand >> drop, half)
582 }
583 };
584 let rounded = if half && (sticky || integer & 1 == 1) { integer + 1 } else { integer };
585 finish(rounded, scale, half || sticky, sign, format)
586}
587
588fn finish(
591 significand: u128,
592 scale: i32,
593 inexact: bool,
594 sign: bool,
595 format: Format,
596) -> (Float, Status) {
597 let precision = format.precision();
598 let mut significand = significand;
599 let mut scale = scale;
600 if significand >> precision != 0 {
601 significand >>= 1;
603 scale += 1;
604 }
605 let mut status = if inexact { Status::INEXACT } else { Status::NONE };
606 if significand == 0 {
607 return (Float::zero(format, sign), status.with(Status::UNDERFLOW));
608 }
609 let exponent = scale + precision as i32 - 1;
610 if exponent > format.max_exponent() {
611 return (
612 Float::infinity(format, sign),
613 status.with(Status::OVERFLOW).with(Status::INEXACT),
614 );
615 }
616 let normal = significand >> (precision - 1) != 0;
617 if !normal && inexact {
618 status = status.with(Status::UNDERFLOW);
619 }
620 let exponent = if normal { exponent } else { format.min_exponent() };
621 (Float { format, category: Category::Finite, sign, exponent, significand }, status)
622}
623
624#[cfg(test)]
625mod tests {
626 use super::*;
627
628 fn double(text: &str) -> u128 {
630 Float::parse(text, Format::Double).expect("a number").0.to_bits()
631 }
632
633 fn single(text: &str) -> u128 {
635 Float::parse(text, Format::Single).expect("a number").0.to_bits()
636 }
637
638 #[test]
639 fn the_ordinary_numbers_land_where_the_host_would_put_them() {
640 for text in ["0", "1", "2", "0.5", "1.5", "3.14159", "2.718281828459045", "100", "1e10"] {
641 let host = text.parse::<f64>().expect("a number Rust reads too");
642 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
643 }
644 }
645
646 #[test]
647 fn a_number_that_needs_the_last_bit_rounded_gets_it_right() {
648 let hard = [
651 "0.1",
652 "0.3",
653 "2.2250738585072011e-308",
654 "2.2250738585072014e-308",
655 "1.7976931348623157e308",
656 "4.9406564584124654e-324",
657 "5e-324",
658 "8.98846567431158e307",
659 "9007199254740993",
660 "123456789012345678901234567890",
661 "1.000000000000000000000000000000000000000000000000000000000000000001",
662 "7.8459735791271921e65",
663 "3.518437208883201171875e13",
664 "0.500000000000000166533453693773481063544750213623046875",
665 ];
666 for text in hard {
667 let host = text.parse::<f64>().expect("a number Rust reads too");
668 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
669 }
670 }
671
672 #[test]
673 fn the_number_that_takes_seven_hundred_and_sixty_seven_digits() {
674 let text = concat!(
677 "2.47032822920623272088284396434110686182529901307162382",
678 "35378852574870103599108683372845652890455735483022221802",
679 "58573249056416711547735232764105795166208503595426876755",
680 "62317084535693494535245273750735013572761315046354601316",
681 "12127849863326369238975694273040488011871029093711789936",
682 "42245692702737764465109076580131048946378905599180391359",
683 "70011386455512221706120629864144453927884519445934871524",
684 "63344875888932891414823975864211858166195965106373837732",
685 "34435703331457550505022232309998195892058070506176382679",
686 "16323484472119097902806154870514036458498974142754747141",
687 "39683784321102080606305920253373777969877864922227306716",
688 "01324339457879181214233820577228206278891620001855078759",
689 "16278352090142077553206262229158550205643778244387017277",
690 "94459649305087139089301871550805125768938177360937844105",
691 "63661045147381814281647890691181239104545396303476425117",
692 "7562185422741845851144691421326303120484712594187004993e-324"
693 );
694 let host = text.parse::<f64>().expect("a number Rust reads too");
695 assert_eq!(double(text), u128::from(host.to_bits()));
696 }
697
698 #[test]
699 fn a_sweep_of_random_numbers_agrees_with_rust_in_every_bit() {
700 let mut state = 0x2545_f491_4f6c_dd1du64;
704 for _ in 0..4000 {
705 state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
706 let digits = state >> 11;
707 let exponent = (state % 600) as i32 - 300;
708 let text = format!("{digits}e{exponent}");
709 let host = text.parse::<f64>().expect("a number Rust reads too");
710 assert_eq!(double(&text), u128::from(host.to_bits()), "{text}");
711 let host = text.parse::<f32>().expect("a number Rust reads too");
712 assert_eq!(single(&text), u128::from(host.to_bits()), "{text} as a float");
713 }
714 }
715
716 #[test]
717 fn the_ends_of_the_range_are_an_infinity_and_a_zero() {
718 let (value, status) = Float::parse("1e400", Format::Double).expect("a number");
719 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
720 let (value, status) = Float::parse("1e-400", Format::Double).expect("a number");
721 assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
722 let (value, status) = Float::parse("1.7976931348623157e308", Format::Double).expect("one");
724 assert!(value.is_finite() && !status.has(Status::OVERFLOW));
725 let (value, _) = Float::parse("1.8e308", Format::Double).expect("a number");
726 assert!(value.is_infinite());
727 assert_eq!(double("2.4e-324"), u128::from((0f64).to_bits()));
729 assert_eq!(double("2.5e-324"), 1);
730 }
731
732 #[test]
733 fn a_number_that_is_exactly_what_was_written_says_so() {
734 assert!(Float::parse("1", Format::Double).expect("a number").1.is_none());
735 assert!(Float::parse("0.5", Format::Double).expect("a number").1.is_none());
736 assert!(Float::parse("0.1", Format::Double).expect("a number").1.has(Status::INEXACT));
737 let (_, status) = Float::parse("1e-320", Format::Double).expect("a number");
739 assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
740 }
741
742 #[test]
743 fn a_hexadecimal_constant_is_exact_and_needs_no_scaling() {
744 assert_eq!(double("0x1p0"), u128::from((1f64).to_bits()));
745 assert_eq!(double("0x1.8p1"), u128::from((3f64).to_bits()));
746 assert_eq!(double("0x1p-1074"), 1);
747 assert_eq!(double("0xa.bp-4"), u128::from((0.66796875f64).to_bits()));
748 assert_eq!(double("0X1.FFFFFFFFFFFFFP+1023"), u128::from(f64::MAX.to_bits()));
749 assert!(Float::parse("0x1p0", Format::Double).expect("a number").1.is_none());
750 let (_, status) = Float::parse("0x1.00000000000008p0", Format::Double).expect("a number");
752 assert!(status.has(Status::INEXACT));
753 assert_eq!(double("0x1.00000000000008p0"), u128::from((1f64).to_bits()));
754 assert_eq!(double("0x1.00000000000018p0"), u128::from((1f64).to_bits() + 2));
755 }
756
757 #[test]
758 fn digit_separators_are_not_part_of_the_number() {
759 assert_eq!(double("1'000.000'1"), double("1000.0001"));
760 assert_eq!(double("0x1'0p0"), double("16.0"));
761 assert_eq!(double("1e1'0"), double("1e10"));
762 }
763
764 #[test]
765 fn a_spelling_that_is_not_a_number_says_which_way_it_is_wrong() {
766 assert_eq!(Float::parse("", Format::Double), Err(ParseError::NoDigits));
767 assert_eq!(Float::parse(".", Format::Double), Err(ParseError::NoDigits));
768 assert_eq!(Float::parse("1e", Format::Double), Err(ParseError::NoExponentDigits));
769 assert_eq!(Float::parse("1e+", Format::Double), Err(ParseError::NoExponentDigits));
770 assert_eq!(Float::parse("0x1p", Format::Double), Err(ParseError::NoExponentDigits));
771 assert_eq!(Float::parse("0xp1", Format::Double), Err(ParseError::NoDigits));
772 assert_eq!(Float::parse("1x0", Format::Double), Err(ParseError::Invalid));
773 }
774
775 #[test]
776 fn a_sign_is_accepted_although_a_c_constant_never_has_one() {
777 let (value, _) = Float::parse("-1.5", Format::Double).expect("a number");
778 assert!(value.is_negative());
779 assert_eq!(value.to_bits(), u128::from((-1.5f64).to_bits()));
780 let (value, _) = Float::parse("-0.0", Format::Double).expect("a number");
781 assert!(value.is_zero() && value.is_negative());
782 assert_eq!(value.to_bits(), u128::from((-0.0f64).to_bits()));
783 }
784
785 #[test]
786 fn every_format_says_how_wide_its_fields_are() {
787 for format in [
788 Format::Half,
789 Format::BFloat16,
790 Format::Single,
791 Format::Double,
792 Format::X87Extended,
793 Format::Quad,
794 ] {
795 assert_eq!(
796 format.exponent_bits() + format.significand_bits() + 1,
797 format.width(),
798 "{format:?}"
799 );
800 assert_eq!(format.min_exponent(), 1 - format.max_exponent());
801 }
802 assert_eq!(Format::Half.exponent_bits(), 5);
803 assert_eq!(Format::BFloat16.exponent_bits(), 8);
804 assert_eq!(Format::Single.exponent_bits(), 8);
805 assert_eq!(Format::Double.exponent_bits(), 11);
806 assert_eq!(Format::X87Extended.exponent_bits(), 15);
807 assert_eq!(Format::Quad.exponent_bits(), 15);
808 }
809
810 #[test]
811 fn a_number_survives_a_trip_through_its_encoding() {
812 for format in [
813 Format::Half,
814 Format::BFloat16,
815 Format::Single,
816 Format::Double,
817 Format::X87Extended,
818 Format::Quad,
819 ] {
820 for text in ["0", "-0", "1", "-1.5", "3.14159", "1e-5", "65504", "0x1p-20"] {
821 let (value, _) = Float::parse(text, format).expect("a number");
822 let bits = value.to_bits();
823 assert_eq!(Float::from_bits(format, bits).to_bits(), bits, "{text} in {format:?}");
824 }
825 assert_eq!(
826 Float::from_bits(format, Float::infinity(format, false).to_bits()).to_bits(),
827 Float::infinity(format, false).to_bits()
828 );
829 }
830 }
831
832 #[test]
833 fn a_hexadecimal_spelling_reads_back_as_the_number_it_came_from() {
834 for format in [
835 Format::Half,
836 Format::BFloat16,
837 Format::Single,
838 Format::Double,
839 Format::X87Extended,
840 Format::Quad,
841 ] {
842 for text in [
843 "0", "-0", "1", "-1", "0.5", "-1.5", "3.14159", "1e-5", "0x1p-20", "0.1", "255",
844 "1e30",
845 ] {
846 let (value, _) = Float::parse(text, format).expect("a number");
847 let spelling = value.to_hex();
848 let (again, status) = Float::parse(&spelling, format).expect("a number");
849 assert_eq!(again.to_bits(), value.to_bits(), "{text} as {spelling} in {format:?}");
850 let rounded = status.has(Status::INEXACT) || status.has(Status::OVERFLOW);
853 assert_eq!(rounded, !value.is_finite(), "{spelling} in {format:?}");
854 }
855 let tiny = Float::from_bits(format, 1);
857 let (again, _) = Float::parse(&tiny.to_hex(), format).expect("a number");
858 assert_eq!(again.to_bits(), tiny.to_bits(), "the smallest subnormal in {format:?}");
859 let huge = Float::infinity(format, true);
861 let (again, status) = Float::parse(&huge.to_hex(), format).expect("a number");
862 assert!(again.is_infinite() && again.is_negative(), "{format:?}");
863 assert!(status.has(Status::OVERFLOW));
864 }
865 }
866
867 #[test]
868 fn a_round_number_gets_a_short_spelling() {
869 let hex = |text: &str| Float::parse(text, Format::Double).expect("a number").0.to_hex();
870 assert_eq!(hex("1"), "0x1p+0");
871 assert_eq!(hex("-1"), "-0x1p+0");
872 assert_eq!(hex("0"), "0x0p+0");
873 assert_eq!(hex("-0"), "-0x0p+0");
874 assert_eq!(hex("2"), "0x1p+1");
875 assert_eq!(hex("0.5"), "0x1p-1");
876 assert_eq!(hex("0.1"), "0x1999999999999ap-56");
877 }
878
879 #[test]
880 fn the_narrow_formats_round_where_they_are_supposed_to() {
881 let (value, status) = Float::parse("65504", Format::Half).expect("a number");
885 assert!(value.is_finite() && status.is_none());
886 assert_eq!(value.to_bits(), 0x7bff);
887 let (value, _) = Float::parse("65536", Format::Half).expect("a number");
888 assert!(value.is_infinite());
889 assert_eq!(Float::parse("1", Format::Half).expect("one").0.to_bits(), 0x3c00);
890 assert_eq!(Float::parse("1", Format::BFloat16).expect("one").0.to_bits(), 0x3f80);
891 assert_eq!(Float::parse("1e30", Format::BFloat16).expect("big").0.to_bits(), 0x714a);
892 assert_eq!(Float::parse("0x1p-24", Format::Half).expect("tiny").0.to_bits(), 1);
894 assert!(Float::parse("0x1p-26", Format::Half).expect("tinier").0.is_zero());
895 }
896
897 #[test]
898 fn the_x87_format_stores_the_bit_the_others_leave_implied() {
899 let one = Float::parse("1", Format::X87Extended).expect("one").0;
902 assert_eq!(one.to_bits(), 0x3fff_8000_0000_0000_0000);
903 assert_eq!(
904 Float::parse("2", Format::X87Extended).expect("two").0.to_bits(),
905 0x4000_8000_0000_0000_0000
906 );
907 let (value, status) = Float::parse("9007199254740993", Format::X87Extended).expect("one");
909 assert!(status.is_none());
910 assert_eq!(value.to_bits(), 0x4034_8000_0000_0000_0400);
911 assert_eq!(
914 Float::parse("0.1", Format::X87Extended).expect("a tenth").0.to_bits(),
915 0x3ffb_cccc_cccc_cccc_cccd
916 );
917 assert_eq!(Float::parse("1e-4950", Format::X87Extended).expect("tiny").0.to_bits(), 3);
920 }
921
922 #[test]
923 fn the_quad_format_has_a_hundred_and_thirteen_bits_of_it() {
924 assert_eq!(
925 Float::parse("1", Format::Quad).expect("one").0.to_bits(),
926 0x3fff_0000_0000_0000_0000_0000_0000_0000
927 );
928 assert_eq!(
930 Float::parse("0.1", Format::Quad).expect("a tenth").0.to_bits(),
931 0x3ffb_9999_9999_9999_9999_9999_9999_999a
932 );
933 assert_eq!(
935 Float::parse("3.14159", Format::Quad).expect("pi, roughly").0.to_bits(),
936 0x4000_921f_9f01_b866_e43a_a79b_badc_0981
937 );
938 let (value, status) = Float::parse("1e5000", Format::Quad).expect("a number");
939 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
940 let (value, _) = Float::parse("1e-5000", Format::Quad).expect("a number");
941 assert!(value.is_zero());
942 }
943}