]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
factor: speed up converting strings to uuint
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 9 Jul 2025 17:36:04 +0000 (10:36 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 10 Jul 2025 00:12:40 +0000 (17:12 -0700)
* src/factor.c: Do not include c-ctype.h.
(strtouuint): Don’t bother generating a number on
error; just return a strtol_error value other than LONGINT_OK.
Speed up overflow checking.

src/factor.c

index 6fe900af3191a0983b3c9e448a22f4a344baf8bd..134c092f8445b8d4ec4170961c935d969fe4a0c6 100644 (file)
@@ -84,7 +84,6 @@
 
 #include "system.h"
 #include "assure.h"
-#include "c-ctype.h"
 #include "full-write.h"
 #include "quote.h"
 #include "readtokens.h"
@@ -1626,61 +1625,35 @@ mp_factor (mpz_t t)
   return factors;
 }
 
-/* Convert to *U the value represnted by S.
-   Return an error indicator.  */
+/* Convert to *U the value represented by S, and return LONGINT_OK.
+   However, on error simply return a value other than LONGINT_OK.  */
 static strtol_error
 strtouuint (uuint *u, char const *s)
 {
-  int lo_carry;
-  mp_limb_t hi = 0, lo = 0;
+  mp_limb_t hi = 0, lo = *s++ - '0';
 
-  strtol_error err = LONGINT_INVALID;
+  if (UNLIKELY (9 < lo))
+    return LONGINT_INVALID;
 
-  /* Initial scan for invalid digits.  */
-  char const *p = s;
-  for (;;)
-    {
-      unsigned char c = *p++;
-      if (c == 0)
-        break;
-
-      if (UNLIKELY (!c_isdigit (c)))
-        {
-          err = LONGINT_INVALID;
-          break;
-        }
-
-      err = LONGINT_OK;           /* we've seen at least one valid digit */
-    }
-
-  while (err == LONGINT_OK)
+  for (; LIKELY (0 <= *s - '0' && *s - '0' <= 9); s++)
     {
-      unsigned char c = *s++;
-      if (c == 0)
-        break;
-
-      c -= '0';
-
       if (UNLIKELY (ckd_mul (&hi, hi, 10)))
-        {
-          err = LONGINT_OVERFLOW;
-          break;
-        }
+        return LONGINT_OVERFLOW;
 
-      lo_carry = (lo >> (W_TYPE_SIZE - 3)) + (lo >> (W_TYPE_SIZE - 1));
+      int lo_carry = (lo >> (W_TYPE_SIZE - 3)) + (lo >> (W_TYPE_SIZE - 1));
       lo_carry += 10 * lo < 2 * lo;
 
       lo = 10 * lo;
-      lo_carry += ckd_add (&lo, lo, c);
+      lo_carry += ckd_add (&lo, lo, *s - '0');
       if (UNLIKELY (ckd_add (&hi, hi, lo_carry)))
-        {
-          err = LONGINT_OVERFLOW;
-          break;
-        }
+        return LONGINT_OVERFLOW;
     }
 
+  if (UNLIKELY (*s))
+    return LONGINT_INVALID;
+
   *u = make_uuint (hi, lo);
-  return err;
+  return LONGINT_OK;
 }
 
 /* FACTOR_PIPE_BUF is chosen to give good performance,