]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
seq: be more accurate with large integer start values
authorPádraig Brady <P@draigBrady.com>
Tue, 2 Sep 2025 15:35:52 +0000 (16:35 +0100)
committerPádraig Brady <P@draigBrady.com>
Tue, 2 Sep 2025 19:51:55 +0000 (20:51 +0100)
* src/seq.c (main): Avoid possibly innacurate conversion
to long double, for all digit start values.
* tests/seq/seq-long-double.sh: Add a test case.
* NEWS: Mention the improvement.
Fixes https://bugs.gnu.org/79369

NEWS
src/seq.c
tests/seq/seq-long-double.sh

diff --git a/NEWS b/NEWS
index 24430cedbea560548ebed33ece288a1f5e231b63..2da3b04b9ef8ce286c871d62b1cd4d9d337709ef 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -112,11 +112,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 more accurate with large integer start values.
+  Previously 'seq 18446744073709551617 inf | head -n1' would
+  output the number before the user specified start value.
+
 ** Build-related
 
   cksum was not compilable by Apple LLVM 10.0.0 x86-64, which
index ea9b7d8a4f55d318eb016b0e167a58d7a366f3c1..59de4979842db3f71fda5557cc02592fded0f5f5 100644 (file)
--- 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.  */
index 86f82d88bc9059109e87432a556123cb55ba984c..eaf812d3bc9bb8ee5b3fa5ec7922dfe9b4bd7a35 100755 (executable)
@@ -40,7 +40,14 @@ a=$INTMAX_MAX
 b=$INTMAX_OFLOW
 
 seq $a $b > out || fail=1
-printf "$a\n$b\n" > exp || fail=1
+printf "$a\n$b\n" > exp || framework_failure_
+compare exp out || fail=1
+
+# Test case fixed in v9.8
+# I.e. All digit start, with non digits end
+a=18446744073709551617
+seq $a inf | head -n1 > out || fail=1
+printf "$a\n" > exp || framework_failure_
 compare exp out || fail=1
 
 Exit $fail