Sindbad~EG File Manager
/* M. Beeson, for Mathpert.
Numerical factoring of not-too-big numbers. See nfactor2.c for
factoring of bignums, which requires waiting and display_progress.
This file can be included in polyval.dll. */
/*
5.12.91 oldest recorded change
6.14.98 last modified
6.24.02 corrected smallfactors
3.20.06 removed include heap.h as it's indirectly included via globals
5.5.13 added line 142 to check if k+2 <= looplimit.
Modified takeout to not assume any fixed sizeof(long).
*/
#include <math.h>
#include <string.h>
#include <assert.h>
#include "globals.h"
#include "dcomplex.h"
#include "algaux.h"
#include "factor.h"
#include "nfactor.h"
/*_____________________________________________________________________*/
static int takeout(long k, unsigned long y, unsigned long *qp)
/* take all factors of k out of y, leaving quotient in *qp,
and returning the number of factors of k that were found.
Assumes k is at most half as many bits as an unsigned long,
and assumes k != 1.
*/
{
unsigned long localy = y;
unsigned long quo;
unsigned long rem= 0;
long q,r;
unsigned i=0;
while(rem == 0)
{ if( (localy >> (sizeof(long) *8 -1)) == 0 ) // that is, high bit of local y is zero
{ lqr( (long) localy, k,&q,&r);
quo = (unsigned long) q;
rem = (unsigned long) r;
}
else
{ quo = localy/k;
rem = localy - k*quo;
}
if( rem == 0)
{ localy = quo;
++i;
}
}
*qp = localy;
return i;
}
/* _______________________________________________________________*/
static unsigned primes[42] = { 3 , 5 , 7 , 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79,
83, 89, 97, 101,103,107,109,113,121,127,
131,137,139,149,151,157,163,167,173,179,181};
/* These are the primes whose square is less than 32K , except 2 */
int small_prime(long n)
/* return 1 if n belongs to the primes array */
{ int i;
for(i = 0;i < sizeof(primes)/sizeof(unsigned); i++)
{ if(n == (long) primes[i])
return 1;
if(n < (long) primes[i])
return 0; /* the array is in order so once you pass n you won't find it */
}
return 0;
}
/* _______________________________________________________________*/
int smallfactors(unsigned long x, unsigned *ans, unsigned long *qp)
/* x is the number to be factored. If unsigned longs are 32 bits, all 16-bit factors will be removed
from the 32-bit integer x, leaving either 1, or a 17-to-32-bit prime
number in *qp. If unsigned longs become 64 bits in the future, this function will take out all
32-bit factors, so it will suddenly run slowly! Thus be careful in calling it. Here we set
looplimit so it will only try to take out 16-bit factors, even if longs are longer than than 32 bits. */
/* ans is a pre-allocated array to hold the prime factors and their powers */
/* The return value is the number of distinct prime factors, i.e.
half the dimension of 'ans' */
{
int i;
int mod5,mod7,mod11;
unsigned k,exponentofk;
unsigned long y=x;
int whichfactor = 0;
unsigned looplimit;
/* is x divisible by 2? */
if( (x & 1) == 0)
{ whichfactor = 2;
ans[0] = 2; /* now count how many twos divide y */
i=0;
while( ((y >> i) & 1) ==0 ) ++ i; /* after this i is the number of 2's */
y >>= i; /* divide out the 2's */
ans[1] = i;
}
if(y == 1) /* finished, x was a power of 2 */
{ *qp = 1;
return 1;
}
looplimit = (unsigned) sqrt( (double) y) + 1;
if(looplimit==0)
looplimit = 0xffff; /* if y is almost 2^32 and longs are 32 bits, this happens */
if(sizeof(long) > 4 && y > 0xffffffff)
looplimit = 0xffff; /* still only try to take out 16-bit factors */
for( i = 0; ((i < 40) && (y != 1)); i++ ) /* take out primes <= 181 */
{ k = primes[i];
if (k > looplimit)
{ *qp = 1;
if (y!= 1)
{ans[whichfactor] = (unsigned) y;
ans[whichfactor+1] = 1;
whichfactor += 2;
}
return whichfactor/2;
}
exponentofk = takeout(k,y,&y); /* is there a factor of k? */
/* Note the first argument of takeout is at most half as long as an unsigned long */
if( exponentofk)
{ ans[whichfactor] = k;
ans[whichfactor + 1] = exponentofk;
whichfactor += 2;
looplimit = (unsigned) sqrt((double) y) + 1;
}
}
/* Now all primes <= 181 are out, and k = 181 is the last prime checked */
mod5 = 1; /* correct values for k = 191 */
mod7 = 2;
mod11 = 4;
/* k in the following loop will be congruent to 5 mod 6 */
for(k=191; k <= looplimit; k +=6, mod5 = (mod5+1)%5,
mod7 = (mod7+6)%7,
mod11 = (mod11 + 6) %11
)
{
if( !((mod5==0) || (mod7==0) || (mod11==0)) )
{ i = takeout(k,y,&y);
if( i > 0)
{
ans[whichfactor]=k;
ans[whichfactor+1] = i;
whichfactor +=2;
looplimit = (unsigned) sqrt((double) y); /* recalculate looplimit */
}
}
if(k+2 >= looplimit)
break; // to ensure that the argument to takeout below is <= looplimit
// Note that sqrt(y) is at most half as long as an unsigned long; so
// primes <= looplimit are also at most half as long as an unsigned long.
if( !((mod5==3) || (mod7==5) || (mod11==9)) )
{ i = takeout(k+2,y,&y);
if( i > 0)
{
ans[whichfactor]=k+2;
ans[whichfactor+1] = i;
whichfactor +=2;
looplimit = (unsigned) sqrt((double) y);
}
}
}
*qp = y;
return whichfactor/2;
}
/*_______________________________________________________________*/
void factor_long(unsigned long x, unsigned *nfactors, term *ans)
/* factor the unsigned long x, returning the number of distinct prime
factors in *nfactors and a term representing the factored form of the
answer in *ans. */
{ unsigned workspace[17];
unsigned long q;
if(x==1)
{ *ans = one;
*nfactors = 1;
return;
}
*nfactors = smallfactors(x,workspace,&q);
assert(q==1);
finish_factor(*nfactors,workspace,1,ans);
SETCOLOR(*ans,YELLOW);
}
/*_____________________________________________________________________*/
void finish_factor(int n, unsigned *workspace, unsigned long q, term * ans)
/* n is the number of factors of the final answer, that is, n counts one
if q is not 1, plus the number of prime-exponent pairs represented in
workspace. *ans is returned as a term representing the prime-power product
formed from workspace together with the extra factor q tacked on the end,
properly handling the cases of a single prime or prime power or of q==1 */
{ int m; /* how many distinct 16-bit factors */
int i;
if(n==1 && q==1 && workspace[1] == 1) /* a 16-bit prime */
{ *ans = make_int(workspace[0]);
SETFACTORED(*ans);
return;
}
if(n==1 && q == 1 ) /* one 16-bit prime raised to a power */
{ *ans = make_term('^',2);
ARGREP(*ans,0,make_int(workspace[0]));
ARGREP(*ans,1,make_int(workspace[1]));
SETFACTORED(*ans);
return;
}
if(n==1 && q != 1 && ((q & 0x80000000UL) ==0)) /* no 16-bit factors */
/* q has 17 to 31 bits */
{ *ans = make_int(q);
return;
}
if(n==1 && q != 1 && sizeof(digit)==2) /* a 32-bit prime, 16-digit bignums */
{ bignum b;
b.ln = 2;
b.val = callocate(2, sizeof(digit));
if(b.val == NULL)
{ nospace();
SETFUNCTOR(*ans,ILLEGAL,0);
return;
}
b.val[0] = (digit) (q & 0x0000ffff);
b.val[1] = (digit) (q >> 16);
*ans = make_bignum(b);
SETFACTORED(*ans);
return;
}
if(n==1 && q != 1 ) /* 32-bit prime, 32-bit bignums */
{ bignum b;
b.ln = 1;
b.val = mallocate(sizeof(digit));
b.val[0] = (digit) q;
*ans = make_bignum(b);
SETFACTORED(*ans);
return;
}
/* Now there's more than one prime factor */
*ans = make_term('*',(unsigned short) n);
m = ((q==1) ? n : n-1); /* number of 16-bit factors */
{ for(i=0;i<m;i++)
{ if(workspace[(i<<1) + 1] > 1)
{ term qq = make_term('^',2);
ARGREP(qq,0,make_int(workspace[i<<1]));
ARGREP(qq,1,make_int(workspace[(i<<1)+1]));
ARGREP(*ans,i,qq);
}
else
ARGREP(*ans,i,make_int(workspace[i<<1]));
}
}
if(q != 1)
ARGREP(*ans,n-1,make_int(q)); /* q can't be 32 bits here,
since there were some 16-bit factors */
SETFACTORED(*ans);
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists