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]
235 pub const fn nan_with(format: Format, sign: bool, quiet: bool, payload: u128) -> Float {
236 let mut significand = payload & (Float::quiet_bit(format) - 1);
237 if quiet {
238 significand |= Float::quiet_bit(format);
239 } else if significand == 0 {
240 significand = Float::quiet_bit(format) >> 1;
241 }
242 Float {
243 format,
244 category: Category::Nan,
245 sign,
246 exponent: 0,
247 significand: significand | Float::leading_bit(format),
248 }
249 }
250
251 const fn quiet_bit(format: Format) -> u128 {
254 1u128 << (format.precision() - 2)
255 }
256
257 const fn leading_bit(format: Format) -> u128 {
260 if format.has_explicit_integer_bit() { 1u128 << (format.precision() - 1) } else { 0 }
261 }
262
263 #[must_use]
265 pub const fn format(self) -> Format {
266 self.format
267 }
268
269 #[must_use]
271 pub const fn is_negative(self) -> bool {
272 self.sign
273 }
274
275 #[must_use]
277 pub const fn is_zero(self) -> bool {
278 matches!(self.category, Category::Zero)
279 }
280
281 #[must_use]
283 pub const fn is_infinite(self) -> bool {
284 matches!(self.category, Category::Infinite)
285 }
286
287 #[must_use]
289 pub const fn is_finite(self) -> bool {
290 matches!(self.category, Category::Zero | Category::Finite)
291 }
292
293 pub fn parse(text: &str, format: Format) -> Result<(Float, Status), ParseError> {
305 let bytes = text.as_bytes();
306 let (sign, rest) = match bytes.first() {
307 Some(b'-') => (true, &bytes[1..]),
308 Some(b'+') => (false, &bytes[1..]),
309 _ => (false, bytes),
310 };
311 if rest.len() > 1 && rest[0] == b'0' && rest[1] | 32 == b'x' {
312 hexadecimal(&rest[2..], sign, format)
313 } else {
314 decimal(rest, sign, format)
315 }
316 }
317
318 #[must_use]
323 pub fn to_bits(self) -> u128 {
324 let format = self.format;
325 let significand_mask = (1u128 << format.significand_bits()) - 1;
326 let (exponent_field, significand_field) = match self.category {
327 Category::Zero => (0, 0),
328 Category::Infinite => (
329 (1u128 << format.exponent_bits()) - 1,
330 if format.has_explicit_integer_bit() {
331 1u128 << (format.precision() - 1)
332 } else {
333 0
334 },
335 ),
336 Category::Nan => ((1u128 << format.exponent_bits()) - 1, self.significand),
339 Category::Finite => {
340 let subnormal = self.significand >> (format.precision() - 1) == 0;
341 let field =
342 if subnormal { 0 } else { (self.exponent + format.max_exponent()) as u128 };
343 (field, self.significand & significand_mask)
344 }
345 };
346 let sign = u128::from(self.sign) << (format.width() - 1);
347 sign | (exponent_field << format.significand_bits()) | significand_field
348 }
349
350 #[must_use]
357 pub fn from_bits(format: Format, bits: u128) -> Float {
358 let significand_bits = format.significand_bits();
359 let sign = (bits >> (format.width() - 1)) & 1 == 1;
360 let exponent_field =
361 ((bits >> significand_bits) & ((1u128 << format.exponent_bits()) - 1)) as i32;
362 let stored = bits & ((1u128 << significand_bits) - 1);
363 if exponent_field == (1 << format.exponent_bits()) - 1 {
364 let fraction = stored & ((1u128 << (format.precision() - 1)) - 1);
367 if fraction == 0 {
368 return Float::infinity(format, sign);
369 }
370 return Float {
371 format,
372 category: Category::Nan,
373 sign,
374 exponent: 0,
375 significand: stored,
376 };
377 }
378 let implicit = if format.has_explicit_integer_bit() || exponent_field == 0 {
379 0
380 } else {
381 1u128 << (format.precision() - 1)
382 };
383 let significand = stored | implicit;
384 if significand == 0 {
385 return Float::zero(format, sign);
386 }
387 let exponent = if exponent_field == 0 {
388 format.min_exponent()
389 } else {
390 exponent_field - format.max_exponent()
391 };
392 Float { format, category: Category::Finite, sign, exponent, significand }
393 }
394
395 #[must_use]
412 pub fn to_hex(self) -> String {
413 let sign = if self.sign { "-" } else { "" };
414 match self.category {
415 Category::Nan => format!("{sign}nan"),
416 Category::Infinite => format!("{sign}0x1p+{}", self.format.max_exponent() + 1),
417 Category::Zero => format!("{sign}0x0p+0"),
418 Category::Finite => {
419 let mut significand = self.significand;
420 let mut exponent = self.exponent - (self.format.precision() as i32 - 1);
421 while significand & 0xf == 0 {
422 significand >>= 4;
423 exponent += 4;
424 }
425 format!("{sign}0x{significand:x}p{exponent:+}")
426 }
427 }
428 }
429}
430
431fn decimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
433 let mut digits = Vec::new();
434 let mut integer_digits = 0i32;
435 let mut seen_point = false;
436 let mut seen_digit = false;
437 let mut index = 0;
438 while index < bytes.len() {
439 match bytes[index] {
440 byte @ b'0'..=b'9' => {
441 digits.push(byte - b'0');
442 if !seen_point {
443 integer_digits += 1;
444 }
445 seen_digit = true;
446 }
447 b'\'' => {}
448 b'.' if !seen_point => seen_point = true,
449 b'e' | b'E' => break,
450 _ => return Err(ParseError::Invalid),
451 }
452 index += 1;
453 }
454 if !seen_digit {
455 return Err(ParseError::NoDigits);
456 }
457 let mut point = integer_digits;
458 if index < bytes.len() {
459 point = point.saturating_add(exponent_of(&bytes[index + 1..])?);
460 }
461 Ok(convert(Decimal::new(digits, point), sign, format))
462}
463
464fn hexadecimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
466 let mut significand: u128 = 0;
467 let mut exponent = 0i32;
468 let mut sticky = false;
469 let mut seen_point = false;
470 let mut seen_digit = false;
471 let mut index = 0;
472 while index < bytes.len() {
473 let byte = bytes[index];
474 let digit = match byte {
475 b'0'..=b'9' => byte - b'0',
476 b'a'..=b'f' => byte - b'a' + 10,
477 b'A'..=b'F' => byte - b'A' + 10,
478 b'\'' => {
479 index += 1;
480 continue;
481 }
482 b'.' if !seen_point => {
483 seen_point = true;
484 index += 1;
485 continue;
486 }
487 b'p' | b'P' => break,
488 _ => return Err(ParseError::Invalid),
489 };
490 seen_digit = true;
491 if significand.leading_zeros() >= 4 {
492 significand = (significand << 4) | u128::from(digit);
493 if seen_point {
494 exponent -= 4;
495 }
496 } else {
497 sticky |= digit != 0;
500 if !seen_point {
501 exponent += 4;
502 }
503 }
504 index += 1;
505 }
506 if !seen_digit {
507 return Err(ParseError::NoDigits);
508 }
509 if index < bytes.len() {
510 exponent = exponent.saturating_add(exponent_of(&bytes[index + 1..])?);
511 }
512 Ok(round(significand, exponent, sticky, sign, format))
513}
514
515fn exponent_of(bytes: &[u8]) -> Result<i32, ParseError> {
517 let (negative, digits) = match bytes.first() {
518 Some(b'-') => (true, &bytes[1..]),
519 Some(b'+') => (false, &bytes[1..]),
520 _ => (false, bytes),
521 };
522 if digits.is_empty() {
523 return Err(ParseError::NoExponentDigits);
524 }
525 let mut value = 0i32;
526 for &byte in digits {
527 if byte == b'\'' {
528 continue;
529 }
530 if !byte.is_ascii_digit() {
531 return Err(ParseError::Invalid);
532 }
533 value = value.saturating_mul(10).saturating_add(i32::from(byte - b'0'));
536 }
537 Ok(if negative { -value } else { value })
538}
539
540fn convert(mut value: Decimal, sign: bool, format: Format) -> (Float, Status) {
542 if value.is_zero() {
543 return (Float::zero(format, sign), Status::NONE);
544 }
545 if value.point() > format.max_decimal_exponent() {
546 return (Float::infinity(format, sign), Status::OVERFLOW.with(Status::INEXACT));
547 }
548 if value.point() < format.min_decimal_exponent() {
549 return (Float::zero(format, sign), Status::UNDERFLOW.with(Status::INEXACT));
550 }
551
552 let mut exponent = 0i32;
556 loop {
557 let point = value.point();
558 if point > 1 || (point == 1 && value.first_digit() >= 2) {
559 let step = binary_digits(point - 1).clamp(1, 60);
560 value.shift(-step);
561 exponent += step;
562 } else if point < 1 {
563 let step = (1 + binary_digits(-point)).clamp(1, 60);
564 value.shift(step);
565 exponent -= step;
566 } else {
567 break;
568 }
569 }
570
571 let precision = format.precision() as i32;
574 let scale = (exponent - precision + 1).max(format.min_exponent() - precision + 1);
575 value.shift(exponent - scale);
576 let (integer, fraction) = value.round_to_u128();
577 let rounded = match fraction {
578 Fraction::Zero | Fraction::BelowHalf => integer,
579 Fraction::Half => integer + (integer & 1),
580 Fraction::AboveHalf => integer + 1,
581 };
582 finish(rounded, scale, fraction != Fraction::Zero, sign, format)
583}
584
585const fn binary_digits(decimal: i32) -> i32 {
587 decimal * 33219 / 10000
588}
589
590fn round(
593 significand: u128,
594 exponent: i32,
595 sticky: bool,
596 sign: bool,
597 format: Format,
598) -> (Float, Status) {
599 if significand == 0 {
600 return (Float::zero(format, sign), Status::NONE);
601 }
602 let precision = format.precision() as i32;
603 let leading = (128 - significand.leading_zeros()) as i32;
604 let scale = (exponent + leading - precision).max(format.min_exponent() - precision + 1);
605 let mut sticky = sticky;
606 let (integer, half) = if scale <= exponent {
607 (significand << (exponent - scale), false)
608 } else {
609 let drop = (scale - exponent) as u32;
610 if drop >= 128 {
611 sticky = true;
612 (0, false)
613 } else {
614 let half = (significand >> (drop - 1)) & 1 == 1;
615 sticky |= drop > 1 && significand & ((1u128 << (drop - 1)) - 1) != 0;
616 (significand >> drop, half)
617 }
618 };
619 let rounded = if half && (sticky || integer & 1 == 1) { integer + 1 } else { integer };
620 finish(rounded, scale, half || sticky, sign, format)
621}
622
623fn finish(
626 significand: u128,
627 scale: i32,
628 inexact: bool,
629 sign: bool,
630 format: Format,
631) -> (Float, Status) {
632 let precision = format.precision();
633 let mut significand = significand;
634 let mut scale = scale;
635 if significand >> precision != 0 {
636 significand >>= 1;
638 scale += 1;
639 }
640 let mut status = if inexact { Status::INEXACT } else { Status::NONE };
641 if significand == 0 {
642 return (Float::zero(format, sign), status.with(Status::UNDERFLOW));
643 }
644 let exponent = scale + precision as i32 - 1;
645 if exponent > format.max_exponent() {
646 return (
647 Float::infinity(format, sign),
648 status.with(Status::OVERFLOW).with(Status::INEXACT),
649 );
650 }
651 let normal = significand >> (precision - 1) != 0;
652 if !normal && inexact {
653 status = status.with(Status::UNDERFLOW);
654 }
655 let exponent = if normal { exponent } else { format.min_exponent() };
656 (Float { format, category: Category::Finite, sign, exponent, significand }, status)
657}
658
659#[cfg(test)]
660mod tests {
661 use super::*;
662
663 fn double(text: &str) -> u128 {
665 Float::parse(text, Format::Double).expect("a number").0.to_bits()
666 }
667
668 fn single(text: &str) -> u128 {
670 Float::parse(text, Format::Single).expect("a number").0.to_bits()
671 }
672
673 #[test]
674 fn the_ordinary_numbers_land_where_the_host_would_put_them() {
675 for text in ["0", "1", "2", "0.5", "1.5", "3.14159", "2.718281828459045", "100", "1e10"] {
676 let host = text.parse::<f64>().expect("a number Rust reads too");
677 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
678 }
679 }
680
681 #[test]
682 fn a_number_that_needs_the_last_bit_rounded_gets_it_right() {
683 let hard = [
686 "0.1",
687 "0.3",
688 "2.2250738585072011e-308",
689 "2.2250738585072014e-308",
690 "1.7976931348623157e308",
691 "4.9406564584124654e-324",
692 "5e-324",
693 "8.98846567431158e307",
694 "9007199254740993",
695 "123456789012345678901234567890",
696 "1.000000000000000000000000000000000000000000000000000000000000000001",
697 "7.8459735791271921e65",
698 "3.518437208883201171875e13",
699 "0.500000000000000166533453693773481063544750213623046875",
700 ];
701 for text in hard {
702 let host = text.parse::<f64>().expect("a number Rust reads too");
703 assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
704 }
705 }
706
707 #[test]
708 fn the_number_that_takes_seven_hundred_and_sixty_seven_digits() {
709 let text = concat!(
712 "2.47032822920623272088284396434110686182529901307162382",
713 "35378852574870103599108683372845652890455735483022221802",
714 "58573249056416711547735232764105795166208503595426876755",
715 "62317084535693494535245273750735013572761315046354601316",
716 "12127849863326369238975694273040488011871029093711789936",
717 "42245692702737764465109076580131048946378905599180391359",
718 "70011386455512221706120629864144453927884519445934871524",
719 "63344875888932891414823975864211858166195965106373837732",
720 "34435703331457550505022232309998195892058070506176382679",
721 "16323484472119097902806154870514036458498974142754747141",
722 "39683784321102080606305920253373777969877864922227306716",
723 "01324339457879181214233820577228206278891620001855078759",
724 "16278352090142077553206262229158550205643778244387017277",
725 "94459649305087139089301871550805125768938177360937844105",
726 "63661045147381814281647890691181239104545396303476425117",
727 "7562185422741845851144691421326303120484712594187004993e-324"
728 );
729 let host = text.parse::<f64>().expect("a number Rust reads too");
730 assert_eq!(double(text), u128::from(host.to_bits()));
731 }
732
733 #[test]
734 fn a_sweep_of_random_numbers_agrees_with_rust_in_every_bit() {
735 let mut state = 0x2545_f491_4f6c_dd1du64;
739 for _ in 0..4000 {
740 state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
741 let digits = state >> 11;
742 let exponent = (state % 600) as i32 - 300;
743 let text = format!("{digits}e{exponent}");
744 let host = text.parse::<f64>().expect("a number Rust reads too");
745 assert_eq!(double(&text), u128::from(host.to_bits()), "{text}");
746 let host = text.parse::<f32>().expect("a number Rust reads too");
747 assert_eq!(single(&text), u128::from(host.to_bits()), "{text} as a float");
748 }
749 }
750
751 #[test]
752 fn the_ends_of_the_range_are_an_infinity_and_a_zero() {
753 let (value, status) = Float::parse("1e400", Format::Double).expect("a number");
754 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
755 let (value, status) = Float::parse("1e-400", Format::Double).expect("a number");
756 assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
757 let (value, status) = Float::parse("1.7976931348623157e308", Format::Double).expect("one");
759 assert!(value.is_finite() && !status.has(Status::OVERFLOW));
760 let (value, _) = Float::parse("1.8e308", Format::Double).expect("a number");
761 assert!(value.is_infinite());
762 assert_eq!(double("2.4e-324"), u128::from((0f64).to_bits()));
764 assert_eq!(double("2.5e-324"), 1);
765 }
766
767 #[test]
768 fn a_number_that_is_exactly_what_was_written_says_so() {
769 assert!(Float::parse("1", Format::Double).expect("a number").1.is_none());
770 assert!(Float::parse("0.5", Format::Double).expect("a number").1.is_none());
771 assert!(Float::parse("0.1", Format::Double).expect("a number").1.has(Status::INEXACT));
772 let (_, status) = Float::parse("1e-320", Format::Double).expect("a number");
774 assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
775 }
776
777 #[test]
778 fn a_hexadecimal_constant_is_exact_and_needs_no_scaling() {
779 assert_eq!(double("0x1p0"), u128::from((1f64).to_bits()));
780 assert_eq!(double("0x1.8p1"), u128::from((3f64).to_bits()));
781 assert_eq!(double("0x1p-1074"), 1);
782 assert_eq!(double("0xa.bp-4"), u128::from((0.66796875f64).to_bits()));
783 assert_eq!(double("0X1.FFFFFFFFFFFFFP+1023"), u128::from(f64::MAX.to_bits()));
784 assert!(Float::parse("0x1p0", Format::Double).expect("a number").1.is_none());
785 let (_, status) = Float::parse("0x1.00000000000008p0", Format::Double).expect("a number");
787 assert!(status.has(Status::INEXACT));
788 assert_eq!(double("0x1.00000000000008p0"), u128::from((1f64).to_bits()));
789 assert_eq!(double("0x1.00000000000018p0"), u128::from((1f64).to_bits() + 2));
790 }
791
792 #[test]
793 fn digit_separators_are_not_part_of_the_number() {
794 assert_eq!(double("1'000.000'1"), double("1000.0001"));
795 assert_eq!(double("0x1'0p0"), double("16.0"));
796 assert_eq!(double("1e1'0"), double("1e10"));
797 }
798
799 #[test]
800 fn a_spelling_that_is_not_a_number_says_which_way_it_is_wrong() {
801 assert_eq!(Float::parse("", Format::Double), Err(ParseError::NoDigits));
802 assert_eq!(Float::parse(".", Format::Double), Err(ParseError::NoDigits));
803 assert_eq!(Float::parse("1e", Format::Double), Err(ParseError::NoExponentDigits));
804 assert_eq!(Float::parse("1e+", Format::Double), Err(ParseError::NoExponentDigits));
805 assert_eq!(Float::parse("0x1p", Format::Double), Err(ParseError::NoExponentDigits));
806 assert_eq!(Float::parse("0xp1", Format::Double), Err(ParseError::NoDigits));
807 assert_eq!(Float::parse("1x0", Format::Double), Err(ParseError::Invalid));
808 }
809
810 #[test]
811 fn a_sign_is_accepted_although_a_c_constant_never_has_one() {
812 let (value, _) = Float::parse("-1.5", Format::Double).expect("a number");
813 assert!(value.is_negative());
814 assert_eq!(value.to_bits(), u128::from((-1.5f64).to_bits()));
815 let (value, _) = Float::parse("-0.0", Format::Double).expect("a number");
816 assert!(value.is_zero() && value.is_negative());
817 assert_eq!(value.to_bits(), u128::from((-0.0f64).to_bits()));
818 }
819
820 #[test]
821 fn every_format_says_how_wide_its_fields_are() {
822 for format in [
823 Format::Half,
824 Format::BFloat16,
825 Format::Single,
826 Format::Double,
827 Format::X87Extended,
828 Format::Quad,
829 ] {
830 assert_eq!(
831 format.exponent_bits() + format.significand_bits() + 1,
832 format.width(),
833 "{format:?}"
834 );
835 assert_eq!(format.min_exponent(), 1 - format.max_exponent());
836 }
837 assert_eq!(Format::Half.exponent_bits(), 5);
838 assert_eq!(Format::BFloat16.exponent_bits(), 8);
839 assert_eq!(Format::Single.exponent_bits(), 8);
840 assert_eq!(Format::Double.exponent_bits(), 11);
841 assert_eq!(Format::X87Extended.exponent_bits(), 15);
842 assert_eq!(Format::Quad.exponent_bits(), 15);
843 }
844
845 #[test]
846 fn a_number_survives_a_trip_through_its_encoding() {
847 for format in [
848 Format::Half,
849 Format::BFloat16,
850 Format::Single,
851 Format::Double,
852 Format::X87Extended,
853 Format::Quad,
854 ] {
855 for text in ["0", "-0", "1", "-1.5", "3.14159", "1e-5", "65504", "0x1p-20"] {
856 let (value, _) = Float::parse(text, format).expect("a number");
857 let bits = value.to_bits();
858 assert_eq!(Float::from_bits(format, bits).to_bits(), bits, "{text} in {format:?}");
859 }
860 assert_eq!(
861 Float::from_bits(format, Float::infinity(format, false).to_bits()).to_bits(),
862 Float::infinity(format, false).to_bits()
863 );
864 }
865 }
866
867 #[test]
868 fn a_hexadecimal_spelling_reads_back_as_the_number_it_came_from() {
869 for format in [
870 Format::Half,
871 Format::BFloat16,
872 Format::Single,
873 Format::Double,
874 Format::X87Extended,
875 Format::Quad,
876 ] {
877 for text in [
878 "0", "-0", "1", "-1", "0.5", "-1.5", "3.14159", "1e-5", "0x1p-20", "0.1", "255",
879 "1e30",
880 ] {
881 let (value, _) = Float::parse(text, format).expect("a number");
882 let spelling = value.to_hex();
883 let (again, status) = Float::parse(&spelling, format).expect("a number");
884 assert_eq!(again.to_bits(), value.to_bits(), "{text} as {spelling} in {format:?}");
885 let rounded = status.has(Status::INEXACT) || status.has(Status::OVERFLOW);
888 assert_eq!(rounded, !value.is_finite(), "{spelling} in {format:?}");
889 }
890 let tiny = Float::from_bits(format, 1);
892 let (again, _) = Float::parse(&tiny.to_hex(), format).expect("a number");
893 assert_eq!(again.to_bits(), tiny.to_bits(), "the smallest subnormal in {format:?}");
894 let huge = Float::infinity(format, true);
896 let (again, status) = Float::parse(&huge.to_hex(), format).expect("a number");
897 assert!(again.is_infinite() && again.is_negative(), "{format:?}");
898 assert!(status.has(Status::OVERFLOW));
899 }
900 }
901
902 #[test]
903 fn a_round_number_gets_a_short_spelling() {
904 let hex = |text: &str| Float::parse(text, Format::Double).expect("a number").0.to_hex();
905 assert_eq!(hex("1"), "0x1p+0");
906 assert_eq!(hex("-1"), "-0x1p+0");
907 assert_eq!(hex("0"), "0x0p+0");
908 assert_eq!(hex("-0"), "-0x0p+0");
909 assert_eq!(hex("2"), "0x1p+1");
910 assert_eq!(hex("0.5"), "0x1p-1");
911 assert_eq!(hex("0.1"), "0x1999999999999ap-56");
912 }
913
914 #[test]
915 fn the_narrow_formats_round_where_they_are_supposed_to() {
916 let (value, status) = Float::parse("65504", Format::Half).expect("a number");
920 assert!(value.is_finite() && status.is_none());
921 assert_eq!(value.to_bits(), 0x7bff);
922 let (value, _) = Float::parse("65536", Format::Half).expect("a number");
923 assert!(value.is_infinite());
924 assert_eq!(Float::parse("1", Format::Half).expect("one").0.to_bits(), 0x3c00);
925 assert_eq!(Float::parse("1", Format::BFloat16).expect("one").0.to_bits(), 0x3f80);
926 assert_eq!(Float::parse("1e30", Format::BFloat16).expect("big").0.to_bits(), 0x714a);
927 assert_eq!(Float::parse("0x1p-24", Format::Half).expect("tiny").0.to_bits(), 1);
929 assert!(Float::parse("0x1p-26", Format::Half).expect("tinier").0.is_zero());
930 }
931
932 #[test]
933 fn the_x87_format_stores_the_bit_the_others_leave_implied() {
934 let one = Float::parse("1", Format::X87Extended).expect("one").0;
937 assert_eq!(one.to_bits(), 0x3fff_8000_0000_0000_0000);
938 assert_eq!(
939 Float::parse("2", Format::X87Extended).expect("two").0.to_bits(),
940 0x4000_8000_0000_0000_0000
941 );
942 let (value, status) = Float::parse("9007199254740993", Format::X87Extended).expect("one");
944 assert!(status.is_none());
945 assert_eq!(value.to_bits(), 0x4034_8000_0000_0000_0400);
946 assert_eq!(
949 Float::parse("0.1", Format::X87Extended).expect("a tenth").0.to_bits(),
950 0x3ffb_cccc_cccc_cccc_cccd
951 );
952 assert_eq!(Float::parse("1e-4950", Format::X87Extended).expect("tiny").0.to_bits(), 3);
955 }
956
957 #[test]
958 fn the_quad_format_has_a_hundred_and_thirteen_bits_of_it() {
959 assert_eq!(
960 Float::parse("1", Format::Quad).expect("one").0.to_bits(),
961 0x3fff_0000_0000_0000_0000_0000_0000_0000
962 );
963 assert_eq!(
965 Float::parse("0.1", Format::Quad).expect("a tenth").0.to_bits(),
966 0x3ffb_9999_9999_9999_9999_9999_9999_999a
967 );
968 assert_eq!(
970 Float::parse("3.14159", Format::Quad).expect("pi, roughly").0.to_bits(),
971 0x4000_921f_9f01_b866_e43a_a79b_badc_0981
972 );
973 let (value, status) = Float::parse("1e5000", Format::Quad).expect("a number");
974 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
975 let (value, _) = Float::parse("1e-5000", Format::Quad).expect("a number");
976 assert!(value.is_zero());
977 }
978
979 #[test]
982 fn a_nan_with_a_payload_has_the_bits_gcc_gives_it() {
983 let double = |quiet, payload| Float::nan_with(Format::Double, false, quiet, payload);
984 assert_eq!(double(true, 0).to_bits(), 0x7ff8_0000_0000_0000, "__builtin_nan(\"\")");
985 assert_eq!(double(true, 1).to_bits(), 0x7ff8_0000_0000_0001, "__builtin_nan(\"0x1\")");
986 assert_eq!(double(true, 8).to_bits(), 0x7ff8_0000_0000_0008, "__builtin_nan(\"010\")");
987 assert_eq!(double(false, 0).to_bits(), 0x7ff4_0000_0000_0000, "__builtin_nans(\"\")");
990 assert_eq!(double(false, 1).to_bits(), 0x7ff0_0000_0000_0001, "__builtin_nans(\"0x1\")");
991 assert_eq!(double(true, 0xf_ffff_ffff_ffff).to_bits(), 0x7fff_ffff_ffff_ffff);
993 assert_eq!(double(true, 1 << 52).to_bits(), 0x7ff8_0000_0000_0000);
994 assert_eq!(
995 Float::nan_with(Format::Single, false, true, 1).to_bits(),
996 0x7fc0_0001,
997 "__builtin_nanf(\"0x1\")"
998 );
999 assert_eq!(
1000 Float::nan_with(Format::Single, false, false, 0).to_bits(),
1001 0x7fa0_0000,
1002 "__builtin_nansf(\"\")"
1003 );
1004 assert_eq!(
1007 Float::nan_with(Format::X87Extended, false, true, 1).to_bits(),
1008 0x7fff_c000_0000_0000_0001,
1009 "__builtin_nanl(\"0x1\") on x86"
1010 );
1011 assert_eq!(
1012 Float::nan_with(Format::X87Extended, false, false, 0).to_bits(),
1013 0x7fff_a000_0000_0000_0000,
1014 "__builtin_nansl(\"\") on x86"
1015 );
1016 }
1017
1018 #[test]
1020 fn a_payload_comes_back_out_of_the_encoding_it_went_into() {
1021 for format in [Format::Half, Format::Single, Format::Double, Format::X87Extended] {
1022 for (quiet, payload) in [(true, 0), (true, 1), (false, 3), (true, 5)] {
1023 let nan = Float::nan_with(format, false, quiet, payload);
1024 assert!(nan.is_nan(), "{format:?}");
1025 assert_eq!(Float::from_bits(format, nan.to_bits()), nan, "{format:?} {payload}");
1026 }
1027 let nan = Float::nan_with(format, true, true, 7);
1029 assert!(nan.is_negative() && nan.negated().negated() == nan, "{format:?}");
1030 }
1031 }
1032}