mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-31 04:57:45 +00:00
uucode: format: format_float_non_finite: Take in &ExtendedBigDecimal
First modify Format.fmt to extract absolute value and sign, then modify printing on non-finite values (inf or nan).
This commit is contained in:
parent
8e11dab995
commit
ce14d01da5
1 changed files with 54 additions and 37 deletions
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
//! Utilities for formatting numbers in various formats
|
//! Utilities for formatting numbers in various formats
|
||||||
|
|
||||||
|
use num_traits::Signed;
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
@ -234,37 +235,44 @@ impl Default for Float {
|
||||||
|
|
||||||
impl Formatter<&ExtendedBigDecimal> for Float {
|
impl Formatter<&ExtendedBigDecimal> for Float {
|
||||||
fn fmt(&self, writer: impl Write, e: &ExtendedBigDecimal) -> std::io::Result<()> {
|
fn fmt(&self, writer: impl Write, e: &ExtendedBigDecimal) -> std::io::Result<()> {
|
||||||
// TODO: For now we just convert ExtendedBigDecimal back to f64, fix this.
|
/* TODO: Might be nice to implement Signed trait for ExtendedBigDecimal (for abs)
|
||||||
let f = match e {
|
* at some point, but that requires implementing a _lot_ of traits.
|
||||||
ExtendedBigDecimal::BigDecimal(bd) => bd.to_f64().unwrap(),
|
* Note that "negative" would be the output of "is_sign_negative" on a f64:
|
||||||
ExtendedBigDecimal::Infinity => f64::INFINITY,
|
* it returns true on `-0.0`.
|
||||||
ExtendedBigDecimal::MinusInfinity => f64::NEG_INFINITY,
|
*/
|
||||||
ExtendedBigDecimal::MinusZero => -0.0,
|
let (abs, negative) = match e {
|
||||||
ExtendedBigDecimal::Nan => f64::NAN,
|
ExtendedBigDecimal::BigDecimal(bd) => {
|
||||||
ExtendedBigDecimal::MinusNan => -f64::NAN,
|
(ExtendedBigDecimal::BigDecimal(bd.abs()), bd.is_negative())
|
||||||
|
}
|
||||||
|
ExtendedBigDecimal::MinusZero => (ExtendedBigDecimal::zero(), true),
|
||||||
|
ExtendedBigDecimal::Infinity => (ExtendedBigDecimal::Infinity, false),
|
||||||
|
ExtendedBigDecimal::MinusInfinity => (ExtendedBigDecimal::Infinity, true),
|
||||||
|
ExtendedBigDecimal::Nan => (ExtendedBigDecimal::Nan, false),
|
||||||
|
ExtendedBigDecimal::MinusNan => (ExtendedBigDecimal::Nan, true),
|
||||||
};
|
};
|
||||||
let x = f.abs();
|
|
||||||
|
|
||||||
let s = if x.is_finite() {
|
let s = match abs {
|
||||||
match self.variant {
|
ExtendedBigDecimal::BigDecimal(bd) => {
|
||||||
FloatVariant::Decimal => {
|
// TODO: Convert format_float_* functions to take in a BigDecimal.
|
||||||
format_float_decimal(x, self.precision, self.force_decimal)
|
let x = bd.to_f64().unwrap();
|
||||||
}
|
match self.variant {
|
||||||
FloatVariant::Scientific => {
|
FloatVariant::Decimal => {
|
||||||
format_float_scientific(x, self.precision, self.case, self.force_decimal)
|
format_float_decimal(x, self.precision, self.force_decimal)
|
||||||
}
|
}
|
||||||
FloatVariant::Shortest => {
|
FloatVariant::Scientific => {
|
||||||
format_float_shortest(x, self.precision, self.case, self.force_decimal)
|
format_float_scientific(x, self.precision, self.case, self.force_decimal)
|
||||||
}
|
}
|
||||||
FloatVariant::Hexadecimal => {
|
FloatVariant::Shortest => {
|
||||||
format_float_hexadecimal(x, self.precision, self.case, self.force_decimal)
|
format_float_shortest(x, self.precision, self.case, self.force_decimal)
|
||||||
|
}
|
||||||
|
FloatVariant::Hexadecimal => {
|
||||||
|
format_float_hexadecimal(x, self.precision, self.case, self.force_decimal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
_ => format_float_non_finite(&abs, self.case),
|
||||||
format_float_non_finite(x, self.case)
|
|
||||||
};
|
};
|
||||||
|
let sign_indicator = get_sign_indicator(self.positive_sign, negative);
|
||||||
let sign_indicator = get_sign_indicator(self.positive_sign, f.is_sign_negative());
|
|
||||||
|
|
||||||
write_output(writer, sign_indicator, s, self.width, self.alignment)
|
write_output(writer, sign_indicator, s, self.width, self.alignment)
|
||||||
}
|
}
|
||||||
|
@ -322,12 +330,18 @@ fn get_sign_indicator(sign: PositiveSign, negative: bool) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_float_non_finite(f: f64, case: Case) -> String {
|
fn format_float_non_finite(e: &ExtendedBigDecimal, case: Case) -> String {
|
||||||
debug_assert!(!f.is_finite());
|
let mut s = match e {
|
||||||
let mut s = format!("{f}");
|
ExtendedBigDecimal::Infinity => String::from("inf"),
|
||||||
match case {
|
ExtendedBigDecimal::Nan => String::from("nan"),
|
||||||
Case::Lowercase => s.make_ascii_lowercase(), // Forces NaN back to nan.
|
_ => {
|
||||||
Case::Uppercase => s.make_ascii_uppercase(),
|
debug_assert!(false);
|
||||||
|
String::from("INVALID")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if case == Case::Uppercase {
|
||||||
|
s.make_ascii_uppercase();
|
||||||
}
|
}
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
@ -532,7 +546,10 @@ fn write_output(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::format::num_format::{Case, ForceDecimal};
|
use crate::format::{
|
||||||
|
num_format::{Case, ForceDecimal},
|
||||||
|
ExtendedBigDecimal,
|
||||||
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unsigned_octal() {
|
fn unsigned_octal() {
|
||||||
|
@ -559,12 +576,12 @@ mod test {
|
||||||
fn non_finite_float() {
|
fn non_finite_float() {
|
||||||
use super::format_float_non_finite;
|
use super::format_float_non_finite;
|
||||||
let f = |x| format_float_non_finite(x, Case::Lowercase);
|
let f = |x| format_float_non_finite(x, Case::Lowercase);
|
||||||
assert_eq!(f(f64::NAN), "nan");
|
assert_eq!(f(&ExtendedBigDecimal::Nan), "nan");
|
||||||
assert_eq!(f(f64::INFINITY), "inf");
|
assert_eq!(f(&ExtendedBigDecimal::Infinity), "inf");
|
||||||
|
|
||||||
let f = |x| format_float_non_finite(x, Case::Uppercase);
|
let f = |x| format_float_non_finite(x, Case::Uppercase);
|
||||||
assert_eq!(f(f64::NAN), "NAN");
|
assert_eq!(f(&ExtendedBigDecimal::Nan), "NAN");
|
||||||
assert_eq!(f(f64::INFINITY), "INF");
|
assert_eq!(f(&ExtendedBigDecimal::Infinity), "INF");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue