changeset 31112:bbb59cc6698c stable

factor.m: Performance tweak to avoid division in certain cases factor.m: For large numbers where only one factor lies outside the fast first round of divisions, check if it is prime before calling primes () trying to factorize it. This is up to 8000X faster for such numbers, and for an "average" input it gives a 22% to 40% speedup over a large number of trials.
author Arun Giridhar <arungiridhar@gmail.com>
date Sat, 25 Jun 2022 16:40:36 -0400
parents 7797481038fc
children 6ee5bd9ad7cc 01e4f3882f54
files scripts/specfun/factor.m
diffstat 1 files changed, 24 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/specfun/factor.m	Tue Jun 21 15:43:27 2022 +0200
+++ b/scripts/specfun/factor.m	Sat Jun 25 16:40:36 2022 -0400
@@ -150,23 +150,31 @@
   ## q itself will be divided by those prime factors to become smaller,
   ## unless q was prime to begin with.
 
-  ## Now go all the way to sqrt(q), where q is smaller than the original q in
-  ## most cases.
-  ##
-  ## Note: Do not try to weed out the smallprimes inside largeprimes, whether
-  ## using length(smallprimes) or max(smallprimes) -- it slows it down!
-  largeprimes = primes (sqrt (q));
-  [pf, q] = reducefactors (q, pf, largeprimes);
+  if (isprime (q))
+    ## This is an optimization for numbers like 18446744073709551566
+    ## == 2 * 9223372036854775783, where the small factors can be pulled
+    ## out easily and the remaining is prime.  This optimization reduces
+    ## 14.3 s to 1.8 ms (8000X faster) for such cases.
+    pf(end+1) = q;
+  else
+    ## Now go all the way to sqrt(q), where q is smaller than the original q in
+    ## most cases.
+    ##
+    ## Note: Do not try to weed out the smallprimes inside largeprimes, whether
+    ## using length(smallprimes) or max(smallprimes) -- it slows it down!
+    largeprimes = primes (sqrt (q));
+    [pf, q] = reducefactors (q, pf, largeprimes);
 
-  ## At this point, all prime factors <= the sqrt of the original q have been
-  ## pulled out in ascending order.
-  ##
-  ## If q = 1, then no further primes are left.
-  ## If q > 1, then q itself must be prime, and it must be the single prime
-  ## factor that was larger than the sqrt of the original q.
-  if (q > 1)
-    pf(end+1) = q;
-  endif
+    ## At this point, all prime factors <= the sqrt of the original q have been
+    ## pulled out in ascending order.
+    ##
+    ## If q = 1, then no further primes are left.
+    ## If q > 1, then q itself must be prime, and it must be the single prime
+    ## factor that was larger than the sqrt of the original q.
+    if (q > 1)
+      pf(end+1) = q;
+    endif
+  end
 
   ## At this point, all prime factors have been pulled out of q in ascending
   ## order.  There is no need to sort(pf).