1use std::cmp::Ordering;
36
37use crate::float::{Category, Float, Format, Status, round};
38
39const GUARD: u32 = 3;
45
46impl Float {
47 #[must_use]
52 pub const fn nan(format: Format) -> Float {
53 Float {
54 format,
55 category: Category::Nan,
56 sign: false,
57 exponent: 0,
58 significand: Float::quiet_bit(format) | Float::leading_bit(format),
59 }
60 }
61
62 #[must_use]
64 pub const fn is_nan(self) -> bool {
65 matches!(self.category, Category::Nan)
66 }
67
68 #[must_use]
70 pub const fn negated(self) -> Float {
71 Float { sign: !self.sign, ..self }
72 }
73
74 #[must_use]
76 pub const fn abs(self) -> Float {
77 Float { sign: false, ..self }
78 }
79
80 #[must_use]
83 pub const fn with_sign(self, sign: bool) -> Float {
84 Float { sign, ..self }
85 }
86
87 #[must_use]
99 pub fn sum(self, other: Float) -> (Float, Status) {
100 self.total(other, false)
101 }
102
103 #[must_use]
113 pub fn difference(self, other: Float) -> (Float, Status) {
114 self.total(other, true)
115 }
116
117 #[must_use]
126 pub fn product(self, other: Float) -> (Float, Status) {
127 let format = self.agreed_format(other);
128 let sign = self.sign != other.sign;
129 if let Some(nan) = Float::propagated_nan(self, other) {
130 return nan;
131 }
132 match (self.category, other.category) {
133 (Category::Infinite, Category::Zero) | (Category::Zero, Category::Infinite) => {
134 (Float::nan(format), Status::INVALID)
135 }
136 (Category::Infinite, _) | (_, Category::Infinite) => {
137 (Float::infinity(format, sign), Status::NONE)
138 }
139 (Category::Zero, _) | (_, Category::Zero) => (Float::zero(format, sign), Status::NONE),
140 _ => {
141 let (left, left_exponent) = self.parts();
142 let (right, right_exponent) = other.parts();
143 let (high, low) = wide_multiply(left, right);
144 let exponent = left_exponent + right_exponent;
145 if high == 0 {
146 return round(low, exponent, false, sign, format);
147 }
148 let drop = 128 - high.leading_zeros();
152 let sticky = low & ((1u128 << drop) - 1) != 0;
153 let significand = (high << (128 - drop)) | (low >> drop);
154 round(significand, exponent + drop as i32, sticky, sign, format)
155 }
156 }
157 }
158
159 #[must_use]
170 pub fn quotient(self, other: Float) -> (Float, Status) {
171 let format = self.agreed_format(other);
172 let sign = self.sign != other.sign;
173 if let Some(nan) = Float::propagated_nan(self, other) {
174 return nan;
175 }
176 match (self.category, other.category) {
177 (Category::Infinite, Category::Infinite) | (Category::Zero, Category::Zero) => {
178 (Float::nan(format), Status::INVALID)
179 }
180 (Category::Infinite, _) => (Float::infinity(format, sign), Status::NONE),
181 (_, Category::Infinite) | (Category::Zero, _) => {
182 (Float::zero(format, sign), Status::NONE)
183 }
184 (_, Category::Zero) => (Float::infinity(format, sign), Status::DIVIDE_BY_ZERO),
185 _ => {
186 let (left, left_exponent) = self.parts();
191 let (right, right_exponent) = other.parts();
192 let (left_shift, right_shift) = (left.leading_zeros(), right.leading_zeros());
193 let extra = format.precision() + 2;
194 let numerator = left << left_shift;
195 let (quotient, remainder) = long_divide(numerator, right << right_shift, extra);
196 let exponent = (left_exponent - left_shift as i32)
197 - (right_exponent - right_shift as i32)
198 - extra as i32;
199 round(quotient, exponent, remainder != 0, sign, format)
200 }
201 }
202 }
203
204 #[must_use]
214 pub fn compare(self, other: Float) -> Option<Ordering> {
215 self.agreed_format(other);
216 if self.is_nan() || other.is_nan() {
217 return None;
218 }
219 if self.is_zero() && other.is_zero() {
220 return Some(Ordering::Equal);
221 }
222 if self.sign != other.sign {
223 return Some(if self.sign { Ordering::Less } else { Ordering::Greater });
224 }
225 let magnitudes = self.compare_magnitude(other);
226 Some(if self.sign { magnitudes.reverse() } else { magnitudes })
227 }
228
229 #[must_use]
235 pub fn to_format(self, format: Format) -> (Float, Status) {
236 match self.category {
237 Category::Nan => (Float { sign: self.sign, ..Float::nan(format) }, Status::NONE),
238 Category::Infinite => (Float::infinity(format, self.sign), Status::NONE),
239 Category::Zero => (Float::zero(format, self.sign), Status::NONE),
240 Category::Finite => {
241 let (significand, exponent) = self.parts();
242 round(significand, exponent, false, self.sign, format)
243 }
244 }
245 }
246
247 #[must_use]
249 pub fn from_signed(value: i128, format: Format) -> (Float, Status) {
250 if value == 0 {
251 return (Float::zero(format, false), Status::NONE);
252 }
253 round(value.unsigned_abs(), 0, false, value < 0, format)
254 }
255
256 #[must_use]
258 pub fn from_unsigned(value: u128, format: Format) -> (Float, Status) {
259 if value == 0 {
260 return (Float::zero(format, false), Status::NONE);
261 }
262 round(value, 0, false, false, format)
263 }
264
265 #[must_use]
281 pub fn to_integer(self, width: u32, signed: bool) -> (i128, Status) {
282 assert!(width > 0 && width <= 128, "an integer type of {width} bits");
283 let limit = self.limit(width, signed);
284 match self.category {
285 Category::Nan => (0, Status::INVALID),
286 Category::Infinite => (self.signed_value(limit), Status::INVALID),
287 Category::Zero => (0, Status::NONE),
288 Category::Finite => {
289 let (significand, exponent) = self.parts();
290 let (magnitude, inexact) = if exponent >= 0 {
291 if exponent > significand.leading_zeros() as i32 {
292 return (self.signed_value(limit), Status::INVALID);
293 }
294 (significand << exponent, false)
295 } else if -exponent >= 128 {
296 (0, true)
297 } else {
298 let dropped = -exponent as u32;
299 (significand >> dropped, significand & ((1u128 << dropped) - 1) != 0)
300 };
301 if magnitude > limit {
302 return (self.signed_value(limit), Status::INVALID);
303 }
304 let status = if inexact { Status::INEXACT } else { Status::NONE };
305 (self.signed_value(magnitude), status)
306 }
307 }
308 }
309
310 fn limit(self, width: u32, signed: bool) -> u128 {
312 match (signed, self.sign) {
313 (true, true) => 1u128 << (width - 1),
314 (true, false) => (1u128 << (width - 1)) - 1,
315 (false, true) => 0,
318 (false, false) => u128::MAX >> (128 - width),
319 }
320 }
321
322 fn signed_value(self, magnitude: u128) -> i128 {
324 if self.sign { (magnitude as i128).wrapping_neg() } else { magnitude as i128 }
325 }
326
327 fn parts(self) -> (u128, i32) {
330 (self.significand, self.exponent - self.format.precision() as i32 + 1)
331 }
332
333 fn agreed_format(self, other: Float) -> Format {
341 assert_eq!(self.format, other.format, "an operation on two floating formats at once");
342 self.format
343 }
344
345 fn propagated_nan(left: Float, right: Float) -> Option<(Float, Status)> {
347 (left.is_nan() || right.is_nan()).then(|| (Float::nan(left.format), Status::NONE))
348 }
349
350 fn compare_magnitude(self, other: Float) -> Ordering {
356 match (self.category, other.category) {
357 (Category::Zero, Category::Zero) | (Category::Infinite, Category::Infinite) => {
358 Ordering::Equal
359 }
360 (Category::Zero, _) | (_, Category::Infinite) => Ordering::Less,
361 (Category::Infinite, _) | (_, Category::Zero) => Ordering::Greater,
362 _ => (self.exponent, self.significand).cmp(&(other.exponent, other.significand)),
363 }
364 }
365
366 fn total(self, other: Float, subtract: bool) -> (Float, Status) {
369 let format = self.agreed_format(other);
370 let other = if subtract { other.negated() } else { other };
371 if let Some(nan) = Float::propagated_nan(self, other) {
372 return nan;
373 }
374 match (self.category, other.category) {
375 (Category::Infinite, Category::Infinite) => {
376 if self.sign == other.sign {
377 (self, Status::NONE)
378 } else {
379 (Float::nan(format), Status::INVALID)
380 }
381 }
382 (Category::Infinite, _) => (self, Status::NONE),
383 (_, Category::Infinite) => (other, Status::NONE),
384 (Category::Zero, Category::Zero) => {
387 (Float::zero(format, self.sign && other.sign), Status::NONE)
388 }
389 (Category::Zero, _) => (other, Status::NONE),
390 (_, Category::Zero) => (self, Status::NONE),
391 _ => {
392 let (big, small) = if self.compare_magnitude(other) == Ordering::Less {
393 (other, self)
394 } else {
395 (self, other)
396 };
397 let (left, exponent) = big.parts();
398 let (right, small_exponent) = small.parts();
399 let distance = (exponent - small_exponent) as u32;
400 let left = left << GUARD;
401 let (mut right, sticky) = if distance <= GUARD {
402 (right << (GUARD - distance), false)
403 } else if distance - GUARD >= 128 {
404 (0, true)
405 } else {
406 let dropped = distance - GUARD;
407 (right >> dropped, right & ((1u128 << dropped) - 1) != 0)
408 };
409 let exponent = exponent - GUARD as i32;
410 if big.sign == small.sign {
411 return round(left + right, exponent, sticky, big.sign, format);
412 }
413 right += u128::from(sticky);
420 if left == right {
421 return (Float::zero(format, false), Status::NONE);
422 }
423 round(left - right, exponent, sticky, big.sign, format)
424 }
425 }
426 }
427}
428
429fn wide_multiply(left: u128, right: u128) -> (u128, u128) {
435 const LOW: u128 = u64::MAX as u128;
436 let (left_low, left_high) = (left & LOW, left >> 64);
437 let (right_low, right_high) = (right & LOW, right >> 64);
438 let low = left_low * right_low;
439 let first = left_low * right_high;
440 let second = left_high * right_low;
441 let middle = (low >> 64) + (first & LOW) + (second & LOW);
442 let high = left_high * right_high + (first >> 64) + (second >> 64) + (middle >> 64);
443 (high, (middle << 64) | (low & LOW))
444}
445
446fn long_divide(numerator: u128, divisor: u128, extra: u32) -> (u128, u128) {
452 let mut remainder = 0u128;
453 let mut quotient = 0u128;
454 for step in 0..128 + extra {
455 let bit = if step < 128 { (numerator >> (127 - step)) & 1 } else { 0 };
456 let carry = remainder >> 127 == 1;
459 remainder = (remainder << 1) | bit;
460 quotient <<= 1;
461 if carry || remainder >= divisor {
462 remainder = remainder.wrapping_sub(divisor);
463 quotient |= 1;
464 }
465 }
466 (quotient, remainder)
467}
468
469#[cfg(test)]
470mod tests {
471 use super::*;
472
473 fn double(value: f64) -> Float {
475 Float::from_bits(Format::Double, u128::from(value.to_bits()))
476 }
477
478 fn host(value: Float) -> f64 {
480 f64::from_bits(value.to_bits() as u64)
481 }
482
483 fn single(value: f32) -> Float {
484 Float::from_bits(Format::Single, u128::from(value.to_bits()))
485 }
486
487 fn host_single(value: Float) -> f32 {
488 f32::from_bits(value.to_bits() as u32)
489 }
490
491 fn next(state: &mut u64) -> u64 {
493 *state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
494 *state
495 }
496
497 fn agrees(left: f64, right: f64) {
499 let (a, b) = (double(left), double(right));
500 for (name, mine, theirs) in [
501 ("+", a.sum(b).0, left + right),
502 ("-", a.difference(b).0, left - right),
503 ("*", a.product(b).0, left * right),
504 ("/", a.quotient(b).0, left / right),
505 ] {
506 if theirs.is_nan() {
507 assert!(mine.is_nan(), "{left:e} {name} {right:e} gave {}", host(mine));
508 } else {
509 assert_eq!(
510 host(mine).to_bits(),
511 theirs.to_bits(),
512 "{left:e} {name} {right:e} gave {} not {theirs:e}",
513 host(mine)
514 );
515 }
516 }
517 }
518
519 fn agrees_single(left: f32, right: f32) {
521 let (a, b) = (single(left), single(right));
522 for (name, mine, theirs) in [
523 ("+", a.sum(b).0, left + right),
524 ("-", a.difference(b).0, left - right),
525 ("*", a.product(b).0, left * right),
526 ("/", a.quotient(b).0, left / right),
527 ] {
528 if theirs.is_nan() {
529 assert!(mine.is_nan(), "{left:e} {name} {right:e}");
530 } else {
531 assert_eq!(
532 host_single(mine).to_bits(),
533 theirs.to_bits(),
534 "{left:e} {name} {right:e} gave {} not {theirs:e}",
535 host_single(mine)
536 );
537 }
538 }
539 }
540
541 #[test]
542 fn the_ordinary_sums_are_the_ones_the_host_computes() {
543 for (left, right) in [
544 (1.0, 1.0),
545 (1.0, 2.0),
546 (0.1, 0.2),
547 (1.0, -1.0),
548 (1e308, 1e308),
549 (1.0, 1e-308),
550 (3.0, 7.0),
551 (1.0, 3.0),
552 (2.5, 0.5),
553 (1e-320, 1e-320),
554 (f64::MAX, f64::MIN),
555 ] {
556 agrees(left, right);
557 agrees(right, left);
558 agrees(-left, right);
559 agrees(left, -right);
560 }
561 }
562
563 #[test]
564 fn a_sweep_of_random_doubles_agrees_with_the_host_in_every_bit() {
565 let mut state = 0x2545_f491_4f6c_dd1du64;
568 for _ in 0..20_000 {
569 agrees(f64::from_bits(next(&mut state)), f64::from_bits(next(&mut state)));
570 }
571 }
572
573 #[test]
574 fn a_sweep_of_random_floats_agrees_with_the_host_in_every_bit() {
575 let mut state = 0x1234_5678_9abc_def0u64;
576 for _ in 0..20_000 {
577 let bits = next(&mut state);
578 agrees_single(f32::from_bits(bits as u32), f32::from_bits((bits >> 32) as u32));
579 }
580 }
581
582 #[test]
583 fn a_sweep_of_numbers_close_together_agrees_too() {
584 let mut state = 0x9e37_79b9_7f4a_7c15u64;
587 for _ in 0..20_000 {
588 let left = (next(&mut state) >> 11) as f64;
589 let scale = f64::from(next(&mut state) as u32 % 8) - 4.0;
590 let right = (next(&mut state) >> 11) as f64 * scale.exp2();
591 agrees(left, right);
592 agrees(left, left);
593 agrees(left, -left);
594 }
595 }
596
597 #[test]
598 fn the_operations_with_no_answer_say_so() {
599 let (infinity, zero) = (Float::infinity(Format::Double, false), double(0.0));
600 let (one, nan) = (double(1.0), Float::nan(Format::Double));
601
602 let (value, status) = infinity.difference(infinity);
603 assert!(value.is_nan() && status.has(Status::INVALID));
604 let (value, status) = infinity.product(zero);
605 assert!(value.is_nan() && status.has(Status::INVALID));
606 let (value, status) = zero.quotient(zero);
607 assert!(value.is_nan() && status.has(Status::INVALID));
608 let (value, status) = infinity.quotient(infinity);
609 assert!(value.is_nan() && status.has(Status::INVALID));
610
611 let (value, status) = one.quotient(zero);
613 assert!(value.is_infinite() && !value.is_negative());
614 assert!(status.has(Status::DIVIDE_BY_ZERO) && !status.has(Status::INVALID));
615 assert!(one.negated().quotient(zero).0.is_negative());
616 assert!(one.quotient(zero.negated()).0.is_negative());
617
618 for (value, status) in
620 [nan.sum(one), one.sum(nan), nan.product(one), nan.quotient(one), one.difference(nan)]
621 {
622 assert!(value.is_nan() && status.is_none());
623 }
624 assert!(infinity.sum(infinity).0.is_infinite());
625 assert!(infinity.sum(one).0.is_infinite());
626 }
627
628 #[test]
629 fn the_sign_of_a_zero_is_the_one_the_host_gives() {
630 let (positive, negative) = (double(0.0), double(-0.0));
631 for (mine, theirs) in [
632 (positive.sum(positive), 0.0 + 0.0),
633 (positive.sum(negative), 0.0 + -0.0),
634 (negative.sum(positive), -0.0 + 0.0),
635 (negative.sum(negative), -0.0 + -0.0),
636 (positive.difference(positive), 0.0 - 0.0),
637 (negative.difference(positive), -0.0 - 0.0),
638 (double(1.0).difference(double(1.0)), 1.0 - 1.0),
639 (double(-1.0).sum(double(1.0)), -1.0 + 1.0),
640 (positive.product(double(3.0)), 0.0 * 3.0),
641 (negative.product(double(3.0)), -0.0 * 3.0),
642 (positive.quotient(double(-3.0)), 0.0 / -3.0),
643 ] {
644 assert_eq!(host(mine.0).to_bits(), f64::to_bits(theirs), "{theirs}");
645 }
646 }
647
648 #[test]
649 fn an_operation_says_what_it_had_to_do_to_the_answer() {
650 let (one, three) = (double(1.0), double(3.0));
651 assert!(one.sum(one).1.is_none());
652 assert!(one.product(three).1.is_none());
653 assert!(one.quotient(double(2.0)).1.is_none());
654 assert!(one.quotient(three).1.has(Status::INEXACT));
655
656 let (value, status) = double(f64::MAX).product(double(2.0));
657 assert!(value.is_infinite() && status.has(Status::OVERFLOW) && status.has(Status::INEXACT));
658 let (value, status) = double(f64::MIN_POSITIVE).quotient(double(1e300));
659 assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
660 let four = Float::from_bits(Format::Double, 4);
662 assert!(four.quotient(double(2.0)).1.is_none());
663 assert!(four.quotient(double(4.0)).1.is_none());
664 let status = Float::from_bits(Format::Double, 3).quotient(double(2.0)).1;
666 assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
667 }
668
669 #[test]
670 fn a_comparison_orders_the_numbers_and_leaves_the_nans_out() {
671 let (one, two) = (double(1.0), double(2.0));
672 assert_eq!(one.compare(two), Some(Ordering::Less));
673 assert_eq!(two.compare(one), Some(Ordering::Greater));
674 assert_eq!(one.compare(one), Some(Ordering::Equal));
675 assert_eq!(one.negated().compare(two.negated()), Some(Ordering::Greater));
676 assert_eq!(one.negated().compare(one), Some(Ordering::Less));
677 assert_eq!(double(0.0).compare(double(-0.0)), Some(Ordering::Equal));
679 assert_eq!(double(-0.0).compare(double(0.0)), Some(Ordering::Equal));
680 assert_eq!(double(-0.0).compare(one), Some(Ordering::Less));
681 let infinity = Float::infinity(Format::Double, false);
683 assert_eq!(infinity.compare(double(f64::MAX)), Some(Ordering::Greater));
684 assert_eq!(infinity.negated().compare(double(f64::MIN)), Some(Ordering::Less));
685 assert_eq!(infinity.compare(infinity), Some(Ordering::Equal));
686 let nan = Float::nan(Format::Double);
687 assert_eq!(nan.compare(one), None);
688 assert_eq!(one.compare(nan), None);
689 assert_eq!(nan.compare(nan), None);
690 }
691
692 #[test]
693 fn a_comparison_of_random_numbers_is_the_host_order() {
694 let mut state = 0xdead_beef_cafe_f00du64;
695 for _ in 0..20_000 {
696 let left = f64::from_bits(next(&mut state));
697 let right = f64::from_bits(next(&mut state));
698 assert_eq!(
699 double(left).compare(double(right)),
700 left.partial_cmp(&right),
701 "{left:e} against {right:e}"
702 );
703 }
704 }
705
706 #[test]
707 fn a_conversion_between_formats_rounds_the_way_the_host_does() {
708 let mut state = 0x0123_4567_89ab_cdefu64;
709 for _ in 0..20_000 {
710 let value = f64::from_bits(next(&mut state));
711 let narrowed = double(value).to_format(Format::Single);
712 let theirs = value as f32;
713 if theirs.is_nan() {
714 assert!(narrowed.0.is_nan(), "{value:e}");
715 continue;
716 }
717 assert_eq!(host_single(narrowed.0).to_bits(), theirs.to_bits(), "{value:e}");
718 let widened = narrowed.0.to_format(Format::Double);
720 assert_eq!(host(widened.0).to_bits(), f64::from(theirs).to_bits(), "{value:e}");
721 assert!(widened.1.is_none(), "{value:e}");
722 }
723 }
724
725 #[test]
726 fn a_narrowing_conversion_says_what_it_did() {
727 let (value, status) = double(0.1).to_format(Format::Single);
728 assert_eq!(host_single(value).to_bits(), (0.1f32).to_bits());
729 assert!(status.has(Status::INEXACT));
730 assert!(double(0.5).to_format(Format::Single).1.is_none());
731 let (value, status) = double(1e300).to_format(Format::Single);
732 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
733 let (value, status) = double(1e-300).to_format(Format::Single);
734 assert!(value.is_zero() && status.has(Status::UNDERFLOW));
735 let (up, status) = double(0.1).to_format(Format::X87Extended);
738 assert!(status.is_none());
739 assert_eq!(up.to_bits(), 0x3ffb_cccc_cccc_cccc_d000);
740 assert_eq!(host(up.to_format(Format::Double).0).to_bits(), (0.1f64).to_bits());
741 let tenth = Float::parse("0.1", Format::X87Extended).expect("a tenth").0;
744 assert_eq!(tenth.to_bits(), 0x3ffb_cccc_cccc_cccc_cccd);
745 assert_ne!(up.to_bits(), tenth.to_bits());
746 }
747
748 #[test]
749 fn an_integer_becomes_the_nearest_number_to_it() {
750 let mut state = 0xfeed_face_dead_c0dcu64;
751 for _ in 0..20_000 {
752 let value = next(&mut state) as i64;
753 let mine = Float::from_signed(i128::from(value), Format::Double).0;
754 assert_eq!(host(mine).to_bits(), (value as f64).to_bits(), "{value}");
755 let value = next(&mut state);
756 let mine = Float::from_unsigned(u128::from(value), Format::Single).0;
757 assert_eq!(host_single(mine).to_bits(), (value as f32).to_bits(), "{value}");
758 }
759 assert_eq!(host(Float::from_signed(0, Format::Double).0).to_bits(), (0f64).to_bits());
761 assert!(Float::from_signed(1 << 52, Format::Double).1.is_none());
762 assert!(Float::from_signed((1 << 53) + 1, Format::Double).1.has(Status::INEXACT));
763 let (value, status) = Float::from_signed(i128::MIN, Format::Double);
764 assert!(value.is_negative() && status.is_none());
765 assert_eq!(host(value), -(2f64).powi(127));
766 let (value, status) = Float::from_unsigned(u128::MAX, Format::Double);
767 assert!(status.has(Status::INEXACT));
768 assert_eq!(host(value), (2f64).powi(128));
769 }
770
771 #[test]
772 fn a_number_becomes_an_integer_by_dropping_its_fraction() {
773 for (value, expected) in [
774 (1.5, 1),
775 (-1.5, -1),
776 (0.9, 0),
777 (-0.9, 0),
778 (2.0, 2),
779 (-2.0, -2),
780 (1e18, 1_000_000_000_000_000_000),
781 ] {
782 assert_eq!(double(value).to_integer(64, true).0, expected, "{value}");
783 }
784 assert!(double(2.0).to_integer(64, true).1.is_none());
785 assert!(double(1.5).to_integer(64, true).1.has(Status::INEXACT));
786 assert_eq!(double(-0.5).to_integer(32, false), (0, Status::INEXACT));
788 let (value, status) = double(-1.0).to_integer(32, false);
789 assert!(value == 0 && status.has(Status::INVALID));
790 }
791
792 #[test]
793 fn a_number_that_will_not_fit_gives_the_end_of_the_range() {
794 let (value, status) = double(1e30).to_integer(32, true);
795 assert!(value == i128::from(i32::MAX) && status.has(Status::INVALID));
796 let (value, status) = double(-1e30).to_integer(32, true);
797 assert!(value == i128::from(i32::MIN) && status.has(Status::INVALID));
798 let (value, status) = double(1e30).to_integer(32, false);
799 assert!(value == i128::from(u32::MAX) && status.has(Status::INVALID));
800 let (value, status) = Float::infinity(Format::Double, false).to_integer(64, true);
801 assert!(value == i128::from(i64::MAX) && status.has(Status::INVALID));
802 let (value, status) = Float::nan(Format::Double).to_integer(64, true);
803 assert!(value == 0 && status.has(Status::INVALID));
804 let (value, status) = double(f64::MAX).to_integer(128, false);
806 assert!(value == -1 && status.has(Status::INVALID));
807 let smallest = double(-(2f64).powi(127));
809 assert_eq!(smallest.to_integer(128, true), (i128::MIN, Status::NONE));
810 }
811
812 #[test]
813 fn a_conversion_to_an_integer_is_the_one_the_host_does() {
814 let mut state = 0xabad_1dea_0000_0001u64;
817 for _ in 0..20_000 {
818 let value = f64::from_bits(next(&mut state));
819 assert_eq!(double(value).to_integer(64, true).0, i128::from(value as i64), "{value:e}");
820 assert_eq!(
821 double(value).to_integer(32, false).0,
822 i128::from(value as u32),
823 "{value:e}"
824 );
825 }
826 }
827
828 #[test]
829 fn the_wide_formats_compute_what_they_are_supposed_to() {
830 let quad = |text: &str| Float::parse(text, Format::Quad).expect("a number").0;
831 let (third, status) = quad("1").quotient(quad("3"));
835 assert_eq!(third.to_bits(), 0x3ffd_5555_5555_5555_5555_5555_5555_5555);
836 assert!(status.has(Status::INEXACT));
837 let (whole, status) = third.sum(third).0.sum(third);
839 assert_eq!(whole.to_bits(), quad("1").to_bits());
840 assert!(status.has(Status::INEXACT));
841
842 let x87 = |text: &str| Float::parse(text, Format::X87Extended).expect("a number").0;
845 let (sum, status) = x87("9007199254740993").sum(x87("1"));
846 assert!(status.is_none());
847 assert_eq!(sum.to_bits(), x87("9007199254740994").to_bits());
848
849 let half = |text: &str| Float::parse(text, Format::Half).expect("a number").0;
852 let (value, status) = half("2048").sum(half("1"));
853 assert!(status.has(Status::INEXACT));
854 assert_eq!(value.to_bits(), half("2048").to_bits());
855 }
856
857 #[test]
858 fn a_nan_survives_a_trip_through_its_encoding() {
859 for format in [
860 Format::Half,
861 Format::BFloat16,
862 Format::Single,
863 Format::Double,
864 Format::X87Extended,
865 Format::Quad,
866 ] {
867 let nan = Float::nan(format);
868 assert!(nan.is_nan() && !nan.is_finite() && !nan.is_infinite(), "{format:?}");
869 assert_eq!(Float::from_bits(format, nan.to_bits()), nan, "{format:?}");
870 assert_eq!(nan.negated().to_hex(), "-nan", "{format:?}");
871 let infinity = Float::infinity(format, false);
874 assert!(Float::from_bits(format, infinity.to_bits()).is_infinite(), "{format:?}");
875 }
876 assert_eq!(Float::nan(Format::Double).to_bits(), u128::from(f64::NAN.to_bits()));
878 assert!(Float::from_bits(Format::Double, u128::from(f64::NAN.to_bits())).is_nan());
879 }
880
881 #[test]
882 fn the_helpers_underneath_do_what_they_say() {
883 assert_eq!(wide_multiply(0, 12345), (0, 0));
884 assert_eq!(wide_multiply(3, 5), (0, 15));
885 assert_eq!(wide_multiply(1, u128::MAX), (0, u128::MAX));
886 assert_eq!(wide_multiply(u128::MAX, u128::MAX), (u128::MAX - 1, 1));
887 assert_eq!(wide_multiply(1 << 127, 1 << 127), (1 << 126, 0));
888 assert_eq!(long_divide(1 << 127, 1 << 127, 4), (16, 0));
890 assert_eq!(long_divide(3 << 126, 1 << 127, 4), (24, 0));
891 assert_eq!(long_divide(1 << 127, 3 << 126, 4), (10, 1 << 127));
892 }
893}