@@ -36,42 +36,26 @@ pub fn escape_pango_text(text: String) -> String {
3636 . collect ( )
3737}
3838
39- pub fn format_number ( raw_value : f64 , total_digits : usize , min_unit : & str , suffix : & str ) -> String {
40- let ( min_unit_value, min_unit_level) = match min_unit {
41- "T" => ( raw_value / 1_000_000_000_000.0 , 4 ) ,
42- "G" => ( raw_value / 1_000_000_000.0 , 3 ) ,
43- "M" => ( raw_value / 1_000_000.0 , 2 ) ,
44- "K" => ( raw_value / 1_000.0 , 1 ) ,
45- "1" => ( raw_value, 0 ) ,
46- "m" => ( raw_value * 1_000.0 , -1 ) ,
47- "u" => ( raw_value * 1_000_000.0 , -2 ) ,
48- "n" => ( raw_value * 1_000_000_000.0 , -3 ) ,
49- _ => ( raw_value * 1_000_000_000_000.0 , -4 ) ,
39+ /// Format `raw_value` to engineering notation
40+ pub fn format_number ( raw_value : f64 , total_digits : usize , min_suffix : & str , unit : & str ) -> String {
41+ let min_exp_level = match min_suffix {
42+ "T" => 4 ,
43+ "G" => 3 ,
44+ "M" => 2 ,
45+ "K" => 1 ,
46+ "1" => 0 ,
47+ "m" => -1 ,
48+ "u" => -2 ,
49+ "n" => -3 ,
50+ _ => -4 ,
5051 } ;
5152
52- //println!("Min Unit: ({}, {})", min_unit_value, min_unit_level);
53-
54- let ( magnitude_value, magnitude_level) = match raw_value {
55- x if x >= 100_000_000_000.0 => ( raw_value / 1_000_000_000_000.0 , 4 ) ,
56- x if x >= 100_000_000.0 => ( raw_value / 1_000_000_000.0 , 3 ) ,
57- x if x >= 100_000.0 => ( raw_value / 1_000_000.0 , 2 ) ,
58- x if x >= 100.0 => ( raw_value / 1_000.0 , 1 ) ,
59- x if x >= 0.1 => ( raw_value, 0 ) ,
60- x if x >= 0.000_1 => ( raw_value * 1_000.0 , -1 ) ,
61- x if x >= 0.000_000_1 => ( raw_value * 1_000_000.0 , -2 ) ,
62- x if x >= 0.000_000_000_1 => ( raw_value * 1_000_000_000.0 , -3 ) ,
63- _ => ( raw_value * 1_000_000_000_000.0 , -4 ) ,
64- } ;
65-
66- //println!("Magnitude: ({}, {})", magnitude_value, magnitude_level);
67-
68- let ( value, level) = if magnitude_level < min_unit_level {
69- ( min_unit_value, min_unit_level)
70- } else {
71- ( magnitude_value, magnitude_level)
72- } ;
53+ let exp_level = ( raw_value. log10 ( ) . div_euclid ( 3. ) as i32 )
54+ . max ( min_exp_level)
55+ . min ( 4 ) ;
56+ let value = raw_value / ( 10f64 ) . powi ( exp_level * 3 ) ;
7357
74- let unit = match level {
58+ let suffix = match exp_level {
7559 4 => "T" ,
7660 3 => "G" ,
7761 2 => "M" ,
@@ -83,14 +67,17 @@ pub fn format_number(raw_value: f64, total_digits: usize, min_unit: &str, suffix
8367 _ => "p" ,
8468 } ;
8569
86- let _decimal_precision = total_digits as i16 - if value >= 10.0 { 2 } else { 1 } ;
87- let decimal_precision = if _decimal_precision < 0 {
88- 0
70+ let total_digits = total_digits as isize ;
71+ let decimals = ( if value >= 100. {
72+ total_digits - 3
73+ } else if value >= 10. {
74+ total_digits - 2
8975 } else {
90- _decimal_precision
91- } ;
76+ total_digits - 1
77+ } )
78+ . max ( 0 ) ;
9279
93- format ! ( "{:.*}{}{}" , decimal_precision as usize , value, unit , suffix )
80+ format ! ( "{:.*}{}{}" , decimals as usize , value, suffix , unit )
9481}
9582
9683pub fn battery_level_to_icon ( charge_level : Result < u64 > ) -> & ' static str {
@@ -512,7 +499,18 @@ macro_rules! if_debug {
512499
513500#[ cfg( test) ]
514501mod tests {
515- use crate :: util:: { color_from_rgba, has_command} ;
502+ use crate :: util:: { color_from_rgba, format_number, has_command} ;
503+
504+ #[ test]
505+ fn test_format_number ( ) {
506+ assert_eq ! ( format_number( 1.0 , 3 , "" , "s" ) , "1.00s" ) ;
507+ assert_eq ! ( format_number( 1.007 , 3 , "" , "s" ) , "1.01s" ) ;
508+ assert_eq ! ( format_number( 1.007 , 4 , "K" , "s" ) , "0.001Ks" ) ;
509+ assert_eq ! ( format_number( 1007. , 3 , "K" , "s" ) , "1.01Ks" ) ;
510+ assert_eq ! ( format_number( 107_000. , 3 , "" , "s" ) , "107Ks" ) ;
511+ assert_eq ! ( format_number( 107. , 3 , "" , "s" ) , "107s" ) ;
512+ assert_eq ! ( format_number( 0.000_123_123 , 3 , "" , "N" ) , "123uN" ) ;
513+ }
516514
517515 #[ test]
518516 // we assume sh is always available
0 commit comments