]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
factor: port to platforms
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 25 Sep 2024 22:59:09 +0000 (15:59 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sat, 28 Sep 2024 00:42:58 +0000 (17:42 -0700)
* src/factor.c (mod2): Work even if cntd <= cnta.  The old version
of the code assumed that shifts by N had unspecified behavior
unless 0 <= N < wordsize.  Although this assumption is portable to
all known practical platforms, the C standard says these shifts
have undefined behavior and some pedantic platforms check this.
* tests/factor/create-test.sh:
* tests/local.mk (factor_tests): New test t37.

src/factor.c
tests/factor/create-test.sh
tests/local.mk

index 2649e9fc60e1b528d377256e5bd9083422b1a01d..f4dd6f6d4f08331ca17de7ae3cc0ec6675254181 100644 (file)
@@ -317,12 +317,14 @@ static void factor (uintmax_t, uintmax_t, struct factors *);
   } while (0)
 #endif
 
+/* Set (rh,rl) = (ah,al) >> cnt, where 0 < cnt < W_TYPE_SIZE.  */
 #define rsh2(rh, rl, ah, al, cnt)                                       \
   do {                                                                  \
     (rl) = ((ah) << (W_TYPE_SIZE - (cnt))) | ((al) >> (cnt));           \
     (rh) = (ah) >> (cnt);                                               \
   } while (0)
 
+/* Set (rh,rl) = (ah,al) << cnt, where 0 < cnt < W_TYPE_SIZE.  */
 #define lsh2(rh, rl, ah, al, cnt)                                       \
   do {                                                                  \
     (rh) = ((ah) << cnt) | ((al) >> (W_TYPE_SIZE - (cnt)));             \
@@ -422,12 +424,15 @@ mod2 (uintmax_t *r1, uintmax_t a1, uintmax_t a0, uintmax_t d1, uintmax_t d0)
   count_leading_zeros (cntd, d1);
   count_leading_zeros (cnta, a1);
   int cnt = cntd - cnta;
-  lsh2 (d1, d0, d1, d0, cnt);
-  for (int i = 0; i < cnt; i++)
+  if (0 < cnt)
     {
-      if (ge2 (a1, a0, d1, d0))
-        sub_ddmmss (a1, a0, a1, a0, d1, d0);
-      rsh2 (d1, d0, d1, d0, 1);
+      lsh2 (d1, d0, d1, d0, cnt);
+      for (int i = 0; i < cnt; i++)
+        {
+          if (ge2 (a1, a0, d1, d0))
+            sub_ddmmss (a1, a0, a1, a0, d1, d0);
+          rsh2 (d1, d0, d1, d0, 1);
+        }
     }
 
   *r1 = a1;
index eda52f89cf68c9adb89ad4fd5cc365ba98e490fa..2d587c0d9908deb985e3749839887feae8df35ac 100755 (executable)
@@ -24,6 +24,9 @@ t2=170141183460469229545748130981302223887
 # t1: 9223372036854775421 18446744073709551709
 # t2: 9223372036854775643 18446744073709551709
 
+# https://bugs.gnu.org/73474
+bug73474=22222222222222222202111121111
+
 # Each test is a triple: lo, hi, sha1 of result.
 # The test script, run.sh, runs seq lo hi|factor|sha1sum
 # and verifies that the actual and expected checksums are the same.
@@ -66,6 +69,7 @@ case $t in
   t34) set   ${q}956336   ${q}958335 d1ae6bc712d994f35edf55c785d71ddf31f16535 ;;
   t35) set   ${q}958336   ${q}960335 2374919a89196e1fce93adfe779cb4664556d4b6 ;;
   t36) set   ${q}960336   ${q}962335 569e4363e8d9e8830a187d9ab27365eef08abde1 ;;
+  t37) set    $bug73474    $bug73474 61d04aaf757acc5a37eb1d5581a98eea78ef50e8 ;;
   *)
     echo "$0: error: unknown test: '$test_name' -> '$t'" >&2
     exit 1
index f7235386282f88274029668d222c7dc390948199..2b885798a9722a862b96d7ba5df08d15c237cb7b 100644 (file)
@@ -759,7 +759,7 @@ factor_tests = \
   $(tf)/t20.sh $(tf)/t21.sh $(tf)/t22.sh $(tf)/t23.sh $(tf)/t24.sh \
   $(tf)/t25.sh $(tf)/t26.sh $(tf)/t27.sh $(tf)/t28.sh $(tf)/t29.sh \
   $(tf)/t30.sh $(tf)/t31.sh $(tf)/t32.sh $(tf)/t33.sh $(tf)/t34.sh \
-  $(tf)/t35.sh $(tf)/t36.sh
+  $(tf)/t35.sh $(tf)/t36.sh $(tf)/t37.sh
 
 $(factor_tests): $(tf)/run.sh $(tf)/create-test.sh
        $(AM_V_GEN)$(MKDIR_P) $(tf)