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 if format.decimal().is_some() {
81 let category = Category::Nan;
82 return Float { format, category, sign: false, exponent: 0, significand: 0 };
83 }
84 Float {
85 format,
86 category: Category::Nan,
87 sign: false,
88 exponent: 0,
89 significand: Float::quiet_bit(format) | Float::leading_bit(format),
90 }
91 }
92
93 #[must_use]
95 pub const fn is_nan(self) -> bool {
96 matches!(self.category, Category::Nan)
97 }
98
99 #[must_use]
101 pub const fn negated(self) -> Float {
102 Float { sign: !self.sign, ..self }
103 }
104
105 #[must_use]
107 pub const fn abs(self) -> Float {
108 Float { sign: false, ..self }
109 }
110
111 #[must_use]
114 pub const fn with_sign(self, sign: bool) -> Float {
115 Float { sign, ..self }
116 }
117
118 #[must_use]
130 pub fn sum(self, other: Float) -> (Float, Status) {
131 self.total(other, false)
132 }
133
134 #[must_use]
144 pub fn difference(self, other: Float) -> (Float, Status) {
145 self.total(other, true)
146 }
147
148 #[must_use]
157 pub fn product(self, other: Float) -> (Float, Status) {
158 let format = self.agreed_format(other);
159 let sign = self.sign != other.sign;
160 if let Some(nan) = Float::propagated_nan(self, other) {
161 return nan;
162 }
163 match (self.category, other.category) {
164 (Category::Infinite, Category::Zero) | (Category::Zero, Category::Infinite) => {
165 (Float::nan(format), Status::INVALID)
166 }
167 (Category::Infinite, _) | (_, Category::Infinite) => {
168 (Float::infinity(format, sign), Status::NONE)
169 }
170 (Category::Zero, _) | (_, Category::Zero) => (Float::zero(format, sign), Status::NONE),
171 _ => {
172 let (left, left_exponent) = self.parts();
173 let (right, right_exponent) = other.parts();
174 let (high, low) = wide_multiply(left, right);
175 let exponent = left_exponent + right_exponent;
176 if high == 0 {
177 return round(low, exponent, false, sign, format);
178 }
179 let drop = 128 - high.leading_zeros();
183 let sticky = low & ((1u128 << drop) - 1) != 0;
184 let significand = (high << (128 - drop)) | (low >> drop);
185 round(significand, exponent + drop as i32, sticky, sign, format)
186 }
187 }
188 }
189
190 #[must_use]
201 pub fn quotient(self, other: Float) -> (Float, Status) {
202 let format = self.agreed_format(other);
203 let sign = self.sign != other.sign;
204 if let Some(nan) = Float::propagated_nan(self, other) {
205 return nan;
206 }
207 match (self.category, other.category) {
208 (Category::Infinite, Category::Infinite) | (Category::Zero, Category::Zero) => {
209 (Float::nan(format), Status::INVALID)
210 }
211 (Category::Infinite, _) => (Float::infinity(format, sign), Status::NONE),
212 (_, Category::Infinite) | (Category::Zero, _) => {
213 (Float::zero(format, sign), Status::NONE)
214 }
215 (_, Category::Zero) => (Float::infinity(format, sign), Status::DIVIDE_BY_ZERO),
216 _ => {
217 let (left, left_exponent) = self.parts();
222 let (right, right_exponent) = other.parts();
223 let (left_shift, right_shift) = (left.leading_zeros(), right.leading_zeros());
224 let extra = format.precision() + 2;
225 let numerator = left << left_shift;
226 let (quotient, remainder) = long_divide(numerator, right << right_shift, extra);
227 let exponent = (left_exponent - left_shift as i32)
228 - (right_exponent - right_shift as i32)
229 - extra as i32;
230 round(quotient, exponent, remainder != 0, sign, format)
231 }
232 }
233 }
234
235 #[must_use]
245 pub fn compare(self, other: Float) -> Option<Ordering> {
246 if self.agreed_format(other).decimal().is_some() {
247 return self.decimal_compare(other);
248 }
249 if self.is_nan() || other.is_nan() {
250 return None;
251 }
252 if self.is_zero() && other.is_zero() {
253 return Some(Ordering::Equal);
254 }
255 if self.sign != other.sign {
256 return Some(if self.sign { Ordering::Less } else { Ordering::Greater });
257 }
258 let magnitudes = self.compare_magnitude(other);
259 Some(if self.sign { magnitudes.reverse() } else { magnitudes })
260 }
261
262 #[must_use]
275 pub fn to_integral(self, toward: Integral) -> Float {
276 let Category::Finite = self.category else { return self };
277 let (significand, exponent) = self.parts();
278 if exponent >= 0 {
280 return self;
281 }
282 let dropped = exponent.unsigned_abs();
283 let (kept, fraction, half) = if dropped >= 128 {
286 (0, true, false)
287 } else {
288 let rest = significand & ((1 << dropped) - 1);
289 (significand >> dropped, rest != 0, rest >= 1 << (dropped - 1))
290 };
291 if !fraction {
292 return self;
293 }
294 let away = match toward {
295 Integral::TowardZero => false,
296 Integral::Upward => !self.sign,
297 Integral::Downward => self.sign,
298 Integral::NearestTiesAway => half,
299 };
300 let magnitude = kept + u128::from(away);
301 if magnitude == 0 {
302 return Float::zero(self.format, self.sign);
303 }
304 let (value, _) = Float::from_unsigned(magnitude, self.format);
306 value.with_sign(self.sign)
307 }
308
309 #[must_use]
324 pub fn larger(self, other: Float) -> Float {
325 self.pick(other, Ordering::Greater)
326 }
327
328 #[must_use]
334 pub fn smaller(self, other: Float) -> Float {
335 self.pick(other, Ordering::Less)
336 }
337
338 fn pick(self, other: Float, want: Ordering) -> Float {
340 let format = self.agreed_format(other);
341 if self.is_nan() {
342 return if other.is_nan() { Float::nan(format) } else { other };
343 }
344 if other.is_nan() {
345 return self;
346 }
347 if self.is_zero() && other.is_zero() {
350 let wanted = matches!(want, Ordering::Less);
351 return if self.sign == wanted { self } else { other };
352 }
353 match self.compare(other) {
354 Some(order) if order == want => self,
355 _ => other,
356 }
357 }
358
359 #[must_use]
365 pub fn to_format(self, format: Format) -> (Float, Status) {
366 if self.format.decimal().is_some() || format.decimal().is_some() {
367 return self.decimal_to_format(format);
368 }
369 match self.category {
370 Category::Nan => (Float { sign: self.sign, ..Float::nan(format) }, Status::NONE),
371 Category::Infinite => (Float::infinity(format, self.sign), Status::NONE),
372 Category::Zero => (Float::zero(format, self.sign), Status::NONE),
373 Category::Finite => {
374 let (significand, exponent) = self.parts();
375 round(significand, exponent, false, self.sign, format)
376 }
377 }
378 }
379
380 #[must_use]
382 pub fn from_signed(value: i128, format: Format) -> (Float, Status) {
383 if let Some(width) = format.decimal() {
384 return Float::decimal_from_integer(value < 0, value.unsigned_abs(), format, width);
385 }
386 if value == 0 {
387 return (Float::zero(format, false), Status::NONE);
388 }
389 round(value.unsigned_abs(), 0, false, value < 0, format)
390 }
391
392 #[must_use]
394 pub fn from_unsigned(value: u128, format: Format) -> (Float, Status) {
395 if let Some(width) = format.decimal() {
396 return Float::decimal_from_integer(false, value, format, width);
397 }
398 if value == 0 {
399 return (Float::zero(format, false), Status::NONE);
400 }
401 round(value, 0, false, false, format)
402 }
403
404 #[must_use]
420 pub fn to_integer(self, width: u32, signed: bool) -> (i128, Status) {
421 assert!(width > 0 && width <= 128, "an integer type of {width} bits");
422 let limit = self.limit(width, signed);
423 if self.format.decimal().is_some() {
424 return self.decimal_integer(limit);
425 }
426 match self.category {
427 Category::Nan => (0, Status::INVALID),
428 Category::Infinite => (self.signed_value(limit), Status::INVALID),
429 Category::Zero => (0, Status::NONE),
430 Category::Finite => {
431 let (significand, exponent) = self.parts();
432 let (magnitude, inexact) = if exponent >= 0 {
433 if exponent > significand.leading_zeros() as i32 {
434 return (self.signed_value(limit), Status::INVALID);
435 }
436 (significand << exponent, false)
437 } else if -exponent >= 128 {
438 (0, true)
439 } else {
440 let dropped = -exponent as u32;
441 (significand >> dropped, significand & ((1u128 << dropped) - 1) != 0)
442 };
443 if magnitude > limit {
444 return (self.signed_value(limit), Status::INVALID);
445 }
446 let status = if inexact { Status::INEXACT } else { Status::NONE };
447 (self.signed_value(magnitude), status)
448 }
449 }
450 }
451
452 fn limit(self, width: u32, signed: bool) -> u128 {
454 match (signed, self.sign) {
455 (true, true) => 1u128 << (width - 1),
456 (true, false) => (1u128 << (width - 1)) - 1,
457 (false, true) => 0,
460 (false, false) => u128::MAX >> (128 - width),
461 }
462 }
463
464 pub(super) fn signed_value(self, magnitude: u128) -> i128 {
466 if self.sign { (magnitude as i128).wrapping_neg() } else { magnitude as i128 }
467 }
468
469 pub(super) fn parts(self) -> (u128, i32) {
472 (self.significand, self.exponent - self.format.precision() as i32 + 1)
473 }
474
475 fn agreed_format(self, other: Float) -> Format {
483 assert_eq!(self.format, other.format, "an operation on two floating formats at once");
484 self.format
485 }
486
487 fn propagated_nan(left: Float, right: Float) -> Option<(Float, Status)> {
489 (left.is_nan() || right.is_nan()).then(|| (Float::nan(left.format), Status::NONE))
490 }
491
492 fn compare_magnitude(self, other: Float) -> Ordering {
498 match (self.category, other.category) {
499 (Category::Zero, Category::Zero) | (Category::Infinite, Category::Infinite) => {
500 Ordering::Equal
501 }
502 (Category::Zero, _) | (_, Category::Infinite) => Ordering::Less,
503 (Category::Infinite, _) | (_, Category::Zero) => Ordering::Greater,
504 _ => (self.exponent, self.significand).cmp(&(other.exponent, other.significand)),
505 }
506 }
507
508 fn total(self, other: Float, subtract: bool) -> (Float, Status) {
511 let format = self.agreed_format(other);
512 let other = if subtract { other.negated() } else { other };
513 if let Some(nan) = Float::propagated_nan(self, other) {
514 return nan;
515 }
516 match (self.category, other.category) {
517 (Category::Infinite, Category::Infinite) => {
518 if self.sign == other.sign {
519 (self, Status::NONE)
520 } else {
521 (Float::nan(format), Status::INVALID)
522 }
523 }
524 (Category::Infinite, _) => (self, Status::NONE),
525 (_, Category::Infinite) => (other, Status::NONE),
526 (Category::Zero, Category::Zero) => {
529 (Float::zero(format, self.sign && other.sign), Status::NONE)
530 }
531 (Category::Zero, _) => (other, Status::NONE),
532 (_, Category::Zero) => (self, Status::NONE),
533 _ => {
534 let (big, small) = if self.compare_magnitude(other) == Ordering::Less {
535 (other, self)
536 } else {
537 (self, other)
538 };
539 let (left, exponent) = big.parts();
540 let (right, small_exponent) = small.parts();
541 let distance = (exponent - small_exponent) as u32;
542 let left = left << GUARD;
543 let (mut right, sticky) = if distance <= GUARD {
544 (right << (GUARD - distance), false)
545 } else if distance - GUARD >= 128 {
546 (0, true)
547 } else {
548 let dropped = distance - GUARD;
549 (right >> dropped, right & ((1u128 << dropped) - 1) != 0)
550 };
551 let exponent = exponent - GUARD as i32;
552 if big.sign == small.sign {
553 return round(left + right, exponent, sticky, big.sign, format);
554 }
555 right += u128::from(sticky);
562 if left == right {
563 return (Float::zero(format, false), Status::NONE);
564 }
565 round(left - right, exponent, sticky, big.sign, format)
566 }
567 }
568 }
569}
570
571fn wide_multiply(left: u128, right: u128) -> (u128, u128) {
577 const LOW: u128 = u64::MAX as u128;
578 let (left_low, left_high) = (left & LOW, left >> 64);
579 let (right_low, right_high) = (right & LOW, right >> 64);
580 let low = left_low * right_low;
581 let first = left_low * right_high;
582 let second = left_high * right_low;
583 let middle = (low >> 64) + (first & LOW) + (second & LOW);
584 let high = left_high * right_high + (first >> 64) + (second >> 64) + (middle >> 64);
585 (high, (middle << 64) | (low & LOW))
586}
587
588fn long_divide(numerator: u128, divisor: u128, extra: u32) -> (u128, u128) {
594 let mut remainder = 0u128;
595 let mut quotient = 0u128;
596 for step in 0..128 + extra {
597 let bit = if step < 128 { (numerator >> (127 - step)) & 1 } else { 0 };
598 let carry = remainder >> 127 == 1;
601 remainder = (remainder << 1) | bit;
602 quotient <<= 1;
603 if carry || remainder >= divisor {
604 remainder = remainder.wrapping_sub(divisor);
605 quotient |= 1;
606 }
607 }
608 (quotient, remainder)
609}
610
611#[cfg(test)]
612mod tests {
613 use super::*;
614
615 fn double(value: f64) -> Float {
617 Float::from_bits(Format::Double, u128::from(value.to_bits()))
618 }
619
620 fn host(value: Float) -> f64 {
622 f64::from_bits(value.to_bits() as u64)
623 }
624
625 fn single(value: f32) -> Float {
626 Float::from_bits(Format::Single, u128::from(value.to_bits()))
627 }
628
629 fn host_single(value: Float) -> f32 {
630 f32::from_bits(value.to_bits() as u32)
631 }
632
633 fn next(state: &mut u64) -> u64 {
635 *state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
636 *state
637 }
638
639 fn agrees(left: f64, right: f64) {
641 let (a, b) = (double(left), double(right));
642 for (name, mine, theirs) in [
643 ("+", a.sum(b).0, left + right),
644 ("-", a.difference(b).0, left - right),
645 ("*", a.product(b).0, left * right),
646 ("/", a.quotient(b).0, left / right),
647 ] {
648 if theirs.is_nan() {
649 assert!(mine.is_nan(), "{left:e} {name} {right:e} gave {}", host(mine));
650 } else {
651 assert_eq!(
652 host(mine).to_bits(),
653 theirs.to_bits(),
654 "{left:e} {name} {right:e} gave {} not {theirs:e}",
655 host(mine)
656 );
657 }
658 }
659 }
660
661 fn agrees_single(left: f32, right: f32) {
663 let (a, b) = (single(left), single(right));
664 for (name, mine, theirs) in [
665 ("+", a.sum(b).0, left + right),
666 ("-", a.difference(b).0, left - right),
667 ("*", a.product(b).0, left * right),
668 ("/", a.quotient(b).0, left / right),
669 ] {
670 if theirs.is_nan() {
671 assert!(mine.is_nan(), "{left:e} {name} {right:e}");
672 } else {
673 assert_eq!(
674 host_single(mine).to_bits(),
675 theirs.to_bits(),
676 "{left:e} {name} {right:e} gave {} not {theirs:e}",
677 host_single(mine)
678 );
679 }
680 }
681 }
682
683 #[test]
684 fn the_ordinary_sums_are_the_ones_the_host_computes() {
685 for (left, right) in [
686 (1.0, 1.0),
687 (1.0, 2.0),
688 (0.1, 0.2),
689 (1.0, -1.0),
690 (1e308, 1e308),
691 (1.0, 1e-308),
692 (3.0, 7.0),
693 (1.0, 3.0),
694 (2.5, 0.5),
695 (1e-320, 1e-320),
696 (f64::MAX, f64::MIN),
697 ] {
698 agrees(left, right);
699 agrees(right, left);
700 agrees(-left, right);
701 agrees(left, -right);
702 }
703 }
704
705 #[test]
706 fn a_sweep_of_random_doubles_agrees_with_the_host_in_every_bit() {
707 let mut state = 0x2545_f491_4f6c_dd1du64;
710 for _ in 0..20_000 {
711 agrees(f64::from_bits(next(&mut state)), f64::from_bits(next(&mut state)));
712 }
713 }
714
715 #[test]
716 fn a_sweep_of_random_floats_agrees_with_the_host_in_every_bit() {
717 let mut state = 0x1234_5678_9abc_def0u64;
718 for _ in 0..20_000 {
719 let bits = next(&mut state);
720 agrees_single(f32::from_bits(bits as u32), f32::from_bits((bits >> 32) as u32));
721 }
722 }
723
724 #[test]
725 fn a_sweep_of_numbers_close_together_agrees_too() {
726 let mut state = 0x9e37_79b9_7f4a_7c15u64;
729 for _ in 0..20_000 {
730 let left = (next(&mut state) >> 11) as f64;
731 let scale = f64::from(next(&mut state) as u32 % 8) - 4.0;
732 let right = (next(&mut state) >> 11) as f64 * scale.exp2();
733 agrees(left, right);
734 agrees(left, left);
735 agrees(left, -left);
736 }
737 }
738
739 #[test]
740 fn the_operations_with_no_answer_say_so() {
741 let (infinity, zero) = (Float::infinity(Format::Double, false), double(0.0));
742 let (one, nan) = (double(1.0), Float::nan(Format::Double));
743
744 let (value, status) = infinity.difference(infinity);
745 assert!(value.is_nan() && status.has(Status::INVALID));
746 let (value, status) = infinity.product(zero);
747 assert!(value.is_nan() && status.has(Status::INVALID));
748 let (value, status) = zero.quotient(zero);
749 assert!(value.is_nan() && status.has(Status::INVALID));
750 let (value, status) = infinity.quotient(infinity);
751 assert!(value.is_nan() && status.has(Status::INVALID));
752
753 let (value, status) = one.quotient(zero);
755 assert!(value.is_infinite() && !value.is_negative());
756 assert!(status.has(Status::DIVIDE_BY_ZERO) && !status.has(Status::INVALID));
757 assert!(one.negated().quotient(zero).0.is_negative());
758 assert!(one.quotient(zero.negated()).0.is_negative());
759
760 for (value, status) in
762 [nan.sum(one), one.sum(nan), nan.product(one), nan.quotient(one), one.difference(nan)]
763 {
764 assert!(value.is_nan() && status.is_none());
765 }
766 assert!(infinity.sum(infinity).0.is_infinite());
767 assert!(infinity.sum(one).0.is_infinite());
768 }
769
770 #[test]
771 fn the_sign_of_a_zero_is_the_one_the_host_gives() {
772 let (positive, negative) = (double(0.0), double(-0.0));
773 for (mine, theirs) in [
774 (positive.sum(positive), 0.0 + 0.0),
775 (positive.sum(negative), 0.0 + -0.0),
776 (negative.sum(positive), -0.0 + 0.0),
777 (negative.sum(negative), -0.0 + -0.0),
778 (positive.difference(positive), 0.0 - 0.0),
779 (negative.difference(positive), -0.0 - 0.0),
780 (double(1.0).difference(double(1.0)), 1.0 - 1.0),
781 (double(-1.0).sum(double(1.0)), -1.0 + 1.0),
782 (positive.product(double(3.0)), 0.0 * 3.0),
783 (negative.product(double(3.0)), -0.0 * 3.0),
784 (positive.quotient(double(-3.0)), 0.0 / -3.0),
785 ] {
786 assert_eq!(host(mine.0).to_bits(), f64::to_bits(theirs), "{theirs}");
787 }
788 }
789
790 #[test]
791 fn an_operation_says_what_it_had_to_do_to_the_answer() {
792 let (one, three) = (double(1.0), double(3.0));
793 assert!(one.sum(one).1.is_none());
794 assert!(one.product(three).1.is_none());
795 assert!(one.quotient(double(2.0)).1.is_none());
796 assert!(one.quotient(three).1.has(Status::INEXACT));
797
798 let (value, status) = double(f64::MAX).product(double(2.0));
799 assert!(value.is_infinite() && status.has(Status::OVERFLOW) && status.has(Status::INEXACT));
800 let (value, status) = double(f64::MIN_POSITIVE).quotient(double(1e300));
801 assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
802 let four = Float::from_bits(Format::Double, 4);
804 assert!(four.quotient(double(2.0)).1.is_none());
805 assert!(four.quotient(double(4.0)).1.is_none());
806 let status = Float::from_bits(Format::Double, 3).quotient(double(2.0)).1;
808 assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
809 }
810
811 #[test]
812 fn a_comparison_orders_the_numbers_and_leaves_the_nans_out() {
813 let (one, two) = (double(1.0), double(2.0));
814 assert_eq!(one.compare(two), Some(Ordering::Less));
815 assert_eq!(two.compare(one), Some(Ordering::Greater));
816 assert_eq!(one.compare(one), Some(Ordering::Equal));
817 assert_eq!(one.negated().compare(two.negated()), Some(Ordering::Greater));
818 assert_eq!(one.negated().compare(one), Some(Ordering::Less));
819 assert_eq!(double(0.0).compare(double(-0.0)), Some(Ordering::Equal));
821 assert_eq!(double(-0.0).compare(double(0.0)), Some(Ordering::Equal));
822 assert_eq!(double(-0.0).compare(one), Some(Ordering::Less));
823 let infinity = Float::infinity(Format::Double, false);
825 assert_eq!(infinity.compare(double(f64::MAX)), Some(Ordering::Greater));
826 assert_eq!(infinity.negated().compare(double(f64::MIN)), Some(Ordering::Less));
827 assert_eq!(infinity.compare(infinity), Some(Ordering::Equal));
828 let nan = Float::nan(Format::Double);
829 assert_eq!(nan.compare(one), None);
830 assert_eq!(one.compare(nan), None);
831 assert_eq!(nan.compare(nan), None);
832 }
833
834 #[test]
835 fn a_comparison_of_random_numbers_is_the_host_order() {
836 let mut state = 0xdead_beef_cafe_f00du64;
837 for _ in 0..20_000 {
838 let left = f64::from_bits(next(&mut state));
839 let right = f64::from_bits(next(&mut state));
840 assert_eq!(
841 double(left).compare(double(right)),
842 left.partial_cmp(&right),
843 "{left:e} against {right:e}"
844 );
845 }
846 }
847
848 #[test]
849 fn a_conversion_between_formats_rounds_the_way_the_host_does() {
850 let mut state = 0x0123_4567_89ab_cdefu64;
851 for _ in 0..20_000 {
852 let value = f64::from_bits(next(&mut state));
853 let narrowed = double(value).to_format(Format::Single);
854 let theirs = value as f32;
855 if theirs.is_nan() {
856 assert!(narrowed.0.is_nan(), "{value:e}");
857 continue;
858 }
859 assert_eq!(host_single(narrowed.0).to_bits(), theirs.to_bits(), "{value:e}");
860 let widened = narrowed.0.to_format(Format::Double);
862 assert_eq!(host(widened.0).to_bits(), f64::from(theirs).to_bits(), "{value:e}");
863 assert!(widened.1.is_none(), "{value:e}");
864 }
865 }
866
867 #[test]
868 fn a_narrowing_conversion_says_what_it_did() {
869 let (value, status) = double(0.1).to_format(Format::Single);
870 assert_eq!(host_single(value).to_bits(), (0.1f32).to_bits());
871 assert!(status.has(Status::INEXACT));
872 assert!(double(0.5).to_format(Format::Single).1.is_none());
873 let (value, status) = double(1e300).to_format(Format::Single);
874 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
875 let (value, status) = double(1e-300).to_format(Format::Single);
876 assert!(value.is_zero() && status.has(Status::UNDERFLOW));
877 let (up, status) = double(0.1).to_format(Format::X87Extended);
880 assert!(status.is_none());
881 assert_eq!(up.to_bits(), 0x3ffb_cccc_cccc_cccc_d000);
882 assert_eq!(host(up.to_format(Format::Double).0).to_bits(), (0.1f64).to_bits());
883 let tenth = Float::parse("0.1", Format::X87Extended).expect("a tenth").0;
886 assert_eq!(tenth.to_bits(), 0x3ffb_cccc_cccc_cccc_cccd);
887 assert_ne!(up.to_bits(), tenth.to_bits());
888 }
889
890 #[test]
891 fn an_integer_becomes_the_nearest_number_to_it() {
892 let mut state = 0xfeed_face_dead_c0dcu64;
893 for _ in 0..20_000 {
894 let value = next(&mut state) as i64;
895 let mine = Float::from_signed(i128::from(value), Format::Double).0;
896 assert_eq!(host(mine).to_bits(), (value as f64).to_bits(), "{value}");
897 let value = next(&mut state);
898 let mine = Float::from_unsigned(u128::from(value), Format::Single).0;
899 assert_eq!(host_single(mine).to_bits(), (value as f32).to_bits(), "{value}");
900 }
901 assert_eq!(host(Float::from_signed(0, Format::Double).0).to_bits(), (0f64).to_bits());
903 assert!(Float::from_signed(1 << 52, Format::Double).1.is_none());
904 assert!(Float::from_signed((1 << 53) + 1, Format::Double).1.has(Status::INEXACT));
905 let (value, status) = Float::from_signed(i128::MIN, Format::Double);
906 assert!(value.is_negative() && status.is_none());
907 assert_eq!(host(value), -(2f64).powi(127));
908 let (value, status) = Float::from_unsigned(u128::MAX, Format::Double);
909 assert!(status.has(Status::INEXACT));
910 assert_eq!(host(value), (2f64).powi(128));
911 }
912
913 #[test]
914 fn a_number_becomes_an_integer_by_dropping_its_fraction() {
915 for (value, expected) in [
916 (1.5, 1),
917 (-1.5, -1),
918 (0.9, 0),
919 (-0.9, 0),
920 (2.0, 2),
921 (-2.0, -2),
922 (1e18, 1_000_000_000_000_000_000),
923 ] {
924 assert_eq!(double(value).to_integer(64, true).0, expected, "{value}");
925 }
926 assert!(double(2.0).to_integer(64, true).1.is_none());
927 assert!(double(1.5).to_integer(64, true).1.has(Status::INEXACT));
928 assert_eq!(double(-0.5).to_integer(32, false), (0, Status::INEXACT));
930 let (value, status) = double(-1.0).to_integer(32, false);
931 assert!(value == 0 && status.has(Status::INVALID));
932 }
933
934 #[test]
935 fn a_number_that_will_not_fit_gives_the_end_of_the_range() {
936 let (value, status) = double(1e30).to_integer(32, true);
937 assert!(value == i128::from(i32::MAX) && status.has(Status::INVALID));
938 let (value, status) = double(-1e30).to_integer(32, true);
939 assert!(value == i128::from(i32::MIN) && status.has(Status::INVALID));
940 let (value, status) = double(1e30).to_integer(32, false);
941 assert!(value == i128::from(u32::MAX) && status.has(Status::INVALID));
942 let (value, status) = Float::infinity(Format::Double, false).to_integer(64, true);
943 assert!(value == i128::from(i64::MAX) && status.has(Status::INVALID));
944 let (value, status) = Float::nan(Format::Double).to_integer(64, true);
945 assert!(value == 0 && status.has(Status::INVALID));
946 let (value, status) = double(f64::MAX).to_integer(128, false);
948 assert!(value == -1 && status.has(Status::INVALID));
949 let smallest = double(-(2f64).powi(127));
951 assert_eq!(smallest.to_integer(128, true), (i128::MIN, Status::NONE));
952 }
953
954 #[test]
955 fn a_conversion_to_an_integer_is_the_one_the_host_does() {
956 let mut state = 0xabad_1dea_0000_0001u64;
959 for _ in 0..20_000 {
960 let value = f64::from_bits(next(&mut state));
961 assert_eq!(double(value).to_integer(64, true).0, i128::from(value as i64), "{value:e}");
962 assert_eq!(
963 double(value).to_integer(32, false).0,
964 i128::from(value as u32),
965 "{value:e}"
966 );
967 }
968 }
969
970 #[test]
971 fn the_wide_formats_compute_what_they_are_supposed_to() {
972 let quad = |text: &str| Float::parse(text, Format::Quad).expect("a number").0;
973 let (third, status) = quad("1").quotient(quad("3"));
977 assert_eq!(third.to_bits(), 0x3ffd_5555_5555_5555_5555_5555_5555_5555);
978 assert!(status.has(Status::INEXACT));
979 let (whole, status) = third.sum(third).0.sum(third);
981 assert_eq!(whole.to_bits(), quad("1").to_bits());
982 assert!(status.has(Status::INEXACT));
983
984 let x87 = |text: &str| Float::parse(text, Format::X87Extended).expect("a number").0;
987 let (sum, status) = x87("9007199254740993").sum(x87("1"));
988 assert!(status.is_none());
989 assert_eq!(sum.to_bits(), x87("9007199254740994").to_bits());
990
991 let half = |text: &str| Float::parse(text, Format::Half).expect("a number").0;
994 let (value, status) = half("2048").sum(half("1"));
995 assert!(status.has(Status::INEXACT));
996 assert_eq!(value.to_bits(), half("2048").to_bits());
997 }
998
999 #[test]
1000 fn a_nan_survives_a_trip_through_its_encoding() {
1001 for format in [
1002 Format::Half,
1003 Format::BFloat16,
1004 Format::Single,
1005 Format::Double,
1006 Format::X87Extended,
1007 Format::Quad,
1008 ] {
1009 let nan = Float::nan(format);
1010 assert!(nan.is_nan() && !nan.is_finite() && !nan.is_infinite(), "{format:?}");
1011 assert_eq!(Float::from_bits(format, nan.to_bits()), nan, "{format:?}");
1012 assert_eq!(nan.negated().to_hex(), "-nan", "{format:?}");
1013 let infinity = Float::infinity(format, false);
1016 assert!(Float::from_bits(format, infinity.to_bits()).is_infinite(), "{format:?}");
1017 }
1018 assert_eq!(Float::nan(Format::Double).to_bits(), u128::from(f64::NAN.to_bits()));
1020 assert!(Float::from_bits(Format::Double, u128::from(f64::NAN.to_bits())).is_nan());
1021 }
1022
1023 #[test]
1026 fn a_number_taken_to_an_integer_lands_where_the_host_puts_it() {
1027 let mut state = 0x5eed_1234_u64;
1028 for _ in 0..20000 {
1029 let bits = next(&mut state);
1030 let value = f64::from_bits(bits);
1031 if !value.is_finite() {
1032 continue;
1033 }
1034 for (name, toward, theirs) in [
1035 ("trunc", Integral::TowardZero, value.trunc()),
1036 ("ceil", Integral::Upward, value.ceil()),
1037 ("floor", Integral::Downward, value.floor()),
1038 ("round", Integral::NearestTiesAway, value.round()),
1039 ] {
1040 let mine = double(value).to_integral(toward);
1041 assert_eq!(
1042 host(mine).to_bits(),
1043 theirs.to_bits(),
1044 "{name} of {value:e} gave {}",
1045 host(mine)
1046 );
1047 }
1048 }
1049 }
1050
1051 #[test]
1054 fn the_sign_of_a_number_rounded_away_to_nothing_is_still_there() {
1055 let cases: &[(f64, Integral, f64)] = &[
1056 (-0.5, Integral::Upward, -0.0),
1057 (-0.2, Integral::Upward, -0.0),
1058 (-0.5, Integral::TowardZero, -0.0),
1059 (0.5, Integral::Downward, 0.0),
1060 (0.4, Integral::NearestTiesAway, 0.0),
1061 (-0.4, Integral::NearestTiesAway, -0.0),
1062 (-0.0, Integral::Upward, -0.0),
1063 (0.5, Integral::NearestTiesAway, 1.0),
1064 (-0.5, Integral::NearestTiesAway, -1.0),
1065 (2.5, Integral::NearestTiesAway, 3.0),
1066 (-2.5, Integral::NearestTiesAway, -3.0),
1067 (1e300, Integral::Upward, 1e300),
1068 (f64::MIN_POSITIVE / 4.0, Integral::Downward, 0.0),
1069 (-f64::MIN_POSITIVE / 4.0, Integral::Upward, -0.0),
1070 ];
1071 for &(value, toward, want) in cases {
1072 let mine = double(value).to_integral(toward);
1073 assert_eq!(host(mine).to_bits(), want.to_bits(), "{toward:?} of {value:e}");
1074 }
1075 assert!(double(f64::NAN).to_integral(Integral::Upward).is_nan());
1077 let infinity = double(f64::NEG_INFINITY).to_integral(Integral::Upward);
1078 assert!(infinity.is_infinite() && infinity.is_negative());
1079 }
1080
1081 #[test]
1084 fn a_half_is_taken_to_an_integer_in_every_format() {
1085 for format in
1086 [Format::Half, Format::Single, Format::Double, Format::X87Extended, Format::Quad]
1087 {
1088 let (half, _) = Float::parse("2.5", format).expect("a number");
1089 let (three, _) = Float::parse("3", format).expect("a number");
1090 let (two, _) = Float::parse("2", format).expect("a number");
1091 assert_eq!(half.to_integral(Integral::Upward), three, "{format:?}");
1092 assert_eq!(half.to_integral(Integral::TowardZero), two, "{format:?}");
1093 assert_eq!(half.to_integral(Integral::NearestTiesAway), three, "{format:?}");
1094 assert_eq!(
1095 half.negated().to_integral(Integral::Downward),
1096 three.negated(),
1097 "{format:?}"
1098 );
1099 }
1100 }
1101
1102 #[test]
1104 fn the_larger_of_two_is_the_one_the_library_would_return() {
1105 let (one, two) = (double(1.0), double(2.0));
1106 assert_eq!(host(one.larger(two)), 2.0);
1107 assert_eq!(host(one.smaller(two)), 1.0);
1108 assert_eq!(host(two.larger(one)), 2.0);
1109 assert_eq!(host(two.smaller(one)), 1.0);
1110 let nan = double(f64::NAN);
1113 assert_eq!(host(nan.larger(two)), 2.0);
1114 assert_eq!(host(two.larger(nan)), 2.0);
1115 assert_eq!(host(nan.smaller(two)), 2.0);
1116 assert!(nan.larger(nan).is_nan());
1117 let (zero, minus) = (double(0.0), double(-0.0));
1119 let zeros: &[(&str, Float, f64)] = &[
1120 ("fmax(0, -0)", zero.larger(minus), 0.0),
1121 ("fmax(-0, 0)", minus.larger(zero), 0.0),
1122 ("fmin(0, -0)", zero.smaller(minus), -0.0),
1123 ("fmin(-0, 0)", minus.smaller(zero), -0.0),
1124 ];
1125 for &(name, mine, want) in zeros {
1126 assert_eq!(host(mine).to_bits(), want.to_bits(), "{name}");
1127 }
1128 let infinity = double(f64::INFINITY);
1130 assert!(infinity.larger(two).is_infinite());
1131 assert_eq!(host(infinity.smaller(two)), 2.0);
1132 }
1133
1134 #[test]
1135 fn the_helpers_underneath_do_what_they_say() {
1136 assert_eq!(wide_multiply(0, 12345), (0, 0));
1137 assert_eq!(wide_multiply(3, 5), (0, 15));
1138 assert_eq!(wide_multiply(1, u128::MAX), (0, u128::MAX));
1139 assert_eq!(wide_multiply(u128::MAX, u128::MAX), (u128::MAX - 1, 1));
1140 assert_eq!(wide_multiply(1 << 127, 1 << 127), (1 << 126, 0));
1141 assert_eq!(long_divide(1 << 127, 1 << 127, 4), (16, 0));
1143 assert_eq!(long_divide(3 << 126, 1 << 127, 4), (24, 0));
1144 assert_eq!(long_divide(1 << 127, 3 << 126, 4), (10, 1 << 127));
1145 }
1146}