]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
factor: don’t prove primality
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 21 Jun 2025 18:41:11 +0000 (11:41 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 10 Jul 2025 00:12:40 +0000 (17:12 -0700)
Suggested for consideration by Torbjörn Granlund in:
https://lists.gnu.org/r/coreutils/2025-01/msg00000.html
* src/factor.c (PROVE_PRIMALITY): Now defaults to false.
(mp_prime_p): Help the compiler by telling it mpz_prob_prime_p
returns nonnegative.
* tests/factor/create-test.sh (bigprime): Test 2^400 - 593,
since that’s now practical.
* tests/local.mk (factor_tests): Add new test.

NEWS
doc/coreutils.texi
src/factor.c
tests/factor/create-test.sh
tests/local.mk

diff --git a/NEWS b/NEWS
index 87ba2659cf4f6060d163d44c88cc836a4848a2fb..eda971bb6a79f067e52b93e61adcfcd42135d44d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Changes in behavior
+
+  'factor' is now much faster at identifying large prime numbers.
+
 ** Bug fixes
 
   cksum was not compilable by Apple LLVM 10.0.0 x86-64, which
index 89a0b597236d1d2ee39f4506862af10ab41b078a..0648463dfbb3e25950afffadafcf51cb5a04f859 100644 (file)
@@ -19180,11 +19180,21 @@ takes about 14 seconds, and the slower algorithm would have taken
 about 750 ms to factor @math{2^{127} - 3} instead of the 50 ms needed by
 the faster algorithm.
 
-Factoring large numbers is, in general, hard.  The Pollard-Brent rho
+Factoring large numbers is, in general, hard.  The Pollard--Brent rho
 algorithm used by @command{factor} is particularly effective for
-numbers with relatively small factors.  If you wish to factor large
-numbers which do not have small factors (for example, numbers which
-are the product of two large primes), other methods are far better.
+numbers with relatively small factors.  Other methods are far better
+for factoring large composite numbers that lack relatively small
+factors, such as numbers that are the product of two large primes.
+
+When testing whether a number is prime, @command{factor} uses the
+Baillie--PSW primality heuristic for speed.  Although Baillie--PSW has
+not been proven to reject all composite numbers, the probability of a
+Baillie--PSW pseudoprime is astronomically small and no such
+pseudoprime has been discovered despite decades of searching by
+mathematicians.  Any such pseudoprime is greater than @math{2^{64}}.
+For more, see: Baillie R, Fiori A, Wagstaff Jr SS.@: Strengthening the
+Baillie--PSW primality test.@: @i{Math Comp}.@: 2021;90:1931--1955.@:
+@uref{https://doi.org/10.1090/mcom/3616}.
 
 @exitstatus
 
index b5656f00e9d481577b74b8d8e9eeb392d815f050..19f75802e16cd2c061509605efb79c314e4dd2e6 100644 (file)
       pre-inversion (such as GMP's invert_limb) and udiv_qrnnd_preinv (from
       GMP's gmp-impl.h).  The redcify2 function could be vastly improved using
       similar methods.  These functions currently dominate run time when
-      PROVE_PRIMALITY is nonzero (the default).
+      PROVE_PRIMALITY is true (which is not the default).
 */
 
 /* Whether to recursively factor to prove primality,
-   or run faster probabilistic tests.  */
+   or run faster probabilistic tests.
+   FIXME: Simplify the code by assuming PROVE_PRIMALITY is false,
+   and remove PROVE_PRIMALITY.  */
 #ifndef PROVE_PRIMALITY
-# define PROVE_PRIMALITY 1
+# define PROVE_PRIMALITY false
 #endif
 
 
@@ -1523,6 +1525,7 @@ mp_prime_p (mpz_t n)
     return true;
 
   int probab_prime = mpz_probab_prime_p (n, MR_REPS);
+  assume (0 <= probab_prime);
   if (probab_prime == 0)
     return false;
   if (flag_prove_primality < probab_prime)
index fc84b148433452bbfedf9cd754011f61b9fc842b..7fad40cdcc56cd0af8de232ffad4cc1eeddb9af1 100755 (executable)
@@ -27,6 +27,10 @@ t2=170141183460469229545748130981302223887
 # https://bugs.gnu.org/73474
 bug73474=22222222222222222202111121111
 
+# 2^400 - 593
+bigprime=25822498780869085896559191720030118743297057928292235128306593565406\
+47622016841194629645353280137831435903171972747492783
+
 # 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.
@@ -70,6 +74,7 @@ case $t in
   t35) set   ${q}958336   ${q}960335 2374919a89196e1fce93adfe779cb4664556d4b6 ;;
   t36) set   ${q}960336   ${q}962335 569e4363e8d9e8830a187d9ab27365eef08abde1 ;;
   t37) set    $bug73474    $bug73474 61d04aaf757acc5a37eb1d5581a98eea78ef50e8 ;;
+  t38) set    $bigprime    $bigprime 02f3c51a2896ff4524fd76de5f5854029879a179 ;;
   *)
     echo "$0: error: unknown test: '$test_name' -> '$t'" >&2
     exit 1
index 03114f75923140d65893fc53acf59e022d28fcd6..dd07032dab1727110f7959b3d9a35ffdeb8d5786 100644 (file)
@@ -765,7 +765,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)/t37.sh
+  $(tf)/t35.sh $(tf)/t36.sh $(tf)/t37.sh $(tf)/t38.sh
 
 $(factor_tests): $(tf)/run.sh $(tf)/create-test.sh
        $(AM_V_GEN)$(MKDIR_P) $(tf)