1/*==============================================================================
  2| 
  3|  File Name:     
  4|
  5|     ppFactor.c
  6|
  7|  Description:   
  8|
  9|     Routines for integer factorization and primality prime testing.
 10| 
 11|  Functions:
 12|
 13|     factor
 14|     is_probably_prime
 15|     is_almost_surely_prime
 16|
 17|  LEGAL
 18|
 19|     Primpoly Version 16.4 - A Program for Computing Primitive Polynomials.
 20|     Copyright (C) 1999-2025 by Sean Erik O'Connor.  All Rights Reserved.
 21|
 22|     This program is free software: you can redistribute it and/or modify
 23|     it under the terms of the GNU General Public License as published by
 24|     the Free Software Foundation, either version 3 of the License, or
 25|     (at your option) any later version.
 26|
 27|     This program is distributed in the hope that it will be useful,
 28|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 29|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 30|     GNU General Public License for more details.
 31|
 32|     You should have received a copy of the GNU General Public License
 33|     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 34|     
 35|     The author's address is seanerikoconnor!AT!gmail!DOT!com
 36|     with !DOT! replaced by . and the !AT! replaced by @
 37|
 38==============================================================================*/
 39
 40/*------------------------------------------------------------------------------
 41|                                Include Files                                 |
 42------------------------------------------------------------------------------*/
 43
 44#include <stdio.h>
 45#include <stdlib.h> /* for rand() function */
 46
 47#include "Primpoly.h"
 48
 49
 50/*==============================================================================
 51|                                    factor                                    |
 52================================================================================
 53
 54DESCRIPTION
 55
 56     Factor n into primes.  Record all the distinct prime factors and how
 57     many times each occurs.  Return the number of primes - 1.
 58
 59INPUT
 60                   
 61     n      (int, n >= 1)     The integer to be factored.
 62
 63OUTPUT
 64
 65     primes (bigint *)   List of distinct prime factors.
 66     count  (int *)      List of how many times each factor occurred.
 67
 68     When n = 1, t = 0, and primes[ 0 ] = count[ 0 ] = 1.
 69
 70RETURNS
 71
 72     t (int)             Number of prime factors - 1.  
 73	                     Prime factors and their multiplicites are in locations 0 to t.
 74
 75EXAMPLE 
 76                   2
 77    For n = 156 = 2  * 3 * 13 we have
 78
 79    k   primes[ k ]   count[ k ]
 80    ----------------------------
 81    0        2            2
 82    1        3            1
 83    2       13            1
 84
 85METHOD
 86
 87    Method described by D.E. Knuth, ART OF COMPUTER PROGRAMMING, vol. 2, 2nd ed.,
 88	                                                            -----
 89	in Algorithm A, pgs. 364-365.  The running time is O( max \/ p   , p  )
 90                                                                  t-1   t
 91    where p  is the largest prime divisor of n and p    is the next largest.
 92	       t                                        t-1
 93
 94    (1)  First divide out all multiples of 2 and 3 and count them.  
 95	
 96	(2)  Next, divide n by all integers d >= 5 except multiples of 2 and 3. 
 97
 98    (3)  Halt either when all prime factors have been divided out (leaving n = 1) 
 99	     or when the current value of n is prime.  The stopping test 
100
101          (d > | n/d | AND r != 0)
102               --   --
103         detects when n is prime.
104
105    In the example above, we divided out 2's and 3's first, leaving
106    n = 13.  We continued with trial divisor d = 3.  But now the stopping
107    test was activated because 5 > | 13/5 | = 2, and remainder = 3 (non-zero).
108                                   --    --
109    n = 13 itself is the last prime factor of 156.  We return t = 2.  There
110    are 2 + 1 = 3 distinct primes.
111
112
113    If we start with d = 5, and add 2 and 4 in succession, we will run through all
114	the integers except multiples of 2 and 3.  To see this, observe the pattern:
115
116    Integers:     1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
117	Mult. of 2:      x     x     x     x     x     x     x     x
118	Mult. of 3:         x        x        x        x        x
119	d:                        x     x           x     x          x
120	Separation:                  2       4         2       4
121
122    The sequence of divisors d, includes all the primes, so is safe to use for
123	factorization testing.
124
125    Theorem.  Suppose no divisor d in the sequence divides n.  Suppose at some point,
126	q < d with r != 0.  Then n must be prime.
127
128    Proof.  We begin with an integer n which has all powers of 2 and 3 removed.
129    Assume, to the contrary, that n is composite:  n = p ... p
130	      t                                             1     t
131    n >= p    since p  is the smallest prime factor.
132	      1          1
133
134	      2                                      
135    n >= p    since n is composite, so has at least 2 prime factors.
136	      1
137		        2
138	  >= (d + 1)   since p  > d implies p >= (d + 1).  p > d because we assumed
139                          1              1              1
140      that no d in the sequence divided n, so d couldn't be any of the prime divisors
141	  p
142	   i
143         2            2               2
144	  = d + 2d + 1 = d + d + d + 1 > d + d
145         2
146      > d + n mod d   since n mod d < d
147                                                                              2
148      > | n / d | d + n mod d  because our test said q < d, so | n / d | d < d
149	    --     --                                              --     --
150
151      = n.  So we get the contradiction n > n.  Thus n must be prime. 
152	                                               ---
153    Note that this is sharper than the bound d > \/ n
154
155    Theorem.  Conversely, if n is a prime, no d will divide it, so at some point, 
156	d will be large enough that q = | n / d | < d.  r != 0 since n is prime.
157	                                --     --
158
159    Theorem.  The factoring algorithm works.
160	
161	Proof.  If n == 1 we exit immediately.  If n is composite, we divide out all powers
162	of 2 and 3 (if any).  Since d runs through all possible prime divisors, we divide
163	these out also.  Composite trial d causes no problem;  prime factors of d are divided
164	out of n before we try to divide by d, so such a d cannot divide n.
165
166    We end in one of two ways (1) All divisors of n have been divided out in which case n = 1.
167	(2) n is a prime, so the stopping test is activiated and n != 1 is recorded as a prime
168	divisor.
169
170
171BUGS
172
173    Can be slow when n is a prime.  We could do a probabilistic test for
174    the primality of n at the statement, "n_is_prime = (r != 0 && q < d) ;"
175    which would speed up the test.  
176    
177    Or we could implement the Pollard rho algorithm instead.
178
179--------------------------------------------------------------------------------
180|                                Function Call                                 |
181------------------------------------------------------------------------------*/
182
183int 
184factor( bigint n, bigint * primes, int * count )
185{
186
187/*------------------------------------------------------------------------------
188|                               Local Variables                                |
189------------------------------------------------------------------------------*/
190
191int
192    t = 0,              /*  Array index for primes and count.         */
193    cnt = 0,            /*  Counter for factors of 2 and 3.           */
194    new_d = YES,        /*  YES if current divisor is different from
195                            the previous one.                         */
196    n_is_prime = NO,    /*  YES if current value of n is prime.       */
197    flag = YES ;        /*  Alternately YES and NO.                   */
198
199bigint
200    q,                  /*  The quotient, floor( n / d )              */
201    r,                  /*  The remainder, n mod d                    */
202    d = 5 ;             /*  Trial divisor and its first value.        */
203
204/*------------------------------------------------------------------------------
205|                                Function Body                                 |
206------------------------------------------------------------------------------*/
207
208/*  Handle special cases for speed. 
209    These are cases where r = (p^n - 1)/(p-1) is a large prime or has large prime 
210	factors and p^n is less than the maximum size allowed by this program.
211	(I don't have all these cases).
212*/
213if (n == 1)
214{
215    primes[ 0 ] = count[ 0 ] = 1 ;
216    return( 0 ) ;
217}
218else if (n == (bigint)4611686018427387903ULL) /*  (2^62 - 1)/(2 - 1)  */
219{
220	primes[ 0 ] = 3 ;
221	count [ 0 ] = 1 ;
222
223	primes[ 1 ] = 715827883ULL ;
224	count [ 1 ] = 1 ;
225
226	primes[ 2 ] = 2147483647ULL ;
227	count [ 2 ] = 1 ;
228
229	return( 2 ) ;
230}
231else if (n == (bigint)2305843009213693951ULL) /*  (2^61 - 1)/(2 - 1)  */
232{
233	primes[ 0 ] = (bigint)2305843009213693951ULL ;
234	count [ 0 ] = 1 ;
235
236	return( 0 ) ;
237}
238
239
240while( n % 2 == 0 )       /*  Remove factors of 2. */
241{
242    n /= 2 ;
243    ++cnt ;
244}
245
246if (cnt != 0)
247{
248    primes[ t ] = 2 ;
249    count[ t++ ] = cnt ;
250}
251
252cnt = 0 ;  
253
254while( n % 3 == 0 )       /*  Remove factors of 3. */
255{
256    n /= 3 ;
257    ++cnt ;
258}
259
260if (cnt != 0)
261{
262    primes[ t ] = 3 ;
263    count[ t++ ] = cnt ;
264}
265
266
267/*
268    Factor the rest of n.  Continue until n = 1 (all factors divided out)
269    or until n is prime (so n itself is the last prime factor).
270*/
271
272do {
273
274	/*  Integer divide to get quotient and remainder:  n = qd + r */
275
276    q = n / d ;
277
278    r = n % d ; 
279
280    n_is_prime = (r != 0 && q < d) ;   /* n is prime. */
281
282    if (r == 0)    
283    {
284        n = q ;     /*  Divide d out of n. */
285
286        if (new_d)  /*  New prime factor. */
287        {
288            primes[ t ] = d ;
289            count[ t++ ] = 1 ;
290            new_d = NO ;
291         }
292         else
293
294             ++count[ t-1 ] ;   /*  Same divisor again.  Increment its count. */ 
295    }
296    else {
297
298        d += (flag ? 2 : 4) ;  /* d did not divide n.  Try a new divisor. */
299
300        flag = !flag ;
301        new_d = YES ;
302    }
303
304} while ( ! n_is_prime && (n != 1)) ;
305
306if (n == 1)       /*  All factors were divided out. */
307
308    return( t - 1 ) ;
309
310else {  /*  Current value of n is prime.  It is the last prime factor. */
311
312    primes[ t ] = n ;
313    count[ t ] = 1 ;
314    return( t ) ;
315}
316
317} /* ========================= end of function factor ======================= */
318
319/*
320      4
321Phi[ 5  - 1 ] / 4 
322
323   4              4
324  5  - 1 = 624 = 2  3  13
325
326  Phi = 624 (1 - 1/2) (1 - 1/3)(1 - 1/13) = 192
327
328  192 / 4 = 48
329
330
331  Handle special cases.
332
333  Warning: can take a long time due to factorization.
334  */
335
336bigint 
337EulerPhi( bigint n )
338{
339	int prime_count = 0 ;
340	int i = 0 ;
341	bigint phi ;
342
343	/* Factor n into primes. */
344	bigint primes[ MAXNUMPRIMEFACTORS ] ;
345	int    count [ MAXNUMPRIMEFACTORS ] ;
346
347    /* Error return and special cases. */
348	if (n <= 0)
349		return 0 ;
350	else if (n == 1)
351		return 1 ;
352
353	/* Factor n >= 2 into distinct primes. */
354    prime_count = factor( n, primes, count ) ;
355
356	/* Compute Euler phi[ n ] =   */
357	/*                            */
358	/*      num prime factors     */
359	/*        -------             */
360	/*     n   |  |   (1 - 1/p )  */
361	/*         i = 1          i   */
362    phi = n ;
363	for (i = 0 ;  i <= prime_count ; ++i)
364	{
365        phi /=  primes[ i ] ;
366		phi *= (primes[ i ] - 1) ;
367	}
368
369	return phi ;
370}
371
372
373/*==============================================================================
374|                             is_probably_prime                                |
375================================================================================
376
377DESCRIPTION
378
379     Test whether the number n is probably prime.  If n is composite
380     we are correct always.  If n is prime, we will be wrong no more
381     than about 1/4 of the time on average, probably less for
382     any x and n.
383
384INPUT
385                   
386     n      (int, n >= 0)    Number to test for primality.
387     x      (int, 1 < x < n for n > 6) A random integer.
388
389RETURNS
390
391
392     YES    If n is probably prime.
393     NO     If n is definitely not prime or n < 0,
394            or x is out of range.
395
396EXAMPLE 
397 
398METHOD
399
400     Miller-Rabin probabilistic primality test, described by Knuth.
401     If n = 1 + 2^k q is prime, and x^q mod n != 1 the sequence, 
402     { x^q mod n, x^(2q) mod n, ..., x^(2^k q) mod n} 
403     will end with 1 and the element in the sequence just before 
404     1 first appears = n-1, since y^2 = 1 (mod p) satisfies 
405     y = +1 or y = -1 only. The probability the algorithm fails is 
406     bounded above by about 1/4 for all n.
407
408BUGS
409
410    None.
411
412--------------------------------------------------------------------------------
413|                                Function Call                                 |
414------------------------------------------------------------------------------*/
415
416int is_probably_prime( int n, int x )
417{
418
419/*------------------------------------------------------------------------------
420|                               Local Variables                                |
421------------------------------------------------------------------------------*/
422
423int 
424    j,
425    k = 0,
426	nm1,
427	q = 0,
428	y = 0 ;
429
430/*------------------------------------------------------------------------------
431|                                Function Body                                 |
432------------------------------------------------------------------------------*/
433
434/*  Not prime if input is out of range. */
435if (n < 0)
436    return NO ;
437
438/*  Handle special cases. */
439if (n == 0 || n == 1 || n == 4)
440    return NO ;
441
442if (n == 2 || n == 3 || n == 5)
443    return YES ;
444
445/* Even numbers aren't prime. */
446if (n % 2 == 0)
447    return NO ;
448
449/* Return not prime if x is out of range. */
450if (x <= 1 || x >= n)
451    return NO ;
452
453/* Factor out powers of 2 to get n = 1 + 2^k q, q odd. */
454nm1 = n - 1 ;
455k = 0 ;
456while( nm1 % 2 == 0)
457{
458	nm1 /= 2 ;
459	++k ;
460}
461
462q = nm1 ;
463
464
465
466/*  y = x^q (mod n) */
467y = power_mod( x, q, n ) ;
468
469for (j = 0 ;  j < k ;  ++j)
470{
471    if ( (j == 0 && y == 1) || (y == n-1))
472		return YES ;
473	else if (j > 0 && y == 1)
474		return NO ;
475
476	/* Compute y^2 (mod n) */
477	y = power_mod( y, 2, n ) ;
478}
479
480/*  Shouldn't get here, but do it anyway for safety. */
481return NO ;
482
483} /* =============== end of function is_probably_prime ===================== */
484
485
486
487/*==============================================================================
488|                           is_almost_surely_prime                             |
489================================================================================
490
491DESCRIPTION
492
493     Test whether the number n is almost surely prime.  If n is
494     composite, we always return NO.  If n is prime, the 
495     probability of returning YES successfully is
496
497                 NUM_PRIME_TEST_TRIALS
498        1 - (1/4)
499
500INPUT
501                   
502     n      (int, n >= 0)
503
504RETURNS
505
506
507     YES    If n is probably prime with a very high degree of
508            probability.
509     NO     If n is definitely not prime.
510	 -1     If inputs are out of range.
511
512EXAMPLE
513  
514METHOD
515
516    Use the Miller-Rabin probabilitic primality test for lots of
517    random integers x.  If the test shows n is composite for any 
518    given x, is is non-prime for sure.  
519    
520    If it passes the the primality test for several random values
521    of x, the probability is it prime is approximately
522    
523         NUM_PRIME_TEST_TRIALS
524    1 - 2
525
526    assuming the random number generator is really random.
527
528BUGS
529
530    The system pseudorandom number generator needs to be a good one
531    (i.e. passes the spectral test and other statistical tests).
532
533--------------------------------------------------------------------------------
534|                                Function Call                                 |
535------------------------------------------------------------------------------*/
536
537int is_almost_surely_prime( int n )
538{
539
540/*------------------------------------------------------------------------------
541|                               Local Variables                                |
542------------------------------------------------------------------------------*/
543
544int 
545    trial = 0,
546    x     = 3 ;
547
548/*------------------------------------------------------------------------------
549|                                Function Body                                 |
550------------------------------------------------------------------------------*/
551
552/* Seed the random-number generator. */
553srand( 314159 );
554   
555for (trial = 1 ;  trial <= NUM_PRIME_TEST_TRIALS ;  ++trial)
556{
557    /*  Generate a new random integer such that 1 < x < n. */
558    x = rand() % n ;
559    if (x <= 1) x = 3 ;
560
561	/* Definitely not prime. */
562	if (is_probably_prime( n, x ) == NO)
563		return NO ;
564}
565
566/* Almost surely prime because it passed the probably prime test
567 * above many times.
568 */
569return YES ;
570
571} /* ============== end of function is_almost_surely_prime ================ */