Skip to main content

rucc_base/
float.rs

1//! Binary floating point, in software, for every format the compiler has to produce.
2//!
3//! A compiler cannot ask the machine it is running on what a floating constant means. The host
4//! may not have the format at all, `long double` is eighty bits on x86-64 and a hundred and
5//! twenty eight on AArch64 Linux and sixty four on Apple, and `strtod` is the host's libc
6//! rather than the target's semantics. Reproducible output means the same source gives the same
7//! bits whoever compiles it, so the conversion is done here, exactly, in integer arithmetic.
8//!
9//! [`Float`] is a sign, a category, an exponent and a significand of up to a hundred and
10//! thirteen bits, which is every format in [`Format`] including the x87 eighty bit one with its
11//! stored leading bit. The value of a finite number is `significand * 2^(exponent - precision +
12//! 1)`, so the significand is an integer rather than a fraction and the exponent is that of its
13//! leading bit.
14//!
15//! Conversion from text is correctly rounded, round to nearest with ties to even, which is the
16//! only rounding mode a translation-time constant uses. The decimal path scales the number by
17//! powers of two until it is in `[1, 2)` and then reads the significand off it, using the exact
18//! decimal in `decimal.rs` so that no step ever loses a bit. A naive `mantissa * 10^exponent`
19//! in `f64` is wrong in the last place for a noticeable fraction of literals, and the last
20//! place is exactly what a differential test against another compiler notices. Hexadecimal
21//! constants are exact by construction and only have to be rounded once.
22//!
23//! ```
24//! use rucc_base::float::{Float, Format};
25//!
26//! let (value, status) = Float::parse("0.1", Format::Double).expect("a number");
27//! assert_eq!(value.to_bits(), (0.1f64).to_bits() as u128);
28//! assert!(status.has(rucc_base::float::Status::INEXACT));
29//! ```
30//!
31//! Arithmetic is not here yet. The constant evaluator needs it and will bring it.
32
33use crate::decimal::{Decimal, Fraction};
34
35/// A binary floating point format.
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
37pub enum Format {
38    /// IEEE binary16, which C spells `_Float16`.
39    Half,
40    /// The brain float, an IEEE binary32 with the low sixteen bits of its significand cut off,
41    /// which C spells `__bf16`. It has the range of a `float` and less than half its precision.
42    BFloat16,
43    /// IEEE binary32, which C spells `float`.
44    Single,
45    /// IEEE binary64, which C spells `double`.
46    Double,
47    /// The x87 eighty bit format, which is `long double` on x86. It is the one format here that
48    /// stores the leading significand bit rather than leaving it implied.
49    X87Extended,
50    /// IEEE binary128, which C spells `_Float128`, and which is `long double` on AArch64 Linux
51    /// and on RISC-V.
52    Quad,
53}
54
55impl Format {
56    /// The number of significand bits, counting the leading one whether it is stored or not.
57    #[must_use]
58    pub const fn precision(self) -> u32 {
59        match self {
60            Format::Half => 11,
61            Format::BFloat16 => 8,
62            Format::Single => 24,
63            Format::Double => 53,
64            Format::X87Extended => 64,
65            Format::Quad => 113,
66        }
67    }
68
69    /// The exponent of the largest finite number, which is also the exponent bias.
70    #[must_use]
71    pub const fn max_exponent(self) -> i32 {
72        match self {
73            Format::Half => 15,
74            Format::BFloat16 | Format::Single => 127,
75            Format::Double => 1023,
76            Format::X87Extended | Format::Quad => 16383,
77        }
78    }
79
80    /// The exponent of the smallest normal number.
81    #[must_use]
82    pub const fn min_exponent(self) -> i32 {
83        1 - self.max_exponent()
84    }
85
86    /// The width of the encoding in bits, which for x87 is the eighty bits that matter and not
87    /// the ninety six or hundred and twenty eight an ABI pads them out to.
88    #[must_use]
89    pub const fn width(self) -> u32 {
90        match self {
91            Format::Half | Format::BFloat16 => 16,
92            Format::Single => 32,
93            Format::Double => 64,
94            Format::X87Extended => 80,
95            Format::Quad => 128,
96        }
97    }
98
99    /// Whether the leading significand bit is stored rather than implied.
100    #[must_use]
101    pub const fn has_explicit_integer_bit(self) -> bool {
102        matches!(self, Format::X87Extended)
103    }
104
105    /// The width of the exponent field.
106    const fn exponent_bits(self) -> u32 {
107        self.width() - self.significand_bits() - 1
108    }
109
110    /// The width of the stored significand field.
111    const fn significand_bits(self) -> u32 {
112        if self.has_explicit_integer_bit() { self.precision() } else { self.precision() - 1 }
113    }
114
115    /// A decimal exponent above which every number is too large for the format.
116    ///
117    /// The value is at least `10^(point - 1)`, so a point past this cannot be finite. It is
118    /// deliberately loose: it exists to stop the scaling loop from walking a million powers of
119    /// ten, not to decide anything.
120    const fn max_decimal_exponent(self) -> i32 {
121        (self.max_exponent() + 1) * 30103 / 100000 + 2
122    }
123
124    /// A decimal exponent below which every number rounds to zero.
125    const fn min_decimal_exponent(self) -> i32 {
126        (self.min_exponent() - self.precision() as i32) * 30103 / 100000 - 2
127    }
128}
129
130/// What a conversion had to do to the number to fit it in the format.
131///
132/// A bitmask, so that one conversion can report several. The names are IEEE 754's exceptions,
133/// which is what the diagnostics are ultimately about: GCC warns that a floating constant
134/// exceeds the range of its type, or that it was truncated to zero.
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
136pub struct Status(u8);
137
138impl Status {
139    /// The value is exactly what was written.
140    pub const NONE: Status = Status(0);
141    /// The value had to be rounded, so it is not what was written.
142    pub const INEXACT: Status = Status(1);
143    /// The value is too large for the format and became an infinity.
144    pub const OVERFLOW: Status = Status(2);
145    /// The value is too small for the format and became a subnormal or a zero.
146    pub const UNDERFLOW: Status = Status(4);
147
148    /// Whether every flag in `other` is set here.
149    #[inline]
150    #[must_use]
151    pub const fn has(self, other: Status) -> bool {
152        self.0 & other.0 == other.0
153    }
154
155    /// This set with `other` added.
156    #[inline]
157    #[must_use]
158    pub const fn with(self, other: Status) -> Status {
159        Status(self.0 | other.0)
160    }
161
162    /// Whether nothing happened to the number.
163    #[inline]
164    #[must_use]
165    pub const fn is_none(self) -> bool {
166        self.0 == 0
167    }
168}
169
170/// Why a spelling is not a number.
171///
172/// The caller is expected to have checked the shape of the token already, so these are the
173/// cases a lexer cannot rule out rather than a full grammar.
174#[derive(Debug, Clone, Copy, PartialEq, Eq)]
175pub enum ParseError {
176    /// There is no digit anywhere in it.
177    NoDigits,
178    /// There is an exponent marker with no digits after it.
179    NoExponentDigits,
180    /// There is a character in it that a number does not have.
181    Invalid,
182}
183
184/// What kind of number this is.
185#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
186enum Category {
187    Zero,
188    Finite,
189    Infinite,
190}
191
192/// A floating point number in a given format.
193///
194/// A finite value is `significand * 2^(exponent - precision + 1)`. A normal number has its
195/// leading significand bit set, a subnormal does not and has the format's minimum exponent.
196#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197pub struct Float {
198    format: Format,
199    category: Category,
200    sign: bool,
201    exponent: i32,
202    significand: u128,
203}
204
205impl Float {
206    /// A zero of the given sign.
207    #[must_use]
208    pub const fn zero(format: Format, sign: bool) -> Float {
209        Float { format, category: Category::Zero, sign, exponent: 0, significand: 0 }
210    }
211
212    /// An infinity of the given sign.
213    #[must_use]
214    pub const fn infinity(format: Format, sign: bool) -> Float {
215        Float { format, category: Category::Infinite, sign, exponent: 0, significand: 0 }
216    }
217
218    /// The format this number is in.
219    #[must_use]
220    pub const fn format(self) -> Format {
221        self.format
222    }
223
224    /// Whether the number is negative, which a zero can be.
225    #[must_use]
226    pub const fn is_negative(self) -> bool {
227        self.sign
228    }
229
230    /// Whether the number is a zero.
231    #[must_use]
232    pub const fn is_zero(self) -> bool {
233        matches!(self.category, Category::Zero)
234    }
235
236    /// Whether the number is an infinity.
237    #[must_use]
238    pub const fn is_infinite(self) -> bool {
239        matches!(self.category, Category::Infinite)
240    }
241
242    /// Whether the number is finite, which a zero is.
243    #[must_use]
244    pub const fn is_finite(self) -> bool {
245        !self.is_infinite()
246    }
247
248    /// Converts a decimal or hexadecimal spelling into the nearest number in `format`, rounding
249    /// to nearest with ties to even.
250    ///
251    /// The spelling is the number alone: no suffix, because the suffix is what chose the
252    /// format, and no infinity or nan, because C has no spelling for those. A sign is accepted
253    /// even though a C constant never has one, since the value the constant evaluator folds
254    /// does. C23 digit separators are stripped here.
255    ///
256    /// # Errors
257    ///
258    /// [`ParseError`], for a spelling that is not a number at all.
259    pub fn parse(text: &str, format: Format) -> Result<(Float, Status), ParseError> {
260        let bytes = text.as_bytes();
261        let (sign, rest) = match bytes.first() {
262            Some(b'-') => (true, &bytes[1..]),
263            Some(b'+') => (false, &bytes[1..]),
264            _ => (false, bytes),
265        };
266        if rest.len() > 1 && rest[0] == b'0' && rest[1] | 32 == b'x' {
267            hexadecimal(&rest[2..], sign, format)
268        } else {
269            decimal(rest, sign, format)
270        }
271    }
272
273    /// The bits of the encoding, in the low [`Format::width`] bits.
274    ///
275    /// The x87 format keeps its leading significand bit, so its eightieth bit is the sign and
276    /// its sixty fourth is the one every other format leaves implied.
277    #[must_use]
278    pub fn to_bits(self) -> u128 {
279        let format = self.format;
280        let significand_mask = (1u128 << format.significand_bits()) - 1;
281        let (exponent_field, significand_field) = match self.category {
282            Category::Zero => (0, 0),
283            Category::Infinite => (
284                (1u128 << format.exponent_bits()) - 1,
285                if format.has_explicit_integer_bit() {
286                    1u128 << (format.precision() - 1)
287                } else {
288                    0
289                },
290            ),
291            Category::Finite => {
292                let subnormal = self.significand >> (format.precision() - 1) == 0;
293                let field =
294                    if subnormal { 0 } else { (self.exponent + format.max_exponent()) as u128 };
295                (field, self.significand & significand_mask)
296            }
297        };
298        let sign = u128::from(self.sign) << (format.width() - 1);
299        sign | (exponent_field << format.significand_bits()) | significand_field
300    }
301
302    /// Reads a number back out of its encoding, which is what makes [`Float::to_bits`] testable
303    /// and what a constant folded in the IR is stored as.
304    ///
305    /// A signalling or quiet nan comes back as an infinity, because nothing here makes one and
306    /// nothing here has anywhere to put the payload yet.
307    #[must_use]
308    pub fn from_bits(format: Format, bits: u128) -> Float {
309        let significand_bits = format.significand_bits();
310        let sign = (bits >> (format.width() - 1)) & 1 == 1;
311        let exponent_field =
312            ((bits >> significand_bits) & ((1u128 << format.exponent_bits()) - 1)) as i32;
313        let stored = bits & ((1u128 << significand_bits) - 1);
314        if exponent_field == (1 << format.exponent_bits()) - 1 {
315            return Float::infinity(format, sign);
316        }
317        let implicit = if format.has_explicit_integer_bit() || exponent_field == 0 {
318            0
319        } else {
320            1u128 << (format.precision() - 1)
321        };
322        let significand = stored | implicit;
323        if significand == 0 {
324            return Float::zero(format, sign);
325        }
326        let exponent = if exponent_field == 0 {
327            format.min_exponent()
328        } else {
329            exponent_field - format.max_exponent()
330        };
331        Float { format, category: Category::Finite, sign, exponent, significand }
332    }
333}
334
335/// Converts a decimal spelling.
336fn decimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
337    let mut digits = Vec::new();
338    let mut integer_digits = 0i32;
339    let mut seen_point = false;
340    let mut seen_digit = false;
341    let mut index = 0;
342    while index < bytes.len() {
343        match bytes[index] {
344            byte @ b'0'..=b'9' => {
345                digits.push(byte - b'0');
346                if !seen_point {
347                    integer_digits += 1;
348                }
349                seen_digit = true;
350            }
351            b'\'' => {}
352            b'.' if !seen_point => seen_point = true,
353            b'e' | b'E' => break,
354            _ => return Err(ParseError::Invalid),
355        }
356        index += 1;
357    }
358    if !seen_digit {
359        return Err(ParseError::NoDigits);
360    }
361    let mut point = integer_digits;
362    if index < bytes.len() {
363        point = point.saturating_add(exponent_of(&bytes[index + 1..])?);
364    }
365    Ok(convert(Decimal::new(digits, point), sign, format))
366}
367
368/// Converts a hexadecimal spelling, which is exact until the one rounding at the end.
369fn hexadecimal(bytes: &[u8], sign: bool, format: Format) -> Result<(Float, Status), ParseError> {
370    let mut significand: u128 = 0;
371    let mut exponent = 0i32;
372    let mut sticky = false;
373    let mut seen_point = false;
374    let mut seen_digit = false;
375    let mut index = 0;
376    while index < bytes.len() {
377        let byte = bytes[index];
378        let digit = match byte {
379            b'0'..=b'9' => byte - b'0',
380            b'a'..=b'f' => byte - b'a' + 10,
381            b'A'..=b'F' => byte - b'A' + 10,
382            b'\'' => {
383                index += 1;
384                continue;
385            }
386            b'.' if !seen_point => {
387                seen_point = true;
388                index += 1;
389                continue;
390            }
391            b'p' | b'P' => break,
392            _ => return Err(ParseError::Invalid),
393        };
394        seen_digit = true;
395        if significand.leading_zeros() >= 4 {
396            significand = (significand << 4) | u128::from(digit);
397            if seen_point {
398                exponent -= 4;
399            }
400        } else {
401            // Past a hundred and twenty eight bits the digits cannot change the value, only
402            // whether it is exactly halfway, which is what the sticky bit is for.
403            sticky |= digit != 0;
404            if !seen_point {
405                exponent += 4;
406            }
407        }
408        index += 1;
409    }
410    if !seen_digit {
411        return Err(ParseError::NoDigits);
412    }
413    if index < bytes.len() {
414        exponent = exponent.saturating_add(exponent_of(&bytes[index + 1..])?);
415    }
416    Ok(round(significand, exponent, sticky, sign, format))
417}
418
419/// Reads the digits of an exponent, which may be signed.
420fn exponent_of(bytes: &[u8]) -> Result<i32, ParseError> {
421    let (negative, digits) = match bytes.first() {
422        Some(b'-') => (true, &bytes[1..]),
423        Some(b'+') => (false, &bytes[1..]),
424        _ => (false, bytes),
425    };
426    if digits.is_empty() {
427        return Err(ParseError::NoExponentDigits);
428    }
429    let mut value = 0i32;
430    for &byte in digits {
431        if byte == b'\'' {
432            continue;
433        }
434        if !byte.is_ascii_digit() {
435            return Err(ParseError::Invalid);
436        }
437        // An exponent far past the format's range is the same as one at the edge of it, so it
438        // saturates rather than overflowing.
439        value = value.saturating_mul(10).saturating_add(i32::from(byte - b'0'));
440    }
441    Ok(if negative { -value } else { value })
442}
443
444/// Scales an exact decimal down to the format's significand and rounds it.
445fn convert(mut value: Decimal, sign: bool, format: Format) -> (Float, Status) {
446    if value.is_zero() {
447        return (Float::zero(format, sign), Status::NONE);
448    }
449    if value.point() > format.max_decimal_exponent() {
450        return (Float::infinity(format, sign), Status::OVERFLOW.with(Status::INEXACT));
451    }
452    if value.point() < format.min_decimal_exponent() {
453        return (Float::zero(format, sign), Status::UNDERFLOW.with(Status::INEXACT));
454    }
455
456    // Scale until the value is in `[1, 2)`, counting the powers of two taken out of it. Each
457    // step is an underestimate of the distance left, so no step overshoots and the loop always
458    // moves, which is what stops it oscillating.
459    let mut exponent = 0i32;
460    loop {
461        let point = value.point();
462        if point > 1 || (point == 1 && value.first_digit() >= 2) {
463            let step = binary_digits(point - 1).clamp(1, 60);
464            value.shift(-step);
465            exponent += step;
466        } else if point < 1 {
467            let step = (1 + binary_digits(-point)).clamp(1, 60);
468            value.shift(step);
469            exponent -= step;
470        } else {
471            break;
472        }
473    }
474
475    // The significand is the value scaled by this many powers of two, clamped so that a number
476    // below the smallest normal loses precision instead of exponent.
477    let precision = format.precision() as i32;
478    let scale = (exponent - precision + 1).max(format.min_exponent() - precision + 1);
479    value.shift(exponent - scale);
480    let (integer, fraction) = value.round_to_u128();
481    let rounded = match fraction {
482        Fraction::Zero | Fraction::BelowHalf => integer,
483        Fraction::Half => integer + (integer & 1),
484        Fraction::AboveHalf => integer + 1,
485    };
486    finish(rounded, scale, fraction != Fraction::Zero, sign, format)
487}
488
489/// Roughly how many binary digits a decimal one of this many digits has, never overestimating.
490const fn binary_digits(decimal: i32) -> i32 {
491    decimal * 33219 / 10000
492}
493
494/// Rounds `significand * 2^exponent` into the format, with `sticky` saying that something
495/// nonzero was already dropped below it.
496fn round(
497    significand: u128,
498    exponent: i32,
499    sticky: bool,
500    sign: bool,
501    format: Format,
502) -> (Float, Status) {
503    if significand == 0 {
504        return (Float::zero(format, sign), Status::NONE);
505    }
506    let precision = format.precision() as i32;
507    let leading = (128 - significand.leading_zeros()) as i32;
508    let scale = (exponent + leading - precision).max(format.min_exponent() - precision + 1);
509    let mut sticky = sticky;
510    let (integer, half) = if scale <= exponent {
511        (significand << (exponent - scale), false)
512    } else {
513        let drop = (scale - exponent) as u32;
514        if drop >= 128 {
515            sticky = true;
516            (0, false)
517        } else {
518            let half = (significand >> (drop - 1)) & 1 == 1;
519            sticky |= drop > 1 && significand & ((1u128 << (drop - 1)) - 1) != 0;
520            (significand >> drop, half)
521        }
522    };
523    let rounded = if half && (sticky || integer & 1 == 1) { integer + 1 } else { integer };
524    finish(rounded, scale, half || sticky, sign, format)
525}
526
527/// Turns a rounded significand and the power of two it is scaled by into a number, handling the
528/// carry out of the significand and the two ends of the format's range.
529fn finish(
530    significand: u128,
531    scale: i32,
532    inexact: bool,
533    sign: bool,
534    format: Format,
535) -> (Float, Status) {
536    let precision = format.precision();
537    let mut significand = significand;
538    let mut scale = scale;
539    if significand >> precision != 0 {
540        // Rounding up carried out of the top bit, which only ever gives a power of two.
541        significand >>= 1;
542        scale += 1;
543    }
544    let mut status = if inexact { Status::INEXACT } else { Status::NONE };
545    if significand == 0 {
546        return (Float::zero(format, sign), status.with(Status::UNDERFLOW));
547    }
548    let exponent = scale + precision as i32 - 1;
549    if exponent > format.max_exponent() {
550        return (
551            Float::infinity(format, sign),
552            status.with(Status::OVERFLOW).with(Status::INEXACT),
553        );
554    }
555    let normal = significand >> (precision - 1) != 0;
556    if !normal && inexact {
557        status = status.with(Status::UNDERFLOW);
558    }
559    let exponent = if normal { exponent } else { format.min_exponent() };
560    (Float { format, category: Category::Finite, sign, exponent, significand }, status)
561}
562
563#[cfg(test)]
564mod tests {
565    use super::*;
566
567    /// The bits a `double` conversion gives, next to what Rust's own parser gives.
568    fn double(text: &str) -> u128 {
569        Float::parse(text, Format::Double).expect("a number").0.to_bits()
570    }
571
572    /// The bits a `float` conversion gives.
573    fn single(text: &str) -> u128 {
574        Float::parse(text, Format::Single).expect("a number").0.to_bits()
575    }
576
577    #[test]
578    fn the_ordinary_numbers_land_where_the_host_would_put_them() {
579        for text in ["0", "1", "2", "0.5", "1.5", "3.14159", "2.718281828459045", "100", "1e10"] {
580            let host = text.parse::<f64>().expect("a number Rust reads too");
581            assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
582        }
583    }
584
585    #[test]
586    fn a_number_that_needs_the_last_bit_rounded_gets_it_right() {
587        // Every one of these is a literal a naive `mantissa * 10^exponent` gets wrong, and the
588        // last is the longest one a `double` conversion has to read to round correctly.
589        let hard = [
590            "0.1",
591            "0.3",
592            "2.2250738585072011e-308",
593            "2.2250738585072014e-308",
594            "1.7976931348623157e308",
595            "4.9406564584124654e-324",
596            "5e-324",
597            "8.98846567431158e307",
598            "9007199254740993",
599            "123456789012345678901234567890",
600            "1.000000000000000000000000000000000000000000000000000000000000000001",
601            "7.8459735791271921e65",
602            "3.518437208883201171875e13",
603            "0.500000000000000166533453693773481063544750213623046875",
604        ];
605        for text in hard {
606            let host = text.parse::<f64>().expect("a number Rust reads too");
607            assert_eq!(double(text), u128::from(host.to_bits()), "{text}");
608        }
609    }
610
611    #[test]
612    fn the_number_that_takes_seven_hundred_and_sixty_seven_digits() {
613        // The exact decimal of a `double` halfway case. A conversion that truncates its input
614        // rounds this one the wrong way, which is the bug this buffer size exists to avoid.
615        let text = concat!(
616            "2.47032822920623272088284396434110686182529901307162382",
617            "35378852574870103599108683372845652890455735483022221802",
618            "58573249056416711547735232764105795166208503595426876755",
619            "62317084535693494535245273750735013572761315046354601316",
620            "12127849863326369238975694273040488011871029093711789936",
621            "42245692702737764465109076580131048946378905599180391359",
622            "70011386455512221706120629864144453927884519445934871524",
623            "63344875888932891414823975864211858166195965106373837732",
624            "34435703331457550505022232309998195892058070506176382679",
625            "16323484472119097902806154870514036458498974142754747141",
626            "39683784321102080606305920253373777969877864922227306716",
627            "01324339457879181214233820577228206278891620001855078759",
628            "16278352090142077553206262229158550205643778244387017277",
629            "94459649305087139089301871550805125768938177360937844105",
630            "63661045147381814281647890691181239104545396303476425117",
631            "7562185422741845851144691421326303120484712594187004993e-324"
632        );
633        let host = text.parse::<f64>().expect("a number Rust reads too");
634        assert_eq!(double(text), u128::from(host.to_bits()));
635    }
636
637    #[test]
638    fn a_sweep_of_random_numbers_agrees_with_rust_in_every_bit() {
639        // A conversion that is wrong in the last place is wrong on a small fraction of inputs,
640        // so this is a sweep rather than a handful. The generator is a fixed sequence, so a
641        // failure names the same number on every machine.
642        let mut state = 0x2545_f491_4f6c_dd1du64;
643        for _ in 0..4000 {
644            state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
645            let digits = state >> 11;
646            let exponent = (state % 600) as i32 - 300;
647            let text = format!("{digits}e{exponent}");
648            let host = text.parse::<f64>().expect("a number Rust reads too");
649            assert_eq!(double(&text), u128::from(host.to_bits()), "{text}");
650            let host = text.parse::<f32>().expect("a number Rust reads too");
651            assert_eq!(single(&text), u128::from(host.to_bits()), "{text} as a float");
652        }
653    }
654
655    #[test]
656    fn the_ends_of_the_range_are_an_infinity_and_a_zero() {
657        let (value, status) = Float::parse("1e400", Format::Double).expect("a number");
658        assert!(value.is_infinite() && status.has(Status::OVERFLOW));
659        let (value, status) = Float::parse("1e-400", Format::Double).expect("a number");
660        assert!(value.is_zero() && status.has(Status::UNDERFLOW) && status.has(Status::INEXACT));
661        // The largest `double` is finite and the next number up is not.
662        let (value, status) = Float::parse("1.7976931348623157e308", Format::Double).expect("one");
663        assert!(value.is_finite() && !status.has(Status::OVERFLOW));
664        let (value, _) = Float::parse("1.8e308", Format::Double).expect("a number");
665        assert!(value.is_infinite());
666        // Half the smallest subnormal rounds to zero, and just over half rounds up to it.
667        assert_eq!(double("2.4e-324"), u128::from((0f64).to_bits()));
668        assert_eq!(double("2.5e-324"), 1);
669    }
670
671    #[test]
672    fn a_number_that_is_exactly_what_was_written_says_so() {
673        assert!(Float::parse("1", Format::Double).expect("a number").1.is_none());
674        assert!(Float::parse("0.5", Format::Double).expect("a number").1.is_none());
675        assert!(Float::parse("0.1", Format::Double).expect("a number").1.has(Status::INEXACT));
676        // A number small enough to lose bits is inexact and underflowed, both.
677        let (_, status) = Float::parse("1e-320", Format::Double).expect("a number");
678        assert!(status.has(Status::INEXACT) && status.has(Status::UNDERFLOW));
679    }
680
681    #[test]
682    fn a_hexadecimal_constant_is_exact_and_needs_no_scaling() {
683        assert_eq!(double("0x1p0"), u128::from((1f64).to_bits()));
684        assert_eq!(double("0x1.8p1"), u128::from((3f64).to_bits()));
685        assert_eq!(double("0x1p-1074"), 1);
686        assert_eq!(double("0xa.bp-4"), u128::from((0.66796875f64).to_bits()));
687        assert_eq!(double("0X1.FFFFFFFFFFFFFP+1023"), u128::from(f64::MAX.to_bits()));
688        assert!(Float::parse("0x1p0", Format::Double).expect("a number").1.is_none());
689        // Seventeen hexadecimal digits is more than a `double` has, so this one rounds.
690        let (_, status) = Float::parse("0x1.00000000000008p0", Format::Double).expect("a number");
691        assert!(status.has(Status::INEXACT));
692        assert_eq!(double("0x1.00000000000008p0"), u128::from((1f64).to_bits()));
693        assert_eq!(double("0x1.00000000000018p0"), u128::from((1f64).to_bits() + 2));
694    }
695
696    #[test]
697    fn digit_separators_are_not_part_of_the_number() {
698        assert_eq!(double("1'000.000'1"), double("1000.0001"));
699        assert_eq!(double("0x1'0p0"), double("16.0"));
700        assert_eq!(double("1e1'0"), double("1e10"));
701    }
702
703    #[test]
704    fn a_spelling_that_is_not_a_number_says_which_way_it_is_wrong() {
705        assert_eq!(Float::parse("", Format::Double), Err(ParseError::NoDigits));
706        assert_eq!(Float::parse(".", Format::Double), Err(ParseError::NoDigits));
707        assert_eq!(Float::parse("1e", Format::Double), Err(ParseError::NoExponentDigits));
708        assert_eq!(Float::parse("1e+", Format::Double), Err(ParseError::NoExponentDigits));
709        assert_eq!(Float::parse("0x1p", Format::Double), Err(ParseError::NoExponentDigits));
710        assert_eq!(Float::parse("0xp1", Format::Double), Err(ParseError::NoDigits));
711        assert_eq!(Float::parse("1x0", Format::Double), Err(ParseError::Invalid));
712    }
713
714    #[test]
715    fn a_sign_is_accepted_although_a_c_constant_never_has_one() {
716        let (value, _) = Float::parse("-1.5", Format::Double).expect("a number");
717        assert!(value.is_negative());
718        assert_eq!(value.to_bits(), u128::from((-1.5f64).to_bits()));
719        let (value, _) = Float::parse("-0.0", Format::Double).expect("a number");
720        assert!(value.is_zero() && value.is_negative());
721        assert_eq!(value.to_bits(), u128::from((-0.0f64).to_bits()));
722    }
723
724    #[test]
725    fn every_format_says_how_wide_its_fields_are() {
726        for format in [
727            Format::Half,
728            Format::BFloat16,
729            Format::Single,
730            Format::Double,
731            Format::X87Extended,
732            Format::Quad,
733        ] {
734            assert_eq!(
735                format.exponent_bits() + format.significand_bits() + 1,
736                format.width(),
737                "{format:?}"
738            );
739            assert_eq!(format.min_exponent(), 1 - format.max_exponent());
740        }
741        assert_eq!(Format::Half.exponent_bits(), 5);
742        assert_eq!(Format::BFloat16.exponent_bits(), 8);
743        assert_eq!(Format::Single.exponent_bits(), 8);
744        assert_eq!(Format::Double.exponent_bits(), 11);
745        assert_eq!(Format::X87Extended.exponent_bits(), 15);
746        assert_eq!(Format::Quad.exponent_bits(), 15);
747    }
748
749    #[test]
750    fn a_number_survives_a_trip_through_its_encoding() {
751        for format in [
752            Format::Half,
753            Format::BFloat16,
754            Format::Single,
755            Format::Double,
756            Format::X87Extended,
757            Format::Quad,
758        ] {
759            for text in ["0", "-0", "1", "-1.5", "3.14159", "1e-5", "65504", "0x1p-20"] {
760                let (value, _) = Float::parse(text, format).expect("a number");
761                let bits = value.to_bits();
762                assert_eq!(Float::from_bits(format, bits).to_bits(), bits, "{text} in {format:?}");
763            }
764            assert_eq!(
765                Float::from_bits(format, Float::infinity(format, false).to_bits()).to_bits(),
766                Float::infinity(format, false).to_bits()
767            );
768        }
769    }
770
771    #[test]
772    fn the_narrow_formats_round_where_they_are_supposed_to() {
773        // `_Float16` has eleven bits, so its largest finite number is 65504 and the next power
774        // of two is an infinity. `__bf16` has eight, so it loses a `float`'s low bits and keeps
775        // its range, which is the whole point of the format.
776        let (value, status) = Float::parse("65504", Format::Half).expect("a number");
777        assert!(value.is_finite() && status.is_none());
778        assert_eq!(value.to_bits(), 0x7bff);
779        let (value, _) = Float::parse("65536", Format::Half).expect("a number");
780        assert!(value.is_infinite());
781        assert_eq!(Float::parse("1", Format::Half).expect("one").0.to_bits(), 0x3c00);
782        assert_eq!(Float::parse("1", Format::BFloat16).expect("one").0.to_bits(), 0x3f80);
783        assert_eq!(Float::parse("1e30", Format::BFloat16).expect("big").0.to_bits(), 0x714a);
784        // The smallest `_Float16` subnormal, and half of it.
785        assert_eq!(Float::parse("0x1p-24", Format::Half).expect("tiny").0.to_bits(), 1);
786        assert!(Float::parse("0x1p-26", Format::Half).expect("tinier").0.is_zero());
787    }
788
789    #[test]
790    fn the_x87_format_stores_the_bit_the_others_leave_implied() {
791        // 1.0 is 0x3fff8000000000000000: the exponent field, then a significand whose top bit
792        // is stored rather than implied. Every other format here would have zeros there.
793        let one = Float::parse("1", Format::X87Extended).expect("one").0;
794        assert_eq!(one.to_bits(), 0x3fff_8000_0000_0000_0000);
795        assert_eq!(
796            Float::parse("2", Format::X87Extended).expect("two").0.to_bits(),
797            0x4000_8000_0000_0000_0000
798        );
799        // Sixty four bits of precision, so this is exact where a `double` would round it.
800        let (value, status) = Float::parse("9007199254740993", Format::X87Extended).expect("one");
801        assert!(status.is_none());
802        assert_eq!(value.to_bits(), 0x4034_8000_0000_0000_0400);
803        // Measured, by compiling the constant with gcc 13.3 on x86-64 and reading the ten
804        // bytes back out of the program rather than trusting a table.
805        assert_eq!(
806            Float::parse("0.1", Format::X87Extended).expect("a tenth").0.to_bits(),
807            0x3ffb_cccc_cccc_cccc_cccd
808        );
809        // A subnormal four thousand powers of ten down, which is three of the smallest number
810        // the format has. gcc puts the same three there.
811        assert_eq!(Float::parse("1e-4950", Format::X87Extended).expect("tiny").0.to_bits(), 3);
812    }
813
814    #[test]
815    fn the_quad_format_has_a_hundred_and_thirteen_bits_of_it() {
816        assert_eq!(
817            Float::parse("1", Format::Quad).expect("one").0.to_bits(),
818            0x3fff_0000_0000_0000_0000_0000_0000_0000
819        );
820        // 0.1 in binary128, which is the same digits a `double` gets and then sixty more bits.
821        assert_eq!(
822            Float::parse("0.1", Format::Quad).expect("a tenth").0.to_bits(),
823            0x3ffb_9999_9999_9999_9999_9999_9999_999a
824        );
825        // Also measured against gcc, through `__float128`.
826        assert_eq!(
827            Float::parse("3.14159", Format::Quad).expect("pi, roughly").0.to_bits(),
828            0x4000_921f_9f01_b866_e43a_a79b_badc_0981
829        );
830        let (value, status) = Float::parse("1e5000", Format::Quad).expect("a number");
831        assert!(value.is_infinite() && status.has(Status::OVERFLOW));
832        let (value, _) = Float::parse("1e-5000", Format::Quad).expect("a number");
833        assert!(value.is_zero());
834    }
835}