Skip to main content

rucc_base/float/
arith.rs

1//! Arithmetic on [`Float`], correctly rounded, in integer operations only.
2//!
3//! The constant evaluator folds `1.0 / 3.0` at translation time and the program it compiles
4//! computes the same thing at run time, and the two have to agree in the last bit. Asking the
5//! host to do the arithmetic gets that wrong in three separate ways: the host may not have the
6//! format at all, its `long double` is not the target's, and a compiler that folds one way on one
7//! machine and another way on another is a compiler whose output depends on where it ran.
8//!
9//! So the operations are here, on integers, rounded to nearest with ties to even. Each one
10//! computes the exact answer to more bits than the format has and rounds once, which is what
11//! makes it correctly rounded: the answer is the representable number nearest the exact result.
12//! Every operation below either fits that exact result in a [`u128`] or keeps a sticky bit saying
13//! that something nonzero was dropped below the bits it kept, which is all the rounding needs to
14//! know about what it cannot see.
15//!
16//! # Naming
17//!
18//! An operation returns a number and a [`Status`], because the caller has to be able to warn that
19//! a constant overflowed or that a fold was inexact, so these cannot be the `std::ops` traits and
20//! are named for what they return rather than for what they do. [`Float`] deliberately implements
21//! no arithmetic trait at all: an operator with a discarded status is exactly the kind of quiet
22//! wrongness this module exists to prevent.
23//!
24//! # What is not here
25//!
26//! A rounding mode other than to nearest. C's `#pragma STDC FENV_ACCESS` and the dynamic rounding
27//! modes change what the running program does rather than what a translation time constant means,
28//! and a constant is folded to nearest whatever the mode is.
29//!
30//! A nan payload out of an operation. [`Float`] carries one, since `__builtin_nan` can spell one
31//! and a static initializer written with it has to keep it, but every nan produced here is the
32//! default quiet one. Propagating a payload would mean deciding which of two operands wins, which
33//! IEEE 754 leaves to the implementation and which no C program can see.
34
35use std::cmp::Ordering;
36
37use crate::float::{Category, Float, Format, Status, round};
38
39/// How many bits are kept below the significand while two numbers are lined up for an addition.
40///
41/// Two of them are the guard and round bits an addition needs in order to round correctly, and
42/// the third is where the sticky bit lands, so anything shifted past all three is nonzero or it
43/// is nothing, which is the one fact the rounding needs about it.
44const GUARD: u32 = 3;
45
46impl Float {
47    /// A quiet nan, which is what an operation with no answer gives.
48    ///
49    /// The default one, whose payload is nothing. [`Float::nan_with`] is where a payload comes
50    /// from, and there is only one thing in C that can spell one.
51    #[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    /// Whether the number is a nan.
63    #[must_use]
64    pub const fn is_nan(self) -> bool {
65        matches!(self.category, Category::Nan)
66    }
67
68    /// The number with its sign flipped, which is exact and which a zero and a nan both have.
69    #[must_use]
70    pub const fn negated(self) -> Float {
71        Float { sign: !self.sign, ..self }
72    }
73
74    /// The number without its sign, which is exact.
75    #[must_use]
76    pub const fn abs(self) -> Float {
77        Float { sign: false, ..self }
78    }
79
80    /// The number with the sign given, which is exact and which is what `copysign` answers. Every
81    /// value has a sign to be set, a zero and a nan as much as a number.
82    #[must_use]
83    pub const fn with_sign(self, sign: bool) -> Float {
84        Float { sign, ..self }
85    }
86
87    /// `self + other`, rounded to nearest with ties to even.
88    ///
89    /// A nan operand gives a nan and nothing else. Two infinities of opposite sign give a nan and
90    /// [`Status::INVALID`], because the answer depends on how they got there. Two zeros give a
91    /// negative zero only when both of them are negative, which is the round to nearest rule and
92    /// the reason `x + 0.0` is not a way to drop a sign.
93    ///
94    /// # Panics
95    ///
96    /// If the two numbers are not in the same format. The usual arithmetic conversions have
97    /// already made them so, and converting here would be a conversion nobody asked for.
98    #[must_use]
99    pub fn sum(self, other: Float) -> (Float, Status) {
100        self.total(other, false)
101    }
102
103    /// `self - other`, rounded to nearest with ties to even.
104    ///
105    /// This is the sum of `self` and the negation of `other`, which is exactly what it is in IEEE
106    /// 754, so a subtraction that cancels completely gives a positive zero and an infinity minus
107    /// itself gives a nan.
108    ///
109    /// # Panics
110    ///
111    /// If the two numbers are not in the same format.
112    #[must_use]
113    pub fn difference(self, other: Float) -> (Float, Status) {
114        self.total(other, true)
115    }
116
117    /// `self * other`, rounded to nearest with ties to even.
118    ///
119    /// A zero times an infinity gives a nan and [`Status::INVALID`]. The sign is the two signs
120    /// multiplied, which a zero and a nan have as much as any other number does.
121    ///
122    /// # Panics
123    ///
124    /// If the two numbers are not in the same format.
125    #[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                // Two significands of at most a hundred and thirteen bits make a product of at
149                // most two hundred and twenty six, so the count below is between one and ninety
150                // eight and every shift here has somewhere to go.
151                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    /// `self / other`, rounded to nearest with ties to even.
160    ///
161    /// A finite number divided by zero gives an infinity and [`Status::DIVIDE_BY_ZERO`]. Zero
162    /// divided by zero and an infinity divided by an infinity both give a nan and
163    /// [`Status::INVALID`], which is the difference between a division that has no answer and one
164    /// whose answer is only too large to be a number.
165    ///
166    /// # Panics
167    ///
168    /// If the two numbers are not in the same format.
169    #[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                // Both significands are shifted up until their leading bit is the top bit of a
187                // `u128`, which puts their quotient between a half and two and so puts its
188                // leading bit in a known place. The quotient is then taken to two bits more than
189                // the format has, and whatever is left over is the sticky bit.
190                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    /// How the two compare, or [`None`] if either is a nan and they do not compare at all.
205    ///
206    /// This is the comparison C's relational operators do, so a positive zero and a negative zero
207    /// are equal and the unordered case is the one that makes `x < y` and `!(x >= y)` different
208    /// questions.
209    ///
210    /// # Panics
211    ///
212    /// If the two numbers are not in the same format.
213    #[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    /// The nearest number to this one in another format, rounded to nearest with ties to even.
230    ///
231    /// Widening is exact for every pair of formats here except a `__bf16` widened to a
232    /// `_Float16`, which has more precision and less range. Narrowing is what a cast does, and it
233    /// reports what it had to do to make the number fit.
234    #[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    /// The nearest number in `format` to a signed integer.
248    #[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    /// The nearest number in `format` to an unsigned integer.
257    #[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    /// The number truncated toward zero into an integer of `width` bits.
266    ///
267    /// What comes back is what an integer constant is stored as, which is the value sign extended
268    /// out of the type it has, so an unsigned conversion of a hundred and twenty eight bits comes
269    /// back with its top bit in the sign of the [`i128`].
270    ///
271    /// Converting a number that does not fit is undefined behaviour in C rather than a value, so
272    /// what comes back is the nearest end of the range together with [`Status::INVALID`], which
273    /// is what the caller warns about. A nan comes back as zero, for the same reason and with the
274    /// same flag. Dropping a fraction is [`Status::INEXACT`] and nothing worse, since that is the
275    /// conversion doing what it is for.
276    ///
277    /// # Panics
278    ///
279    /// If `width` is zero or wider than a hundred and twenty eight bits.
280    #[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    /// The largest magnitude an integer of this type can hold with this number's sign.
311    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            // An unsigned type has nowhere for a negative number to go, but truncating one whose
316            // magnitude is below one lands on zero, which is in range and is not an error.
317            (false, true) => 0,
318            (false, false) => u128::MAX >> (128 - width),
319        }
320    }
321
322    /// A magnitude given this number's sign, as an integer constant is stored.
323    fn signed_value(self, magnitude: u128) -> i128 {
324        if self.sign { (magnitude as i128).wrapping_neg() } else { magnitude as i128 }
325    }
326
327    /// The significand and the power of two it is scaled by, so that the value of a finite number
328    /// is the first of these shifted by the second.
329    fn parts(self) -> (u128, i32) {
330        (self.significand, self.exponent - self.format.precision() as i32 + 1)
331    }
332
333    /// The format both numbers are in.
334    ///
335    /// # Panics
336    ///
337    /// If they are not in the same one. Every operation here is on two numbers of one type,
338    /// because the usual arithmetic conversions ran first, and converting one here instead would
339    /// silently round an operand on the way in.
340    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    /// The nan an operation gives when an operand is one, if either is.
346    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    /// How the magnitudes of two numbers in the same format compare, nans aside.
351    ///
352    /// Comparing the exponent before the significand works across the subnormals as well as the
353    /// normals, because a subnormal has the smallest exponent there is and a leading zero where a
354    /// normal number has its leading one.
355    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    /// The sum of two numbers, or their difference, which is the sum of one of them and the other
367    /// negated and is not a separate operation anywhere below this line.
368    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            // Round to nearest makes the sum of two zeros positive unless both of them were
385            // negative, which is the one rule here that is about the sign rather than the value.
386            (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                // What was dropped belongs to the number being taken away, so the answer is a
414                // little below what the bits that are left say it is. Taking one more off, with
415                // the sticky bit set, says exactly that: the answer is between the two, which is
416                // all the rounding needs. It cannot go below zero, because the two are ordered by
417                // magnitude and a dropped bit means the smaller one is smaller by more than the
418                // last bit of the larger.
419                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
429/// The full two hundred and fifty six bit product of two numbers, high half first.
430///
431/// The halves of each operand multiply into products that fit, and the middle column is the one
432/// that has to be carried by hand. There is no `u256` and no widening multiply in the language,
433/// so this is what multiplying two significands looks like.
434fn 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
446/// The quotient of `numerator` shifted up by `extra` bits and `divisor`, and what is left over.
447///
448/// Both arguments have their top bit set, so their quotient is between a half and two and the
449/// answer here has either `extra` or `extra` plus one bits. Restoring division a bit at a time,
450/// because the alternatives are a longer program and this runs once per constant folded.
451fn 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        // The remainder is below the divisor, so doubling it can carry out of the top of a `u128`
457        // and still be a number the divisor goes into exactly once.
458        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    /// A `double` from the host's bits, which is what makes the host an oracle.
474    fn double(value: f64) -> Float {
475        Float::from_bits(Format::Double, u128::from(value.to_bits()))
476    }
477
478    /// The host number a `double` holds.
479    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    /// A fixed sequence, so that a failure names the same numbers on every machine.
492    fn next(state: &mut u64) -> u64 {
493        *state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
494        *state
495    }
496
497    /// Every operation on a pair of `double` values, against what the host computes.
498    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    /// The same, for a pair of `float` values.
520    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        // Random bits cover the infinities, the nans and the subnormals as well as the ordinary
566        // numbers, which is the point of taking bits rather than taking values.
567        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        // Two numbers of nearly the same size are where a subtraction cancels and where the bits
585        // that are left come from the guard bits rather than from either operand.
586        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        // A division by zero has an answer, which is why it is not the same flag.
612        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        // A nan on the way in is a nan on the way out, and nothing is reported for it.
619        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        // A subnormal answer that lost no bits is exact, small as it is.
661        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        // One that lost a bit is inexact and underflowed, both.
665        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        // The two zeros are the same number as far as a comparison is concerned.
678        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        // An infinity is at the end of the order, and a nan is not in the order at all.
682        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            // Widening is exact, so the number that comes back is the one that went in.
719            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        // The x87 format has more bits than a `double`, so a number goes up into it exactly and
736        // comes back down as the number it started as.
737        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        // Widening keeps the error the number already had rather than removing it: a tenth that
742        // went through a `double` is not the tenth an x87 number can hold.
743        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        // The ends of the two widest integer types, which are where the rounding shows.
760        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        // Truncation toward zero lands inside an unsigned type, and anything below it does not.
787        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        // The widest unsigned type has its top bit where the sign of the value holding it is.
805        let (value, status) = double(f64::MAX).to_integer(128, false);
806        assert!(value == -1 && status.has(Status::INVALID));
807        // The widest signed one holds its own smallest number exactly.
808        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        // Rust's own conversion saturates and turns a nan into zero, which is what C leaves
815        // undefined and what this fills it in with, so the host answers for this too.
816        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        // A third in binary128 is the exact quotient rounded down, since the digits repeat and
832        // the first one dropped is below a half. Worked out by hand rather than measured, because
833        // no host here has the format.
834        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        // Three of them is one exactly, because the sum is a tie and the tie rounds up.
838        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        // The x87 format has sixty four bits of significand, so this is exact where a `double`
843        // would have to round it.
844        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        // Half precision has eleven, so 2049 is a tie between the two numbers either side of it
850        // and rounds to the even one below.
851        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            // An infinity is not a nan, in the format that stores the bit above the fraction as
872            // well as in the ones that leave it implied.
873            let infinity = Float::infinity(format, false);
874            assert!(Float::from_bits(format, infinity.to_bits()).is_infinite(), "{format:?}");
875        }
876        // The host agrees about where the quiet bit is.
877        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        // A number divided by itself is one, at whatever scale the extra bits put it.
889        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}