1use std::cmp::Ordering;
35
36use crate::float::{Category, Float, Format, Status, round};
37
38const GUARD: u32 = 3;
44
45impl Float {
46 #[must_use]
48 pub const fn nan(format: Format) -> Float {
49 Float { format, category: Category::Nan, sign: false, exponent: 0, significand: 0 }
50 }
51
52 #[must_use]
54 pub const fn is_nan(self) -> bool {
55 matches!(self.category, Category::Nan)
56 }
57
58 #[must_use]
60 pub const fn negated(self) -> Float {
61 Float { sign: !self.sign, ..self }
62 }
63
64 #[must_use]
66 pub const fn abs(self) -> Float {
67 Float { sign: false, ..self }
68 }
69
70 #[must_use]
82 pub fn sum(self, other: Float) -> (Float, Status) {
83 self.total(other, false)
84 }
85
86 #[must_use]
96 pub fn difference(self, other: Float) -> (Float, Status) {
97 self.total(other, true)
98 }
99
100 #[must_use]
109 pub fn product(self, other: Float) -> (Float, Status) {
110 let format = self.agreed_format(other);
111 let sign = self.sign != other.sign;
112 if let Some(nan) = Float::propagated_nan(self, other) {
113 return nan;
114 }
115 match (self.category, other.category) {
116 (Category::Infinite, Category::Zero) | (Category::Zero, Category::Infinite) => {
117 (Float::nan(format), Status::INVALID)
118 }
119 (Category::Infinite, _) | (_, Category::Infinite) => {
120 (Float::infinity(format, sign), Status::NONE)
121 }
122 (Category::Zero, _) | (_, Category::Zero) => (Float::zero(format, sign), Status::NONE),
123 _ => {
124 let (left, left_exponent) = self.parts();
125 let (right, right_exponent) = other.parts();
126 let (high, low) = wide_multiply(left, right);
127 let exponent = left_exponent + right_exponent;
128 if high == 0 {
129 return round(low, exponent, false, sign, format);
130 }
131 let drop = 128 - high.leading_zeros();
135 let sticky = low & ((1u128 << drop) - 1) != 0;
136 let significand = (high << (128 - drop)) | (low >> drop);
137 round(significand, exponent + drop as i32, sticky, sign, format)
138 }
139 }
140 }
141
142 #[must_use]
153 pub fn quotient(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::Infinite) | (Category::Zero, Category::Zero) => {
161 (Float::nan(format), Status::INVALID)
162 }
163 (Category::Infinite, _) => (Float::infinity(format, sign), Status::NONE),
164 (_, Category::Infinite) | (Category::Zero, _) => {
165 (Float::zero(format, sign), Status::NONE)
166 }
167 (_, Category::Zero) => (Float::infinity(format, sign), Status::DIVIDE_BY_ZERO),
168 _ => {
169 let (left, left_exponent) = self.parts();
174 let (right, right_exponent) = other.parts();
175 let (left_shift, right_shift) = (left.leading_zeros(), right.leading_zeros());
176 let extra = format.precision() + 2;
177 let numerator = left << left_shift;
178 let (quotient, remainder) = long_divide(numerator, right << right_shift, extra);
179 let exponent = (left_exponent - left_shift as i32)
180 - (right_exponent - right_shift as i32)
181 - extra as i32;
182 round(quotient, exponent, remainder != 0, sign, format)
183 }
184 }
185 }
186
187 #[must_use]
197 pub fn compare(self, other: Float) -> Option<Ordering> {
198 self.agreed_format(other);
199 if self.is_nan() || other.is_nan() {
200 return None;
201 }
202 if self.is_zero() && other.is_zero() {
203 return Some(Ordering::Equal);
204 }
205 if self.sign != other.sign {
206 return Some(if self.sign { Ordering::Less } else { Ordering::Greater });
207 }
208 let magnitudes = self.compare_magnitude(other);
209 Some(if self.sign { magnitudes.reverse() } else { magnitudes })
210 }
211
212 #[must_use]
218 pub fn to_format(self, format: Format) -> (Float, Status) {
219 match self.category {
220 Category::Nan => (Float { sign: self.sign, ..Float::nan(format) }, Status::NONE),
221 Category::Infinite => (Float::infinity(format, self.sign), Status::NONE),
222 Category::Zero => (Float::zero(format, self.sign), Status::NONE),
223 Category::Finite => {
224 let (significand, exponent) = self.parts();
225 round(significand, exponent, false, self.sign, format)
226 }
227 }
228 }
229
230 #[must_use]
232 pub fn from_signed(value: i128, format: Format) -> (Float, Status) {
233 if value == 0 {
234 return (Float::zero(format, false), Status::NONE);
235 }
236 round(value.unsigned_abs(), 0, false, value < 0, format)
237 }
238
239 #[must_use]
241 pub fn from_unsigned(value: u128, format: Format) -> (Float, Status) {
242 if value == 0 {
243 return (Float::zero(format, false), Status::NONE);
244 }
245 round(value, 0, false, false, format)
246 }
247
248 #[must_use]
264 pub fn to_integer(self, width: u32, signed: bool) -> (i128, Status) {
265 assert!(width > 0 && width <= 128, "an integer type of {width} bits");
266 let limit = self.limit(width, signed);
267 match self.category {
268 Category::Nan => (0, Status::INVALID),
269 Category::Infinite => (self.signed_value(limit), Status::INVALID),
270 Category::Zero => (0, Status::NONE),
271 Category::Finite => {
272 let (significand, exponent) = self.parts();
273 let (magnitude, inexact) = if exponent >= 0 {
274 if exponent > significand.leading_zeros() as i32 {
275 return (self.signed_value(limit), Status::INVALID);
276 }
277 (significand << exponent, false)
278 } else if -exponent >= 128 {
279 (0, true)
280 } else {
281 let dropped = -exponent as u32;
282 (significand >> dropped, significand & ((1u128 << dropped) - 1) != 0)
283 };
284 if magnitude > limit {
285 return (self.signed_value(limit), Status::INVALID);
286 }
287 let status = if inexact { Status::INEXACT } else { Status::NONE };
288 (self.signed_value(magnitude), status)
289 }
290 }
291 }
292
293 fn limit(self, width: u32, signed: bool) -> u128 {
295 match (signed, self.sign) {
296 (true, true) => 1u128 << (width - 1),
297 (true, false) => (1u128 << (width - 1)) - 1,
298 (false, true) => 0,
301 (false, false) => u128::MAX >> (128 - width),
302 }
303 }
304
305 fn signed_value(self, magnitude: u128) -> i128 {
307 if self.sign { (magnitude as i128).wrapping_neg() } else { magnitude as i128 }
308 }
309
310 fn parts(self) -> (u128, i32) {
313 (self.significand, self.exponent - self.format.precision() as i32 + 1)
314 }
315
316 fn agreed_format(self, other: Float) -> Format {
324 assert_eq!(self.format, other.format, "an operation on two floating formats at once");
325 self.format
326 }
327
328 fn propagated_nan(left: Float, right: Float) -> Option<(Float, Status)> {
330 (left.is_nan() || right.is_nan()).then(|| (Float::nan(left.format), Status::NONE))
331 }
332
333 fn compare_magnitude(self, other: Float) -> Ordering {
339 match (self.category, other.category) {
340 (Category::Zero, Category::Zero) | (Category::Infinite, Category::Infinite) => {
341 Ordering::Equal
342 }
343 (Category::Zero, _) | (_, Category::Infinite) => Ordering::Less,
344 (Category::Infinite, _) | (_, Category::Zero) => Ordering::Greater,
345 _ => (self.exponent, self.significand).cmp(&(other.exponent, other.significand)),
346 }
347 }
348
349 fn total(self, other: Float, subtract: bool) -> (Float, Status) {
352 let format = self.agreed_format(other);
353 let other = if subtract { other.negated() } else { other };
354 if let Some(nan) = Float::propagated_nan(self, other) {
355 return nan;
356 }
357 match (self.category, other.category) {
358 (Category::Infinite, Category::Infinite) => {
359 if self.sign == other.sign {
360 (self, Status::NONE)
361 } else {
362 (Float::nan(format), Status::INVALID)
363 }
364 }
365 (Category::Infinite, _) => (self, Status::NONE),
366 (_, Category::Infinite) => (other, Status::NONE),
367 (Category::Zero, Category::Zero) => {
370 (Float::zero(format, self.sign && other.sign), Status::NONE)
371 }
372 (Category::Zero, _) => (other, Status::NONE),
373 (_, Category::Zero) => (self, Status::NONE),
374 _ => {
375 let (big, small) = if self.compare_magnitude(other) == Ordering::Less {
376 (other, self)
377 } else {
378 (self, other)
379 };
380 let (left, exponent) = big.parts();
381 let (right, small_exponent) = small.parts();
382 let distance = (exponent - small_exponent) as u32;
383 let left = left << GUARD;
384 let (mut right, sticky) = if distance <= GUARD {
385 (right << (GUARD - distance), false)
386 } else if distance - GUARD >= 128 {
387 (0, true)
388 } else {
389 let dropped = distance - GUARD;
390 (right >> dropped, right & ((1u128 << dropped) - 1) != 0)
391 };
392 let exponent = exponent - GUARD as i32;
393 if big.sign == small.sign {
394 return round(left + right, exponent, sticky, big.sign, format);
395 }
396 right += u128::from(sticky);
403 if left == right {
404 return (Float::zero(format, false), Status::NONE);
405 }
406 round(left - right, exponent, sticky, big.sign, format)
407 }
408 }
409 }
410}
411
412fn wide_multiply(left: u128, right: u128) -> (u128, u128) {
418 const LOW: u128 = u64::MAX as u128;
419 let (left_low, left_high) = (left & LOW, left >> 64);
420 let (right_low, right_high) = (right & LOW, right >> 64);
421 let low = left_low * right_low;
422 let first = left_low * right_high;
423 let second = left_high * right_low;
424 let middle = (low >> 64) + (first & LOW) + (second & LOW);
425 let high = left_high * right_high + (first >> 64) + (second >> 64) + (middle >> 64);
426 (high, (middle << 64) | (low & LOW))
427}
428
429fn long_divide(numerator: u128, divisor: u128, extra: u32) -> (u128, u128) {
435 let mut remainder = 0u128;
436 let mut quotient = 0u128;
437 for step in 0..128 + extra {
438 let bit = if step < 128 { (numerator >> (127 - step)) & 1 } else { 0 };
439 let carry = remainder >> 127 == 1;
442 remainder = (remainder << 1) | bit;
443 quotient <<= 1;
444 if carry || remainder >= divisor {
445 remainder = remainder.wrapping_sub(divisor);
446 quotient |= 1;
447 }
448 }
449 (quotient, remainder)
450}
451
452#[cfg(test)]
453mod tests {
454 use super::*;
455
456 fn double(value: f64) -> Float {
458 Float::from_bits(Format::Double, u128::from(value.to_bits()))
459 }
460
461 fn host(value: Float) -> f64 {
463 f64::from_bits(value.to_bits() as u64)
464 }
465
466 fn single(value: f32) -> Float {
467 Float::from_bits(Format::Single, u128::from(value.to_bits()))
468 }
469
470 fn host_single(value: Float) -> f32 {
471 f32::from_bits(value.to_bits() as u32)
472 }
473
474 fn next(state: &mut u64) -> u64 {
476 *state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
477 *state
478 }
479
480 fn agrees(left: f64, right: f64) {
482 let (a, b) = (double(left), double(right));
483 for (name, mine, theirs) in [
484 ("+", a.sum(b).0, left + right),
485 ("-", a.difference(b).0, left - right),
486 ("*", a.product(b).0, left * right),
487 ("/", a.quotient(b).0, left / right),
488 ] {
489 if theirs.is_nan() {
490 assert!(mine.is_nan(), "{left:e} {name} {right:e} gave {}", host(mine));
491 } else {
492 assert_eq!(
493 host(mine).to_bits(),
494 theirs.to_bits(),
495 "{left:e} {name} {right:e} gave {} not {theirs:e}",
496 host(mine)
497 );
498 }
499 }
500 }
501
502 fn agrees_single(left: f32, right: f32) {
504 let (a, b) = (single(left), single(right));
505 for (name, mine, theirs) in [
506 ("+", a.sum(b).0, left + right),
507 ("-", a.difference(b).0, left - right),
508 ("*", a.product(b).0, left * right),
509 ("/", a.quotient(b).0, left / right),
510 ] {
511 if theirs.is_nan() {
512 assert!(mine.is_nan(), "{left:e} {name} {right:e}");
513 } else {
514 assert_eq!(
515 host_single(mine).to_bits(),
516 theirs.to_bits(),
517 "{left:e} {name} {right:e} gave {} not {theirs:e}",
518 host_single(mine)
519 );
520 }
521 }
522 }
523
524 #[test]
525 fn the_ordinary_sums_are_the_ones_the_host_computes() {
526 for (left, right) in [
527 (1.0, 1.0),
528 (1.0, 2.0),
529 (0.1, 0.2),
530 (1.0, -1.0),
531 (1e308, 1e308),
532 (1.0, 1e-308),
533 (3.0, 7.0),
534 (1.0, 3.0),
535 (2.5, 0.5),
536 (1e-320, 1e-320),
537 (f64::MAX, f64::MIN),
538 ] {
539 agrees(left, right);
540 agrees(right, left);
541 agrees(-left, right);
542 agrees(left, -right);
543 }
544 }
545
546 #[test]
547 fn a_sweep_of_random_doubles_agrees_with_the_host_in_every_bit() {
548 let mut state = 0x2545_f491_4f6c_dd1du64;
551 for _ in 0..20_000 {
552 agrees(f64::from_bits(next(&mut state)), f64::from_bits(next(&mut state)));
553 }
554 }
555
556 #[test]
557 fn a_sweep_of_random_floats_agrees_with_the_host_in_every_bit() {
558 let mut state = 0x1234_5678_9abc_def0u64;
559 for _ in 0..20_000 {
560 let bits = next(&mut state);
561 agrees_single(f32::from_bits(bits as u32), f32::from_bits((bits >> 32) as u32));
562 }
563 }
564
565 #[test]
566 fn a_sweep_of_numbers_close_together_agrees_too() {
567 let mut state = 0x9e37_79b9_7f4a_7c15u64;
570 for _ in 0..20_000 {
571 let left = (next(&mut state) >> 11) as f64;
572 let scale = f64::from(next(&mut state) as u32 % 8) - 4.0;
573 let right = (next(&mut state) >> 11) as f64 * scale.exp2();
574 agrees(left, right);
575 agrees(left, left);
576 agrees(left, -left);
577 }
578 }
579
580 #[test]
581 fn the_operations_with_no_answer_say_so() {
582 let (infinity, zero) = (Float::infinity(Format::Double, false), double(0.0));
583 let (one, nan) = (double(1.0), Float::nan(Format::Double));
584
585 let (value, status) = infinity.difference(infinity);
586 assert!(value.is_nan() && status.has(Status::INVALID));
587 let (value, status) = infinity.product(zero);
588 assert!(value.is_nan() && status.has(Status::INVALID));
589 let (value, status) = zero.quotient(zero);
590 assert!(value.is_nan() && status.has(Status::INVALID));
591 let (value, status) = infinity.quotient(infinity);
592 assert!(value.is_nan() && status.has(Status::INVALID));
593
594 let (value, status) = one.quotient(zero);
596 assert!(value.is_infinite() && !value.is_negative());
597 assert!(status.has(Status::DIVIDE_BY_ZERO) && !status.has(Status::INVALID));
598 assert!(one.negated().quotient(zero).0.is_negative());
599 assert!(one.quotient(zero.negated()).0.is_negative());
600
601 for (value, status) in
603 [nan.sum(one), one.sum(nan), nan.product(one), nan.quotient(one), one.difference(nan)]
604 {
605 assert!(value.is_nan() && status.is_none());
606 }
607 assert!(infinity.sum(infinity).0.is_infinite());
608 assert!(infinity.sum(one).0.is_infinite());
609 }
610
611 #[test]
612 fn the_sign_of_a_zero_is_the_one_the_host_gives() {
613 let (positive, negative) = (double(0.0), double(-0.0));
614 for (mine, theirs) in [
615 (positive.sum(positive), 0.0 + 0.0),
616 (positive.sum(negative), 0.0 + -0.0),
617 (negative.sum(positive), -0.0 + 0.0),
618 (negative.sum(negative), -0.0 + -0.0),
619 (positive.difference(positive), 0.0 - 0.0),
620 (negative.difference(positive), -0.0 - 0.0),
621 (double(1.0).difference(double(1.0)), 1.0 - 1.0),
622 (double(-1.0).sum(double(1.0)), -1.0 + 1.0),
623 (positive.product(double(3.0)), 0.0 * 3.0),
624 (negative.product(double(3.0)), -0.0 * 3.0),
625 (positive.quotient(double(-3.0)), 0.0 / -3.0),
626 ] {
627 assert_eq!(host(mine.0).to_bits(), f64::to_bits(theirs), "{theirs}");
628 }
629 }
630
631 #[test]
632 fn an_operation_says_what_it_had_to_do_to_the_answer() {
633 let (one, three) = (double(1.0), double(3.0));
634 assert!(one.sum(one).1.is_none());
635 assert!(one.product(three).1.is_none());
636 assert!(one.quotient(double(2.0)).1.is_none());
637 assert!(one.quotient(three).1.has(Status::INEXACT));
638
639 let (value, status) = double(f64::MAX).product(double(2.0));
640 assert!(value.is_infinite() && status.has(Status::OVERFLOW) && status.has(Status::INEXACT));
641 let (value, status) = double(f64::MIN_POSITIVE).quotient(double(1e300));
642 assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
643 let four = Float::from_bits(Format::Double, 4);
645 assert!(four.quotient(double(2.0)).1.is_none());
646 assert!(four.quotient(double(4.0)).1.is_none());
647 let status = Float::from_bits(Format::Double, 3).quotient(double(2.0)).1;
649 assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
650 }
651
652 #[test]
653 fn a_comparison_orders_the_numbers_and_leaves_the_nans_out() {
654 let (one, two) = (double(1.0), double(2.0));
655 assert_eq!(one.compare(two), Some(Ordering::Less));
656 assert_eq!(two.compare(one), Some(Ordering::Greater));
657 assert_eq!(one.compare(one), Some(Ordering::Equal));
658 assert_eq!(one.negated().compare(two.negated()), Some(Ordering::Greater));
659 assert_eq!(one.negated().compare(one), Some(Ordering::Less));
660 assert_eq!(double(0.0).compare(double(-0.0)), Some(Ordering::Equal));
662 assert_eq!(double(-0.0).compare(double(0.0)), Some(Ordering::Equal));
663 assert_eq!(double(-0.0).compare(one), Some(Ordering::Less));
664 let infinity = Float::infinity(Format::Double, false);
666 assert_eq!(infinity.compare(double(f64::MAX)), Some(Ordering::Greater));
667 assert_eq!(infinity.negated().compare(double(f64::MIN)), Some(Ordering::Less));
668 assert_eq!(infinity.compare(infinity), Some(Ordering::Equal));
669 let nan = Float::nan(Format::Double);
670 assert_eq!(nan.compare(one), None);
671 assert_eq!(one.compare(nan), None);
672 assert_eq!(nan.compare(nan), None);
673 }
674
675 #[test]
676 fn a_comparison_of_random_numbers_is_the_host_order() {
677 let mut state = 0xdead_beef_cafe_f00du64;
678 for _ in 0..20_000 {
679 let left = f64::from_bits(next(&mut state));
680 let right = f64::from_bits(next(&mut state));
681 assert_eq!(
682 double(left).compare(double(right)),
683 left.partial_cmp(&right),
684 "{left:e} against {right:e}"
685 );
686 }
687 }
688
689 #[test]
690 fn a_conversion_between_formats_rounds_the_way_the_host_does() {
691 let mut state = 0x0123_4567_89ab_cdefu64;
692 for _ in 0..20_000 {
693 let value = f64::from_bits(next(&mut state));
694 let narrowed = double(value).to_format(Format::Single);
695 let theirs = value as f32;
696 if theirs.is_nan() {
697 assert!(narrowed.0.is_nan(), "{value:e}");
698 continue;
699 }
700 assert_eq!(host_single(narrowed.0).to_bits(), theirs.to_bits(), "{value:e}");
701 let widened = narrowed.0.to_format(Format::Double);
703 assert_eq!(host(widened.0).to_bits(), f64::from(theirs).to_bits(), "{value:e}");
704 assert!(widened.1.is_none(), "{value:e}");
705 }
706 }
707
708 #[test]
709 fn a_narrowing_conversion_says_what_it_did() {
710 let (value, status) = double(0.1).to_format(Format::Single);
711 assert_eq!(host_single(value).to_bits(), (0.1f32).to_bits());
712 assert!(status.has(Status::INEXACT));
713 assert!(double(0.5).to_format(Format::Single).1.is_none());
714 let (value, status) = double(1e300).to_format(Format::Single);
715 assert!(value.is_infinite() && status.has(Status::OVERFLOW));
716 let (value, status) = double(1e-300).to_format(Format::Single);
717 assert!(value.is_zero() && status.has(Status::UNDERFLOW));
718 let (up, status) = double(0.1).to_format(Format::X87Extended);
721 assert!(status.is_none());
722 assert_eq!(up.to_bits(), 0x3ffb_cccc_cccc_cccc_d000);
723 assert_eq!(host(up.to_format(Format::Double).0).to_bits(), (0.1f64).to_bits());
724 let tenth = Float::parse("0.1", Format::X87Extended).expect("a tenth").0;
727 assert_eq!(tenth.to_bits(), 0x3ffb_cccc_cccc_cccc_cccd);
728 assert_ne!(up.to_bits(), tenth.to_bits());
729 }
730
731 #[test]
732 fn an_integer_becomes_the_nearest_number_to_it() {
733 let mut state = 0xfeed_face_dead_c0dcu64;
734 for _ in 0..20_000 {
735 let value = next(&mut state) as i64;
736 let mine = Float::from_signed(i128::from(value), Format::Double).0;
737 assert_eq!(host(mine).to_bits(), (value as f64).to_bits(), "{value}");
738 let value = next(&mut state);
739 let mine = Float::from_unsigned(u128::from(value), Format::Single).0;
740 assert_eq!(host_single(mine).to_bits(), (value as f32).to_bits(), "{value}");
741 }
742 assert_eq!(host(Float::from_signed(0, Format::Double).0).to_bits(), (0f64).to_bits());
744 assert!(Float::from_signed(1 << 52, Format::Double).1.is_none());
745 assert!(Float::from_signed((1 << 53) + 1, Format::Double).1.has(Status::INEXACT));
746 let (value, status) = Float::from_signed(i128::MIN, Format::Double);
747 assert!(value.is_negative() && status.is_none());
748 assert_eq!(host(value), -(2f64).powi(127));
749 let (value, status) = Float::from_unsigned(u128::MAX, Format::Double);
750 assert!(status.has(Status::INEXACT));
751 assert_eq!(host(value), (2f64).powi(128));
752 }
753
754 #[test]
755 fn a_number_becomes_an_integer_by_dropping_its_fraction() {
756 for (value, expected) in [
757 (1.5, 1),
758 (-1.5, -1),
759 (0.9, 0),
760 (-0.9, 0),
761 (2.0, 2),
762 (-2.0, -2),
763 (1e18, 1_000_000_000_000_000_000),
764 ] {
765 assert_eq!(double(value).to_integer(64, true).0, expected, "{value}");
766 }
767 assert!(double(2.0).to_integer(64, true).1.is_none());
768 assert!(double(1.5).to_integer(64, true).1.has(Status::INEXACT));
769 assert_eq!(double(-0.5).to_integer(32, false), (0, Status::INEXACT));
771 let (value, status) = double(-1.0).to_integer(32, false);
772 assert!(value == 0 && status.has(Status::INVALID));
773 }
774
775 #[test]
776 fn a_number_that_will_not_fit_gives_the_end_of_the_range() {
777 let (value, status) = double(1e30).to_integer(32, true);
778 assert!(value == i128::from(i32::MAX) && status.has(Status::INVALID));
779 let (value, status) = double(-1e30).to_integer(32, true);
780 assert!(value == i128::from(i32::MIN) && status.has(Status::INVALID));
781 let (value, status) = double(1e30).to_integer(32, false);
782 assert!(value == i128::from(u32::MAX) && status.has(Status::INVALID));
783 let (value, status) = Float::infinity(Format::Double, false).to_integer(64, true);
784 assert!(value == i128::from(i64::MAX) && status.has(Status::INVALID));
785 let (value, status) = Float::nan(Format::Double).to_integer(64, true);
786 assert!(value == 0 && status.has(Status::INVALID));
787 let (value, status) = double(f64::MAX).to_integer(128, false);
789 assert!(value == -1 && status.has(Status::INVALID));
790 let smallest = double(-(2f64).powi(127));
792 assert_eq!(smallest.to_integer(128, true), (i128::MIN, Status::NONE));
793 }
794
795 #[test]
796 fn a_conversion_to_an_integer_is_the_one_the_host_does() {
797 let mut state = 0xabad_1dea_0000_0001u64;
800 for _ in 0..20_000 {
801 let value = f64::from_bits(next(&mut state));
802 assert_eq!(double(value).to_integer(64, true).0, i128::from(value as i64), "{value:e}");
803 assert_eq!(
804 double(value).to_integer(32, false).0,
805 i128::from(value as u32),
806 "{value:e}"
807 );
808 }
809 }
810
811 #[test]
812 fn the_wide_formats_compute_what_they_are_supposed_to() {
813 let quad = |text: &str| Float::parse(text, Format::Quad).expect("a number").0;
814 let (third, status) = quad("1").quotient(quad("3"));
818 assert_eq!(third.to_bits(), 0x3ffd_5555_5555_5555_5555_5555_5555_5555);
819 assert!(status.has(Status::INEXACT));
820 let (whole, status) = third.sum(third).0.sum(third);
822 assert_eq!(whole.to_bits(), quad("1").to_bits());
823 assert!(status.has(Status::INEXACT));
824
825 let x87 = |text: &str| Float::parse(text, Format::X87Extended).expect("a number").0;
828 let (sum, status) = x87("9007199254740993").sum(x87("1"));
829 assert!(status.is_none());
830 assert_eq!(sum.to_bits(), x87("9007199254740994").to_bits());
831
832 let half = |text: &str| Float::parse(text, Format::Half).expect("a number").0;
835 let (value, status) = half("2048").sum(half("1"));
836 assert!(status.has(Status::INEXACT));
837 assert_eq!(value.to_bits(), half("2048").to_bits());
838 }
839
840 #[test]
841 fn a_nan_survives_a_trip_through_its_encoding() {
842 for format in [
843 Format::Half,
844 Format::BFloat16,
845 Format::Single,
846 Format::Double,
847 Format::X87Extended,
848 Format::Quad,
849 ] {
850 let nan = Float::nan(format);
851 assert!(nan.is_nan() && !nan.is_finite() && !nan.is_infinite(), "{format:?}");
852 assert_eq!(Float::from_bits(format, nan.to_bits()), nan, "{format:?}");
853 assert_eq!(nan.negated().to_hex(), "-nan", "{format:?}");
854 let infinity = Float::infinity(format, false);
857 assert!(Float::from_bits(format, infinity.to_bits()).is_infinite(), "{format:?}");
858 }
859 assert_eq!(Float::nan(Format::Double).to_bits(), u128::from(f64::NAN.to_bits()));
861 assert!(Float::from_bits(Format::Double, u128::from(f64::NAN.to_bits())).is_nan());
862 }
863
864 #[test]
865 fn the_helpers_underneath_do_what_they_say() {
866 assert_eq!(wide_multiply(0, 12345), (0, 0));
867 assert_eq!(wide_multiply(3, 5), (0, 15));
868 assert_eq!(wide_multiply(1, u128::MAX), (0, u128::MAX));
869 assert_eq!(wide_multiply(u128::MAX, u128::MAX), (u128::MAX - 1, 1));
870 assert_eq!(wide_multiply(1 << 127, 1 << 127), (1 << 126, 0));
871 assert_eq!(long_divide(1 << 127, 1 << 127, 4), (16, 0));
873 assert_eq!(long_divide(3 << 126, 1 << 127, 4), (24, 0));
874 assert_eq!(long_divide(1 << 127, 3 << 126, 4), (10, 1 << 127));
875 }
876}