On 09/14/2012 07:54 AM, Jim Meyering wrote:
Inspired by Pádraig's April-fools post,
   http://thread.gmane.org/gmane.comp.gnu.coreutils.general/972
and spurred by the fact that Torbjorn and Niels had to roll
their own seq-like program to test their new factoring code
(http://gmplib.org:8000/factoring), I have made coreutils' seq
usable for arbitrarily large, non-negative whole numbers.
This has two advantages:

     - correctness with large numbers
     - improved performance in common cases

For very large numbers, the new seq now appears to be correct:

     $ b=10000000000000000000000000000000000000000000000000000000000000
     $ src/seq ${b}09 ${b}11
     1000000000000000000000000000000000000000000000000000000000000009
     1000000000000000000000000000000000000000000000000000000000000010
     1000000000000000000000000000000000000000000000000000000000000011

while the old one would infloop, printing garbage:

     $ seq ${b}09 ${b}11 |head -2
     999999999999999999965225407341472151966654053379893968647487488
     999999999999999999965225407341472151966654053379893968647487488

This also means that nt-factor's tests can now use coreutils' seq
to generate their inputs.

Excellent :)

How about the attached follow up to enable the
fast code in more cases?

cheers,
Pádraig.
>From e0ded6c5ae8da61a326a77259ddb7cf10d993a43 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com>
Date: Fri, 14 Sep 2012 14:21:03 +0100
Subject: [PATCH] seq: enable the fast integer printing code in more cases

* src/seq.c (main): Adjust the initial arbitrary precision
seq_fast enablement checks to be more maintainable, and
a little more general, by allowing single character
separators to use seq_fast.
Also Check again after the number arguments are processed,
to see if we can still use seq_fast, which while not
allowing arbitarly large integers, it will handle
integers of the form 0x20 or 10E10 etc.
---
 src/seq.c |   30 +++++++++++++++++++++++-------
 1 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/src/seq.c b/src/seq.c
index cedd25d..7ffd95f 100644
--- a/src/seq.c
+++ b/src/seq.c
@@ -417,7 +417,7 @@ seq_fast (char const *a, char const *b)
         {
           incr (&p, &p_len);
           z = mempcpy (z, p, p_len);
-          *z++ = '\n';
+          *z++ = *separator;
           if (buf_end - n - 1 < z)
             {
               fwrite (buf, z - buf, 1, stdout);
@@ -536,13 +536,13 @@ main (int argc, char **argv)
      - integer end
      - increment == 1 or not specified [FIXME: relax this, eventually]
      then use the much more efficient integer-only code.  */
-  if (format_str == NULL
-      && all_digits_p (argv[1])
-      && (n_args == 1 || all_digits_p (argv[2]))
-      && (n_args < 3 || STREQ ("1", argv[3])))
+  if (all_digits_p (argv[optind])
+      && (n_args == 1 || all_digits_p (argv[optind + 1]))
+      && (n_args < 3 || STREQ ("1", argv[optind + 2]))
+      && !equal_width && !format_str && strlen (separator) == 1)
     {
-      char const *s1 = n_args == 1 ? "1" : argv[1];
-      char const *s2 = n_args == 1 ? argv[1] : argv[2];
+      char const *s1 = n_args == 1 ? "1" : argv[optind];
+      char const *s2 = n_args == 1 ? argv[optind] : argv[optind + 1];
       if (seq_fast (s1, s2))
         exit (EXIT_SUCCESS);
 
@@ -563,6 +563,22 @@ main (int argc, char **argv)
         }
     }
 
+  if (first.precision == 0 && step.precision == 0 && last.precision == 0
+      && 0 <= first.value && step.value == 1 && 0 <= last.value
+      && !equal_width && !format_str && strlen (separator) == 1)
+    {
+      char *s1;
+      char *s2;
+      if (asprintf (&s1, "%0.Lf", first.value) < 0)
+        xalloc_die ();
+      if (asprintf (&s2, "%0.Lf", last.value) < 0)
+        xalloc_die ();
+      if (seq_fast (s1, s2))
+        exit (EXIT_SUCCESS);
+
+      /* Upon any failure, let the more general code deal with it.  */
+    }
+
   if (format_str == NULL)
     format_str = get_default_format (first, step, last);
 
-- 
1.7.6.4

Reply via email to