1use std::cmp::Ordering;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub enum Integral {
53 TowardZero,
55 Upward,
57 Downward,
59 NearestTiesAway,
62}
63
64use crate::float::{Category, Float, Format, Status, round};
65
66const GUARD: u32 = 3;
72
73impl Float {
74 #[must_use]
79 pub const fn nan(format: Format) -> Float {
80 Float {
81 format,
82 category: Category::Nan,
83 sign: false,
84 exponent: 0,
85 significand: Float::quiet_bit(format) | Float::leading_bit(format),
86 }
87 }
88
89 #[must_use]
91 pub const fn is_nan(self) -> bool {
92 matches!(self.category, Category::Nan)
93 }
94
95 #[must_use]
97 pub const fn negated(self) -> Float {
98 Float { sign: !self.sign, ..self }
99 }
100
101 #[must_use]
103 pub const fn abs(self) -> Float {
104 Float { sign: false, ..self }
105 }
106
107 #[must_use]
110 pub const fn with_sign(self, sign: bool) -> Float {
111 Float { sign, ..self }
112 }
113
114 #[must_use]
126 pub fn sum(self, other: Float) -> (Float, Status) {
127 self.total(other, false)
128 }
129
130 #[must_use]
140 pub fn difference(self, other: Float) -> (Float, Status) {
141 self.total(other, true)
142 }
143
144 #[must_use]
153 pub fn product(self, other: Float) -> (Float, Status) {
154 let format = self.agreed_format(other);
155 let sign = self.sign != other.sign;
156 if let Some(nan) = Float::propagated_nan(self, other) {
157 return nan;
158 }
159 match (self.category, other.category) {
160 (Category::Infinite, Category::Zero) | (Category::Zero, Category::Infinite) => {
161 (Float::nan(format), Status::INVALID)
162 }
163 (Category::Infinite, _) | (_, Category::Infinite) => {
164 (Float::infinity(format, sign), Status::NONE)
165 }
166 (Category::Zero, _) | (_, Category::Zero) => (Float::zero(format, sign), Status::NONE),
167 _ => {
168 let (left, left_exponent) = self.parts();
169 let (right, right_exponent) = other.parts();
170 let (high, low) = wide_multiply(left, right);
171 let exponent = left_exponent + right_exponent;
172 if high == 0 {
173 return round(low, exponent, false, sign, format);
174 }
175 let drop = 128 - high.leading_zeros();
179 let sticky = low & ((1u128 << drop) - 1) != 0;
180 let significand = (high << (128 - drop)) | (low >> drop);
181 round(significand, exponent + drop as i32, sticky, sign, format)
182 }
183 }
184 }
185
186 #[must_use]
197 pub fn quotient(self, other: Float) -> (Float, Status) {
198 let format = self.agreed_format(other);
199 let sign = self.sign != other.sign;
200 if let Some(nan) = Float::propagated_nan(self, other) {
201 return nan;
202 }
203 match (self.category, other.category) {
204 (Category::Infinite, Category::Infinite) | (Category::Zero, Category::Zero) => {
205 (Float::nan(format), Status::INVALID)
206 }
207 (Category::Infinite, _) => (Float::infinity(format, sign), Status::NONE),
208 (_, Category::Infinite) | (Category::Zero, _) => {
209 (Float::zero(format, sign), Status::NONE)
210 }
211 (_, Category::Zero) => (Float::infinity(format, sign), Status::DIVIDE_BY_ZERO),
212 _ => {
213 let (left, left_exponent) = self.parts();
218 let (right, right_exponent) = other.parts();
219 let (left_shift, right_shift) = (left.leading_zeros(), right.leading_zeros());
220 let extra = format.precision() + 2;
221 let numerator = left << left_shift;
222 let (quotient, remainder) = long_divide(numerator, right << right_shift, extra);
223 let exponent = (left_exponent - left_shift as i32)
224 - (right_exponent - right_shift as i32)
225 - extra as i32;
226 round(quotient, exponent, remainder != 0, sign, format)
227 }
228 }
229 }
230
231 #[must_use]
241 pub fn compare(self, other: Float) -> Option<Ordering> {
242 self.agreed_format(other);
243 if self.is_nan() || other.is_nan() {
244 return None;
245 }
246 if self.is_zero() && other.is_zero() {
247 return Some(Ordering::Equal);
248 }
249 if self.sign != other.sign {
250 return Some(if self.sign { Ordering::Less } else { Ordering::Greater });
251 }
252 let magnitudes = self.compare_magnitude(other);
253 Some(if self.sign { magnitudes.reverse() } else { magnitudes })
254 }
255
256 #[must_use]
269 pub fn to_integral(self, toward: Integral) -> Float {
270 let Category::Finite = self.category else { return self };
271 let (significand, exponent) = self.parts();
272 if exponent >= 0 {
274 return self;
275 }
276 let dropped = exponent.unsigned_abs();
277 let (kept, fraction, half) = if dropped >= 128 {
280 (0, true, false)
281 } else {
282 let rest = significand & ((1 << dropped) - 1);
283 (significand >> dropped, rest != 0, rest >= 1 << (dropped - 1))
284 };
285 if !fraction {
286 return self;
287 }
288 let away = match toward {
289 Integral::TowardZero => false,
290 Integral::Upward => !self.sign,
291 Integral::Downward => self.sign,
292 Integral::NearestTiesAway => half,
293 };
294 let magnitude = kept + u128::from(away);
295 if magnitude == 0 {
296 return Float::zero(self.format, self.sign);
297 }
298 let (value, _) = Float::from_unsigned(magnitude, self.format);
300 value.with_sign(self.sign)
301 }
302
303 #[must_use]
318 pub fn larger(self, other: Float) -> Float {
319 self.pick(other, Ordering::Greater)
320 }
321
322 #[must_use]
328 pub fn smaller(self, other: Float) -> Float {
329 self.pick(other, Ordering::Less)
330 }
331
332 fn pick(self, other: Float, want: Ordering) -> Float {
334 let format = self.agreed_format(other);
335 if self.is_nan() {
336 return if other.is_nan() { Float::nan(format) } else { other };
337 }
338 if other.is_nan() {
339 return self;
340 }
341 if self.is_zero() && other.is_zero() {
344 let wanted = matches!(want, Ordering::Less);
345 return if self.sign == wanted { self } else { other };
346 }
347 match self.compare(other) {
348 Some(order) if order == want => self,
349 _ => other,
350 }
351 }
352
353 #[must_use]
359 pub fn to_format(self, format: Format) -> (Float, Status) {
360 match self.category {
361 Category::Nan => (Float { sign: self.sign, ..Float::nan(format) }, Status::NONE),
362 Category::Infinite => (Float::infinity(format, self.sign), Status::NONE),
363 Category::Zero => (Float::zero(format, self.sign), Status::NONE),
364 Category::Finite => {
365 let (significand, exponent) = self.parts();
366 round(significand, exponent, false, self.sign, format)
367 }
368 }
369 }
370
371 #[must_use]
373 pub fn from_signed(value: i128, format: Format) -> (Float, Status) {
374 if value == 0 {
375 return (Float::zero(format, false), Status::NONE);
376 }
377 round(value.unsigned_abs(), 0, false, value < 0, format)
378 }
379
380 #[must_use]
382 pub fn from_unsigned(value: u128, format: Format) -> (Float, Status) {
383 if value == 0 {
384 return (Float::zero(format, false), Status::NONE);
385 }
386 round(value, 0, false, false, format)
387 }
388
389 #[must_use]
405 pub fn to_integer(self, width: u32, signed: bool) -> (i128, Status) {
406 assert!(width > 0 && width <= 128, "an integer type of {width} bits");
407 let limit = self.limit(width, signed);
408 match self.category {
409 Category::Nan => (0, Status::INVALID),
410 Category::Infinite => (self.signed_value(limit), Status::INVALID),
411 Category::Zero => (0, Status::NONE),
412 Category::Finite => {
413 let (significand, exponent) = self.parts();
414 let (magnitude, inexact) = if exponent >= 0 {
415 if exponent > significand.leading_zeros() as i32 {
416 return (self.signed_value(limit), Status::INVALID);
417 }
418 (significand << exponent, false)
419 } else if -exponent >= 128 {
420 (0, true)
421 } else {
422 let dropped = -exponent as u32;
423 (significand >> dropped, significand & ((1u128 << dropped) - 1) != 0)
424 };
425 if magnitude > limit {
426 return (self.signed_value(limit), Status::INVALID);
427 }
428 let status = if inexact { Status::INEXACT } else { Status::NONE };
429 (self.signed_value(magnitude), status)
430 }
431 }
432 }
433
434 fn limit(self, width: u32, signed: bool) -> u128 {
436 match (signed, self.sign) {
437 (true, true) => 1u128 << (width - 1),
438 (true, false) => (1u128 << (width - 1)) - 1,
439 (false, true) => 0,
442 (false, false) => u128::MAX >> (128 - width),
443 }
444 }
445
446 fn signed_value(self, magnitude: u128) -> i128 {
448 if self.sign { (magnitude as i128).wrapping_neg() } else { magnitude as i128 }
449 }
450
451 fn parts(self) -> (u128, i32) {
454 (self.significand, self.exponent - self.format.precision() as i32 + 1)
455 }
456
457 fn agreed_format(self, other: Float) -> Format {
465 assert_eq!(self.format, other.format, "an operation on two floating formats at once");
466 self.format
467 }
468
469 fn propagated_nan(left: Float, right: Float) -> Option<(Float, Status)> {
471 (left.is_nan() || right.is_nan()).then(|| (Float::nan(left.format), Status::NONE))
472 }
473
474 fn compare_magnitude(self, other: Float) -> Ordering {
480 match (self.category, other.category) {
481 (Category::Zero, Category::Zero) | (Category::Infinite, Category::Infinite) => {
482 Ordering::Equal
483 }
484 (Category::Zero, _) | (_, Category::Infinite) => Ordering::Less,
485 (Category::Infinite, _) | (_, Category::Zero) => Ordering::Greater,
486 _ => (self.exponent, self.significand).cmp(&(other.exponent, other.significand)),
487 }
488 }
489
490 fn total(self, other: Float, subtract: bool) -> (Float, Status) {
493 let format = self.agreed_format(other);
494 let other = if subtract { other.negated() } else { other };
495 if let Some(nan) = Float::propagated_nan(self, other) {
496 return nan;
497 }
498 match (self.category, other.category) {
499 (Category::Infinite, Category::Infinite) => {
500 if self.sign == other.sign {
501 (self, Status::NONE)
502 } else {
503 (Float::nan(format), Status::INVALID)
504 }
505 }
506 (Category::Infinite, _) => (self, Status::NONE),
507 (_, Category::Infinite) => (other, Status::NONE),
508 (Category::Zero, Category::Zero) => {
511 (Float::zero(format, self.sign && other.sign), Status::NONE)
512 }
513 (Category::Zero, _) => (other, Status::NONE),
514 (_, Category::Zero) => (self, Status::NONE),
515 _ => {
516 let (big, small) = if self.compare_magnitude(other) == Ordering::Less {
517 (other, self)
518 } else {
519 (self, other)
520 };
521 let (left, exponent) = big.parts();
522 let (right, small_exponent) = small.parts();
523 let distance = (exponent - small_exponent) as u32;
524 let left = left << GUARD;
525 let (mut right, sticky) = if distance <= GUARD {
526 (right << (GUARD - distance), false)
527 } else if distance - GUARD >= 128 {
528 (0, true)
529 } else {
530 let dropped = distance - GUARD;
531 (right >> dropped, right & ((1u128 << dropped) - 1) != 0)
532 };
533 let exponent = exponent - GUARD as i32;
534 if big.sign == small.sign {
535 return round(left + right, exponent, sticky, big.sign, format);
536 }
537 right += u128::from(sticky);
544 if left == right {
545 return (Float::zero(format, false), Status::NONE);
546 }
547 round(left - right, exponent, sticky, big.sign, format)
548 }
549 }
550 }
551}
552
553fn wide_multiply(left: u128, right: u128) -> (u128, u128) {
559 const LOW: u128 = u64::MAX as u128;
560 let (left_low, left_high) = (left & LOW, left >> 64);
561 let (right_low, right_high) = (right & LOW, right >> 64);
562 let low = left_low * right_low;
563 let first = left_low * right_high;
564 let second = left_high * right_low;
565 let middle = (low >> 64) + (first & LOW) + (second & LOW);
566 let high = left_high * right_high + (first >> 64) + (second >> 64) + (middle >> 64);
567 (high, (middle << 64) | (low & LOW))
568}
569
570fn long_divide(numerator: u128, divisor: u128, extra: u32) -> (u128, u128) {
576 let mut remainder = 0u128;
577 let mut quotient = 0u128;
578 for step in 0..128 + extra {
579 let bit = if step < 128 { (numerator >> (127 - step)) & 1 } else { 0 };
580 let carry = remainder >> 127 == 1;
583 remainder = (remainder << 1) | bit;
584 quotient <<= 1;
585 if carry || remainder >= divisor {
586 remainder = remainder.wrapping_sub(divisor);
587 quotient |= 1;
588 }
589 }
590 (quotient, remainder)
591}
592
593#[cfg(test)]
594mod tests {
595 use super::*;
596
597 fn double(value: f64) -> Float {
599 Float::from_bits(Format::Double, u128::from(value.to_bits()))
600 }
601
602 fn host(value: Float) -> f64 {
604 f64::from_bits(value.to_bits() as u64)
605 }
606
607 fn single(value: f32) -> Float {
608 Float::from_bits(Format::Single, u128::from(value.to_bits()))
609 }
610
611 fn host_single(value: Float) -> f32 {
612 f32::from_bits(value.to_bits() as u32)
613 }
614
615 fn next(state: &mut u64) -> u64 {
617 *state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
618 *state
619 }
620
621 fn agrees(left: f64, right: f64) {
623 let (a, b) = (double(left), double(right));
624 for (name, mine, theirs) in [
625 ("+", a.sum(b).0, left + right),
626 ("-", a.difference(b).0, left - right),
627 ("*", a.product(b).0, left * right),
628 ("/", a.quotient(b).0, left / right),
629 ] {
630 if theirs.is_nan() {
631 assert!(mine.is_nan(), "{left:e} {name} {right:e} gave {}", host(mine));
632 } else {
633 assert_eq!(
634 host(mine).to_bits(),
635 theirs.to_bits(),
636 "{left:e} {name} {right:e} gave {} not {theirs:e}",
637 host(mine)
638 );
639 }
640 }
641 }
642
643 fn agrees_single(left: f32, right: f32) {
645 let (a, b) = (single(left), single(right));
646 for (name, mine, theirs) in [
647 ("+", a.sum(b).0, left + right),
648 ("-", a.difference(b).0, left - right),
649 ("*", a.product(b).0, left * right),
650 ("/", a.quotient(b).0, left / right),
651 ] {
652 if theirs.is_nan() {
653 assert!(mine.is_nan(), "{left:e} {name} {right:e}");
654 } else {
655 assert_eq!(
656 host_single(mine).to_bits(),
657 theirs.to_bits(),
658 "{left:e} {name} {right:e} gave {} not {theirs:e}",
659 host_single(mine)
660 );
661 }
662 }
663 }
664
665 #[test]
666 fn the_ordinary_sums_are_the_ones_the_host_computes() {
667 for (left, right) in [
668 (1.0, 1.0),
669 (1.0, 2.0),
670 (0.1, 0.2),
671 (1.0, -1.0),
672 (1e308, 1e308),
673 (1.0, 1e-308),
674 (3.0, 7.0),
675 (1.0, 3.0),
676 (2.5, 0.5),
677 (1e-320, 1e-320),
678 (f64::MAX, f64::MIN),
679 ] {
680 agrees(left, right);
681 agrees(right, left);
682 agrees(-left, right);
683 agrees(left, -right);
684 }
685 }
686
687 #[test]
688 fn a_sweep_of_random_doubles_agrees_with_the_host_in_every_bit() {
689 let mut state = 0x2545_f491_4f6c_dd1du64;
692 for _ in 0..20_000 {
693 agrees(f64::from_bits(next(&mut state)), f64::from_bits(next(&mut state)));
694 }
695 }
696
697 #[test]
698 fn a_sweep_of_random_floats_agrees_with_the_host_in_every_bit() {
699 let mut state = 0x1234_5678_9abc_def0u64;
700 for _ in 0..20_000 {
701 let bits = next(&mut state);
702 agrees_single(f32::from_bits(bits as u32), f32::from_bits((bits >> 32) as u32));
703 }
704 }
705
706 #[test]
707 fn a_sweep_of_numbers_close_together_agrees_too() {
708 let mut state = 0x9e37_79b9_7f4a_7c15u64;
711 for _ in 0..20_000 {
712 let left = (next(&mut state) >> 11) as f64;
713 let scale = f64::from(next(&mut state) as u32 % 8) - 4.0;
714 let right = (next(&mut state) >> 11) as f64 * scale.exp2();
715 agrees(left, right);
716 agrees(left, left);
717 agrees(left, -left);
718 }
719 }
720
721 #[test]
722 fn the_operations_with_no_answer_say_so() {
723 let (infinity, zero) = (Float::infinity(Format::Double, false), double(0.0));
724 let (one, nan) = (double(1.0), Float::nan(Format::Double));
725
726 let (value, status) = infinity.difference(infinity);
727 assert!(value.is_nan() && status.has(Status::INVALID));
728 let (value, status) = infinity.product(zero);
729 assert!(value.is_nan() && status.has(Status::INVALID));
730 let (value, status) = zero.quotient(zero);
731 assert!(value.is_nan() && status.has(Status::INVALID));
732 let (value, status) = infinity.quotient(infinity);
733 assert!(value.is_nan() && status.has(Status::INVALID));
734
735 let (value, status) = one.quotient(zero);
737 assert!(value.is_infinite() && !value.is_negative());
738 assert!(status.has(Status::DIVIDE_BY_ZERO) && !status.has(Status::INVALID));
739 assert!(one.negated().quotient(zero).0.is_negative());
740 assert!(one.quotient(zero.negated()).0.is_negative());
741
742 for (value, status) in
744 [nan.sum(one), one.sum(nan), nan.product(one), nan.quotient(one), one.difference(nan)]
745 {
746 assert!(value.is_nan() && status.is_none());
747 }
748 assert!(infinity.sum(infinity).0.is_infinite());
749 assert!(infinity.sum(one).0.is_infinite());
750 }
751
752 #[test]
753 fn the_sign_of_a_zero_is_the_one_the_host_gives() {
754 let (positive, negative) = (double(0.0), double(-0.0));
755 for (mine, theirs) in [
756 (positive.sum(positive), 0.0 + 0.0),
757 (positive.sum(negative), 0.0 + -0.0),
758 (negative.sum(positive), -0.0 + 0.0),
759 (negative.sum(negative), -0.0 + -0.0),
760 (positive.difference(positive), 0.0 - 0.0),
761 (negative.difference(positive), -0.0 - 0.0),
762 (double(1.0).difference(double(1.0)), 1.0 - 1.0),
763 (double(-1.0).sum(double(1.0)), -1.0 + 1.0),
764 (positive.product(double(3.0)), 0.0 * 3.0),
765 (negative.product(double(3.0)), -0.0 * 3.0),
766 (positive.quotient(double(-3.0)), 0.0 / -3.0),
767 ] {
768 assert_eq!(host(mine.0).to_bits(), f64::to_bits(theirs), "{theirs}");
769 }
770 }
771
772 #[test]
773 fn an_operation_says_what_it_had_to_do_to_the_answer() {
774 let (one, three) = (double(1.0), double(3.0));
775 assert!(one.sum(one).1.is_none());
776 assert!(one.product(three).1.is_none());
777 assert!(one.quotient(double(2.0)).1.is_none());
778 assert!(one.quotient(three).1.has(Status::INEXACT));
779
780 let (value, status) = double(f64::MAX).product(double(2.0));
781 assert!(value.is_infinite() && status.has(Status::OVERFLOW) && status.has(Status::INEXACT));
782 let (value, status) = double(f64::MIN_POSITIVE).quotient(double(1e300));
783 assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
784 let four = Float::from_bits(Format::Double, 4);
786 assert!(four.quotient(double(2.0)).1.is_none());
787 assert!(four.quotient(double(4.0)).1.is_none());
788 let status = Float::from_bits(Format::Double, 3).quotient(double(2.0)).1;
790 assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
791 }
792
793 #[test]
794 fn a_comparison_orders_the_numbers_and_leaves_the_nans_out() {
795 let (one, two) = (double(1.0), double(2.0));
796 assert_eq!(one.compare(two), Some(Ordering::Less));
797 assert_eq!(two.compare(one), Some(Ordering::Greater));
798 assert_eq!(one.compare(one), Some(Ordering::Equal));
799 assert_eq!(one.negated().compare(two.negated()), Some(Ordering::Greater));
800 assert_eq!(one.negated().compare(one), Some(Ordering::Less));
801 assert_eq!(double(0.0).compare(double(-0.0)), Some(Ordering::Equal));
803 assert_eq!(double(-0.0).compare(double(0.0)), Some(Ordering::Equal));
804 assert_eq!(double(-0.0).compare(one), Some(Ordering::Less));
805 let infinity = Float::infinity(Format::Double, false);
807 assert_eq!(infinity.compare(double(f64::MAX)), Some(Ordering::Greater));
808 assert_eq!(infinity.negated().compare(double(f64::MIN)), Some(Ordering::Less));
809 assert_eq!(infinity.compare(infinity), Some(Ordering::Equal));
810 let nan = Float::nan(Format::Double);
811 assert_eq!(nan.compare(one), None);
812 assert_eq!(one.compare(nan), None);
813 assert_eq!(nan.compare(nan), None);
814 }
815
816 #[test]
817 fn a_comparison_of_random_numbers_is_the_host_order() {
818 let mut state = 0xdead_beef_cafe_f00du64;
819 for _ in 0..20_000 {
820 let left = f64::from_bits(next(&mut state));
821 let right = f64::from_bits(next(&mut state));
822 assert_eq!(
823 double(left).compare(double(right)),
824 left.partial_cmp(&right),
825 "{left:e} against {right:e}"
826 );
827 }
828 }
829
830 #[test]
831 fn a_conversion_between_formats_rounds_the_way_the_host_does() {
832 let mut state = 0x0123_4567_89ab_cdefu64;
833 for _ in 0..20_000 {
834 let value = f64::from_bits(next(&mut state));
835 let narrowed = double(value).to_format(Format::Single);
836 let theirs = value as f32;
837 if theirs.is_nan() {
838 assert!(narrowed.0.is_nan(), "{value:e}");
839 continue;
840 }
841 assert_eq!(host_single(narrowed.0).to_bits(), theirs.to_bits(), "{value:e}");
842 let widened = narrowed.0.to_format(Format::Double);
844 assert_eq!(host(widened.0).to_bits(), f64::from(theirs).to_bits(), "{value:e}");
845 assert!(widened.1.is_none(), "{value:e}");
846 }
847 }
848
849 #[test]
850 fn a_narrowing_conversion_says_what_it_did() {
851 let (value, status) = double(0.1).to_format(Format::Single);
852 assert_eq!(host_single(value).to_bits(), (0.1f32).to_bits());
853 assert!(status.has(Status::INEXACT));
854 assert!(double(0.5).to_format(Format::Single).1.is_none());
855 let (value, status) = double(1e300).to_format(Format::Single);
856 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
857 let (value, status) = double(1e-300).to_format(Format::Single);
858 assert!(value.is_zero() && status.has(Status::UNDERFLOW));
859 let (up, status) = double(0.1).to_format(Format::X87Extended);
862 assert!(status.is_none());
863 assert_eq!(up.to_bits(), 0x3ffb_cccc_cccc_cccc_d000);
864 assert_eq!(host(up.to_format(Format::Double).0).to_bits(), (0.1f64).to_bits());
865 let tenth = Float::parse("0.1", Format::X87Extended).expect("a tenth").0;
868 assert_eq!(tenth.to_bits(), 0x3ffb_cccc_cccc_cccc_cccd);
869 assert_ne!(up.to_bits(), tenth.to_bits());
870 }
871
872 #[test]
873 fn an_integer_becomes_the_nearest_number_to_it() {
874 let mut state = 0xfeed_face_dead_c0dcu64;
875 for _ in 0..20_000 {
876 let value = next(&mut state) as i64;
877 let mine = Float::from_signed(i128::from(value), Format::Double).0;
878 assert_eq!(host(mine).to_bits(), (value as f64).to_bits(), "{value}");
879 let value = next(&mut state);
880 let mine = Float::from_unsigned(u128::from(value), Format::Single).0;
881 assert_eq!(host_single(mine).to_bits(), (value as f32).to_bits(), "{value}");
882 }
883 assert_eq!(host(Float::from_signed(0, Format::Double).0).to_bits(), (0f64).to_bits());
885 assert!(Float::from_signed(1 << 52, Format::Double).1.is_none());
886 assert!(Float::from_signed((1 << 53) + 1, Format::Double).1.has(Status::INEXACT));
887 let (value, status) = Float::from_signed(i128::MIN, Format::Double);
888 assert!(value.is_negative() && status.is_none());
889 assert_eq!(host(value), -(2f64).powi(127));
890 let (value, status) = Float::from_unsigned(u128::MAX, Format::Double);
891 assert!(status.has(Status::INEXACT));
892 assert_eq!(host(value), (2f64).powi(128));
893 }
894
895 #[test]
896 fn a_number_becomes_an_integer_by_dropping_its_fraction() {
897 for (value, expected) in [
898 (1.5, 1),
899 (-1.5, -1),
900 (0.9, 0),
901 (-0.9, 0),
902 (2.0, 2),
903 (-2.0, -2),
904 (1e18, 1_000_000_000_000_000_000),
905 ] {
906 assert_eq!(double(value).to_integer(64, true).0, expected, "{value}");
907 }
908 assert!(double(2.0).to_integer(64, true).1.is_none());
909 assert!(double(1.5).to_integer(64, true).1.has(Status::INEXACT));
910 assert_eq!(double(-0.5).to_integer(32, false), (0, Status::INEXACT));
912 let (value, status) = double(-1.0).to_integer(32, false);
913 assert!(value == 0 && status.has(Status::INVALID));
914 }
915
916 #[test]
917 fn a_number_that_will_not_fit_gives_the_end_of_the_range() {
918 let (value, status) = double(1e30).to_integer(32, true);
919 assert!(value == i128::from(i32::MAX) && status.has(Status::INVALID));
920 let (value, status) = double(-1e30).to_integer(32, true);
921 assert!(value == i128::from(i32::MIN) && status.has(Status::INVALID));
922 let (value, status) = double(1e30).to_integer(32, false);
923 assert!(value == i128::from(u32::MAX) && status.has(Status::INVALID));
924 let (value, status) = Float::infinity(Format::Double, false).to_integer(64, true);
925 assert!(value == i128::from(i64::MAX) && status.has(Status::INVALID));
926 let (value, status) = Float::nan(Format::Double).to_integer(64, true);
927 assert!(value == 0 && status.has(Status::INVALID));
928 let (value, status) = double(f64::MAX).to_integer(128, false);
930 assert!(value == -1 && status.has(Status::INVALID));
931 let smallest = double(-(2f64).powi(127));
933 assert_eq!(smallest.to_integer(128, true), (i128::MIN, Status::NONE));
934 }
935
936 #[test]
937 fn a_conversion_to_an_integer_is_the_one_the_host_does() {
938 let mut state = 0xabad_1dea_0000_0001u64;
941 for _ in 0..20_000 {
942 let value = f64::from_bits(next(&mut state));
943 assert_eq!(double(value).to_integer(64, true).0, i128::from(value as i64), "{value:e}");
944 assert_eq!(
945 double(value).to_integer(32, false).0,
946 i128::from(value as u32),
947 "{value:e}"
948 );
949 }
950 }
951
952 #[test]
953 fn the_wide_formats_compute_what_they_are_supposed_to() {
954 let quad = |text: &str| Float::parse(text, Format::Quad).expect("a number").0;
955 let (third, status) = quad("1").quotient(quad("3"));
959 assert_eq!(third.to_bits(), 0x3ffd_5555_5555_5555_5555_5555_5555_5555);
960 assert!(status.has(Status::INEXACT));
961 let (whole, status) = third.sum(third).0.sum(third);
963 assert_eq!(whole.to_bits(), quad("1").to_bits());
964 assert!(status.has(Status::INEXACT));
965
966 let x87 = |text: &str| Float::parse(text, Format::X87Extended).expect("a number").0;
969 let (sum, status) = x87("9007199254740993").sum(x87("1"));
970 assert!(status.is_none());
971 assert_eq!(sum.to_bits(), x87("9007199254740994").to_bits());
972
973 let half = |text: &str| Float::parse(text, Format::Half).expect("a number").0;
976 let (value, status) = half("2048").sum(half("1"));
977 assert!(status.has(Status::INEXACT));
978 assert_eq!(value.to_bits(), half("2048").to_bits());
979 }
980
981 #[test]
982 fn a_nan_survives_a_trip_through_its_encoding() {
983 for format in [
984 Format::Half,
985 Format::BFloat16,
986 Format::Single,
987 Format::Double,
988 Format::X87Extended,
989 Format::Quad,
990 ] {
991 let nan = Float::nan(format);
992 assert!(nan.is_nan() && !nan.is_finite() && !nan.is_infinite(), "{format:?}");
993 assert_eq!(Float::from_bits(format, nan.to_bits()), nan, "{format:?}");
994 assert_eq!(nan.negated().to_hex(), "-nan", "{format:?}");
995 let infinity = Float::infinity(format, false);
998 assert!(Float::from_bits(format, infinity.to_bits()).is_infinite(), "{format:?}");
999 }
1000 assert_eq!(Float::nan(Format::Double).to_bits(), u128::from(f64::NAN.to_bits()));
1002 assert!(Float::from_bits(Format::Double, u128::from(f64::NAN.to_bits())).is_nan());
1003 }
1004
1005 #[test]
1008 fn a_number_taken_to_an_integer_lands_where_the_host_puts_it() {
1009 let mut state = 0x5eed_1234_u64;
1010 for _ in 0..20000 {
1011 let bits = next(&mut state);
1012 let value = f64::from_bits(bits);
1013 if !value.is_finite() {
1014 continue;
1015 }
1016 for (name, toward, theirs) in [
1017 ("trunc", Integral::TowardZero, value.trunc()),
1018 ("ceil", Integral::Upward, value.ceil()),
1019 ("floor", Integral::Downward, value.floor()),
1020 ("round", Integral::NearestTiesAway, value.round()),
1021 ] {
1022 let mine = double(value).to_integral(toward);
1023 assert_eq!(
1024 host(mine).to_bits(),
1025 theirs.to_bits(),
1026 "{name} of {value:e} gave {}",
1027 host(mine)
1028 );
1029 }
1030 }
1031 }
1032
1033 #[test]
1036 fn the_sign_of_a_number_rounded_away_to_nothing_is_still_there() {
1037 let cases: &[(f64, Integral, f64)] = &[
1038 (-0.5, Integral::Upward, -0.0),
1039 (-0.2, Integral::Upward, -0.0),
1040 (-0.5, Integral::TowardZero, -0.0),
1041 (0.5, Integral::Downward, 0.0),
1042 (0.4, Integral::NearestTiesAway, 0.0),
1043 (-0.4, Integral::NearestTiesAway, -0.0),
1044 (-0.0, Integral::Upward, -0.0),
1045 (0.5, Integral::NearestTiesAway, 1.0),
1046 (-0.5, Integral::NearestTiesAway, -1.0),
1047 (2.5, Integral::NearestTiesAway, 3.0),
1048 (-2.5, Integral::NearestTiesAway, -3.0),
1049 (1e300, Integral::Upward, 1e300),
1050 (f64::MIN_POSITIVE / 4.0, Integral::Downward, 0.0),
1051 (-f64::MIN_POSITIVE / 4.0, Integral::Upward, -0.0),
1052 ];
1053 for &(value, toward, want) in cases {
1054 let mine = double(value).to_integral(toward);
1055 assert_eq!(host(mine).to_bits(), want.to_bits(), "{toward:?} of {value:e}");
1056 }
1057 assert!(double(f64::NAN).to_integral(Integral::Upward).is_nan());
1059 let infinity = double(f64::NEG_INFINITY).to_integral(Integral::Upward);
1060 assert!(infinity.is_infinite() && infinity.is_negative());
1061 }
1062
1063 #[test]
1066 fn a_half_is_taken_to_an_integer_in_every_format() {
1067 for format in
1068 [Format::Half, Format::Single, Format::Double, Format::X87Extended, Format::Quad]
1069 {
1070 let (half, _) = Float::parse("2.5", format).expect("a number");
1071 let (three, _) = Float::parse("3", format).expect("a number");
1072 let (two, _) = Float::parse("2", format).expect("a number");
1073 assert_eq!(half.to_integral(Integral::Upward), three, "{format:?}");
1074 assert_eq!(half.to_integral(Integral::TowardZero), two, "{format:?}");
1075 assert_eq!(half.to_integral(Integral::NearestTiesAway), three, "{format:?}");
1076 assert_eq!(
1077 half.negated().to_integral(Integral::Downward),
1078 three.negated(),
1079 "{format:?}"
1080 );
1081 }
1082 }
1083
1084 #[test]
1086 fn the_larger_of_two_is_the_one_the_library_would_return() {
1087 let (one, two) = (double(1.0), double(2.0));
1088 assert_eq!(host(one.larger(two)), 2.0);
1089 assert_eq!(host(one.smaller(two)), 1.0);
1090 assert_eq!(host(two.larger(one)), 2.0);
1091 assert_eq!(host(two.smaller(one)), 1.0);
1092 let nan = double(f64::NAN);
1095 assert_eq!(host(nan.larger(two)), 2.0);
1096 assert_eq!(host(two.larger(nan)), 2.0);
1097 assert_eq!(host(nan.smaller(two)), 2.0);
1098 assert!(nan.larger(nan).is_nan());
1099 let (zero, minus) = (double(0.0), double(-0.0));
1101 let zeros: &[(&str, Float, f64)] = &[
1102 ("fmax(0, -0)", zero.larger(minus), 0.0),
1103 ("fmax(-0, 0)", minus.larger(zero), 0.0),
1104 ("fmin(0, -0)", zero.smaller(minus), -0.0),
1105 ("fmin(-0, 0)", minus.smaller(zero), -0.0),
1106 ];
1107 for &(name, mine, want) in zeros {
1108 assert_eq!(host(mine).to_bits(), want.to_bits(), "{name}");
1109 }
1110 let infinity = double(f64::INFINITY);
1112 assert!(infinity.larger(two).is_infinite());
1113 assert_eq!(host(infinity.smaller(two)), 2.0);
1114 }
1115
1116 #[test]
1117 fn the_helpers_underneath_do_what_they_say() {
1118 assert_eq!(wide_multiply(0, 12345), (0, 0));
1119 assert_eq!(wide_multiply(3, 5), (0, 15));
1120 assert_eq!(wide_multiply(1, u128::MAX), (0, u128::MAX));
1121 assert_eq!(wide_multiply(u128::MAX, u128::MAX), (u128::MAX - 1, 1));
1122 assert_eq!(wide_multiply(1 << 127, 1 << 127), (1 << 126, 0));
1123 assert_eq!(long_divide(1 << 127, 1 << 127, 4), (16, 0));
1125 assert_eq!(long_divide(3 << 126, 1 << 127, 4), (24, 0));
1126 assert_eq!(long_divide(1 << 127, 3 << 126, 4), (10, 1 << 127));
1127 }
1128}