1
- // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
1
+ // Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
2
2
// file at the top-level directory of this distribution and at
3
3
// http://rust-lang.org/COPYRIGHT.
4
4
//
8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- #![ allow( missing_docs) ]
12
-
13
11
pub use self :: ExponentFormat :: * ;
14
12
pub use self :: SignificantDigits :: * ;
15
- pub use self :: SignFormat :: * ;
16
13
17
- use char;
18
- use char:: CharExt ;
14
+ use char:: { self , CharExt } ;
19
15
use fmt;
20
16
use iter:: Iterator ;
21
17
use num:: { cast, Float , ToPrimitive } ;
@@ -46,67 +42,42 @@ pub enum SignificantDigits {
46
42
DigExact ( usize )
47
43
}
48
44
49
- /// How to emit the sign of a number.
50
- pub enum SignFormat {
51
- /// `-` will be printed for negative values, but no sign will be emitted
52
- /// for positive numbers.
53
- SignNeg
54
- }
55
-
56
- const DIGIT_E_RADIX : u32 = ( 'e' as u32 ) - ( 'a' as u32 ) + 11 ;
57
-
58
- /// Converts a number to its string representation as a byte vector.
59
- /// This is meant to be a common base implementation for all numeric string
60
- /// conversion functions like `to_string()` or `to_str_radix()`.
45
+ /// Converts a float number to its string representation.
46
+ /// This is meant to be a common base implementation for various formatting styles.
47
+ /// The number is assumed to be non-negative, callers use `Formatter::pad_integral`
48
+ /// to add the right sign, if any.
61
49
///
62
50
/// # Arguments
63
51
///
64
- /// - `num` - The number to convert. Accepts any number that
52
+ /// - `num` - The number to convert (non-negative) . Accepts any number that
65
53
/// implements the numeric traits.
66
- /// - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation
67
- /// is used, then this base is only used for the significand. The exponent
68
- /// itself always printed using a base of 10.
69
- /// - `negative_zero` - Whether to treat the special value `-0` as
70
- /// `-0` or as `+0`.
71
- /// - `sign` - How to emit the sign. See `SignFormat`.
72
54
/// - `digits` - The amount of digits to use for emitting the fractional
73
55
/// part, if any. See `SignificantDigits`.
74
56
/// - `exp_format` - Whether or not to use the exponential (scientific) notation.
75
57
/// See `ExponentFormat`.
76
58
/// - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if
77
59
/// exponential notation is desired.
78
- /// - `f` - A closure to invoke with the bytes representing the
60
+ /// - `f` - A closure to invoke with the string representing the
79
61
/// float.
80
62
///
81
63
/// # Panics
82
64
///
83
- /// - Panics if `radix` < 2 or `radix` > 36.
84
- /// - Panics if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
85
- /// between digit and exponent sign `'e'`.
86
- /// - Panics if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
87
- /// between digit and exponent sign `'p'`.
65
+ /// - Panics if `num` is negative.
88
66
pub fn float_to_str_bytes_common < T : Float , U , F > (
89
67
num : T ,
90
- radix : u32 ,
91
- negative_zero : bool ,
92
- sign : SignFormat ,
93
68
digits : SignificantDigits ,
94
69
exp_format : ExponentFormat ,
95
70
exp_upper : bool ,
96
71
f : F
97
72
) -> U where
98
73
F : FnOnce ( & str ) -> U ,
99
74
{
100
- assert ! ( 2 <= radix && radix <= 36 ) ;
101
- match exp_format {
102
- ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
103
- => panic ! ( "float_to_str_bytes_common: radix {} incompatible with \
104
- use of 'e' as decimal exponent", radix) ,
105
- _ => ( )
106
- }
107
-
108
75
let _0: T = Float :: zero ( ) ;
109
76
let _1: T = Float :: one ( ) ;
77
+ let radix: u32 = 10 ;
78
+ let radix_f: T = cast ( radix) . unwrap ( ) ;
79
+
80
+ assert ! ( num. is_nan( ) || num >= _0, "float_to_str_bytes_common: number is negative" ) ;
110
81
111
82
match num. classify ( ) {
112
83
Fp :: Nan => return f ( "NaN" ) ,
@@ -119,41 +90,28 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
119
90
_ => { }
120
91
}
121
92
122
- let neg = num < _0 || ( negative_zero && _1 / num == Float :: neg_infinity ( ) ) ;
123
- // For an f64 the exponent is in the range of [-1022, 1023] for base 2, so
124
- // we may have up to that many digits. Give ourselves some extra wiggle room
125
- // otherwise as well.
126
- let mut buf = [ 0 ; 1536 ] ;
93
+ // For an f64 the (decimal) exponent is roughly in the range of [-307, 308], so
94
+ // we may have up to that many digits. We err on the side of caution and
95
+ // add 50% extra wiggle room.
96
+ let mut buf = [ 0 ; 462 ] ;
127
97
let mut end = 0 ;
128
- let radix_gen: T = cast ( radix as isize ) . unwrap ( ) ;
129
98
130
99
let ( num, exp) = match exp_format {
131
- ExpNone => ( num, 0 ) ,
132
- ExpDec if num == _0 => ( num, 0 ) ,
133
- ExpDec => {
134
- let ( exp, exp_base) = match exp_format {
135
- ExpDec => ( num. abs ( ) . log10 ( ) . floor ( ) , cast :: < f64 , T > ( 10.0f64 ) . unwrap ( ) ) ,
136
- ExpNone => panic ! ( "unreachable" ) ,
137
- } ;
138
-
139
- ( num / exp_base. powf ( exp) , cast :: < T , i32 > ( exp) . unwrap ( ) )
100
+ ExpDec if num != _0 => {
101
+ let exp = num. log10 ( ) . floor ( ) ;
102
+ ( num / radix_f. powf ( exp) , cast :: < T , i32 > ( exp) . unwrap ( ) )
140
103
}
104
+ _ => ( num, 0 )
141
105
} ;
142
106
143
107
// First emit the non-fractional part, looping at least once to make
144
108
// sure at least a `0` gets emitted.
145
109
let mut deccum = num. trunc ( ) ;
146
110
loop {
147
- // Calculate the absolute value of each digit instead of only
148
- // doing it once for the whole number because a
149
- // representable negative number doesn't necessary have an
150
- // representable additive inverse of the same type
151
- // (See twos complement). But we assume that for the
152
- // numbers [-35 .. 0] we always have [0 .. 35].
153
- let current_digit = ( deccum % radix_gen) . abs ( ) ;
111
+ let current_digit = deccum % radix_f;
154
112
155
113
// Decrease the deccumulator one digit at a time
156
- deccum = deccum / radix_gen ;
114
+ deccum = deccum / radix_f ;
157
115
deccum = deccum. trunc ( ) ;
158
116
159
117
let c = char:: from_digit ( current_digit. to_isize ( ) . unwrap ( ) as u32 , radix) ;
@@ -170,15 +128,6 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
170
128
DigExact ( count) => ( true , count + 1 , true )
171
129
} ;
172
130
173
- // Decide what sign to put in front
174
- match sign {
175
- SignNeg if neg => {
176
- buf[ end] = b'-' ;
177
- end += 1 ;
178
- }
179
- _ => ( )
180
- }
181
-
182
131
buf[ ..end] . reverse ( ) ;
183
132
184
133
// Remember start of the fractional digits.
@@ -205,14 +154,11 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
205
154
)
206
155
) {
207
156
// Shift first fractional digit into the integer part
208
- deccum = deccum * radix_gen ;
157
+ deccum = deccum * radix_f ;
209
158
210
- // Calculate the absolute value of each digit.
211
- // See note in first loop.
212
- let current_digit = deccum. trunc ( ) . abs ( ) ;
159
+ let current_digit = deccum. trunc ( ) ;
213
160
214
- let c = char:: from_digit ( current_digit. to_isize ( ) . unwrap ( ) as u32 ,
215
- radix) ;
161
+ let c = char:: from_digit ( current_digit. to_isize ( ) . unwrap ( ) as u32 , radix) ;
216
162
buf[ end] = c. unwrap ( ) as u8 ;
217
163
end += 1 ;
218
164
@@ -301,12 +247,8 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
301
247
302
248
match exp_format {
303
249
ExpNone => { } ,
304
- _ => {
305
- buf[ end] = match exp_format {
306
- ExpDec if exp_upper => 'E' ,
307
- ExpDec if !exp_upper => 'e' ,
308
- _ => panic ! ( "unreachable" ) ,
309
- } as u8 ;
250
+ ExpDec => {
251
+ buf[ end] = if exp_upper { b'E' } else { b'e' } ;
310
252
end += 1 ;
311
253
312
254
struct Filler < ' a > {
@@ -324,11 +266,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
324
266
}
325
267
326
268
let mut filler = Filler { buf : & mut buf, end : & mut end } ;
327
- match sign {
328
- SignNeg => {
329
- let _ = fmt:: write ( & mut filler, format_args ! ( "{:-}" , exp) ) ;
330
- }
331
- }
269
+ let _ = fmt:: write ( & mut filler, format_args ! ( "{:-}" , exp) ) ;
332
270
}
333
271
}
334
272
0 commit comments