From edc1e5def6472ca708d2af8974070d87bb6046b0 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Tue, 3 Jun 2025 09:21:35 +0200 Subject: [PATCH] uucore: num_parser: Improve scale conversion to i64 It turns out repeatedly calling i64::MAX.into() and i64::MIN.into() is actually very expensive. Just do the conversion first, and if it fails, we know why. Sadly there is still a conversion happening under the hood in `-exponent + scale`, but that'd need to be fixed in Bigint. Improves sort -g performance by ~5%. --- src/uucore/src/lib/features/parser/num_parser.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/uucore/src/lib/features/parser/num_parser.rs b/src/uucore/src/lib/features/parser/num_parser.rs index 84aa82bdd..8d08f7703 100644 --- a/src/uucore/src/lib/features/parser/num_parser.rs +++ b/src/uucore/src/lib/features/parser/num_parser.rs @@ -465,16 +465,15 @@ fn construct_extended_big_decimal<'a>( let bd = if scale == 0 && exponent.is_zero() { BigDecimal::from_bigint(signed_digits, 0) } else if base == Base::Decimal { - let new_scale = BigInt::from(scale) - exponent; + let new_scale = -exponent + scale; // BigDecimal "only" supports i64 scale. - // Note that new_scale is a negative exponent: large value causes an underflow, small value an overflow. - if new_scale > i64::MAX.into() { - return Err(make_error(false, negative)); - } else if new_scale < i64::MIN.into() { - return Err(make_error(true, negative)); + // Note that new_scale is a negative exponent: large positive value causes an underflow, large negative values an overflow. + if let Some(new_scale) = new_scale.to_i64() { + BigDecimal::from_bigint(signed_digits, new_scale) + } else { + return Err(make_error(new_scale.is_negative(), negative)); } - BigDecimal::from_bigint(signed_digits, new_scale.to_i64().unwrap()) } else if base == Base::Hexadecimal { // pow "only" supports u32 values, just error out if given more than 2**32 fractional digits. if scale > u32::MAX.into() {