Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/polyval/
Upload File :
Current File : /usr/home/beeson/MathXpert/polyval/nfactor1.c

/* 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