[libmath-prime-util-perl] 47/59: Work on factoring a little
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:45:01 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.10
in repository libmath-prime-util-perl.
commit 8347ffa7a637d4fed148fd17009910246af61da4
Author: Dana Jacobsen <dana at acm.org>
Date: Thu Jul 12 18:07:32 2012 -0600
Work on factoring a little
---
XS.xs | 32 ++++++++++++++++++++++++++------
factor.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/XS.xs b/XS.xs
index 54937c0..fb0085b 100644
--- a/XS.xs
+++ b/XS.xs
@@ -227,26 +227,46 @@ _XS_factor(IN UV n)
do { /* loop over each remaining factor */
while ( (n >= (tlim*tlim)) && (!is_definitely_prime(n)) ) {
int split_success = 0;
+ /* For larger n, do a different sequence */
if (n > UVCONST(10000000) ) { /* tune this */
- /* For sufficiently large n, try more complex methods. */
/* SQUFOF (succeeds 98-99.9%) */
- split_success = squfof_factor(n, tofac_stack+ntofac, 256*1024)-1;
- /* A few rounds of Pollard rho (succeeds most of the rest) */
if (!split_success) {
- split_success = prho_factor(n, tofac_stack+ntofac, 400)-1;
+ split_success = squfof_factor(n, tofac_stack+ntofac, 256*1024)-1;
+//printf("squfof %d\n", split_success);
+ }
+ /* A few rounds of Pollard's Rho usually gets the factors */
+ if (!split_success) {
+ split_success = prho_factor(n, tofac_stack+ntofac, 800)-1;
+//printf("prho %d\n", split_success);
}
/* Some rounds of HOLF, good for close to perfect squares */
if (!split_success) {
split_success = holf_factor(n, tofac_stack+ntofac, 2000)-1;
+//printf("holf %d\n", split_success);
}
/* Less than 0.00003% of numbers make it past here. */
+ if (!split_success) {
+ split_success = prho(n, tofac_stack+ntofac, 256*1024)-1;
+//printf("prho %d\n", split_success);
+ }
+ } else {
+ /* A few rounds of Pollard rho is good for finding small factors */
+ if (!split_success) {
+ split_success = prho_factor(n, tofac_stack+ntofac, 800)-1;
+//if (split_success) printf("small prho 1: %llu %llu\n", tofac_stack[ntofac], tofac_stack[ntofac+1]); else printf("small prho 0\n");
+ }
}
if (split_success) {
MPUassert( split_success == 1, "split factor returned more than 2 factors");
ntofac++; /* Leave one on the to-be-factored stack */
n = tofac_stack[ntofac]; /* Set n to the other one */
+ } else if (_XS_is_prime(n)) {
+ /* No wonder we couldn't factor it. It's prime. */
+ factored_stack[nfactored++] = n;
+ n = 1;
} else {
/* trial divisions */
+printf("doing trial on %llu\n", n);
UV f = tlim;
UV m = tlim % 30;
UV limit = (UV) (sqrt(n)+0.1);
@@ -317,7 +337,7 @@ fermat_factor(IN UV n, IN UV maxrounds = 64*1024*1024)
SIMPLE_FACTOR(fermat_factor, n, maxrounds);
void
-holf_factor(IN UV n, IN UV maxrounds = 64*1024*1024)
+holf_factor(IN UV n, IN UV maxrounds = 8*1024*1024)
PPCODE:
SIMPLE_FACTOR(holf_factor, n, maxrounds);
@@ -337,7 +357,7 @@ prho_factor(IN UV n, IN UV maxrounds = 4*1024*1024)
SIMPLE_FACTOR(prho_factor, n, maxrounds);
void
-pminus1_factor(IN UV n, IN UV maxrounds = 4*1024*1024)
+pminus1_factor(IN UV n, IN UV maxrounds = 1*1024*1024)
PPCODE:
SIMPLE_FACTOR(pminus1_factor, n, maxrounds);
diff --git a/factor.c b/factor.c
index 42ad2d0..e8621cd 100644
--- a/factor.c
+++ b/factor.c
@@ -406,7 +406,7 @@ int holf_factor(UV n, UV *factors, UV rounds)
MPUassert( (n >= 3) && ((n%2) != 0) , "bad n in holf_factor");
for (i = 1; i <= rounds; i++) {
- s = sqrt(n*i); /* TODO: overflow here */
+ s = sqrt( (double)n * (double)i );
if ( (s*s) != (n*i) ) s++;
m = sqrmod(s, n);
if (is_perfect_square(m, &f)) {
@@ -467,6 +467,7 @@ int pbrent_factor(UV n, UV *factors, UV rounds)
* Probabilistic. If you give this a prime number, it will loop
* until it runs out of rounds.
*/
+#if 0
int prho_factor(UV n, UV *factors, UV rounds)
{
int in_loop = 0;
@@ -502,6 +503,59 @@ int prho_factor(UV n, UV *factors, UV rounds)
factors[0] = n;
return 1;
}
+#else
+int prho_factor(UV n, UV *factors, UV rounds)
+{
+ UV a, f, i, m, oldU, oldV;
+ const UV inner = 8;
+ UV U = 7;
+ UV V = 7;
+
+ MPUassert( (n >= 3) && ((n%2) != 0) , "bad n in prho_factor");
+
+ switch (n%8) {
+ case 1: a = 1; break;
+ case 3: a = 2; break;
+ case 5: a = 3; break;
+ case 7: a = 5; break;
+ default: a = 7; break;
+ }
+
+ rounds = (rounds + inner - 1) / inner;
+
+ while (rounds-- > 0) {
+ m = 1; oldU = U; oldV = V;
+ for (i = 0; i < inner; i++) {
+ U = sqraddmod(U, a, n);
+ V = sqraddmod(V, a, n);
+ V = sqraddmod(V, a, n);
+ f = (U > V) ? U-V : V-U;
+ m = mulmod(m, f, n);
+ }
+ f = gcd_ui(m, n);
+ if (f == 1)
+ continue;
+ if (f == n) { /* backup */
+ U = oldU; V = oldV;
+ i = inner;
+ do {
+ U = sqraddmod(U, a, n);
+ V = sqraddmod(V, a, n);
+ V = sqraddmod(V, a, n);
+ f = gcd_ui( (U > V) ? U-V : V-U, n);
+ } while (f == 1 && i-- != 0);
+ if ( (f == 1) || (f == n) )
+ break;
+ }
+ factors[0] = f;
+ factors[1] = n/f;
+ MPUassert( factors[0] * factors[1] == n , "incorrect factoring");
+ return 2;
+ }
+ factors[0] = n;
+ return 1;
+}
+#endif
/* Pollard's P-1
*
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git
More information about the Pkg-perl-cvs-commits
mailing list