[libmath-prime-util-perl] 28/50: Rewrite p-1 factoring, enhance racing SQUFOF, switch to racing SQUFOF in factor
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:45:36 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.13
in repository libmath-prime-util-perl.
commit 7b380c20c7909848e18c91346cfe9c74b7ba8f38
Author: Dana Jacobsen <dana at acm.org>
Date: Mon Nov 5 01:01:54 2012 -0800
Rewrite p-1 factoring, enhance racing SQUFOF, switch to racing SQUFOF in factor
---
Changes | 6 ++
TODO | 2 +
XS.xs | 81 ++++++++------------
factor.c | 264 ++++++++++++++++++++++++++++++++++++++++-----------------------
4 files changed, 210 insertions(+), 143 deletions(-)
diff --git a/Changes b/Changes
index b4a1784..d85d848 100644
--- a/Changes
+++ b/Changes
@@ -1,6 +1,7 @@
Revision history for Perl extension Math::Prime::Util.
0.12 2 November 2012
+
- Add bin/primes.pl
- Add functions:
@@ -8,6 +9,7 @@ Revision history for Perl extension Math::Prime::Util.
pn_primorial product of first n primes
prime_set_config set config options
RiemannZeta export and make accurate for small reals
+ is_provable_prime prove primes after BPSW
- Add 'assume_rh' configuration option (default: false) which can be set
to allow functions to assume the Riemann Hypothesis.
@@ -22,6 +24,10 @@ Revision history for Perl extension Math::Prime::Util.
- In the PP code, use 2 MR bases for more numbers when possible.
+ - Fixup of racing SQUFOF, and switch to use it in factor().
+
+ - Complete rewrite of XS p-1 factor routine, includes second stage.
+
0.11 23 July 2012
- Turn off threading tests on Cygwin, as threads on some Cygwin platforms
give random panics (my Win7 64-bit works fine, XP 32-bit does not).
diff --git a/TODO b/TODO
index 184d884..9b53584 100644
--- a/TODO
+++ b/TODO
@@ -29,3 +29,5 @@
- Test all functions return either native or bigints. Functions that return
raw MPU::GMP results will return strings, which isn't right.
+
+- Make proper pminus1 in PP code, like factor.c.
diff --git a/XS.xs b/XS.xs
index 11fa453..c846c6b 100644
--- a/XS.xs
+++ b/XS.xs
@@ -196,48 +196,33 @@ erat_primes(IN UV low, IN UV high)
void
_XS_factor(IN UV n)
PPCODE:
- if (n < 4) {
- XPUSHs(sv_2mortal(newSVuv( n ))); /* If n is 0-3, we're done. */
+ UV orign = n;
+ if (n < 4) { /* If n is 0-3, we're done. */
+ XPUSHs(sv_2mortal(newSVuv( n )));
+ } else if (n < 2000000) { /* For small n, just trial division */
+ int i;
+ UV facs[32]; /* maximum number of factors is log2n */
+ UV nfacs = trial_factor(n, facs, 0);
+ for (i = 1; i <= nfacs; i++) {
+ XPUSHs(sv_2mortal(newSVuv( facs[i-1] )));
+ }
} else {
int const verbose = 0;
- UV tlim = 101; /* Below this we've checked with trial division */
+ UV const tlim_lower = 211; /* Trial division through this prime */
+ UV const tlim = 223; /* This means we've checked through here */
UV tofac_stack[MPU_MAX_FACTORS+1];
UV factored_stack[MPU_MAX_FACTORS+1];
int ntofac = 0;
int nfactored = 0;
- /* Quick trial divisions. Crude use of GCD to hopefully go faster. */
- while ( (n% 2) == 0 ) { n /= 2; XPUSHs(sv_2mortal(newSVuv( 2 ))); }
- if ( (n >= UVCONST(3*3)) && (gcd_ui(n, UVCONST(3234846615) != 1)) ) {
- while ( (n% 3) == 0 ) { n /= 3; XPUSHs(sv_2mortal(newSVuv( 3 ))); }
- while ( (n% 5) == 0 ) { n /= 5; XPUSHs(sv_2mortal(newSVuv( 5 ))); }
- while ( (n% 7) == 0 ) { n /= 7; XPUSHs(sv_2mortal(newSVuv( 7 ))); }
- while ( (n%11) == 0 ) { n /= 11; XPUSHs(sv_2mortal(newSVuv( 11 ))); }
- while ( (n%13) == 0 ) { n /= 13; XPUSHs(sv_2mortal(newSVuv( 13 ))); }
- while ( (n%17) == 0 ) { n /= 17; XPUSHs(sv_2mortal(newSVuv( 17 ))); }
- while ( (n%19) == 0 ) { n /= 19; XPUSHs(sv_2mortal(newSVuv( 19 ))); }
- while ( (n%23) == 0 ) { n /= 23; XPUSHs(sv_2mortal(newSVuv( 23 ))); }
- while ( (n%29) == 0 ) { n /= 29; XPUSHs(sv_2mortal(newSVuv( 29 ))); }
- }
- if ( (n >= UVCONST(31*31)) && (gcd_ui(n, UVCONST(95041567) != 1)) ) {
- while ( (n%31) == 0 ) { n /= 31; XPUSHs(sv_2mortal(newSVuv( 31 ))); }
- while ( (n%37) == 0 ) { n /= 37; XPUSHs(sv_2mortal(newSVuv( 37 ))); }
- while ( (n%41) == 0 ) { n /= 41; XPUSHs(sv_2mortal(newSVuv( 41 ))); }
- while ( (n%43) == 0 ) { n /= 43; XPUSHs(sv_2mortal(newSVuv( 43 ))); }
- while ( (n%47) == 0 ) { n /= 47; XPUSHs(sv_2mortal(newSVuv( 47 ))); }
- }
- if ( (n >= UVCONST(53*53)) && (gcd_ui(n, UVCONST(907383479) != 1)) ) {
- while ( (n%53) == 0 ) { n /= 53; XPUSHs(sv_2mortal(newSVuv( 53 ))); }
- while ( (n%59) == 0 ) { n /= 59; XPUSHs(sv_2mortal(newSVuv( 59 ))); }
- while ( (n%61) == 0 ) { n /= 61; XPUSHs(sv_2mortal(newSVuv( 61 ))); }
- while ( (n%67) == 0 ) { n /= 67; XPUSHs(sv_2mortal(newSVuv( 67 ))); }
- while ( (n%71) == 0 ) { n /= 71; XPUSHs(sv_2mortal(newSVuv( 71 ))); }
- }
- if ( (n >= UVCONST(73*73)) && (gcd_ui(n, UVCONST(4132280413) != 1)) ) {
- while ( (n%73) == 0 ) { n /= 73; XPUSHs(sv_2mortal(newSVuv( 73 ))); }
- while ( (n%79) == 0 ) { n /= 79; XPUSHs(sv_2mortal(newSVuv( 79 ))); }
- while ( (n%83) == 0 ) { n /= 83; XPUSHs(sv_2mortal(newSVuv( 83 ))); }
- while ( (n%89) == 0 ) { n /= 89; XPUSHs(sv_2mortal(newSVuv( 89 ))); }
- while ( (n%97) == 0 ) { n /= 97; XPUSHs(sv_2mortal(newSVuv( 97 ))); }
+
+ { /* Trial division, removes all factors below tlim */
+ int i;
+ UV facs[BITS_PER_WORD+1];
+ UV nfacs = trial_factor(n, facs, tlim_lower);
+ for (i = 1; i < nfacs; i++) {
+ XPUSHs(sv_2mortal(newSVuv( facs[i-1] )));
+ }
+ n = facs[nfacs-1];
}
do { /* loop over each remaining factor */
@@ -245,23 +230,19 @@ _XS_factor(IN UV n)
* but in practice it seems slower. */
while ( (n >= (tlim*tlim)) && (!_XS_is_prime(n)) ) {
int split_success = 0;
- /* How many rounds of SQUFOF to try depends on the number size */
- UV sq_rounds = ((n>>29) == 0) ? 100000 :
- ((n>>29) < 100000) ? 250000 :
- 600000;
+ /* Adjust the number of rounds based on the number size */
+ UV br_rounds = ((n>>29) < 100000) ? 1500 : 1500;
+ UV sq_rounds = 80000; /* 20k 91%, 40k 98%, 80k 99.9%, 120k 99.99% */
/* Small factors will be found quite rapidly with this */
if (!split_success) {
- split_success = pbrent_factor(n, tofac_stack+ntofac, 1500)-1;
+ split_success = pbrent_factor(n, tofac_stack+ntofac, br_rounds)-1;
if (verbose) { if (split_success) printf("pbrent 1: %"UVuf" %"UVuf"\n", tofac_stack[ntofac], tofac_stack[ntofac+1]); else printf("pbrent 0\n"); }
}
- if (!split_success) {
+ if (!split_success && n < (UV_MAX>>3)) {
/* SQUFOF does very well with what's left after TD and Rho. */
- /* Racing SQUFOF is about 40% faster and has better success, but
- * has input size restrictions and I'm seeing cases where it gets
- * stuck in stage 2. For now just stick with the old one. */
- split_success = squfof_factor(n, tofac_stack+ntofac, sq_rounds)-1;
+ split_success = racing_squfof_factor(n, tofac_stack+ntofac, sq_rounds)-1;
if (verbose) printf("squfof %d\n", split_success);
}
@@ -276,6 +257,10 @@ _XS_factor(IN UV n)
split_success = holf_factor(n, tofac_stack+ntofac, 2000)-1;
if (verbose) printf("holf %d\n", split_success);
}
+ if (!split_success) {
+ split_success = pminus1_factor(n, tofac_stack+ntofac, 1000)-1;
+ if (verbose) printf("pminus1 %d\n", split_success);
+ }
/* A miniscule fraction of numbers make it here */
if (!split_success) {
@@ -372,9 +357,9 @@ squfof_factor(IN UV n, IN UV maxrounds = 4*1024*1024)
SIMPLE_FACTOR(squfof_factor, n, maxrounds);
void
-rsqufof_factor(IN UV n)
+rsqufof_factor(IN UV n, IN UV maxrounds = 4*1024*1024)
PPCODE:
- SIMPLE_FACTOR(racing_squfof_factor, n, 0);
+ SIMPLE_FACTOR(racing_squfof_factor, n, maxrounds);
void
pbrent_factor(IN UV n, IN UV maxrounds = 4*1024*1024)
diff --git a/factor.c b/factor.c
index a75d85e..c20d246 100644
--- a/factor.c
+++ b/factor.c
@@ -31,20 +31,15 @@ int trial_factor(UV n, UV *factors, UV maxtrial)
factors[0] = n;
return 1;
}
+ while ( (n & 1) == 0 ) { factors[nfactors++] = 2; n /= 2; }
- while ( (n & 1) == 0 ) {
- factors[nfactors++] = 2;
- n /= 2;
- }
-
- for (f = 3; (n > 1) && (f <= 7) && (f <= maxtrial); f += 2) {
- while ( (n % f) == 0 ) {
- factors[nfactors++] = f;
- n /= f;
- }
- }
+ if (3 <= maxtrial) while ( (n % 3) == 0 ) { factors[nfactors++] = 3; n /= 3; }
+ if (5 <= maxtrial) while ( (n % 5) == 0 ) { factors[nfactors++] = 5; n /= 5; }
+ if (7 <= maxtrial) while ( (n % 7) == 0 ) { factors[nfactors++] = 7; n /= 7; }
+ f = 11;
+ m = 11;
- if ( (n < (7*7)) || (maxtrial < 11) ) {
+ if ( (n < (f*f)) || (maxtrial < f) ) {
if (n != 1)
factors[nfactors++] = n;
return nfactors;
@@ -55,8 +50,6 @@ int trial_factor(UV n, UV *factors, UV maxtrial)
limit = maxtrial;
/* wheel 30 */
- f = 11;
- m = 11;
while (f <= limit) {
if ( (n%f) == 0 ) {
UV newlimit;
@@ -143,10 +136,9 @@ int trial_factor(UV n, UV *factors, UV maxtrial)
UV t = 1;
n %= m;
while (power) {
- if (power & 1)
- t = mulmod(t, n, m);
- n = sqrmod(n, m);
+ if (power & 1) t = mulmod(t, n, m);
power >>= 1;
+ if (power) n = sqrmod(n, m);
}
return t;
}
@@ -156,17 +148,15 @@ int trial_factor(UV n, UV *factors, UV maxtrial)
n %= m;
if (m < HALF_WORD) {
while (power) {
- if (power & 1)
- t = (t*n)%m;
- n = (n*n)%m;
+ if (power & 1) t = (t*n)%m;
power >>= 1;
+ if (power) n = (n*n)%m;
}
} else {
while (power) {
- if (power & 1)
- t = mulmod(t, n, m);
- n = sqrmod(n,m);
+ if (power & 1) t = mulmod(t, n, m);
power >>= 1;
+ if (power) n = sqrmod(n,m);
}
}
return t;
@@ -181,10 +171,24 @@ int trial_factor(UV n, UV *factors, UV maxtrial)
/* Return 0 if n is not a perfect square. Set sqrtn to int(sqrt(n)) if so.
*
- * A simplistic solution (but not unhelpful) is:
+ * Some simple solutions:
*
* return ( ((m&2)!= 0) || ((m&7)==5) || ((m&11) == 8) ) ? 0 : 1;
*
+ * or:
+ *
+ * m = n & 31;
+ * if ( m==0 || m==1 || m==4 || m==9 || m==16 || m==17 || m==25 )
+ * ...test for perfect square...
+ *
+ * or:
+ *
+ * if ( ((0x0202021202030213ULL >> (n & 63)) & 1) &&
+ * ((0x0402483012450293ULL >> (n % 63)) & 1) &&
+ * ((0x218a019866014613ULL >> ((n % 65) & 63)) & 1) &&
+ * ((0x23b >> (n % 11) & 1)) ) {
+ *
+ *
* The following Bloom filter cascade works very well indeed. Read all
* about it here: http://mersenneforum.org/showpost.php?p=110896
*/
@@ -219,6 +223,9 @@ static int is_perfect_square(UV n, UV* sqrtn)
m = lm % 11;
if ((m*0xabf1a3a7) & (m*0x2612bf93) & 0x45854000) return 0;
/* 99.92% of non-squares are rejected now */
+#else
+ m = n % 63;
+ if ((m*0x3d491df7) & (m*0xc824a9f9) & 0x10f14008) return 0;
#endif
m = sqrt(n);
if (n != (m*m))
@@ -547,23 +554,91 @@ int prho_factor(UV n, UV *factors, UV rounds)
* Probabilistic. If you give this a prime number, it will loop
* until it runs out of rounds.
*/
-int pminus1_factor(UV n, UV *factors, UV rounds)
+int pminus1_factor(UV n, UV *factors, UV B1)
{
- UV f, i;
- UV kf = 13;
-
+ UV f, q, restartq, restarta;
+ UV a = 2;
+ UV sqrtB1 = sqrt(B1);
MPUassert( (n >= 3) && ((n%2) != 0) , "bad n in pminus1_factor");
-
- for (i = 1; i <= rounds; i++) {
- kf = powmod(kf, i, n);
- if (kf == 0) kf = n;
- f = gcd_ui(kf-1, n);
- if ( (f != 1) && (f != n) ) {
- factors[0] = f;
- factors[1] = n/f;
- MPUassert( factors[0] * factors[1] == n , "incorrect factoring");
- return 2;
+ restartq = 2;
+ restarta = a;
+ for (q = 2; q <= sqrtB1; q = _XS_next_prime(q)) {
+ UV k = q;
+ UV kmin = B1/q;
+ while (k <= kmin)
+ k *= q;
+ a = powmod(a, k, n);
+ }
+ if (a == 0) { factors[0] = n; return 1; }
+ f = gcd_ui(a-1, n);
+ if (f == 1) {
+ restartq = q;
+ restarta = a;
+ for ( ; q <= B1; q = _XS_next_prime(q)) {
+ a = powmod(a, q, n);
}
+ f = gcd_ui(a-1, n);
+ }
+ /* See if we found more than one factor in stage 1, repeat if so */
+ if (f == n) {
+ a = restarta;
+ for (q = restartq; q <= B1; q = _XS_next_prime(q)) {
+ UV k = q;
+ UV kmin = B1/q;
+ while (k <= kmin)
+ k *= q;
+ a = powmod(a, k, n);
+ f = gcd_ui(a-1, n);
+ if (f != 1 && f != n)
+ break;
+ }
+ }
+ if (f == 1 || f == n) { /* stage 2 */
+ UV B2 = B1 * 10;
+ UV bm = a;
+ UV b = 1;
+ UV j = 1;
+ UV precomp_bm[111] = {0}; /* Enough for B2 = 189M */
+
+ /* calculate (a^q)^2, (a^q)^4, etc. */
+ precomp_bm[0] = sqrmod(bm, n);
+
+ a = powmod(a, q, n);
+ while (q <= B2) {
+ UV lastq = q;
+ UV qdiff, bmdiff;
+ q = _XS_next_prime(q);
+ /* compute a^q = a^lastq * a^(q-lastq) */
+ qdiff = (q - lastq) / 2 - 1;
+ if (qdiff >= 111) {
+ bmdiff = powmod(bm, q-lastq, n); /* Too big of gap */
+ } else {
+ bmdiff = precomp_bm[qdiff];
+ if (bmdiff == 0) {
+ if (precomp_bm[qdiff-1] != 0)
+ bmdiff = mulmod(mulmod(precomp_bm[qdiff-1],bm,n),bm,n);
+ else
+ bmdiff = powmod(bm, q-lastq, n);
+ precomp_bm[qdiff] = bmdiff;
+ }
+ }
+ a = mulmod( a, bmdiff, n);
+ if (a <= 1) break;
+ b = mulmod( b, a-1, n);
+ if (b == 0) b = 1;
+ if ( (j++ % 64) == 0 ) {
+ f = gcd_ui(b, n);
+ if (f != 1 && f != n)
+ break;
+ }
+ }
+ f = gcd_ui(b, n);
+ }
+ if ( (f != 1) && (f != n) ) {
+ factors[0] = f;
+ factors[1] = n/f;
+ MPUassert( factors[0] * factors[1] == n , "incorrect factoring");
+ return 2;
}
factors[0] = n;
return 1;
@@ -702,27 +777,24 @@ int squfof_factor(UV n, UV *factors, UV rounds)
/* Another version, based on Ben Buhrow's racing SQUFOF. */
-typedef unsigned int uint32;
-typedef UV uint64;
-
typedef struct
{
- uint32 mult;
- uint32 valid;
- uint32 P;
- uint32 bn;
- uint32 Qn;
- uint32 Q0;
- uint32 b0;
- uint32 it;
- uint32 imax;
+ UV mult;
+ UV valid;
+ UV P;
+ UV bn;
+ UV Qn;
+ UV Q0;
+ UV b0;
+ UV it;
+ UV imax;
} mult_t;
// N < 2^63 (or 2^31). *f == 1 if no factor found
-static void squfof_unit(UV n, mult_t* mult_save, uint64* f)
+static void squfof_unit(UV n, mult_t* mult_save, UV* f)
{
- uint32 imax,i,Q0,b0,Qn,bn,P,bbn,Ro,S,So,t1,t2;
- int j = 0;
+ UV imax,i,Q0,b0,Qn,bn,P,bbn,Ro,S,So,t1,t2;
+ int j;
*f = 0;
@@ -765,14 +837,8 @@ static void squfof_unit(UV n, mult_t* mult_save, uint64* f)
SQUARE_SEARCH_ITERATION;
// Even iteration. Check for square: Qn = S*S
- // TODO: DAJ try bloom filter?
- t2 = Qn & 31;
- if (t2 == 0 || t2 == 1 || t2 == 4 || t2 == 9 ||
- t2 == 16 || t2 == 17 || t2 == 25) {
- S = (uint32)sqrt(Qn);
- if (Qn == S * S)
- break;
- }
+ if (is_perfect_square( Qn, &S ))
+ break;
// Odd iteration.
SQUARE_SEARCH_ITERATION;
@@ -780,10 +846,9 @@ static void squfof_unit(UV n, mult_t* mult_save, uint64* f)
/* printf("found square %lu after %lu iterations with mult %d\n", Qn, i, mult_save->mult); */
// Reduce to G0
- // S = (uint32)sqrt(Qn);
Ro = P + S*((b0 - P)/S);
t1 = Ro;
- So = (uint32)(((uint64)n - (uint64)t1*(uint64)t1)/(uint64)S);
+ So = (n - t1*t1)/S;
bbn = (b0+Ro)/So;
// Search for symmetry point
@@ -796,11 +861,17 @@ static void squfof_unit(UV n, mult_t* mult_save, uint64* f)
bbn = (b0+Ro)/So; \
if (Ro == t1) break;
+ j = 0;
while (1) {
SYMMETRY_POINT_ITERATION;
SYMMETRY_POINT_ITERATION;
SYMMETRY_POINT_ITERATION;
SYMMETRY_POINT_ITERATION;
+ if (j++ > 2000000) {
+ mult_save->valid = 0;
+ *f = 0;
+ return;
+ }
}
*f = gcd_ui(Ro, n);
@@ -809,19 +880,18 @@ static void squfof_unit(UV n, mult_t* mult_save, uint64* f)
}
}
-#define NSQUFOF_MULT 16
+#define NSQUFOF_MULT (sizeof(multipliers)/sizeof(multipliers[0]))
int racing_squfof_factor(UV n, UV *factors, UV rounds)
{
- const int multipliers[NSQUFOF_MULT] = {1, 3, 5, 7, 11,
- 3*5, 3*7, 3*11,
- 5*7, 5*11, 7*11,
- 3*5*7, 3*5*11, 3*7*11,
- 5*7*11, 3*5*7*11};
+ const UV multipliers[] = {
+ 3*5*7*11, 3*5*7, 3*5*11, 3*5, 3*7*11, 3*7, 5*7*11, 5*7,
+ 3*11, 3, 5*11, 5, 7*11, 7, 11, 1 };
const UV big2 = UV_MAX >> 2;
mult_t mult_save[NSQUFOF_MULT];
- int i, j, race_rounds;
- uint64 nn64, f64;
+ int i, still_racing;
+ UV nn64, mult, f64;
+ UV rounds_done = 0;
/* Caller should have handled these trivial cases */
MPUassert( (n >= 3) && ((n%2) != 0) , "bad n in racing_squfof_factor");
@@ -831,23 +901,24 @@ int racing_squfof_factor(UV n, UV *factors, UV rounds)
factors[0] = n; return 1;
}
- for (i = NSQUFOF_MULT-1; i >= 0; i--) {
- nn64 = n * (uint64)multipliers[i];
- if ((big2 / (UV)multipliers[i]) < n) {
- /* This multiplier would overflow 64-bit */
- mult_save[i].mult = multipliers[i];
- mult_save[i].valid = 0;
+ for (i = 0; i < NSQUFOF_MULT; i++) {
+ mult = multipliers[i];
+ nn64 = n * mult;
+ mult_save[i].mult = mult;
+ if ((big2 / mult) < n) {
+ mult_save[i].valid = 0; /* This multiplier would overflow 64-bit */
continue;
}
- mult_save[i].mult = multipliers[i];
mult_save[i].valid = 1;
- mult_save[i].b0 = (uint32) sqrt( (double)nn64 );
- mult_save[i].imax = (uint32) sqrt( (double)mult_save[i].b0 );
+ mult_save[i].b0 = sqrt( (double)nn64 );
+ mult_save[i].imax = sqrt( (double)mult_save[i].b0 ) / 3;
+ if (mult_save[i].imax < 20) mult_save[i].imax = 20;
+ if (mult_save[i].imax > rounds) mult_save[i].imax = rounds;
mult_save[i].Q0 = 1;
mult_save[i].P = mult_save[i].b0;
- mult_save[i].Qn = (uint32) (nn64 - (uint64)mult_save[i].b0 * (uint64)mult_save[i].b0);
+ mult_save[i].Qn = nn64 - (mult_save[i].b0 * mult_save[i].b0);
if (mult_save[i].Qn == 0) {
factors[0] = mult_save[i].b0;
factors[1] = n / mult_save[i].b0;
@@ -858,19 +929,17 @@ int racing_squfof_factor(UV n, UV *factors, UV rounds)
mult_save[i].it = 0;
}
- /* Process the multipliers a little at a time. */
- race_rounds = 6;
- for (i = 0; i < race_rounds; i++) {
- for (j = 0; j < NSQUFOF_MULT; j++) {
- if (!mult_save[j].valid)
+ /* Process the multipliers a little at a time: 0.33*(n*mult)^1/4: 20-20k */
+ do {
+ still_racing = 0;
+ for (i = 0; i < NSQUFOF_MULT; i++) {
+ if (!mult_save[i].valid)
continue;
- nn64 = n * (UV)multipliers[j];
- squfof_unit(nn64, &mult_save[j], &f64);
- if (f64 == -1) { /* -1 is an error */
- mult_save[j].valid = 0;
- } else if (f64 > 1) {
- if (f64 != multipliers[j]) {
- f64 /= gcd_ui(f64, multipliers[j]);
+ nn64 = n * (UV)multipliers[i];
+ squfof_unit(nn64, &mult_save[i], &f64);
+ if (f64 > 1) {
+ if (f64 != multipliers[i]) {
+ f64 /= gcd_ui(f64, multipliers[i]);
if (f64 != 1) {
factors[0] = f64;
factors[1] = n / f64;
@@ -879,10 +948,15 @@ int racing_squfof_factor(UV n, UV *factors, UV rounds)
}
}
/* Found trivial factor. Quit working with this multiplier. */
- mult_save[j].valid = 0;
+ mult_save[i].valid = 0;
}
+ if (mult_save[i].valid == 1)
+ still_racing = 1;
+ rounds_done += mult_save[i].imax;
+ if (rounds_done >= rounds)
+ break;
}
- }
+ } while (still_racing && rounds_done < rounds);
/* No factors found */
factors[0] = n;
--
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