On 02/09/2025 13:11, ondra007....@seznam.cz wrote:
It looks like seq for integers bigger than 2^64 sometimes generate wrong results. There are few examples of wrong output I have found:$ seq 18446744073709551617 inf | head -3 18446744073709551616 18446744073709551617 18446744073709551618 $ seq 10000000000000000000000000000 inf | head -3 9999999999999999999731564544 9999999999999999999731564545 9999999999999999999731564546
We can improve for the above 2 cases anyway, with something like the attached. Large magnitude negative start values are still problematic. cheers, Padraig
From bf3c75911d1b50d557960943daaeb20a65f0140f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com> Date: Tue, 2 Sep 2025 16:35:52 +0100 Subject: [PATCH] seq: be more accurate with large integer start values * src/seq.c (main): Use seq_fast() with large integer only start values, by avoiding innacurate conversion to double. * NEWS: Mention the improvement. --- NEWS | 6 +++++- src/seq.c | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index dd8c1a4cf..e732e3ddd 100644 --- a/NEWS +++ b/NEWS @@ -116,11 +116,15 @@ GNU coreutils NEWS -*- outline -*- tsort now accepts and ignores -w. -** Performance improvements +** Improvements 'factor' is now much faster at identifying large prime numbers, and significantly faster on composite numbers greater than 2^128. + 'seq' is faster and more accurate with large integer start values. + Previously 'seq 18446744073709551617 inf | head -n3' would start + with the number before the user specified start value. + ** Build-related cksum was not compilable by Apple LLVM 10.0.0 x86-64, which diff --git a/src/seq.c b/src/seq.c index ea9b7d8a4..59de49798 100644 --- a/src/seq.c +++ b/src/seq.c @@ -628,6 +628,8 @@ main (int argc, char **argv) usage (EXIT_FAILURE); } + char const *user_start = n_args == 1 ? "1" : argv[optind]; + /* If the following hold: - no format string, [FIXME: relax this, eventually] - integer start (or no start) @@ -648,7 +650,7 @@ main (int argc, char **argv) && all_digits_p (argv[optind + 2]))) && !equal_width && !format_str && strlen (separator) == 1) { - char const *s1 = n_args == 1 ? "1" : argv[optind]; + char const *s1 = user_start; char const *s2 = argv[optind + (n_args - 1)]; seq_fast (s1, s2, step.value); } @@ -683,7 +685,9 @@ main (int argc, char **argv) { char *s1; char *s2; - if (asprintf (&s1, "%0.Lf", first.value) < 0) + if (all_digits_p (user_start)) + s1 = xstrdup (user_start); + else if (asprintf (&s1, "%0.Lf", first.value) < 0) xalloc_die (); if (! isfinite (last.value)) s2 = xstrdup ("inf"); /* Ensure "inf" is used. */ -- 2.50.1