1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use fmt::{Formatter, Result, LowerExp, UpperExp, Display, Debug};
15 // Don't inline this so callers don't use the stack space this function
16 // requires unless they have to.
18 fn float_to_decimal_common_exact<T>(fmt: &mut Formatter, num: &T,
19 sign: flt2dec::Sign, precision: usize) -> Result
20 where T: flt2dec::DecodableFloat
23 let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64
24 let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized();
25 // FIXME(#53491): Technically, this is calling `get_mut` on an uninitialized
26 // `MaybeUninit` (here and elsewhere in this file). Revisit this once
27 // we decided whether that is valid or not.
28 let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact,
29 *num, sign, precision,
30 false, buf.get_mut(), parts.get_mut());
31 fmt.pad_formatted_parts(&formatted)
35 // Don't inline this so callers that call both this and the above won't wind
36 // up using the combined stack space of both functions in some cases.
38 fn float_to_decimal_common_shortest<T>(fmt: &mut Formatter, num: &T,
39 sign: flt2dec::Sign, precision: usize) -> Result
40 where T: flt2dec::DecodableFloat
43 // enough for f32 and f64
44 let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized();
45 let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized();
46 let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num,
47 sign, precision, false, buf.get_mut(),
49 fmt.pad_formatted_parts(&formatted)
53 // Common code of floating point Debug and Display.
54 fn float_to_decimal_common<T>(fmt: &mut Formatter, num: &T,
55 negative_zero: bool, min_precision: usize) -> Result
56 where T: flt2dec::DecodableFloat
58 let force_sign = fmt.sign_plus();
59 let sign = match (force_sign, negative_zero) {
60 (false, false) => flt2dec::Sign::Minus,
61 (false, true) => flt2dec::Sign::MinusRaw,
62 (true, false) => flt2dec::Sign::MinusPlus,
63 (true, true) => flt2dec::Sign::MinusPlusRaw,
66 if let Some(precision) = fmt.precision {
67 float_to_decimal_common_exact(fmt, num, sign, precision)
69 float_to_decimal_common_shortest(fmt, num, sign, min_precision)
73 // Don't inline this so callers don't use the stack space this function
74 // requires unless they have to.
76 fn float_to_exponential_common_exact<T>(fmt: &mut Formatter, num: &T,
77 sign: flt2dec::Sign, precision: usize,
78 upper: bool) -> Result
79 where T: flt2dec::DecodableFloat
82 let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64
83 let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized();
84 let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact,
85 *num, sign, precision,
86 upper, buf.get_mut(), parts.get_mut());
87 fmt.pad_formatted_parts(&formatted)
91 // Don't inline this so callers that call both this and the above won't wind
92 // up using the combined stack space of both functions in some cases.
94 fn float_to_exponential_common_shortest<T>(fmt: &mut Formatter,
95 num: &T, sign: flt2dec::Sign,
96 upper: bool) -> Result
97 where T: flt2dec::DecodableFloat
100 // enough for f32 and f64
101 let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized();
102 let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized();
103 let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest,
104 *num, sign, (0, 0), upper,
105 buf.get_mut(), parts.get_mut());
106 fmt.pad_formatted_parts(&formatted)
110 // Common code of floating point LowerExp and UpperExp.
111 fn float_to_exponential_common<T>(fmt: &mut Formatter, num: &T, upper: bool) -> Result
112 where T: flt2dec::DecodableFloat
114 let force_sign = fmt.sign_plus();
115 let sign = match force_sign {
116 false => flt2dec::Sign::Minus,
117 true => flt2dec::Sign::MinusPlus,
120 if let Some(precision) = fmt.precision {
121 // 1 integral digit + `precision` fractional digits = `precision + 1` total digits
122 float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper)
124 float_to_exponential_common_shortest(fmt, num, sign, upper)
128 macro_rules! floating {
130 #[stable(feature = "rust1", since = "1.0.0")]
132 fn fmt(&self, fmt: &mut Formatter) -> Result {
133 float_to_decimal_common(fmt, self, true, 1)
137 #[stable(feature = "rust1", since = "1.0.0")]
138 impl Display for $ty {
139 fn fmt(&self, fmt: &mut Formatter) -> Result {
140 float_to_decimal_common(fmt, self, false, 0)
144 #[stable(feature = "rust1", since = "1.0.0")]
145 impl LowerExp for $ty {
146 fn fmt(&self, fmt: &mut Formatter) -> Result {
147 float_to_exponential_common(fmt, self, false)
151 #[stable(feature = "rust1", since = "1.0.0")]
152 impl UpperExp for $ty {
153 fn fmt(&self, fmt: &mut Formatter) -> Result {
154 float_to_exponential_common(fmt, self, true)