From: Paul Eggert Date: Wed, 25 Sep 2024 22:59:09 +0000 (-0700) Subject: factor: port to platforms X-Git-Tag: v9.6~163 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5867465510d023ece420e9921fc1034e3abd6455;p=thirdparty%2Fcoreutils.git factor: port to platforms * 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. --- diff --git a/src/factor.c b/src/factor.c index 2649e9fc60..f4dd6f6d4f 100644 --- a/src/factor.c +++ b/src/factor.c @@ -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; diff --git a/tests/factor/create-test.sh b/tests/factor/create-test.sh index eda52f89cf..2d587c0d99 100755 --- a/tests/factor/create-test.sh +++ b/tests/factor/create-test.sh @@ -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 diff --git a/tests/local.mk b/tests/local.mk index f723538628..2b885798a9 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -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)