core/num/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    assert!(!buf.is_empty());
184    assert!(buf[0] > b'0');
185    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 significant 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/// `min_digits` can be less than the number of actual significant 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, `min_digits == 0` means that
254/// it will only print the given digits and nothing else.
255fn digits_to_exp_str<'a>(
256    buf: &'a [u8],
257    exp: i16,
258    min_ndigits: usize,
259    upper: bool,
260    parts: &'a mut [MaybeUninit<Part<'a>>],
261) -> &'a [Part<'a>] {
262    assert!(!buf.is_empty());
263    assert!(buf[0] > b'0');
264    assert!(parts.len() >= 6);
265
266    let mut n = 0;
267
268    parts[n] = MaybeUninit::new(Part::Copy(&buf[..1]));
269    n += 1;
270
271    if buf.len() > 1 || min_ndigits > 1 {
272        parts[n] = MaybeUninit::new(Part::Copy(b"."));
273        parts[n + 1] = MaybeUninit::new(Part::Copy(&buf[1..]));
274        n += 2;
275        if min_ndigits > buf.len() {
276            parts[n] = MaybeUninit::new(Part::Zero(min_ndigits - buf.len()));
277            n += 1;
278        }
279    }
280
281    // 0.1234 x 10^exp = 1.234 x 10^(exp-1)
282    let exp = exp as i32 - 1; // avoid underflow when exp is i16::MIN
283    if exp < 0 {
284        parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E-" } else { b"e-" }));
285        parts[n + 1] = MaybeUninit::new(Part::Num(-exp as u16));
286    } else {
287        parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E" } else { b"e" }));
288        parts[n + 1] = MaybeUninit::new(Part::Num(exp as u16));
289    }
290    // SAFETY: we just initialized the elements `..n + 2`.
291    unsafe { parts[..n + 2].assume_init_ref() }
292}
293
294/// Sign formatting options.
295#[derive(Copy, Clone, PartialEq, Eq, Debug)]
296pub enum Sign {
297    /// Prints `-` for any negative value.
298    Minus, // -inf -1 -0  0  1  inf nan
299    /// Prints `-` for any negative value, or `+` otherwise.
300    MinusPlus, // -inf -1 -0 +0 +1 +inf nan
301}
302
303/// Returns the static byte string corresponding to the sign to be formatted.
304/// It can be either `""`, `"+"` or `"-"`.
305fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static str {
306    match (*decoded, sign) {
307        (FullDecoded::Nan, _) => "",
308        (_, Sign::Minus) => {
309            if negative {
310                "-"
311            } else {
312                ""
313            }
314        }
315        (_, Sign::MinusPlus) => {
316            if negative {
317                "-"
318            } else {
319                "+"
320            }
321        }
322    }
323}
324
325/// Formats the given floating point number into the decimal form with at least
326/// given number of fractional digits. The result is stored to the supplied parts
327/// array while utilizing given byte buffer as a scratch. `upper` is currently
328/// unused but left for the future decision to change the case of non-finite values,
329/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign`
330/// (which can be an empty string if no sign is rendered).
331///
332/// `format_shortest` should be the underlying digit-generation function.
333/// It should return the part of the buffer that it initialized.
334/// You probably would want `strategy::grisu::format_shortest` for this.
335///
336/// `frac_digits` can be less than the number of actual fractional digits in `v`;
337/// it will be ignored and full digits will be printed. It is only used to print
338/// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that
339/// it will only print given digits and nothing else.
340///
341/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
342/// There should be at least 4 parts available, due to the worst case like
343/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
344pub fn to_shortest_str<'a, T, F>(
345    mut format_shortest: F,
346    v: T,
347    sign: Sign,
348    frac_digits: usize,
349    buf: &'a mut [MaybeUninit<u8>],
350    parts: &'a mut [MaybeUninit<Part<'a>>],
351) -> Formatted<'a>
352where
353    T: DecodableFloat,
354    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
355{
356    assert!(parts.len() >= 4);
357    assert!(buf.len() >= MAX_SIG_DIGITS);
358
359    let (negative, full_decoded) = decode(v);
360    let sign = determine_sign(sign, &full_decoded, negative);
361    match full_decoded {
362        FullDecoded::Nan => {
363            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
364            // SAFETY: we just initialized the elements `..1`.
365            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
366        }
367        FullDecoded::Infinite => {
368            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
369            // SAFETY: we just initialized the elements `..1`.
370            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
371        }
372        FullDecoded::Zero => {
373            if frac_digits > 0 {
374                // [0.][0000]
375                parts[0] = MaybeUninit::new(Part::Copy(b"0."));
376                parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
377                Formatted {
378                    sign,
379                    // SAFETY: we just initialized the elements `..2`.
380                    parts: unsafe { parts[..2].assume_init_ref() },
381                }
382            } else {
383                parts[0] = MaybeUninit::new(Part::Copy(b"0"));
384                Formatted {
385                    sign,
386                    // SAFETY: we just initialized the elements `..1`.
387                    parts: unsafe { parts[..1].assume_init_ref() },
388                }
389            }
390        }
391        FullDecoded::Finite(ref decoded) => {
392            let (buf, exp) = format_shortest(decoded, buf);
393            Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) }
394        }
395    }
396}
397
398/// Formats the given floating point number into the decimal form or
399/// the exponential form, depending on the resulting exponent. The result is
400/// stored to the supplied parts array while utilizing given byte buffer
401/// as a scratch. `upper` is used to determine the case of non-finite values
402/// (`inf` and `nan`) or the case of the exponent prefix (`e` or `E`).
403/// The first part to be rendered is always a `Part::Sign` (which can be
404/// an empty string if no sign is rendered).
405///
406/// `format_shortest` should be the underlying digit-generation function.
407/// It should return the part of the buffer that it initialized.
408/// You probably would want `strategy::grisu::format_shortest` for this.
409///
410/// The `dec_bounds` is a tuple `(lo, hi)` such that the number is formatted
411/// as decimal only when `10^lo <= V < 10^hi`. Note that this is the *apparent* `V`
412/// instead of the actual `v`! Thus any printed exponent in the exponential form
413/// cannot be in this range, avoiding any confusion.
414///
415/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
416/// There should be at least 6 parts available, due to the worst case like
417/// `[+][1][.][2345][e][-][6]`.
418pub fn to_shortest_exp_str<'a, T, F>(
419    mut format_shortest: F,
420    v: T,
421    sign: Sign,
422    dec_bounds: (i16, i16),
423    upper: bool,
424    buf: &'a mut [MaybeUninit<u8>],
425    parts: &'a mut [MaybeUninit<Part<'a>>],
426) -> Formatted<'a>
427where
428    T: DecodableFloat,
429    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
430{
431    assert!(parts.len() >= 6);
432    assert!(buf.len() >= MAX_SIG_DIGITS);
433    assert!(dec_bounds.0 <= dec_bounds.1);
434
435    let (negative, full_decoded) = decode(v);
436    let sign = determine_sign(sign, &full_decoded, negative);
437    match full_decoded {
438        FullDecoded::Nan => {
439            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
440            // SAFETY: we just initialized the elements `..1`.
441            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
442        }
443        FullDecoded::Infinite => {
444            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
445            // SAFETY: we just initialized the elements `..1`.
446            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
447        }
448        FullDecoded::Zero => {
449            parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 {
450                MaybeUninit::new(Part::Copy(b"0"))
451            } else {
452                MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }))
453            };
454            // SAFETY: we just initialized the elements `..1`.
455            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
456        }
457        FullDecoded::Finite(ref decoded) => {
458            let (buf, exp) = format_shortest(decoded, buf);
459            let vis_exp = exp as i32 - 1;
460            let parts = if dec_bounds.0 as i32 <= vis_exp && vis_exp < dec_bounds.1 as i32 {
461                digits_to_dec_str(buf, exp, 0, parts)
462            } else {
463                digits_to_exp_str(buf, exp, 0, upper, parts)
464            };
465            Formatted { sign, parts }
466        }
467    }
468}
469
470/// Returns a rather crude approximation (upper bound) for the maximum buffer size
471/// calculated from the given decoded exponent.
472///
473/// The exact limit is:
474///
475/// - when `exp < 0`, the maximum length is `ceil(log_10 (5^-exp * (2^64 - 1)))`.
476/// - when `exp >= 0`, the maximum length is `ceil(log_10 (2^exp * (2^64 - 1)))`.
477///
478/// `ceil(log_10 (x^exp * (2^64 - 1)))` is less than `ceil(log_10 (2^64 - 1)) +
479/// ceil(exp * log_10 x)`, which is in turn less than `20 + (1 + exp * log_10 x)`.
480/// We use the facts that `log_10 2 < 5/16` and `log_10 5 < 12/16`, which is
481/// enough for our purposes.
482///
483/// Why do we need this? `format_exact` functions will fill the entire buffer
484/// unless limited by the last digit restriction, but it is possible that
485/// the number of digits requested is ridiculously large (say, 30,000 digits).
486/// The vast majority of buffer will be filled with zeroes, so we don't want to
487/// allocate all the buffer beforehand. Consequently, for any given arguments,
488/// 826 bytes of buffer should be sufficient for `f64`. Compare this with
489/// the actual number for the worst case: 770 bytes (when `exp = -1074`).
490fn estimate_max_buf_len(exp: i16) -> usize {
491    21 + ((if exp < 0 { -12 } else { 5 } * exp as i32) as usize >> 4)
492}
493
494/// Formats given floating point number into the exponential form with
495/// exactly given number of significant digits. The result is stored to
496/// the supplied parts array while utilizing given byte buffer as a scratch.
497/// `upper` is used to determine the case of the exponent prefix (`e` or `E`).
498/// The first part to be rendered is always a `Part::Sign` (which can be
499/// an empty string if no sign is rendered).
500///
501/// `format_exact` should be the underlying digit-generation function.
502/// It should return the part of the buffer that it initialized.
503/// You probably would want `strategy::grisu::format_exact` for this.
504///
505/// The byte buffer should be at least `ndigits` bytes long unless `ndigits` is
506/// so large that only the fixed number of digits will be ever written.
507/// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.)
508/// There should be at least 6 parts available, due to the worst case like
509/// `[+][1][.][2345][e][-][6]`.
510pub fn to_exact_exp_str<'a, T, F>(
511    mut format_exact: F,
512    v: T,
513    sign: Sign,
514    ndigits: usize,
515    upper: bool,
516    buf: &'a mut [MaybeUninit<u8>],
517    parts: &'a mut [MaybeUninit<Part<'a>>],
518) -> Formatted<'a>
519where
520    T: DecodableFloat,
521    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
522{
523    assert!(parts.len() >= 6);
524    assert!(ndigits > 0);
525
526    let (negative, full_decoded) = decode(v);
527    let sign = determine_sign(sign, &full_decoded, negative);
528    match full_decoded {
529        FullDecoded::Nan => {
530            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
531            // SAFETY: we just initialized the elements `..1`.
532            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
533        }
534        FullDecoded::Infinite => {
535            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
536            // SAFETY: we just initialized the elements `..1`.
537            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
538        }
539        FullDecoded::Zero => {
540            if ndigits > 1 {
541                // [0.][0000][e0]
542                parts[0] = MaybeUninit::new(Part::Copy(b"0."));
543                parts[1] = MaybeUninit::new(Part::Zero(ndigits - 1));
544                parts[2] = MaybeUninit::new(Part::Copy(if upper { b"E0" } else { b"e0" }));
545                Formatted {
546                    sign,
547                    // SAFETY: we just initialized the elements `..3`.
548                    parts: unsafe { parts[..3].assume_init_ref() },
549                }
550            } else {
551                parts[0] = MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }));
552                Formatted {
553                    sign,
554                    // SAFETY: we just initialized the elements `..1`.
555                    parts: unsafe { parts[..1].assume_init_ref() },
556                }
557            }
558        }
559        FullDecoded::Finite(ref decoded) => {
560            let maxlen = estimate_max_buf_len(decoded.exp);
561            assert!(buf.len() >= ndigits || buf.len() >= maxlen);
562
563            let trunc = if ndigits < maxlen { ndigits } else { maxlen };
564            let (buf, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN);
565            Formatted { sign, parts: digits_to_exp_str(buf, exp, ndigits, upper, parts) }
566        }
567    }
568}
569
570/// Formats given floating point number into the decimal form with exactly
571/// given number of fractional digits. The result is stored to the supplied parts
572/// array while utilizing given byte buffer as a scratch. `upper` is currently
573/// unused but left for the future decision to change the case of non-finite values,
574/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign`
575/// (which can be an empty string if no sign is rendered).
576///
577/// `format_exact` should be the underlying digit-generation function.
578/// It should return the part of the buffer that it initialized.
579/// You probably would want `strategy::grisu::format_exact` for this.
580///
581/// The byte buffer should be enough for the output unless `frac_digits` is
582/// so large that only the fixed number of digits will be ever written.
583/// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.)
584/// There should be at least 4 parts available, due to the worst case like
585/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
586pub fn to_exact_fixed_str<'a, T, F>(
587    mut format_exact: F,
588    v: T,
589    sign: Sign,
590    frac_digits: usize,
591    buf: &'a mut [MaybeUninit<u8>],
592    parts: &'a mut [MaybeUninit<Part<'a>>],
593) -> Formatted<'a>
594where
595    T: DecodableFloat,
596    F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
597{
598    assert!(parts.len() >= 4);
599
600    let (negative, full_decoded) = decode(v);
601    let sign = determine_sign(sign, &full_decoded, negative);
602    match full_decoded {
603        FullDecoded::Nan => {
604            parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
605            // SAFETY: we just initialized the elements `..1`.
606            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
607        }
608        FullDecoded::Infinite => {
609            parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
610            // SAFETY: we just initialized the elements `..1`.
611            Formatted { sign, parts: unsafe { parts[..1].assume_init_ref() } }
612        }
613        FullDecoded::Zero => {
614            if frac_digits > 0 {
615                // [0.][0000]
616                parts[0] = MaybeUninit::new(Part::Copy(b"0."));
617                parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
618                Formatted {
619                    sign,
620                    // SAFETY: we just initialized the elements `..2`.
621                    parts: unsafe { parts[..2].assume_init_ref() },
622                }
623            } else {
624                parts[0] = MaybeUninit::new(Part::Copy(b"0"));
625                Formatted {
626                    sign,
627                    // SAFETY: we just initialized the elements `..1`.
628                    parts: unsafe { parts[..1].assume_init_ref() },
629                }
630            }
631        }
632        FullDecoded::Finite(ref decoded) => {
633            let maxlen = estimate_max_buf_len(decoded.exp);
634            assert!(buf.len() >= maxlen);
635
636            // it *is* possible that `frac_digits` is ridiculously large.
637            // `format_exact` will end rendering digits much earlier in this case,
638            // because we are strictly limited by `maxlen`.
639            let limit = if frac_digits < 0x8000 { -(frac_digits as i16) } else { i16::MIN };
640            let (buf, exp) = format_exact(decoded, &mut buf[..maxlen], limit);
641            if exp <= limit {
642                // the restriction couldn't been met, so this should render like zero no matter
643                // `exp` was. this does not include the case that the restriction has been met
644                // only after the final rounding-up; it's a regular case with `exp = limit + 1`.
645                debug_assert_eq!(buf.len(), 0);
646                if frac_digits > 0 {
647                    // [0.][0000]
648                    parts[0] = MaybeUninit::new(Part::Copy(b"0."));
649                    parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
650                    Formatted {
651                        sign,
652                        // SAFETY: we just initialized the elements `..2`.
653                        parts: unsafe { parts[..2].assume_init_ref() },
654                    }
655                } else {
656                    parts[0] = MaybeUninit::new(Part::Copy(b"0"));
657                    Formatted {
658                        sign,
659                        // SAFETY: we just initialized the elements `..1`.
660                        parts: unsafe { parts[..1].assume_init_ref() },
661                    }
662                }
663            } else {
664                Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) }
665            }
666        }
667    }
668}