]> git.lizzy.rs Git - rust.git/blob - src/libcore/fmt/float.rs
Auto merge of #44060 - taleks:issue-43205, r=arielb1
[rust.git] / src / libcore / fmt / float.rs
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.
4 //
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.
10
11 use fmt::{Formatter, Result, LowerExp, UpperExp, Display, Debug};
12 use mem;
13 use num::flt2dec;
14
15 // Don't inline this so callers don't use the stack space this function
16 // requires unless they have to.
17 #[inline(never)]
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
21 {
22     unsafe {
23         let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64
24         let mut parts: [flt2dec::Part; 4] = mem::uninitialized();
25         let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact,
26                                                     *num, sign, precision,
27                                                     false, &mut buf, &mut parts);
28         fmt.pad_formatted_parts(&formatted)
29     }
30 }
31
32 // Don't inline this so callers that call both this and the above won't wind
33 // up using the combined stack space of both functions in some cases.
34 #[inline(never)]
35 fn float_to_decimal_common_shortest<T>(fmt: &mut Formatter,
36                                        num: &T, sign: flt2dec::Sign) -> Result
37     where T: flt2dec::DecodableFloat
38 {
39     unsafe {
40         // enough for f32 and f64
41         let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized();
42         let mut parts: [flt2dec::Part; 4] = mem::uninitialized();
43         let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest,
44                                                  *num, sign, 0, false, &mut buf, &mut parts);
45         fmt.pad_formatted_parts(&formatted)
46     }
47 }
48
49 // Common code of floating point Debug and Display.
50 fn float_to_decimal_common<T>(fmt: &mut Formatter, num: &T, negative_zero: bool) -> Result
51     where T: flt2dec::DecodableFloat
52 {
53     let force_sign = fmt.sign_plus();
54     let sign = match (force_sign, negative_zero) {
55         (false, false) => flt2dec::Sign::Minus,
56         (false, true)  => flt2dec::Sign::MinusRaw,
57         (true,  false) => flt2dec::Sign::MinusPlus,
58         (true,  true)  => flt2dec::Sign::MinusPlusRaw,
59     };
60
61     if let Some(precision) = fmt.precision {
62         float_to_decimal_common_exact(fmt, num, sign, precision)
63     } else {
64         float_to_decimal_common_shortest(fmt, num, sign)
65     }
66 }
67
68 // Don't inline this so callers don't use the stack space this function
69 // requires unless they have to.
70 #[inline(never)]
71 fn float_to_exponential_common_exact<T>(fmt: &mut Formatter, num: &T,
72                                         sign: flt2dec::Sign, precision: usize,
73                                         upper: bool) -> Result
74     where T: flt2dec::DecodableFloat
75 {
76     unsafe {
77         let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64
78         let mut parts: [flt2dec::Part; 6] = mem::uninitialized();
79         let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact,
80                                                   *num, sign, precision,
81                                                   upper, &mut buf, &mut parts);
82         fmt.pad_formatted_parts(&formatted)
83     }
84 }
85
86 // Don't inline this so callers that call both this and the above won't wind
87 // up using the combined stack space of both functions in some cases.
88 #[inline(never)]
89 fn float_to_exponential_common_shortest<T>(fmt: &mut Formatter,
90                                            num: &T, sign: flt2dec::Sign,
91                                            upper: bool) -> Result
92     where T: flt2dec::DecodableFloat
93 {
94     unsafe {
95         // enough for f32 and f64
96         let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized();
97         let mut parts: [flt2dec::Part; 6] = mem::uninitialized();
98         let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest,
99                                                      *num, sign, (0, 0), upper,
100                                                      &mut buf, &mut parts);
101         fmt.pad_formatted_parts(&formatted)
102     }
103 }
104
105 // Common code of floating point LowerExp and UpperExp.
106 fn float_to_exponential_common<T>(fmt: &mut Formatter, num: &T, upper: bool) -> Result
107     where T: flt2dec::DecodableFloat
108 {
109     let force_sign = fmt.sign_plus();
110     let sign = match force_sign {
111         false => flt2dec::Sign::Minus,
112         true  => flt2dec::Sign::MinusPlus,
113     };
114
115     if let Some(precision) = fmt.precision {
116         // 1 integral digit + `precision` fractional digits = `precision + 1` total digits
117         float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper)
118     } else {
119         float_to_exponential_common_shortest(fmt, num, sign, upper)
120     }
121 }
122
123 macro_rules! floating {
124     ($ty:ident) => (
125         #[stable(feature = "rust1", since = "1.0.0")]
126         impl Debug for $ty {
127             fn fmt(&self, fmt: &mut Formatter) -> Result {
128                 float_to_decimal_common(fmt, self, true)
129             }
130         }
131
132         #[stable(feature = "rust1", since = "1.0.0")]
133         impl Display for $ty {
134             fn fmt(&self, fmt: &mut Formatter) -> Result {
135                 float_to_decimal_common(fmt, self, false)
136             }
137         }
138
139         #[stable(feature = "rust1", since = "1.0.0")]
140         impl LowerExp for $ty {
141             fn fmt(&self, fmt: &mut Formatter) -> Result {
142                 float_to_exponential_common(fmt, self, false)
143             }
144         }
145
146         #[stable(feature = "rust1", since = "1.0.0")]
147         impl UpperExp for $ty {
148             fn fmt(&self, fmt: &mut Formatter) -> Result {
149                 float_to_exponential_common(fmt, self, true)
150             }
151         }
152     )
153 }
154
155 floating! { f32 }
156 floating! { f64 }