mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 20:17:45 +00:00
seq: Add constant width support in fast path
It is actually quite easy to implement, we just start with a padded number and increment as usual.
This commit is contained in:
parent
560d1eb1b7
commit
c311e208ae
2 changed files with 28 additions and 14 deletions
|
@ -88,7 +88,8 @@ with the default implementation, at the expense of some added code complexity.
|
||||||
|
|
||||||
Just from performance numbers, it is clear that GNU `seq` uses similar
|
Just from performance numbers, it is clear that GNU `seq` uses similar
|
||||||
tricks, but we are more liberal on when we use our fast path (e.g. large
|
tricks, but we are more liberal on when we use our fast path (e.g. large
|
||||||
increments are supported). Our fast path implementation gets within ~10%
|
increments are supported, equal width is supported). Our fast path
|
||||||
of `seq` performance.
|
implementation gets within ~10% of `seq` performance when its fast
|
||||||
|
path is activated.
|
||||||
|
|
||||||
[0]: https://github.com/sharkdp/hyperfine
|
[0]: https://github.com/sharkdp/hyperfine
|
||||||
|
|
|
@ -151,13 +151,17 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let precision = select_precision(&first, &increment, &last);
|
|
||||||
|
|
||||||
// If a format was passed on the command line, use that.
|
// If a format was passed on the command line, use that.
|
||||||
// If not, use some default format based on parameters precision.
|
// If not, use some default format based on parameters precision.
|
||||||
let format = match options.format {
|
let (format, padding, fast_allowed) = match options.format {
|
||||||
Some(str) => Format::<num_format::Float, &ExtendedBigDecimal>::parse(str)?,
|
Some(str) => (
|
||||||
|
Format::<num_format::Float, &ExtendedBigDecimal>::parse(str)?,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
),
|
||||||
None => {
|
None => {
|
||||||
|
let precision = select_precision(&first, &increment, &last);
|
||||||
|
|
||||||
let padding = if options.equal_width {
|
let padding = if options.equal_width {
|
||||||
let precision_value = precision.unwrap_or(0);
|
let precision_value = precision.unwrap_or(0);
|
||||||
first
|
first
|
||||||
|
@ -188,19 +192,22 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Format::from_formatter(formatter)
|
// Allow fast printing if precision is 0 (integer inputs), `print_seq` will do further checks.
|
||||||
|
(
|
||||||
|
Format::from_formatter(formatter),
|
||||||
|
padding,
|
||||||
|
precision == Some(0),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allow fast printing, `print_seq` will do further checks.
|
|
||||||
let fast_allowed = options.format.is_none() && !options.equal_width && precision == Some(0);
|
|
||||||
|
|
||||||
let result = print_seq(
|
let result = print_seq(
|
||||||
(first.number, increment.number, last.number),
|
(first.number, increment.number, last.number),
|
||||||
&options.separator,
|
&options.separator,
|
||||||
&options.terminator,
|
&options.terminator,
|
||||||
&format,
|
&format,
|
||||||
fast_allowed,
|
fast_allowed,
|
||||||
|
padding,
|
||||||
);
|
);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
@ -304,8 +311,6 @@ fn fast_inc(val: &mut [u8], start: usize, end: usize, inc: &[u8]) -> usize {
|
||||||
|
|
||||||
/// Integer print, default format, positive increment: fast code path
|
/// Integer print, default format, positive increment: fast code path
|
||||||
/// that avoids reformating digit at all iterations.
|
/// that avoids reformating digit at all iterations.
|
||||||
/// TODO: We could easily support equal_width (we do quite a bit of work
|
|
||||||
/// _not_ supporting that and aligning the number to the left).
|
|
||||||
fn fast_print_seq(
|
fn fast_print_seq(
|
||||||
mut stdout: impl Write,
|
mut stdout: impl Write,
|
||||||
first: &BigUint,
|
first: &BigUint,
|
||||||
|
@ -313,6 +318,7 @@ fn fast_print_seq(
|
||||||
last: &BigUint,
|
last: &BigUint,
|
||||||
separator: &str,
|
separator: &str,
|
||||||
terminator: &str,
|
terminator: &str,
|
||||||
|
padding: usize,
|
||||||
) -> std::io::Result<()> {
|
) -> std::io::Result<()> {
|
||||||
// Nothing to do, just return.
|
// Nothing to do, just return.
|
||||||
if last < first {
|
if last < first {
|
||||||
|
@ -338,8 +344,9 @@ fn fast_print_seq(
|
||||||
//
|
//
|
||||||
// We keep track of start in this buffer, as the number grows.
|
// We keep track of start in this buffer, as the number grows.
|
||||||
// When printing, we take a slice between start and end.
|
// When printing, we take a slice between start and end.
|
||||||
let size = separator.len() + last_length;
|
let size = last_length.max(padding) + separator.len();
|
||||||
let mut buf = vec![0u8; size];
|
// Fill with '0', this is needed for equal_width, and harmless otherwise.
|
||||||
|
let mut buf = vec![b'0'; size];
|
||||||
let buf = buf.as_mut_slice();
|
let buf = buf.as_mut_slice();
|
||||||
|
|
||||||
let num_end = buf.len() - separator.len();
|
let num_end = buf.len() - separator.len();
|
||||||
|
@ -349,6 +356,10 @@ fn fast_print_seq(
|
||||||
buf[start..num_end].copy_from_slice(first_str.as_bytes());
|
buf[start..num_end].copy_from_slice(first_str.as_bytes());
|
||||||
buf[num_end..].copy_from_slice(separator.as_bytes());
|
buf[num_end..].copy_from_slice(separator.as_bytes());
|
||||||
|
|
||||||
|
// Normally, if padding is > 0, it should be equal to last_length,
|
||||||
|
// so start would be == 0, but there are corner cases.
|
||||||
|
start = start.min(num_end - padding);
|
||||||
|
|
||||||
// Prepare the number to increment with as a string
|
// Prepare the number to increment with as a string
|
||||||
let inc_str = increment.to_string();
|
let inc_str = increment.to_string();
|
||||||
let inc_str = inc_str.as_bytes();
|
let inc_str = inc_str.as_bytes();
|
||||||
|
@ -379,6 +390,7 @@ fn print_seq(
|
||||||
terminator: &str,
|
terminator: &str,
|
||||||
format: &Format<num_format::Float, &ExtendedBigDecimal>,
|
format: &Format<num_format::Float, &ExtendedBigDecimal>,
|
||||||
fast_allowed: bool,
|
fast_allowed: bool,
|
||||||
|
padding: usize, // Used by fast path only
|
||||||
) -> std::io::Result<()> {
|
) -> std::io::Result<()> {
|
||||||
let stdout = stdout().lock();
|
let stdout = stdout().lock();
|
||||||
let mut stdout = BufWriter::new(stdout);
|
let mut stdout = BufWriter::new(stdout);
|
||||||
|
@ -402,6 +414,7 @@ fn print_seq(
|
||||||
&last_bui,
|
&last_bui,
|
||||||
separator,
|
separator,
|
||||||
terminator,
|
terminator,
|
||||||
|
padding,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue