@@ -207,11 +207,13 @@ pub fn int_to_str_bytes_common<T:NumCast
207
207
* # Arguments
208
208
* - `num` - The number to convert. Accepts any number that
209
209
* implements the numeric traits.
210
- * - `radix` - Base to use. Accepts only the values 2-36.
210
+ * - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation
211
+ * is used, then this base is only used for the significand. The exponent
212
+ * itself always printed using a base of 10.
211
213
* - `negative_zero` - Whether to treat the special value `-0` as
212
214
* `-0` or as `+0`.
213
215
* - `sign` - How to emit the sign. Options are:
214
- * - `SignNone`: No sign at all. Basically emits `abs(num)` .
216
+ * - `SignNone`: No sign at all. The exponent sign is also omitted .
215
217
* - `SignNeg`: Only `-` on negative values.
216
218
* - `SignAll`: Both `+` on positive, and `-` on negative numbers.
217
219
* - `digits` - The amount of digits to use for emitting the
@@ -220,6 +222,17 @@ pub fn int_to_str_bytes_common<T:NumCast
220
222
* fractions!
221
223
* - `DigMax(uint)`: Maximum N digits, truncating any trailing zeros.
222
224
* - `DigExact(uint)`: Exactly N digits.
225
+ * - `exp_format` - Whether or not to use the exponential (scientific) notation.
226
+ * Options are:
227
+ * - `ExpNone`: Do not use the exponential notation.
228
+ * - `ExpDec`: Use the exponential notation with the exponent having a base of 10,
229
+ * and exponent sign being `'e'` or `'E'` depending on the value of
230
+ * the `exp_upper` argument. E.g. the number 1000 would be printed as 1e3.
231
+ * - `ExpBin`: Use the exponential notation with the exponent having a base of 2,
232
+ * and exponent sign being `'p'` or `'P'` depending on the value of
233
+ * the `exp_upper` argument. E.g. the number 8 would be printed as 1p3.
234
+ * - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if
235
+ * exponential notation is desired.
223
236
*
224
237
* # Return value
225
238
* A tuple containing the byte vector, and a boolean flag indicating
@@ -229,12 +242,26 @@ pub fn int_to_str_bytes_common<T:NumCast
229
242
*
230
243
* # Failure
231
244
* - Fails if `radix` < 2 or `radix` > 36.
245
+ * - Fails if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
246
+ * between digit and exponent sign `'e'`.
247
+ * - Fails if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
248
+ * between digit and exponent sign `'p'`.
232
249
*/
233
250
pub fn float_to_str_bytes_common < T : NumCast +Zero +One +Eq +Ord +Float +Round +
234
251
Div < T , T > +Neg < T > +Rem < T , T > +Mul < T , T > > (
235
252
num : T , radix : uint , negative_zero : bool ,
236
- sign : SignFormat , digits : SignificantDigits ) -> ( ~[ u8 ] , bool ) {
253
+ sign : SignFormat , digits : SignificantDigits , exp_format : ExponentFormat , exp_upper : bool
254
+ ) -> ( ~[ u8 ] , bool ) {
237
255
assert ! ( 2 <= radix && radix <= 36 ) ;
256
+ match exp_format {
257
+ ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
258
+ => fail ! ( "float_to_str_bytes_common: radix {} incompatible with \
259
+ use of 'e' as decimal exponent", radix) ,
260
+ ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
261
+ => fail ! ( "float_to_str_bytes_common: radix {} incompatible with \
262
+ use of 'p' as binary exponent", radix) ,
263
+ _ => ( )
264
+ }
238
265
239
266
let _0: T = Zero :: zero ( ) ;
240
267
let _1: T = One :: one ( ) ;
@@ -260,6 +287,23 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
260
287
let mut buf: ~[ u8 ] = ~[ ] ;
261
288
let radix_gen: T = cast ( radix as int ) . unwrap ( ) ;
262
289
290
+ let ( num, exp) = match exp_format {
291
+ ExpNone => ( num, 0i32 ) ,
292
+ ExpDec | ExpBin => {
293
+ if num == _0 {
294
+ ( num, 0i32 )
295
+ } else {
296
+ let ( exp, exp_base) = match exp_format {
297
+ ExpDec => ( num. abs ( ) . log10 ( ) . floor ( ) , cast :: < f64 , T > ( 10.0f64 ) . unwrap ( ) ) ,
298
+ ExpBin => ( num. abs ( ) . log2 ( ) . floor ( ) , cast :: < f64 , T > ( 2.0f64 ) . unwrap ( ) ) ,
299
+ ExpNone => unreachable ! ( )
300
+ } ;
301
+
302
+ ( num / exp_base. powf ( & exp) , cast :: < T , i32 > ( exp) . unwrap ( ) )
303
+ }
304
+ }
305
+ } ;
306
+
263
307
// First emit the non-fractional part, looping at least once to make
264
308
// sure at least a `0` gets emitted.
265
309
let mut deccum = num. trunc ( ) ;
@@ -413,6 +457,21 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
413
457
}
414
458
}
415
459
460
+ match exp_format {
461
+ ExpNone => ( ) ,
462
+ _ => {
463
+ buf. push ( match exp_format {
464
+ ExpDec if exp_upper => 'E' ,
465
+ ExpDec if !exp_upper => 'e' ,
466
+ ExpBin if exp_upper => 'P' ,
467
+ ExpBin if !exp_upper => 'p' ,
468
+ _ => unreachable ! ( )
469
+ } as u8 ) ;
470
+
471
+ int_to_str_bytes_common ( exp, 10 , sign, |c| buf. push ( c) ) ;
472
+ }
473
+ }
474
+
416
475
( buf, false )
417
476
}
418
477
@@ -424,9 +483,10 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
424
483
pub fn float_to_str_common < T : NumCast +Zero +One +Eq +Ord +NumStrConv +Float +Round +
425
484
Div < T , T > +Neg < T > +Rem < T , T > +Mul < T , T > > (
426
485
num : T , radix : uint , negative_zero : bool ,
427
- sign : SignFormat , digits : SignificantDigits ) -> ( ~str , bool ) {
486
+ sign : SignFormat , digits : SignificantDigits , exp_format : ExponentFormat , exp_capital : bool
487
+ ) -> ( ~str , bool ) {
428
488
let ( bytes, special) = float_to_str_bytes_common ( num, radix,
429
- negative_zero, sign, digits) ;
489
+ negative_zero, sign, digits, exp_format , exp_capital ) ;
430
490
( str:: from_utf8_owned ( bytes) . unwrap ( ) , special)
431
491
}
432
492
0 commit comments