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}