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. Every nan produced here is the default quiet one, because nothing in a constant
31//! expression can spell a payload and propagating one would mean deciding which of two operands
32//! wins, which IEEE 754 leaves to the implementation and which no C program can see.
33
34use std::cmp::Ordering;
35
36use crate::float::{Category, Float, Format, Status, round};
37
38/// How many bits are kept below the significand while two numbers are lined up for an addition.
39///
40/// Two of them are the guard and round bits an addition needs in order to round correctly, and
41/// the third is where the sticky bit lands, so anything shifted past all three is nonzero or it
42/// is nothing, which is the one fact the rounding needs about it.
43const GUARD: u32 = 3;
44
45impl Float {
46    /// A quiet nan, which is what an operation with no answer gives.
47    #[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    /// Whether the number is a nan.
53    #[must_use]
54    pub const fn is_nan(self) -> bool {
55        matches!(self.category, Category::Nan)
56    }
57
58    /// The number with its sign flipped, which is exact and which a zero and a nan both have.
59    #[must_use]
60    pub const fn negated(self) -> Float {
61        Float { sign: !self.sign, ..self }
62    }
63
64    /// The number without its sign, which is exact.
65    #[must_use]
66    pub const fn abs(self) -> Float {
67        Float { sign: false, ..self }
68    }
69
70    /// `self + other`, rounded to nearest with ties to even.
71    ///
72    /// A nan operand gives a nan and nothing else. Two infinities of opposite sign give a nan and
73    /// [`Status::INVALID`], because the answer depends on how they got there. Two zeros give a
74    /// negative zero only when both of them are negative, which is the round to nearest rule and
75    /// the reason `x + 0.0` is not a way to drop a sign.
76    ///
77    /// # Panics
78    ///
79    /// If the two numbers are not in the same format. The usual arithmetic conversions have
80    /// already made them so, and converting here would be a conversion nobody asked for.
81    #[must_use]
82    pub fn sum(self, other: Float) -> (Float, Status) {
83        self.total(other, false)
84    }
85
86    /// `self - other`, rounded to nearest with ties to even.
87    ///
88    /// This is the sum of `self` and the negation of `other`, which is exactly what it is in IEEE
89    /// 754, so a subtraction that cancels completely gives a positive zero and an infinity minus
90    /// itself gives a nan.
91    ///
92    /// # Panics
93    ///
94    /// If the two numbers are not in the same format.
95    #[must_use]
96    pub fn difference(self, other: Float) -> (Float, Status) {
97        self.total(other, true)
98    }
99
100    /// `self * other`, rounded to nearest with ties to even.
101    ///
102    /// A zero times an infinity gives a nan and [`Status::INVALID`]. The sign is the two signs
103    /// multiplied, which a zero and a nan have as much as any other number does.
104    ///
105    /// # Panics
106    ///
107    /// If the two numbers are not in the same format.
108    #[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                // Two significands of at most a hundred and thirteen bits make a product of at
132                // most two hundred and twenty six, so the count below is between one and ninety
133                // eight and every shift here has somewhere to go.
134                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    /// `self / other`, rounded to nearest with ties to even.
143    ///
144    /// A finite number divided by zero gives an infinity and [`Status::DIVIDE_BY_ZERO`]. Zero
145    /// divided by zero and an infinity divided by an infinity both give a nan and
146    /// [`Status::INVALID`], which is the difference between a division that has no answer and one
147    /// whose answer is only too large to be a number.
148    ///
149    /// # Panics
150    ///
151    /// If the two numbers are not in the same format.
152    #[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                // Both significands are shifted up until their leading bit is the top bit of a
170                // `u128`, which puts their quotient between a half and two and so puts its
171                // leading bit in a known place. The quotient is then taken to two bits more than
172                // the format has, and whatever is left over is the sticky bit.
173                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    /// How the two compare, or [`None`] if either is a nan and they do not compare at all.
188    ///
189    /// This is the comparison C's relational operators do, so a positive zero and a negative zero
190    /// are equal and the unordered case is the one that makes `x < y` and `!(x >= y)` different
191    /// questions.
192    ///
193    /// # Panics
194    ///
195    /// If the two numbers are not in the same format.
196    #[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    /// The nearest number to this one in another format, rounded to nearest with ties to even.
213    ///
214    /// Widening is exact for every pair of formats here except a `__bf16` widened to a
215    /// `_Float16`, which has more precision and less range. Narrowing is what a cast does, and it
216    /// reports what it had to do to make the number fit.
217    #[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    /// The nearest number in `format` to a signed integer.
231    #[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    /// The nearest number in `format` to an unsigned integer.
240    #[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    /// The number truncated toward zero into an integer of `width` bits.
249    ///
250    /// What comes back is what an integer constant is stored as, which is the value sign extended
251    /// out of the type it has, so an unsigned conversion of a hundred and twenty eight bits comes
252    /// back with its top bit in the sign of the [`i128`].
253    ///
254    /// Converting a number that does not fit is undefined behaviour in C rather than a value, so
255    /// what comes back is the nearest end of the range together with [`Status::INVALID`], which
256    /// is what the caller warns about. A nan comes back as zero, for the same reason and with the
257    /// same flag. Dropping a fraction is [`Status::INEXACT`] and nothing worse, since that is the
258    /// conversion doing what it is for.
259    ///
260    /// # Panics
261    ///
262    /// If `width` is zero or wider than a hundred and twenty eight bits.
263    #[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    /// The largest magnitude an integer of this type can hold with this number's sign.
294    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            // An unsigned type has nowhere for a negative number to go, but truncating one whose
299            // magnitude is below one lands on zero, which is in range and is not an error.
300            (false, true) => 0,
301            (false, false) => u128::MAX >> (128 - width),
302        }
303    }
304
305    /// A magnitude given this number's sign, as an integer constant is stored.
306    fn signed_value(self, magnitude: u128) -> i128 {
307        if self.sign { (magnitude as i128).wrapping_neg() } else { magnitude as i128 }
308    }
309
310    /// The significand and the power of two it is scaled by, so that the value of a finite number
311    /// is the first of these shifted by the second.
312    fn parts(self) -> (u128, i32) {
313        (self.significand, self.exponent - self.format.precision() as i32 + 1)
314    }
315
316    /// The format both numbers are in.
317    ///
318    /// # Panics
319    ///
320    /// If they are not in the same one. Every operation here is on two numbers of one type,
321    /// because the usual arithmetic conversions ran first, and converting one here instead would
322    /// silently round an operand on the way in.
323    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    /// The nan an operation gives when an operand is one, if either is.
329    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    /// How the magnitudes of two numbers in the same format compare, nans aside.
334    ///
335    /// Comparing the exponent before the significand works across the subnormals as well as the
336    /// normals, because a subnormal has the smallest exponent there is and a leading zero where a
337    /// normal number has its leading one.
338    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    /// The sum of two numbers, or their difference, which is the sum of one of them and the other
350    /// negated and is not a separate operation anywhere below this line.
351    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            // Round to nearest makes the sum of two zeros positive unless both of them were
368            // negative, which is the one rule here that is about the sign rather than the value.
369            (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                // What was dropped belongs to the number being taken away, so the answer is a
397                // little below what the bits that are left say it is. Taking one more off, with
398                // the sticky bit set, says exactly that: the answer is between the two, which is
399                // all the rounding needs. It cannot go below zero, because the two are ordered by
400                // magnitude and a dropped bit means the smaller one is smaller by more than the
401                // last bit of the larger.
402                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
412/// The full two hundred and fifty six bit product of two numbers, high half first.
413///
414/// The halves of each operand multiply into products that fit, and the middle column is the one
415/// that has to be carried by hand. There is no `u256` and no widening multiply in the language,
416/// so this is what multiplying two significands looks like.
417fn 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
429/// The quotient of `numerator` shifted up by `extra` bits and `divisor`, and what is left over.
430///
431/// Both arguments have their top bit set, so their quotient is between a half and two and the
432/// answer here has either `extra` or `extra` plus one bits. Restoring division a bit at a time,
433/// because the alternatives are a longer program and this runs once per constant folded.
434fn 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        // The remainder is below the divisor, so doubling it can carry out of the top of a `u128`
440        // and still be a number the divisor goes into exactly once.
441        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    /// A `double` from the host's bits, which is what makes the host an oracle.
457    fn double(value: f64) -> Float {
458        Float::from_bits(Format::Double, u128::from(value.to_bits()))
459    }
460
461    /// The host number a `double` holds.
462    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    /// A fixed sequence, so that a failure names the same numbers on every machine.
475    fn next(state: &mut u64) -> u64 {
476        *state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
477        *state
478    }
479
480    /// Every operation on a pair of `double` values, against what the host computes.
481    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    /// The same, for a pair of `float` values.
503    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        // Random bits cover the infinities, the nans and the subnormals as well as the ordinary
549        // numbers, which is the point of taking bits rather than taking values.
550        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        // Two numbers of nearly the same size are where a subtraction cancels and where the bits
568        // that are left come from the guard bits rather than from either operand.
569        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        // A division by zero has an answer, which is why it is not the same flag.
595        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        // A nan on the way in is a nan on the way out, and nothing is reported for it.
602        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        // A subnormal answer that lost no bits is exact, small as it is.
644        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        // One that lost a bit is inexact and underflowed, both.
648        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        // The two zeros are the same number as far as a comparison is concerned.
661        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        // An infinity is at the end of the order, and a nan is not in the order at all.
665        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            // Widening is exact, so the number that comes back is the one that went in.
702            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        // The x87 format has more bits than a `double`, so a number goes up into it exactly and
719        // comes back down as the number it started as.
720        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        // Widening keeps the error the number already had rather than removing it: a tenth that
725        // went through a `double` is not the tenth an x87 number can hold.
726        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        // The ends of the two widest integer types, which are where the rounding shows.
743        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        // Truncation toward zero lands inside an unsigned type, and anything below it does not.
770        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        // The widest unsigned type has its top bit where the sign of the value holding it is.
788        let (value, status) = double(f64::MAX).to_integer(128, false);
789        assert!(value == -1 && status.has(Status::INVALID));
790        // The widest signed one holds its own smallest number exactly.
791        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        // Rust's own conversion saturates and turns a nan into zero, which is what C leaves
798        // undefined and what this fills it in with, so the host answers for this too.
799        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        // A third in binary128 is the exact quotient rounded down, since the digits repeat and
815        // the first one dropped is below a half. Worked out by hand rather than measured, because
816        // no host here has the format.
817        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        // Three of them is one exactly, because the sum is a tie and the tie rounds up.
821        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        // The x87 format has sixty four bits of significand, so this is exact where a `double`
826        // would have to round it.
827        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        // Half precision has eleven, so 2049 is a tie between the two numbers either side of it
833        // and rounds to the even one below.
834        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            // An infinity is not a nan, in the format that stores the bit above the fraction as
855            // well as in the ones that leave it implied.
856            let infinity = Float::infinity(format, false);
857            assert!(Float::from_bits(format, infinity.to_bits()).is_infinite(), "{format:?}");
858        }
859        // The host agrees about where the quiet bit is.
860        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        // A number divided by itself is one, at whatever scale the extra bits put it.
872        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}