1use crate::decimal::{Decimal, Fraction};
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
37pub enum Format {
38 Half,
40 BFloat16,
43 Single,
45 Double,
47 X87Extended,
50 Quad,
53}
54
55impl Format {
56 #[must_use]
58 pub const fn precision(self) -> u32 {
59 match self {
60 Format::Half => 11,
61 Format::BFloat16 => 8,
62 Format::Single => 24,
63 Format::Double => 53,
64 Format::X87Extended => 64,
65 Format::Quad => 113,
66 }
67 }
68
69 #[must_use]
71 pub const fn max_exponent(self) -> i32 {
72 match self {
73 Format::Half => 15,
74 Format::BFloat16 | Format::Single => 127,
75 Format::Double => 1023,
76 Format::X87Extended | Format::Quad => 16383,
77 }
78 }
79
80 #[must_use]
82 pub const fn min_exponent(self) -> i32 {
83 1 - self.max_exponent()
84 }
85
86 #[must_use]
89 pub const fn width(self) -> u32 {
90 match self {
91 Format::Half | Format::BFloat16 => 16,
92 Format::Single => 32,
93 Format::Double => 64,
94 Format::X87Extended => 80,
95 Format::Quad => 128,
96 }
97 }
98
99 #[must_use]
101 pub const fn has_explicit_integer_bit(self) -> bool {
102 matches!(self, Format::X87Extended)
103 }
104
105 const fn exponent_bits(self) -> u32 {
107 self.width() - self.significand_bits() - 1
108 }
109
110 const fn significand_bits(self) -> u32 {
112 if self.has_explicit_integer_bit() { self.precision() } else { self.precision() - 1 }
113 }
114
115 const fn max_decimal_exponent(self) -> i32 {
121 (self.max_exponent() + 1) * 30103 / 100000 + 2
122 }
123
124 const fn min_decimal_exponent(self) -> i32 {
126 (self.min_exponent() - self.precision() as i32) * 30103 / 100000 - 2
127 }
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
136pub struct Status(u8);
137
138impl Status {
139 pub const NONE: Status = Status(0);
141 pub const INEXACT: Status = Status(1);
143 pub const OVERFLOW: Status = Status(2);
145 pub const UNDERFLOW: Status = Status(4);
147
148 #[inline]
150 #[must_use]
151 pub const fn has(self, other: Status) -> bool {
152 self.0 & other.0 == other.0
153 }
154
155 #[inline]
157 #[must_use]
158 pub const fn with(self, other: Status) -> Status {
159 Status(self.0 | other.0)
160 }
161
162 #[inline]
164 #[must_use]
165 pub const fn is_none(self) -> bool {
166 self.0 == 0
167 }
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq)]
175pub enum ParseError {
176 NoDigits,
178 NoExponentDigits,
180 Invalid,
182}
183
184#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
186enum Category {
187 Zero,
188 Finite,
189 Infinite,
190}
191
192#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197pub struct Float {
198 format: Format,
199 category: Category,
200 sign: bool,
201 exponent: i32,
202 significand: u128,
203}
204
205impl Float {
206 #[must_use]
208 pub const fn zero(format: Format, sign: bool) -> Float {
209 Float { format, category: Category::Zero, sign, exponent: 0, significand: 0 }
210 }
211
212 #[must_use]
214 pub const fn infinity(format: Format, sign: bool) -> Float {
215 Float { format, category: Category::Infinite, sign, exponent: 0, significand: 0 }
216 }
217
218 #[must_use]
220 pub const fn format(self) -> Format {
221 self.format
222 }
223
224 #[must_use]
226 pub const fn is_negative(self) -> bool {
227 self.sign
228 }
229
230 #[must_use]
232 pub const fn is_zero(self) -> bool {
233 matches!(self.category, Category::Zero)
234 }
235
236 #[must_use]
238 pub const fn is_infinite(self) -> bool {
239 matches!(self.category, Category::Infinite)
240 }
241
242 #[must_use]
244 pub const fn is_finite(self) -> bool {
245 !self.is_infinite()
246 }
247
248 pub fn parse(text: &str, format: Format) -> Result<(Float, Status), ParseError> {
260 let bytes = text.as_bytes();
261 let (sign, rest) = match bytes.first() {
262 Some(b'-') => (true, &bytes[1..]),
263 Some(b'+') => (false, &bytes[1..]),
264 _ => (false, bytes),
265 };
266 if rest.len() > 1 && rest[0] == b'0' && rest[1] | 32 == b'x' {
267 hexadecimal(&rest[2..], sign, format)
268 } else {
269 decimal(rest, sign, format)
270 }
271 }
272
273 #[must_use]
278 pub fn to_bits(self) -> u128 {
279 let format = self.format;
280 let significand_mask = (1u128 << format.significand_bits()) - 1;
281 let (exponent_field, significand_field) = match self.category {
282 Category::Zero => (0, 0),
283 Category::Infinite => (
284 (1u128 << format.exponent_bits()) - 1,
285 if format.has_explicit_integer_bit() {
286 1u128 << (format.precision() - 1)
287 } else {
288 0
289 },
290 ),
291 Category::Finite => {
292 let subnormal = self.significand >> (format.precision() - 1) == 0;
293 let field =
294 if subnormal { 0 } else { (self.exponent + format.max_exponent()) as u128 };
295 (field, self.significand & significand_mask)
296 }
297 };
298 let sign = u128::from(self.sign) << (format.width() - 1);
299 sign | (exponent_field << format.significand_bits()) | significand_field
300 }
301
302 #[must_use]
308 pub fn from_bits(format: Format, bits: u128) -> Float {
309 let significand_bits = format.significand_bits();
310 let sign = (bits >> (format.width() - 1)) & 1 == 1;
311 let exponent_field =
312 ((bits >> significand_bits) & ((1u128 << format.exponent_bits()) - 1)) as i32;
313 let stored = bits & ((1u128 << significand_bits) - 1);
314 if exponent_field == (1 << format.exponent_bits()) - 1 {
315 return Float::infinity(format, sign);
316 }
317 let implicit = if format.has_explicit_integer_bit() || exponent_field == 0 {
318 0
319 } else {
320 1u128 << (format.precision() - 1)
321 };
322 let significand = stored | implicit;
323 if significand == 0 {
324 return Float::zero(format, sign);
325 }
326 let exponent = if exponent_field == 0 {
327 format.min_exponent()
328 } else {
329 exponent_field - format.max_exponent()
330 };
331 Float { format, category: Category::Finite, sign, exponent, significand }
332 }
333
334 #[must_use]
350 pub fn to_hex(self) -> String {
351 let sign = if self.sign { "-" } else { "" };
352 match self.category {
353 Category::Infinite => format!("{sign}0x1p+{}", self.format.max_exponent() + 1),
354 Category::Zero => format!("{sign}0x0p+0"),
355 Category::Finite => {
356 let mut significand = self.significand;
357 let mut exponent = self.exponent - (self.format.precision() as i32 - 1);
358 while significand & 0xf == 0 {
359 significand >>= 4;
360 exponent += 4;
361 }
362 format!("{sign}0x{significand:x}p{exponent:+}")
363 }
364 }
365 }
366}
367
368fn decimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
370 let mut digits = Vec::new();
371 let mut integer_digits = 0i32;
372 let mut seen_point = false;
373 let mut seen_digit = false;
374 let mut index = 0;
375 while index < bytes.len() {
376 match bytes[index] {
377 byte @ b'0'..=b'9' => {
378 digits.push(byte - b'0');
379 if !seen_point {
380 integer_digits += 1;
381 }
382 seen_digit = true;
383 }
384 b'\'' => {}
385 b'.' if !seen_point => seen_point = true,
386 b'e' | b'E' => break,
387 _ => return Err(ParseError::Invalid),
388 }
389 index += 1;
390 }
391 if !seen_digit {
392 return Err(ParseError::NoDigits);
393 }
394 let mut point = integer_digits;
395 if index < bytes.len() {
396 point = point.saturating_add(exponent_of(&bytes[index + 1..])?);
397 }
398 Ok(convert(Decimal::new(digits, point), sign, format))
399}
400
401fn hexadecimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
403 let mut significand: u128 = 0;
404 let mut exponent = 0i32;
405 let mut sticky = false;
406 let mut seen_point = false;
407 let mut seen_digit = false;
408 let mut index = 0;
409 while index < bytes.len() {
410 let byte = bytes[index];
411 let digit = match byte {
412 b'0'..=b'9' => byte - b'0',
413 b'a'..=b'f' => byte - b'a' + 10,
414 b'A'..=b'F' => byte - b'A' + 10,
415 b'\'' => {
416 index += 1;
417 continue;
418 }
419 b'.' if !seen_point => {
420 seen_point = true;
421 index += 1;
422 continue;
423 }
424 b'p' | b'P' => break,
425 _ => return Err(ParseError::Invalid),
426 };
427 seen_digit = true;
428 if significand.leading_zeros() >= 4 {
429 significand = (significand << 4) | u128::from(digit);
430 if seen_point {
431 exponent -= 4;
432 }
433 } else {
434 sticky |= digit != 0;
437 if !seen_point {
438 exponent += 4;
439 }
440 }
441 index += 1;
442 }
443 if !seen_digit {
444 return Err(ParseError::NoDigits);
445 }
446 if index < bytes.len() {
447 exponent = exponent.saturating_add(exponent_of(&bytes[index + 1..])?);
448 }
449 Ok(round(significand, exponent, sticky, sign, format))
450}
451
452fn exponent_of(bytes: &[u8]) -> Result<i32, ParseError> {
454 let (negative, digits) = match bytes.first() {
455 Some(b'-') => (true, &bytes[1..]),
456 Some(b'+') => (false, &bytes[1..]),
457 _ => (false, bytes),
458 };
459 if digits.is_empty() {
460 return Err(ParseError::NoExponentDigits);
461 }
462 let mut value = 0i32;
463 for &byte in digits {
464 if byte == b'\'' {
465 continue;
466 }
467 if !byte.is_ascii_digit() {
468 return Err(ParseError::Invalid);
469 }
470 value = value.saturating_mul(10).saturating_add(i32::from(byte - b'0'));
473 }
474 Ok(if negative { -value } else { value })
475}
476
477fn convert(mut value: Decimal, sign: bool, format: Format) -> (Float, Status) {
479 if value.is_zero() {
480 return (Float::zero(format, sign), Status::NONE);
481 }
482 if value.point() > format.max_decimal_exponent() {
483 return (Float::infinity(format, sign), Status::OVERFLOW.with(Status::INEXACT));
484 }
485 if value.point() < format.min_decimal_exponent() {
486 return (Float::zero(format, sign), Status::UNDERFLOW.with(Status::INEXACT));
487 }
488
489 let mut exponent = 0i32;
493 loop {
494 let point = value.point();
495 if point > 1 || (point == 1 && value.first_digit() >= 2) {
496 let step = binary_digits(point - 1).clamp(1, 60);
497 value.shift(-step);
498 exponent += step;
499 } else if point < 1 {
500 let step = (1 + binary_digits(-point)).clamp(1, 60);
501 value.shift(step);
502 exponent -= step;
503 } else {
504 break;
505 }
506 }
507
508 let precision = format.precision() as i32;
511 let scale = (exponent - precision + 1).max(format.min_exponent() - precision + 1);
512 value.shift(exponent - scale);
513 let (integer, fraction) = value.round_to_u128();
514 let rounded = match fraction {
515 Fraction::Zero | Fraction::BelowHalf => integer,
516 Fraction::Half => integer + (integer & 1),
517 Fraction::AboveHalf => integer + 1,
518 };
519 finish(rounded, scale, fraction != Fraction::Zero, sign, format)
520}
521
522const fn binary_digits(decimal: i32) -> i32 {
524 decimal * 33219 / 10000
525}
526
527fn round(
530 significand: u128,
531 exponent: i32,
532 sticky: bool,
533 sign: bool,
534 format: Format,
535) -> (Float, Status) {
536 if significand == 0 {
537 return (Float::zero(format, sign), Status::NONE);
538 }
539 let precision = format.precision() as i32;
540 let leading = (128 - significand.leading_zeros()) as i32;
541 let scale = (exponent + leading - precision).max(format.min_exponent() - precision + 1);
542 let mut sticky = sticky;
543 let (integer, half) = if scale <= exponent {
544 (significand << (exponent - scale), false)
545 } else {
546 let drop = (scale - exponent) as u32;
547 if drop >= 128 {
548 sticky = true;
549 (0, false)
550 } else {
551 let half = (significand >> (drop - 1)) & 1 == 1;
552 sticky |= drop > 1 && significand & ((1u128 << (drop - 1)) - 1) != 0;
553 (significand >> drop, half)
554 }
555 };
556 let rounded = if half && (sticky || integer & 1 == 1) { integer + 1 } else { integer };
557 finish(rounded, scale, half || sticky, sign, format)
558}
559
560fn finish(
563 significand: u128,
564 scale: i32,
565 inexact: bool,
566 sign: bool,
567 format: Format,
568) -> (Float, Status) {
569 let precision = format.precision();
570 let mut significand = significand;
571 let mut scale = scale;
572 if significand >> precision != 0 {
573 significand >>= 1;
575 scale += 1;
576 }
577 let mut status = if inexact { Status::INEXACT } else { Status::NONE };
578 if significand == 0 {
579 return (Float::zero(format, sign), status.with(Status::UNDERFLOW));
580 }
581 let exponent = scale + precision as i32 - 1;
582 if exponent > format.max_exponent() {
583 return (
584 Float::infinity(format, sign),
585 status.with(Status::OVERFLOW).with(Status::INEXACT),
586 );
587 }
588 let normal = significand >> (precision - 1) != 0;
589 if !normal && inexact {
590 status = status.with(Status::UNDERFLOW);
591 }
592 let exponent = if normal { exponent } else { format.min_exponent() };
593 (Float { format, category: Category::Finite, sign, exponent, significand }, status)
594}
595
596#[cfg(test)]
597mod tests {
598 use super::*;
599
600 fn double(text: &str) -> u128 {
602 Float::parse(text, Format::Double).expect("a number").0.to_bits()
603 }
604
605 fn single(text: &str) -> u128 {
607 Float::parse(text, Format::Single).expect("a number").0.to_bits()
608 }
609
610 #[test]
611 fn the_ordinary_numbers_land_where_the_host_would_put_them() {
612 for text in ["0", "1", "2", "0.5", "1.5", "3.14159", "2.718281828459045", "100", "1e10"] {
613 let host = text.parse::<f64>().expect("a number Rust reads too");
614 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
615 }
616 }
617
618 #[test]
619 fn a_number_that_needs_the_last_bit_rounded_gets_it_right() {
620 let hard = [
623 "0.1",
624 "0.3",
625 "2.2250738585072011e-308",
626 "2.2250738585072014e-308",
627 "1.7976931348623157e308",
628 "4.9406564584124654e-324",
629 "5e-324",
630 "8.98846567431158e307",
631 "9007199254740993",
632 "123456789012345678901234567890",
633 "1.000000000000000000000000000000000000000000000000000000000000000001",
634 "7.8459735791271921e65",
635 "3.518437208883201171875e13",
636 "0.500000000000000166533453693773481063544750213623046875",
637 ];
638 for text in hard {
639 let host = text.parse::<f64>().expect("a number Rust reads too");
640 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
641 }
642 }
643
644 #[test]
645 fn the_number_that_takes_seven_hundred_and_sixty_seven_digits() {
646 let text = concat!(
649 "2.47032822920623272088284396434110686182529901307162382",
650 "35378852574870103599108683372845652890455735483022221802",
651 "58573249056416711547735232764105795166208503595426876755",
652 "62317084535693494535245273750735013572761315046354601316",
653 "12127849863326369238975694273040488011871029093711789936",
654 "42245692702737764465109076580131048946378905599180391359",
655 "70011386455512221706120629864144453927884519445934871524",
656 "63344875888932891414823975864211858166195965106373837732",
657 "34435703331457550505022232309998195892058070506176382679",
658 "16323484472119097902806154870514036458498974142754747141",
659 "39683784321102080606305920253373777969877864922227306716",
660 "01324339457879181214233820577228206278891620001855078759",
661 "16278352090142077553206262229158550205643778244387017277",
662 "94459649305087139089301871550805125768938177360937844105",
663 "63661045147381814281647890691181239104545396303476425117",
664 "7562185422741845851144691421326303120484712594187004993e-324"
665 );
666 let host = text.parse::<f64>().expect("a number Rust reads too");
667 assert_eq!(double(text), u128::from(host.to_bits()));
668 }
669
670 #[test]
671 fn a_sweep_of_random_numbers_agrees_with_rust_in_every_bit() {
672 let mut state = 0x2545_f491_4f6c_dd1du64;
676 for _ in 0..4000 {
677 state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
678 let digits = state >> 11;
679 let exponent = (state % 600) as i32 - 300;
680 let text = format!("{digits}e{exponent}");
681 let host = text.parse::<f64>().expect("a number Rust reads too");
682 assert_eq!(double(&text), u128::from(host.to_bits()), "{text}");
683 let host = text.parse::<f32>().expect("a number Rust reads too");
684 assert_eq!(single(&text), u128::from(host.to_bits()), "{text} as a float");
685 }
686 }
687
688 #[test]
689 fn the_ends_of_the_range_are_an_infinity_and_a_zero() {
690 let (value, status) = Float::parse("1e400", Format::Double).expect("a number");
691 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
692 let (value, status) = Float::parse("1e-400", Format::Double).expect("a number");
693 assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
694 let (value, status) = Float::parse("1.7976931348623157e308", Format::Double).expect("one");
696 assert!(value.is_finite() && !status.has(Status::OVERFLOW));
697 let (value, _) = Float::parse("1.8e308", Format::Double).expect("a number");
698 assert!(value.is_infinite());
699 assert_eq!(double("2.4e-324"), u128::from((0f64).to_bits()));
701 assert_eq!(double("2.5e-324"), 1);
702 }
703
704 #[test]
705 fn a_number_that_is_exactly_what_was_written_says_so() {
706 assert!(Float::parse("1", Format::Double).expect("a number").1.is_none());
707 assert!(Float::parse("0.5", Format::Double).expect("a number").1.is_none());
708 assert!(Float::parse("0.1", Format::Double).expect("a number").1.has(Status::INEXACT));
709 let (_, status) = Float::parse("1e-320", Format::Double).expect("a number");
711 assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
712 }
713
714 #[test]
715 fn a_hexadecimal_constant_is_exact_and_needs_no_scaling() {
716 assert_eq!(double("0x1p0"), u128::from((1f64).to_bits()));
717 assert_eq!(double("0x1.8p1"), u128::from((3f64).to_bits()));
718 assert_eq!(double("0x1p-1074"), 1);
719 assert_eq!(double("0xa.bp-4"), u128::from((0.66796875f64).to_bits()));
720 assert_eq!(double("0X1.FFFFFFFFFFFFFP+1023"), u128::from(f64::MAX.to_bits()));
721 assert!(Float::parse("0x1p0", Format::Double).expect("a number").1.is_none());
722 let (_, status) = Float::parse("0x1.00000000000008p0", Format::Double).expect("a number");
724 assert!(status.has(Status::INEXACT));
725 assert_eq!(double("0x1.00000000000008p0"), u128::from((1f64).to_bits()));
726 assert_eq!(double("0x1.00000000000018p0"), u128::from((1f64).to_bits() + 2));
727 }
728
729 #[test]
730 fn digit_separators_are_not_part_of_the_number() {
731 assert_eq!(double("1'000.000'1"), double("1000.0001"));
732 assert_eq!(double("0x1'0p0"), double("16.0"));
733 assert_eq!(double("1e1'0"), double("1e10"));
734 }
735
736 #[test]
737 fn a_spelling_that_is_not_a_number_says_which_way_it_is_wrong() {
738 assert_eq!(Float::parse("", Format::Double), Err(ParseError::NoDigits));
739 assert_eq!(Float::parse(".", Format::Double), Err(ParseError::NoDigits));
740 assert_eq!(Float::parse("1e", Format::Double), Err(ParseError::NoExponentDigits));
741 assert_eq!(Float::parse("1e+", Format::Double), Err(ParseError::NoExponentDigits));
742 assert_eq!(Float::parse("0x1p", Format::Double), Err(ParseError::NoExponentDigits));
743 assert_eq!(Float::parse("0xp1", Format::Double), Err(ParseError::NoDigits));
744 assert_eq!(Float::parse("1x0", Format::Double), Err(ParseError::Invalid));
745 }
746
747 #[test]
748 fn a_sign_is_accepted_although_a_c_constant_never_has_one() {
749 let (value, _) = Float::parse("-1.5", Format::Double).expect("a number");
750 assert!(value.is_negative());
751 assert_eq!(value.to_bits(), u128::from((-1.5f64).to_bits()));
752 let (value, _) = Float::parse("-0.0", Format::Double).expect("a number");
753 assert!(value.is_zero() && value.is_negative());
754 assert_eq!(value.to_bits(), u128::from((-0.0f64).to_bits()));
755 }
756
757 #[test]
758 fn every_format_says_how_wide_its_fields_are() {
759 for format in [
760 Format::Half,
761 Format::BFloat16,
762 Format::Single,
763 Format::Double,
764 Format::X87Extended,
765 Format::Quad,
766 ] {
767 assert_eq!(
768 format.exponent_bits() + format.significand_bits() + 1,
769 format.width(),
770 "{format:?}"
771 );
772 assert_eq!(format.min_exponent(), 1 - format.max_exponent());
773 }
774 assert_eq!(Format::Half.exponent_bits(), 5);
775 assert_eq!(Format::BFloat16.exponent_bits(), 8);
776 assert_eq!(Format::Single.exponent_bits(), 8);
777 assert_eq!(Format::Double.exponent_bits(), 11);
778 assert_eq!(Format::X87Extended.exponent_bits(), 15);
779 assert_eq!(Format::Quad.exponent_bits(), 15);
780 }
781
782 #[test]
783 fn a_number_survives_a_trip_through_its_encoding() {
784 for format in [
785 Format::Half,
786 Format::BFloat16,
787 Format::Single,
788 Format::Double,
789 Format::X87Extended,
790 Format::Quad,
791 ] {
792 for text in ["0", "-0", "1", "-1.5", "3.14159", "1e-5", "65504", "0x1p-20"] {
793 let (value, _) = Float::parse(text, format).expect("a number");
794 let bits = value.to_bits();
795 assert_eq!(Float::from_bits(format, bits).to_bits(), bits, "{text} in {format:?}");
796 }
797 assert_eq!(
798 Float::from_bits(format, Float::infinity(format, false).to_bits()).to_bits(),
799 Float::infinity(format, false).to_bits()
800 );
801 }
802 }
803
804 #[test]
805 fn a_hexadecimal_spelling_reads_back_as_the_number_it_came_from() {
806 for format in [
807 Format::Half,
808 Format::BFloat16,
809 Format::Single,
810 Format::Double,
811 Format::X87Extended,
812 Format::Quad,
813 ] {
814 for text in [
815 "0", "-0", "1", "-1", "0.5", "-1.5", "3.14159", "1e-5", "0x1p-20", "0.1", "255",
816 "1e30",
817 ] {
818 let (value, _) = Float::parse(text, format).expect("a number");
819 let spelling = value.to_hex();
820 let (again, status) = Float::parse(&spelling, format).expect("a number");
821 assert_eq!(again.to_bits(), value.to_bits(), "{text} as {spelling} in {format:?}");
822 let rounded = status.has(Status::INEXACT) || status.has(Status::OVERFLOW);
825 assert_eq!(rounded, !value.is_finite(), "{spelling} in {format:?}");
826 }
827 let tiny = Float::from_bits(format, 1);
829 let (again, _) = Float::parse(&tiny.to_hex(), format).expect("a number");
830 assert_eq!(again.to_bits(), tiny.to_bits(), "the smallest subnormal in {format:?}");
831 let huge = Float::infinity(format, true);
833 let (again, status) = Float::parse(&huge.to_hex(), format).expect("a number");
834 assert!(again.is_infinite() && again.is_negative(), "{format:?}");
835 assert!(status.has(Status::OVERFLOW));
836 }
837 }
838
839 #[test]
840 fn a_round_number_gets_a_short_spelling() {
841 let hex = |text: &str| Float::parse(text, Format::Double).expect("a number").0.to_hex();
842 assert_eq!(hex("1"), "0x1p+0");
843 assert_eq!(hex("-1"), "-0x1p+0");
844 assert_eq!(hex("0"), "0x0p+0");
845 assert_eq!(hex("-0"), "-0x0p+0");
846 assert_eq!(hex("2"), "0x1p+1");
847 assert_eq!(hex("0.5"), "0x1p-1");
848 assert_eq!(hex("0.1"), "0x1999999999999ap-56");
849 }
850
851 #[test]
852 fn the_narrow_formats_round_where_they_are_supposed_to() {
853 let (value, status) = Float::parse("65504", Format::Half).expect("a number");
857 assert!(value.is_finite() && status.is_none());
858 assert_eq!(value.to_bits(), 0x7bff);
859 let (value, _) = Float::parse("65536", Format::Half).expect("a number");
860 assert!(value.is_infinite());
861 assert_eq!(Float::parse("1", Format::Half).expect("one").0.to_bits(), 0x3c00);
862 assert_eq!(Float::parse("1", Format::BFloat16).expect("one").0.to_bits(), 0x3f80);
863 assert_eq!(Float::parse("1e30", Format::BFloat16).expect("big").0.to_bits(), 0x714a);
864 assert_eq!(Float::parse("0x1p-24", Format::Half).expect("tiny").0.to_bits(), 1);
866 assert!(Float::parse("0x1p-26", Format::Half).expect("tinier").0.is_zero());
867 }
868
869 #[test]
870 fn the_x87_format_stores_the_bit_the_others_leave_implied() {
871 let one = Float::parse("1", Format::X87Extended).expect("one").0;
874 assert_eq!(one.to_bits(), 0x3fff_8000_0000_0000_0000);
875 assert_eq!(
876 Float::parse("2", Format::X87Extended).expect("two").0.to_bits(),
877 0x4000_8000_0000_0000_0000
878 );
879 let (value, status) = Float::parse("9007199254740993", Format::X87Extended).expect("one");
881 assert!(status.is_none());
882 assert_eq!(value.to_bits(), 0x4034_8000_0000_0000_0400);
883 assert_eq!(
886 Float::parse("0.1", Format::X87Extended).expect("a tenth").0.to_bits(),
887 0x3ffb_cccc_cccc_cccc_cccd
888 );
889 assert_eq!(Float::parse("1e-4950", Format::X87Extended).expect("tiny").0.to_bits(), 3);
892 }
893
894 #[test]
895 fn the_quad_format_has_a_hundred_and_thirteen_bits_of_it() {
896 assert_eq!(
897 Float::parse("1", Format::Quad).expect("one").0.to_bits(),
898 0x3fff_0000_0000_0000_0000_0000_0000_0000
899 );
900 assert_eq!(
902 Float::parse("0.1", Format::Quad).expect("a tenth").0.to_bits(),
903 0x3ffb_9999_9999_9999_9999_9999_9999_999a
904 );
905 assert_eq!(
907 Float::parse("3.14159", Format::Quad).expect("pi, roughly").0.to_bits(),
908 0x4000_921f_9f01_b866_e43a_a79b_badc_0981
909 );
910 let (value, status) = Float::parse("1e5000", Format::Quad).expect("a number");
911 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
912 let (value, _) = Float::parse("1e-5000", Format::Quad).expect("a number");
913 assert!(value.is_zero());
914 }
915}