1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

uucore: format: Small optimizations in num_format for seq

In most common use cases:
 - We can bypass a lot of `write_output` when width == 0.
 - Simplify format_float_decimal when the input is an integer.

Also document another interesting case in src/uu/seq/BENCHMARKING.md.
This commit is contained in:
Nicolas Boichat 2025-03-18 15:43:45 +01:00 committed by Sylvestre Ledru
parent f31ba2bd28
commit e6c24b245a
2 changed files with 24 additions and 4 deletions

View file

@ -43,6 +43,16 @@ hyperfine -L seq seq,./target/release/seq "{seq} 0 0.000001 1"
hyperfine -L seq seq,./target/release/seq "{seq} -100 1 1000000"
```
It is also interesting to compare performance with large precision
format. But in this case, the output itself should also be compared,
as GNU `seq` may not provide the same precision (`uutils` version of
`seq` provides arbitrary precision, while GNU `seq` appears to be
limited to `long double` on the given platform, i.e. 64/80/128-bit
float):
```shell
hyperfine -L seq seq,target/release/seq "{seq} -f%.30f 0 0.000001 1"
```
## Optimizations
### Buffering stdout

View file

@ -354,11 +354,16 @@ fn format_float_non_finite(e: &ExtendedBigDecimal, case: Case) -> String {
fn format_float_decimal(bd: &BigDecimal, precision: usize, force_decimal: ForceDecimal) -> String {
debug_assert!(!bd.is_negative());
if precision == 0 && force_decimal == ForceDecimal::Yes {
format!("{bd:.0}.")
} else {
format!("{bd:.precision$}")
if precision == 0 {
let (bi, scale) = bd.as_bigint_and_scale();
if scale == 0 && force_decimal != ForceDecimal::Yes {
// Optimization when printing integers.
return bi.to_str_radix(10);
} else if force_decimal == ForceDecimal::Yes {
return format!("{bd:.0}.");
}
}
format!("{bd:.precision$}")
}
fn format_float_scientific(
@ -614,6 +619,11 @@ fn write_output(
width: usize,
alignment: NumberAlignment,
) -> std::io::Result<()> {
if width == 0 {
writer.write_all(sign_indicator.as_bytes())?;
writer.write_all(s.as_bytes())?;
return Ok(());
}
// Take length of `sign_indicator`, which could be 0 or 1, into consideration when padding
// by storing remaining_width indicating the actual width needed.
// Using min() because self.width could be 0, 0usize - 1usize should be avoided