From db976ddc702e1a4dce5eb01601112ab03007a6d1 Mon Sep 17 00:00:00 2001 From: ChJR Date: Tue, 10 Nov 2020 00:57:32 +0900 Subject: [PATCH] Clear up format_float_as_exponent --- common/src/float_ops.rs | 48 ++++++++++++++++++++++++++++++----------- vm/src/cformat.rs | 12 ++++++++--- vm/src/format.rs | 16 ++++++++------ 3 files changed, 55 insertions(+), 21 deletions(-) diff --git a/common/src/float_ops.rs b/common/src/float_ops.rs index 8b1ac8633..034b9dbf9 100644 --- a/common/src/float_ops.rs +++ b/common/src/float_ops.rs @@ -83,21 +83,45 @@ pub fn is_integer(v: f64) -> bool { (v - v.round()).abs() < std::f64::EPSILON } +#[derive(Debug)] +pub enum FloatFormatCase { + Lower, + Upper, +} + +fn format_nan(case: FloatFormatCase) -> String { + let nan = match case { + FloatFormatCase::Lower => "nan", + FloatFormatCase::Upper => "NAN", + }; + + nan.to_string() +} + +fn format_inf(case: FloatFormatCase) -> String { + let inf = match case { + FloatFormatCase::Lower => "inf", + FloatFormatCase::Upper => "INF", + }; + + inf.to_string() +} + // Formats floats into Python style exponent notation, by first formatting in Rust style // exponent notation (`1.0000e0`), then convert to Python style (`1.0000e+00`). -pub fn format_float_as_exponent(precision: usize, magnitude: f64) -> String { - if magnitude.is_nan() { - return "nan".to_string(); +pub fn format_float_as_exponent(precision: usize, magnitude: f64, case: FloatFormatCase) -> String { + match magnitude { + magnitude if magnitude.is_finite() => { + let r_exp = format!("{:.*e}", precision, magnitude); + let mut parts = r_exp.splitn(2, 'e'); + let base = parts.next().unwrap(); + let exponent = parts.next().unwrap().parse::().unwrap(); + format!("{}e{:+#03}", base, exponent) + } + magnitude if magnitude.is_nan() => format_nan(case), + magnitude if magnitude.is_infinite() => format_inf(case), + _ => "".to_string(), } - if magnitude.is_infinite() { - return "inf".to_string(); - } - - let r_exp = format!("{:.*e}", precision, magnitude); - let mut parts = r_exp.splitn(2, 'e'); - let base = parts.next().unwrap(); - let exponent = parts.next().unwrap().parse::().unwrap(); - format!("{}e{:+#03}", base, exponent) } pub fn to_string(value: f64) -> String { diff --git a/vm/src/cformat.rs b/vm/src/cformat.rs index a45a57c27..607951280 100644 --- a/vm/src/cformat.rs +++ b/vm/src/cformat.rs @@ -250,7 +250,7 @@ impl CFormatSpec { "-" }; - let magnitude_string = match self.format_type { + let magnitude_string = match &self.format_type { CFormatType::Float(CFloatType::PointDecimal(_)) => { let precision = match self.precision { Some(CFormatQuantity::Amount(p)) => p, @@ -259,13 +259,19 @@ impl CFormatSpec { let magnitude = num.abs(); Ok(format!("{:.*}", precision, magnitude)) } - CFormatType::Float(CFloatType::Exponent(_)) => { + CFormatType::Float(CFloatType::Exponent(case)) => { let precision = match self.precision { Some(CFormatQuantity::Amount(p)) => p, _ => 6, }; let magnitude = num.abs(); - Ok(float_ops::format_float_as_exponent(precision, magnitude)) + let float_case = match case { + CFormatCase::Lowercase => float_ops::FloatFormatCase::Lower, + CFormatCase::Uppercase => float_ops::FloatFormatCase::Upper, + }; + Ok(float_ops::format_float_as_exponent( + precision, magnitude, float_case, + )) } CFormatType::Float(CFloatType::General(_)) => { Err("Not yet implemented for %g and %G".to_owned()) diff --git a/vm/src/format.rs b/vm/src/format.rs index 042f7da83..3d58b5e26 100644 --- a/vm/src/format.rs +++ b/vm/src/format.rs @@ -375,12 +375,16 @@ impl FormatSpec { Some(FormatType::GeneralFormatLower) => { Err("Format code 'g' for object of type 'float' not implemented yet") } - Some(FormatType::ExponentUpper) => { - Ok(float_ops::format_float_as_exponent(precision, magnitude).to_uppercase()) - } - Some(FormatType::ExponentLower) => { - Ok(float_ops::format_float_as_exponent(precision, magnitude).to_lowercase()) - } + Some(FormatType::ExponentUpper) => Ok(float_ops::format_float_as_exponent( + precision, + magnitude, + float_ops::FloatFormatCase::Upper, + )), + Some(FormatType::ExponentLower) => Ok(float_ops::format_float_as_exponent( + precision, + magnitude, + float_ops::FloatFormatCase::Lower, + )), Some(FormatType::Percentage) => match magnitude { magnitude if magnitude.is_nan() => Ok("nan%".to_owned()), magnitude if magnitude.is_infinite() => Ok("inf%".to_owned()),