Skip to main content

core/num/imp/flt2dec/
mod.rs

1/*!
2
3Floating-point number to decimal conversion routines.
4
5# Problem statement
6
7We are given the floating-point number `v = f * 2^e` with an integer `f`,
8and its bounds `minus` and `plus` such that any number between `v - minus` and
9`v + plus` will be rounded to `v`. For the simplicity we assume that
10this range is exclusive. Then we would like to get the unique decimal
11representation `V = 0.d[0..n-1] * 10^k` such that:
12
13- `d[0]` is non-zero.
14
15- It's correctly rounded when parsed back: `v - minus < V < v + plus`.
16  Furthermore it is shortest such one, i.e., there is no representation
17  with less than `n` digits that is correctly rounded.
18
19- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Note that
20  there might be two representations satisfying this uniqueness requirement,
21  in which case some tie-breaking mechanism is used.
22
23We will call this mode of operation as to the *shortest* mode. This mode is used
24when there is no additional constraint, and can be thought as a "natural" mode
25as it matches the ordinary intuition (it at least prints `0.1f32` as "0.1").
26
27We have two more modes of operation closely related to each other. In these modes
28we are given either the number of significant digits `n` or the last-digit
29limitation `limit` (which determines the actual `n`), and we would like to get
30the representation `V = 0.d[0..n-1] * 10^k` such that:
31
32- `d[0]` is non-zero, unless `n` was zero in which case only `k` is returned.
33
34- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Again,
35  there might be some tie-breaking mechanism.
36
37When `limit` is given but not `n`, we set `n` such that `k - n = limit`
38so that the last digit `d[n-1]` is scaled by `10^(k-n) = 10^limit`.
39If such `n` is negative, we clip it to zero so that we will only get `k`.
40We are also limited by the supplied buffer. This limitation is used to print
41the number up to given number of fractional digits without knowing
42the correct `k` beforehand.
43
44We will call the mode of operation requiring `n` as to the *exact* mode,
45and one requiring `limit` as to the *fixed* mode. The exact mode is a subset of
46the fixed mode: the sufficiently large last-digit limitation will eventually fill
47the supplied buffer and let the algorithm to return.
48
49# Implementation overview
50
51It is easy to get the floating point printing correct but slow (Russ Cox has
52[demonstrated](https://research.swtch.com/ftoa) how it's easy), or incorrect but
53fast (naïve division and modulo). But it is surprisingly hard to print
54floating point numbers correctly *and* efficiently.
55
56There are two classes of algorithms widely known to be correct.
57
58- The "Dragon" family of algorithm is first described by Guy L. Steele Jr. and
59  Jon L. White. They rely on the fixed-size big integer for their correctness.
60  A slight improvement was found later, which is posthumously described by
61  Robert G. Burger and R. Kent Dybvig. David Gay's `dtoa.c` routine is
62  a popular implementation of this strategy.
63
64- The "Grisu" family of algorithm is first described by Florian Loitsch.
65  They use very cheap integer-only procedure to determine the close-to-correct
66  representation which is at least guaranteed to be shortest. The variant,
67  Grisu3, actively detects if the resulting representation is incorrect.
68
69We implement both algorithms with necessary tweaks to suit our requirements.
70In particular, published literatures are short of the actual implementation
71difficulties like how to avoid arithmetic overflows. Each implementation,
72available in `strategy::dragon` and `strategy::grisu` respectively,
73extensively describes all necessary justifications and many proofs for them.
74(It is still difficult to follow though. You have been warned.)
75
76Both implementations expose two public functions:
77
78- `format_shortest(decoded, buf)`, which always needs at least
79  `MAX_SIG_DIGITS` digits of buffer. Implements the shortest mode.
80
81- `format_exact(decoded, buf, limit)`, which accepts as small as
82  one digit of buffer. Implements exact and fixed modes.
83
84They try to fill the `u8` buffer with digits and returns the number of digits
85written and the exponent `k`. They are total for all finite `f32` and `f64`
86inputs (Grisu internally falls back to Dragon if necessary).
87
88The rendered digits are formatted into the actual string form with
89four functions:
90
91- `to_shortest_str` prints the shortest representation, which can be padded by
92  zeroes to make *at least* given number of fractional digits.
93
94- `to_shortest_exp_str` prints the shortest representation, which can be
95  padded by zeroes when its exponent is in the specified ranges,
96  or can be printed in the exponential form such as `1.23e45`.
97
98- `to_exact_exp_str` prints the exact representation with given number of
99  digits in the exponential form.
100
101- `to_exact_fixed_str` prints the fixed representation with *exactly*
102  given number of fractional digits.
103
104They all return a slice of preallocated `Part` array, which corresponds to
105the individual part of strings: a fixed string, a part of rendered digits,
106a number of zeroes or a small (`u16`) number. The caller is expected to
107provide a large enough buffer and `Part` array, and to assemble the final
108string from resulting `Part`s itself.
109
110All algorithms and formatting functions are accompanied by extensive tests
111in `coretests::num::flt2dec` module. It also shows how to use individual
112functions.
113
114*/
115
116// while this is extensively documented, this is in principle private which is
117// only made public for testing. do not expose us.
118#![doc(hidden)]
119#![unstable(
120    feature = "flt2dec",
121    reason = "internal routines only exposed for testing",
122    issue = "none"
123)]
124
125pub use self::decoder::{DecodableFloat, Decoded, FullDecoded, decode};
126use super::fmt::{Formatted, Part};
127use crate::mem::MaybeUninit;
128
129pub mod decoder;
130pub mod estimator;
131
132/// Digit-generation algorithms.
133pub mod strategy {
134    pub mod dragon;
135    pub mod grisu;
136}
137
138/// The minimum size of buffer necessary for the shortest mode.
139///
140/// It is a bit non-trivial to derive, but this is one plus the maximal number of
141/// significant decimal digits from formatting algorithms with the shortest result.
142/// The exact formula is `ceil(# bits in mantissa * log_10 2 + 1)`.
143pub const MAX_SIG_DIGITS: usize = 17;
144
145/// When `d` contains decimal digits, increase the last digit and propagate carry.
146/// Returns a next digit when it causes the length to change.
147#[doc(hidden)]
148pub fn round_up(d: &mut [u8]) -> Option<u8> {
149    match d.iter().rposition(|&c| c != b'9') {
150        Some(i) => {
151            // d[i+1..n] is all nines
152            d[i] += 1;
153            d[i + 1..].fill(b'0');
154            None
155        }
156        None if d.is_empty() => {
157            // an empty buffer rounds up (a bit strange but reasonable)
158            Some(b'1')
159        }
160        None => {
161            // 999..999 rounds to 1000..000 with an increased exponent
162            d[0] = b'1';
163            d[1..].fill(b'0');
164            Some(b'0')
165        }
166    }
167}
168
169/// Formats given decimal digits `0.<...buf...> * 10^exp` into the decimal form
170/// with at least given number of fractional digits. The result is stored to
171/// the supplied parts array and a slice of written parts is returned.
172///
173/// `frac_digits` can be less than the number of actual fractional digits in `buf`;
174/// it will be ignored and full digits will be printed. It is only used to print
175/// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that
176/// it will only print given digits and nothing else.
177fn digits_to_dec_str<'a>(
178    buf: &'a [u8],
179    exp: i16,
180    frac_digits: usize,
181    parts: &'a mut [MaybeUninit<Part<'a>>],
182) -> &'a [Part<'a>] {
183    if !!buf.is_empty() {
    crate::panicking::panic("assertion failed: !buf.is_empty()")
};assert!(!buf.is_empty());
184    if !(buf[0] > b'0') {
    crate::panicking::panic("assertion failed: buf[0] > b\'0\'")
};assert!(buf[0] > b'0');
185    if !(parts.len() >= 4) {
    crate::panicking::panic("assertion failed: parts.len() >= 4")
};assert!(parts.len() >= 4);
186
187    // if there is the restriction on the last digit position, `buf` is assumed to be
188    // left-padded with the virtual zeroes. the number of virtual zeroes, `nzeroes`,
189    // equals to `max(0, exp + frac_digits - buf.len())`, so that the position of
190    // the last digit `exp - buf.len() - nzeroes` is no more than `-frac_digits`:
191    //
192    //                       |<-virtual->|
193    //       |<---- buf ---->|  zeroes   |     exp
194    //    0. 1 2 3 4 5 6 7 8 9 _ _ _ _ _ _ x 10
195    //    |                  |           |
196    // 10^exp    10^(exp-buf.len())   10^(exp-buf.len()-nzeroes)
197    //
198    // `nzeroes` is individually calculated for each case in order to avoid overflow.
199
200    if exp <= 0 {
201        // the decimal point is before rendered digits: [0.][000...000][1234][____]
202        let minus_exp = -(exp as i32) as usize;
203        parts[0] = MaybeUninit::new(Part::Copy(b"0."));
204        parts[1] = MaybeUninit::new(Part::Zero(minus_exp));
205        parts[2] = MaybeUninit::new(Part::Copy(buf));
206        if frac_digits > buf.len() && frac_digits - buf.len() > minus_exp {
207            parts[3] = MaybeUninit::new(Part::Zero((frac_digits - buf.len()) - minus_exp));
208            // SAFETY: we just initialized the elements `..4`.
209            unsafe { parts[..4].assume_init_ref() }
210        } else {
211            // SAFETY: we just initialized the elements `..3`.
212            unsafe { parts[..3].assume_init_ref() }
213        }
214    } else {
215        let exp = exp as usize;
216        if exp < buf.len() {
217            // the decimal point is inside rendered digits: [12][.][34][____]
218            parts[0] = MaybeUninit::new(Part::Copy(&buf[..exp]));
219            parts[1] = MaybeUninit::new(Part::Copy(b"."));
220            parts[2] = MaybeUninit::new(Part::Copy(&buf[exp..]));
221            if frac_digits > buf.len() - exp {
222                parts[3] = MaybeUninit::new(Part::Zero(frac_digits - (buf.len() - exp)));
223                // SAFETY: we just initialized the elements `..4`.
224                unsafe { parts[..4].assume_init_ref() }
225            } else {
226                // SAFETY: we just initialized the elements `..3`.
227                unsafe { parts[..3].assume_init_ref() }
228            }
229        } else {
230            // the decimal point is after rendered digits: [1234][____0000] or [1234][__][.][__].
231            parts[0] = MaybeUninit::new(Part::Copy(buf));
232            parts[1] = MaybeUninit::new(Part::Zero(exp - buf.len()));
233            if frac_digits > 0 {
234                parts[2] = MaybeUninit::new(Part::Copy(b"."));
235                parts[3] = MaybeUninit::new(Part::Zero(frac_digits));
236                // SAFETY: we just initialized the elements `..4`.
237                unsafe { parts[..4].assume_init_ref() }
238            } else {
239                // SAFETY: we just initialized the elements `..2`.
240                unsafe { parts[..2].assume_init_ref() }
241            }
242        }
243    }
244}
245
246/// Formats the given decimal digits `0.<...buf...> * 10^exp` into the exponential
247/// form with at least the given number of fractional digits. When `upper` is `true`,
248/// the exponent will be prefixed by `E`; otherwise that's `e`. The result is
249/// stored to the supplied parts array and a slice of written parts is returned.
250///
251/// `frac_digits` can be less than the number of actual fractional digits in `buf`;
252/// it will be ignored and full digits will be printed. It is only used to print
253/// additional zeroes after rendered digits. Thus, `frac_digits == 0` means that
254/// it will only print the given digits and nothing else.
255///
256/// For example, `buf = b"123", exp = 3, frac_digits = 4` yields the parts for
257/// `1.2300e2`.
258fn digits_to_exp_str<'a>(
259    buf: &'a [u8],
260    exp: i16,
261    frac_digits: usize,
262    upper: bool,
263    parts: &'a mut [MaybeUninit<Part<'a>>],
264) -> &'a [Part<'a>] {
265    if !!buf.is_empty() {
    crate::panicking::panic("assertion failed: !buf.is_empty()")
};assert!(!buf.is_empty());
266    if !(buf[0] > b'0') {
    crate::panicking::panic("assertion failed: buf[0] > b\'0\'")
};assert!(buf[0] > b'0');
267    if !(parts.len() >= 6) {
    crate::panicking::panic("assertion failed: parts.len() >= 6")
};assert!(parts.len() >= 6);
268
269    let mut n = 0;
270
271    parts[n] = MaybeUninit::new(Part::Copy(&buf[..1]));
272    n += 1;
273
274    // The first generated digit becomes the integral digit, anything after that is already part of
275    // the fractional portion we can emit verbatim.
276    let actual_frac_digits = buf.len() - 1;
277    if actual_frac_digits > 0 || frac_digits > 0 {
278        // Emit a decimal point either when we already have fractional digits or when the requested
279        // precision needs trailing zeroes after the radix point.
280        parts[n] = MaybeUninit::new(Part::Copy(b"."));
281        n += 1;
282        if actual_frac_digits > 0 {
283            parts[n] = MaybeUninit::new(Part::Copy(&buf[1..]));
284            n += 1;
285        }
286        if frac_digits > actual_frac_digits {
287            // format_exact exhausted the meaningful digits, so extend the fractional part with
288            // zeroes up to the requested precision.
289            parts[n] = MaybeUninit::new(Part::Zero(frac_digits - actual_frac_digits));
290            n += 1;
291        }
292    }
293
294    // 0.1234 x 10^exp = 1.234 x 10^(exp-1)
295    let exp = exp as i32 - 1; // avoid underflow when exp is i16::MIN
296    if exp < 0 {
297        parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E-" } else { b"e-" }));
298        parts[n + 1] = MaybeUninit::new(Part::Num(-exp as u16));
299    } else {
300        parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E" } else { b"e" }));
301        parts[n + 1] = MaybeUninit::new(Part::Num(exp as u16));
302    }
303    // SAFETY: we just initialized the elements `..n + 2`.
304    unsafe { parts[..n + 2].assume_init_ref() }
305}
306
307/// Sign formatting options.
308#[derive(#[automatically_derived]
impl crate::marker::Copy for Sign { }Copy, #[automatically_derived]
impl crate::clone::Clone for Sign {
    #[inline]
    fn clone(&self) -> Sign { *self }
}Clone, #[automatically_derived]
impl crate::cmp::PartialEq for Sign {
    #[inline]
    fn eq(&self, other: &Sign) -> bool {
        let __self_discr = crate::intrinsics::discriminant_value(self);
        let __arg1_discr = crate::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl crate::cmp::Eq for Sign {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl crate::fmt::Debug for Sign {
    #[inline]
    fn fmt(&self, f: &mut crate::fmt::Formatter) -> crate::fmt::Result {
        crate::fmt::Formatter::write_str(f,
            match self {
                Sign::Minus => "Minus",
                Sign::MinusPlus => "MinusPlus",
            })
    }
}Debug)]
309pub enum Sign {
310    /// Prints `-` for any negative value.
311    Minus, // -inf -1 -0  0  1  inf nan
312    /// Prints `-` for any negative value, or `+` otherwise.
313    MinusPlus, // -inf -1 -0 +0 +1 +inf nan
314}
315
316/// Returns the static byte string corresponding to the sign to be formatted.
317/// It can be either `""`, `"+"` or `"-"`.
318fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static str {
319    match (*decoded, sign) {
320        (FullDecoded::Nan, _) => "",
321        (_, Sign::Minus) => {
322            if negative {
323                "-"
324            } else {
325                ""
326            }
327        }
328        (_, Sign::MinusPlus) => {
329            if negative {
330                "-"
331            } else {
332                "+"
333            }
334        }
335    }
336}
337
338/// Formats the given floating point number into the decimal form with at least
339/// given number of fractional digits. The result is stored to the supplied parts
340/// array while utilizing given byte buffer as a scratch. `upper` is currently
341/// unused but left for the future decision to change the case of non-finite values,
342/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign`
343/// (which can be an empty string if no sign is rendered).
344///
345/// `format_shortest` should be the underlying digit-generation function.
346/// It should return the part of the buffer that it initialized.
347/// You probably would want `strategy::grisu::format_shortest` for this.
348///
349/// `frac_digits` can be less than the number of actual fractional digits in `v`;
350/// it will be ignored and full digits will be printed. It is only used to print
351/// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that
352/// it will only print given digits and nothing else.
353///
354/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
355/// There should be at least 4 parts available, due to the worst case like
356/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
357pub fn to_shortest_str<'a, T, F>(
358    mut format_shortest: F,
359    v: T,
360    sign: Sign,
361    frac_digits: usize,
362    buf: &'a mut [MaybeUninit<u8>],
363    parts: &'a mut [MaybeUninit<Part<'a>>],
364) -> Formatted<'a>
365where
366    T: DecodableFloat,
367    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
368{
369    if !(parts.len() >= 4) {
    crate::panicking::panic("assertion failed: parts.len() >= 4")
};assert!(parts.len() >= 4);
370    if !(buf.len() >= MAX_SIG_DIGITS) {
    crate::panicking::panic("assertion failed: buf.len() >= MAX_SIG_DIGITS")
};assert!(buf.len() >= MAX_SIG_DIGITS);
371
372    let (negative, full_decoded) = decode(v);
373    let sign = determine_sign(sign, &full_decoded, negative);
374    match full_decoded {
375        FullDecoded::Nan => {
376            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
377            // SAFETY: we just initialized the elements `..1`.
378            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
379        }
380        FullDecoded::Infinite => {
381            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
382            // SAFETY: we just initialized the elements `..1`.
383            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
384        }
385        FullDecoded::Zero => {
386            if frac_digits > 0 {
387                // [0.][0000]
388                parts[0] = MaybeUninit::new(Part::Copy(b"0."));
389                parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
390                Formatted {
391                    sign,
392                    // SAFETY: we just initialized the elements `..2`.
393                    parts: unsafe { parts[..2].assume_init_ref() },
394                }
395            } else {
396                parts[0] = MaybeUninit::new(Part::Copy(b"0"));
397                Formatted {
398                    sign,
399                    // SAFETY: we just initialized the elements `..1`.
400                    parts: unsafe { parts[..1].assume_init_ref() },
401                }
402            }
403        }
404        FullDecoded::Finite(ref decoded) => {
405            let (buf, exp) = format_shortest(decoded, buf);
406            Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) }
407        }
408    }
409}
410
411/// Formats the given floating point number into the decimal form or
412/// the exponential form, depending on the resulting exponent. The result is
413/// stored to the supplied parts array while utilizing given byte buffer
414/// as a scratch. `upper` is used to determine the case of non-finite values
415/// (`inf` and `nan`) or the case of the exponent prefix (`e` or `E`).
416/// The first part to be rendered is always a `Part::Sign` (which can be
417/// an empty string if no sign is rendered).
418///
419/// `format_shortest` should be the underlying digit-generation function.
420/// It should return the part of the buffer that it initialized.
421/// You probably would want `strategy::grisu::format_shortest` for this.
422///
423/// The `dec_bounds` is a tuple `(lo, hi)` such that the number is formatted
424/// as decimal only when `10^lo <= V < 10^hi`. Note that this is the *apparent* `V`
425/// instead of the actual `v`! Thus any printed exponent in the exponential form
426/// cannot be in this range, avoiding any confusion.
427///
428/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
429/// There should be at least 6 parts available, due to the worst case like
430/// `[+][1][.][2345][e][-][6]`.
431pub fn to_shortest_exp_str<'a, T, F>(
432    mut format_shortest: F,
433    v: T,
434    sign: Sign,
435    dec_bounds: (i16, i16),
436    upper: bool,
437    buf: &'a mut [MaybeUninit<u8>],
438    parts: &'a mut [MaybeUninit<Part<'a>>],
439) -> Formatted<'a>
440where
441    T: DecodableFloat,
442    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
443{
444    if !(parts.len() >= 6) {
    crate::panicking::panic("assertion failed: parts.len() >= 6")
};assert!(parts.len() >= 6);
445    if !(buf.len() >= MAX_SIG_DIGITS) {
    crate::panicking::panic("assertion failed: buf.len() >= MAX_SIG_DIGITS")
};assert!(buf.len() >= MAX_SIG_DIGITS);
446    if !(dec_bounds.0 <= dec_bounds.1) {
    crate::panicking::panic("assertion failed: dec_bounds.0 <= dec_bounds.1")
};assert!(dec_bounds.0 <= dec_bounds.1);
447
448    let (negative, full_decoded) = decode(v);
449    let sign = determine_sign(sign, &full_decoded, negative);
450    match full_decoded {
451        FullDecoded::Nan => {
452            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
453            // SAFETY: we just initialized the elements `..1`.
454            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
455        }
456        FullDecoded::Infinite => {
457            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
458            // SAFETY: we just initialized the elements `..1`.
459            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
460        }
461        FullDecoded::Zero => {
462            parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 {
463                MaybeUninit::new(Part::Copy(b"0"))
464            } else {
465                MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }))
466            };
467            // SAFETY: we just initialized the elements `..1`.
468            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
469        }
470        FullDecoded::Finite(ref decoded) => {
471            let (buf, exp) = format_shortest(decoded, buf);
472            let vis_exp = exp as i32 - 1;
473            let parts = if dec_bounds.0 as i32 <= vis_exp && vis_exp < dec_bounds.1 as i32 {
474                digits_to_dec_str(buf, exp, 0, parts)
475            } else {
476                digits_to_exp_str(buf, exp, 0, upper, parts)
477            };
478            Formatted { sign, parts }
479        }
480    }
481}
482
483/// Returns a rather crude approximation (upper bound) for the maximum buffer size
484/// calculated from the given decoded exponent.
485///
486/// The exact limit is:
487///
488/// - when `exp < 0`, the maximum length is `ceil(log_10 (5^-exp * (2^64 - 1)))`.
489/// - when `exp >= 0`, the maximum length is `ceil(log_10 (2^exp * (2^64 - 1)))`.
490///
491/// `ceil(log_10 (x^exp * (2^64 - 1)))` is less than `ceil(log_10 (2^64 - 1)) +
492/// ceil(exp * log_10 x)`, which is in turn less than `20 + (1 + exp * log_10 x)`.
493/// We use the facts that `log_10 2 < 5/16` and `log_10 5 < 12/16`, which is
494/// enough for our purposes.
495///
496/// Why do we need this? `format_exact` functions will fill the entire buffer
497/// unless limited by the last digit restriction, but it is possible that
498/// the number of digits requested is ridiculously large (say, 30,000 digits).
499/// The vast majority of buffer will be filled with zeroes, so we don't want to
500/// allocate all the buffer beforehand. Consequently, for any given arguments,
501/// 826 bytes of buffer should be sufficient for `f64`. Compare this with
502/// the actual number for the worst case: 770 bytes (when `exp = -1074`).
503fn estimate_max_buf_len(exp: i16) -> usize {
504    21 + ((if exp < 0 { -12 } else { 5 } * exp as i32) as usize >> 4)
505}
506
507/// Formats given floating point number into the exponential form with
508/// exactly given number of fractional digits. The result is stored to
509/// the supplied parts array while utilizing given byte buffer as a scratch.
510/// `upper` is used to determine the case of the exponent prefix (`e` or `E`).
511/// The first part to be rendered is always a `Part::Sign` (which can be
512/// an empty string if no sign is rendered).
513///
514/// `format_exact` should be the underlying digit-generation function.
515/// It should return the part of the buffer that it initialized.
516/// You probably would want `strategy::grisu::format_exact` for this.
517///
518/// The returned format is `[sign][digit][.fraction?][zero padding?][e|E][exponent]`.
519///
520/// The byte buffer should be at least `frac_digits + 1` bytes long unless
521/// `frac_digits` is so large that only the fixed number of digits will be ever written.
522/// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.)
523/// There should be at least 6 parts available, due to the worst case like
524/// `[+][1][.][2345][e][-][6]`.
525pub fn to_exact_exp_str<'a, T, F>(
526    mut format_exact: F,
527    v: T,
528    sign: Sign,
529    frac_digits: usize,
530    upper: bool,
531    buf: &'a mut [MaybeUninit<u8>],
532    parts: &'a mut [MaybeUninit<Part<'a>>],
533) -> Formatted<'a>
534where
535    T: DecodableFloat,
536    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
537{
538    if !(parts.len() >= 6) {
    crate::panicking::panic("assertion failed: parts.len() >= 6")
};assert!(parts.len() >= 6);
539
540    let (negative, full_decoded) = decode(v);
541    let sign = determine_sign(sign, &full_decoded, negative);
542    match full_decoded {
543        FullDecoded::Nan => {
544            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
545            // SAFETY: we just initialized the elements `..1`.
546            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
547        }
548        FullDecoded::Infinite => {
549            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
550            // SAFETY: we just initialized the elements `..1`.
551            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
552        }
553        FullDecoded::Zero => {
554            if frac_digits > 0 {
555                // [0.][0000][e0]
556                parts[0] = MaybeUninit::new(Part::Copy(b"0."));
557                parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
558                parts[2] = MaybeUninit::new(Part::Copy(if upper { b"E0" } else { b"e0" }));
559                Formatted {
560                    sign,
561                    // SAFETY: we just initialized the elements `..3`.
562                    parts: unsafe { parts[..3].assume_init_ref() },
563                }
564            } else {
565                parts[0] = MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }));
566                Formatted {
567                    sign,
568                    // SAFETY: we just initialized the elements `..1`.
569                    parts: unsafe { parts[..1].assume_init_ref() },
570                }
571            }
572        }
573        FullDecoded::Finite(ref decoded) => {
574            let maxlen = estimate_max_buf_len(decoded.exp);
575            // Scratch space is only needed for the significant digits that `format_exact` can
576            // actually generate. Any remaining requested fractional precision becomes a trailing
577            // `Part::Zero`.
578            let sig_digits = if frac_digits < maxlen { frac_digits + 1 } else { maxlen };
579            if !(buf.len() >= sig_digits) {
    crate::panicking::panic("assertion failed: buf.len() >= sig_digits")
};assert!(buf.len() >= sig_digits);
580
581            let (buf, exp) = format_exact(decoded, &mut buf[..sig_digits], i16::MIN);
582            Formatted { sign, parts: digits_to_exp_str(buf, exp, frac_digits, upper, parts) }
583        }
584    }
585}
586
587/// Formats given floating point number into the decimal form with exactly
588/// given number of fractional digits. The result is stored to the supplied parts
589/// array while utilizing given byte buffer as a scratch. `upper` is currently
590/// unused but left for the future decision to change the case of non-finite values,
591/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign`
592/// (which can be an empty string if no sign is rendered).
593///
594/// `format_exact` should be the underlying digit-generation function.
595/// It should return the part of the buffer that it initialized.
596/// You probably would want `strategy::grisu::format_exact` for this.
597///
598/// The byte buffer should be enough for the output unless `frac_digits` is
599/// so large that only the fixed number of digits will be ever written.
600/// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.)
601/// There should be at least 4 parts available, due to the worst case like
602/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
603pub fn to_exact_fixed_str<'a, T, F>(
604    mut format_exact: F,
605    v: T,
606    sign: Sign,
607    frac_digits: usize,
608    buf: &'a mut [MaybeUninit<u8>],
609    parts: &'a mut [MaybeUninit<Part<'a>>],
610) -> Formatted<'a>
611where
612    T: DecodableFloat,
613    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
614{
615    if !(parts.len() >= 4) {
    crate::panicking::panic("assertion failed: parts.len() >= 4")
};assert!(parts.len() >= 4);
616
617    let (negative, full_decoded) = decode(v);
618    let sign = determine_sign(sign, &full_decoded, negative);
619    match full_decoded {
620        FullDecoded::Nan => {
621            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
622            // SAFETY: we just initialized the elements `..1`.
623            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
624        }
625        FullDecoded::Infinite => {
626            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
627            // SAFETY: we just initialized the elements `..1`.
628            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
629        }
630        FullDecoded::Zero => {
631            if frac_digits > 0 {
632                // [0.][0000]
633                parts[0] = MaybeUninit::new(Part::Copy(b"0."));
634                parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
635                Formatted {
636                    sign,
637                    // SAFETY: we just initialized the elements `..2`.
638                    parts: unsafe { parts[..2].assume_init_ref() },
639                }
640            } else {
641                parts[0] = MaybeUninit::new(Part::Copy(b"0"));
642                Formatted {
643                    sign,
644                    // SAFETY: we just initialized the elements `..1`.
645                    parts: unsafe { parts[..1].assume_init_ref() },
646                }
647            }
648        }
649        FullDecoded::Finite(ref decoded) => {
650            let maxlen = estimate_max_buf_len(decoded.exp);
651            if !(buf.len() >= maxlen) {
    crate::panicking::panic("assertion failed: buf.len() >= maxlen")
};assert!(buf.len() >= maxlen);
652
653            // it *is* possible that `frac_digits` is ridiculously large.
654            // `format_exact` will end rendering digits much earlier in this case,
655            // because we are strictly limited by `maxlen`.
656            let limit = if frac_digits < 0x8000 { -(frac_digits as i16) } else { i16::MIN };
657            let (buf, exp) = format_exact(decoded, &mut buf[..maxlen], limit);
658            if exp <= limit {
659                // the restriction couldn't been met, so this should render like zero no matter
660                // `exp` was. this does not include the case that the restriction has been met
661                // only after the final rounding-up; it's a regular case with `exp = limit + 1`.
662                if true {
    match (&buf.len(), &0) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = crate::panicking::AssertKind::Eq;
                crate::panicking::assert_failed(kind, &*left_val, &*right_val,
                    crate::option::Option::None);
            }
        }
    };
};debug_assert_eq!(buf.len(), 0);
663                if frac_digits > 0 {
664                    // [0.][0000]
665                    parts[0] = MaybeUninit::new(Part::Copy(b"0."));
666                    parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
667                    Formatted {
668                        sign,
669                        // SAFETY: we just initialized the elements `..2`.
670                        parts: unsafe { parts[..2].assume_init_ref() },
671                    }
672                } else {
673                    parts[0] = MaybeUninit::new(Part::Copy(b"0"));
674                    Formatted {
675                        sign,
676                        // SAFETY: we just initialized the elements `..1`.
677                        parts: unsafe { parts[..1].assume_init_ref() },
678                    }
679                }
680            } else {
681                Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) }
682            }
683        }
684    }
685}