1/*==============================================================================
  2|
  3|  File Name:
  4|
  5|     ppArith.c
  6|
  7|  Description:
  8|
  9|     Routines for integer arithmetic modulo p.
 10|
 11|  Functions:
 12|
 13|      mod
 14|      power
 15|      power_mod
 16|      is_primitive_root
 17|
 18|  LEGAL
 19|
 20|     Primpoly Version 16.4 - A Program for Computing Primitive Polynomials.
 21|     Copyright (C) 1999-2025 by Sean Erik O'Connor.  All Rights Reserved.
 22|
 23|     This program is free software: you can redistribute it and/or modify
 24|     it under the terms of the GNU General Public License as published by
 25|     the Free Software Foundation, either version 3 of the License, or
 26|     (at your option) any later version.
 27|
 28|     This program is distributed in the hope that it will be useful,
 29|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 30|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 31|     GNU General Public License for more details.
 32|
 33|     You should have received a copy of the GNU General Public License
 34|     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 35|     
 36|     The author's address is seanerikoconnor!AT!gmail!DOT!com
 37|     with !DOT! replaced by . and the !AT! replaced by @
 38|
 39==============================================================================*/
 40
 41/*------------------------------------------------------------------------------
 42|                                Include Files                                 |
 43------------------------------------------------------------------------------*/
 44
 45#include "Primpoly.h"
 46
 47/*==============================================================================
 48|                                  mod                                         |
 49================================================================================
 50
 51DESCRIPTION
 52
 53     A mod function for both positive and negative arguments.
 54
 55INPUT
 56
 57    n (int, -infinity < n < infinity)
 58    p (int, p > 0)
 59
 60RETURNS
 61
 62    n mod p (0 <= n mod p < p)
 63
 64EXAMPLE
 65
 66    The C language gives -5 % 3 = - ( -(-5) mod 3 ) = -( 5 mod 3 ) = -2.
 67    The result is nonzero, so we add p=3 to give 1.
 68
 69    C computes -3 % 3 = - ( -(-3) mod 3  ) = 0, which we leave unchanged.
 70
 71METHOD
 72
 73     For n >= 0, the C language defines r = n mod p by the equation
 74
 75         n = kp + r    0 <= r < p
 76
 77     but when n < 0, C returns the quantity
 78
 79         r = - ( (-n) mod p )
 80
 81     To put the result into the correct range 0 to p-1, add p to r if
 82     r is non-zero.
 83
 84     By the way, FORTRAN's MOD function does the same thing.
 85
 86BUGS
 87
 88     None.
 89
 90--------------------------------------------------------------------------------
 91|                                Function Call                                 |
 92------------------------------------------------------------------------------*/
 93
 94int
 95    mod( int n, int p )
 96{
 97
 98/*------------------------------------------------------------------------------
 99|                               Local Variables                                |
100------------------------------------------------------------------------------*/
101
102register int
103    raw_mod ;      /*  The value n % p computed by C's mod function.  */
104
105/*------------------------------------------------------------------------------
106|                                Function Body                                 |
107------------------------------------------------------------------------------*/
108
109raw_mod = n % p ;
110
111if (raw_mod == 0)
112
113    return( 0 ) ;
114
115else if (n >= 0)             /*  mod is not 0.  n >= 0. */
116
117    return( raw_mod ) ;
118
119else
120
121    return( raw_mod + p ) ;  /* mod is not 0.  n < 0. */
122
123} /* =========================== end of function mod ======================== */
124
125
126
127/*==============================================================================
128|                                       power                                  |
129================================================================================
130
131DESCRIPTION
132
133     Raise a positive integer to a positive power exactly.
134
135INPUT
136
137     x (int, x > 0)   The base.
138     y (int, y > 0)   The exponent.
139
140RETURNS
141
142     y
143    x
144
145EXAMPLE CALLING SEQUENCE
146
147     power( 2, 3 ) => 8
148
149METHOD
150
151     Multiply x by itself y times.
152
153BUGS
154
155     None.
156
157--------------------------------------------------------------------------------
158|                                Function Call                                 |
159------------------------------------------------------------------------------*/
160
161bigint power( int x, int y )
162{
163
164/*------------------------------------------------------------------------------
165|                               Local Variables                                |
166------------------------------------------------------------------------------*/
167
168bigint
169    pow ;   /*  x to the y.  */
170
171/*------------------------------------------------------------------------------
172|                                Function Body                                 |
173------------------------------------------------------------------------------*/
174
175for (pow = 1 ;  y > 0 ;  --y)
176
177    pow *= x ;
178
179return( pow ) ;
180
181} /* ========================= end of function power ======================== */
182
183
184
185/*==============================================================================
186|                                power_mod                                     |
187================================================================================
188
189DESCRIPTION
190
191     Raise a positive integer to a positive power modulo an integer.
192
193INPUT
194
195     a (int, a >= 0)   The base.
196     n (int, n >= 0)   The exponent.
197     p (int, p >= 2)   The modulus.
198
199RETURNS
200
201      n
202     a  (modulo p)
203    -1 if a < 0, n < 0, or p <= 1, or 0^0 case.
204
205EXAMPLE CALLING SEQUENCE
206
207     power_mod( 2, 3, 7 ) => 1
208
209METHOD
210
211     Multiplication by repeated squaring.
212
213BUGS
214
215     None.
216
217--------------------------------------------------------------------------------
218|                                Function Call                                 |
219------------------------------------------------------------------------------*/
220
221int power_mod( int a, int n, int p )
222{
223
224/*------------------------------------------------------------------------------
225|                               Local Variables                                |
226------------------------------------------------------------------------------*/
227
228/*
229    mask = 1000 ... 000.  That is, all bits of mask are zero except for the
230    most significant bit of the computer word holding its value.  Signed or
231	unsigned type for bigint shouldn't matter here, since we just mask and
232	compare bits.
233*/
234
235int
236    mask = (1 << (8 * sizeof( int ) - 1)),
237    bit_count = 0 ;  /* Number of bits in exponent to the right of the leading bit. */
238
239/*  Use extra precision since we need to square an integer within the
240    calculations below. */
241long int product = (int) a ;
242
243
244/*------------------------------------------------------------------------------
245|                                Function Body                                 |
246------------------------------------------------------------------------------*/
247
248/*
249    Out of range conditions.
250*/
251
252if (a < 0 || n < 0 || p <= 1 || (a == 0 && n == 0))
253
254    return -1 ;
255
256/*  Quick return for 0 ^ n, a^0 and a^1.  */
257if (a == 0)
258    return 0 ;
259
260if (n == 0)
261    return 1 ;
262
263if (n == 1)
264    return a % p ;
265
266/*
267    Advance the leading bit of the exponent up to the word's left
268    hand boundary.  Count how many bits were to the right of the
269    leading bit.
270*/
271
272while (! (n & mask))
273{
274    n <<= 1 ;
275    ++bit_count ;
276}
277
278bit_count = (8 * sizeof( int )) - bit_count ;
279
280
281/*
282    Exponentiation by repeated squaring.  Discard the leading 1 bit.
283    Thereafter, square for every 0 bit;  square and multiply by x for
284    every 1 bit.
285*/
286
287while ( --bit_count > 0 )
288{
289    /*  Expose the next bit. */
290    n <<= 1 ;
291
292	/* Square modulo p. */
293	product = (product * product) % p ;
294
295	/*  Leading bit is 1: multiply by a modulo p. */
296    if (n & mask)
297        product = (a * product) % p ;
298}
299
300/*  We don't lose precision because product is always reduced modulo p. */
301return (int) product ;
302
303} /* ========================= end of function power_mod ==================== */
304
305
306
307/*==============================================================================
308|                             is_primitive_root                                |
309================================================================================
310
311DESCRIPTION
312
313     Test whether the number a is a primitive root of the prime p.
314
315INPUT
316
317     a      (int, a >= 1)     The number to be tested.
318     p      (int, p >= 2)     A prime number.
319
320RETURNS
321
322     YES    If a is a primitive root of p.
323     NO     If a isn't a primitive root of p or if inputs are out of range.
324
325EXAMPLE
326                                                     1      2      3
327     3 is a primitive root of the prime p = 7 since 3 = 3, 3 = 2, 3 = 6,
328      4      5                                       p-1    6
329     3 = 4, 3 = 5 (mod 7); all not equal to 1 until 3    = 3 = 1 (mod 7).
330
331     So 3 is a primitive root of 7 because it has maximal period.  a = 2
332                                                      3
333	 isn't a primitive root of p = 7 because already 2 = 1 (mod 7).
334
335METHOD
336
337    From number theory, a is a primitive root of the prime p iff
338     (p-1)/q
339    a        != 1 (mod p) for all prime divisors q of (p-1).
340                            (p-1)
341    Don't need to check if a     = 1 (mod p):  Fermat's little
342    theorem guarantees it.
343
344BUGS
345
346    We don't check if p is not a prime.
347
348--------------------------------------------------------------------------------
349|                                Function Call                                 |
350------------------------------------------------------------------------------*/
351
352int is_primitive_root( int a, int p )
353{
354
355/*------------------------------------------------------------------------------
356|                               Local Variables                                |
357------------------------------------------------------------------------------*/
358
359bigint
360    primes[ MAXNUMPRIMEFACTORS ] ; /* The distinct prime factors of p-1. */
361
362int
363    count[ MAXNUMPRIMEFACTORS ],   /* ... and their multiplicities.      */
364    t,                             /*  Primes are indexed from 0 to t.   */
365	i ;                            /*  Loop index.                       */
366
367/*------------------------------------------------------------------------------
368|                                Function Body                                 |
369------------------------------------------------------------------------------*/
370
371/*  Error for out of range inputs, including p
372    being an even number greater than 2.
373*/
374if (p < 2 || a < 1 || (p > 2 && (p % 2 == 0)))
375    return NO ;
376
377/*  Special cases:
378    1 is the only primitive root of 2;  i.e. 1 generates the unit elements
379	of GF( 2 );  2 is the only primitive root of 3, and 2 and 3 are the only
380	primitive roots of 5, etc.  See http://mathworld.wolfram.com/PrimitiveRoot.html
381*/
382if ( (p == 2  && a == 1) ||
383     (p == 3  && a == 2) ||
384     (p == 5  && (a == 2 || a == 3)) ||
385     (p == 7  && (a == 3 || a == 5)) ||
386     (p == 11 && (a == 2 || a == 6 || a == 7 || a ==  8)) ||
387     (p == 13 && (a == 2 || a == 6 || a == 7 || a == 11)) )
388    return YES ;
389
390
391/*  Reduce a down modulo p. */
392a = a % p ;
393
394
395/*  a = 0 (mod p);  Zero can't be a primitive root of p. */
396if (a == 0)
397    return NO ;
398
399/*  Factor p-1 into primes. */
400t = factor( (bigint)(p - 1), primes, count ) ;
401
402
403/*  Check if a^(p-1)/q <> 1 (mod p) for all primes q | (p-1).
404    If so, we have a primitive root of p, otherwise, we exit early.
405 */
406for (i = 0 ;  i <= t ;  ++i)
407{
408	/*  The prime factors can be safely cast from bigint to int
409	    because p-1 needs only integer precision.  */
410    if (power_mod( a, (p-1) / (int)primes[ i ], p ) == 1)
411		return NO ;
412}
413
414return YES ;
415
416} /* =============== end of function is_primitive_root ===================== */
417
418
419/* Divide modulo p.
420
421Do extended Euclid's algorithm on u and v to find u1, u2, and u3 such that
422
423    u u1 + v u2 = u3 = gcd( u, v ).
424
425Now let v = p = prime number, so gcd = u3 = 1.  Then we get
426
427  u u1 + p ? = 1
428
429or u u1 = 0 (mod p) which makes u (mod p) the unique multiplicative
430inverse of u.
431
432
433Assume 0 <= u < p, p is prime >= 2.
434
435*/
436int inverse_mod_p( int u, int p )
437{
438    /*  Do Euclid's algorithm to find the quantities */
439	int t1 = 0 ;
440	int t3 = 0 ;
441	int q  = 0 ;
442
443    int u1 = 1 ;
444    int u3 = u ;
445    int v1 = 0 ;
446    int v3 = p ;
447
448	int inv_v = 0 ;
449
450	while( v3 != 0)
451	{
452        q = (int)(u3 / v3) ;
453
454		t1 = u1 - v1 * q ;
455		t3 = u3 - v3 * q ;
456
457		u1 = v1 ;
458		u3 = v3 ;
459
460		v1 = t1 ;
461		v3 = t3 ;
462	}
463
464    inv_v = mod( u1, p ) ;
465
466	/* Self check. */
467	if ( mod( u * inv_v, p ) != 1)
468	{
469		return 0 ;
470	}
471
472	return inv_v ;
473}