0% found this document useful (0 votes)
52 views42 pages

Binary Polynomials: Arithmetic & Algorithms

Chapter 40 introduces binary polynomials, their arithmetic operations, and methods for irreducibility, primitivity, and factorization. It explains how binary polynomials are represented in binary computers and details operations such as addition, multiplication, squaring, and exponentiation. The chapter also covers optimization techniques for these operations and methods for computing the greatest common divisor (GCD) using the Euclidean algorithm.

Uploaded by

6798fb55x
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
52 views42 pages

Binary Polynomials: Arithmetic & Algorithms

Chapter 40 introduces binary polynomials, their arithmetic operations, and methods for irreducibility, primitivity, and factorization. It explains how binary polynomials are represented in binary computers and details operations such as addition, multiplication, squaring, and exponentiation. The chapter also covers optimization techniques for these operations and methods for computing the greatest common divisor (GCD) using the Euclidean algorithm.

Uploaded by

6798fb55x
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Chapter 40

Binary polynomials

We introduce binary polynomials and their arithmetic. Tests for irreducibility, primitivity, and a method
for factorization are given. Many of the algorithms shown can easily be implemented in hardware. An
important application is the linear feedback shift registers, described in chapter 41. The arithmetic
operations with binary polynomials are the underlying methods for computations in binary finite fields
which are treated in chapter 42.
A polynomial with coefficients in the field GF(2) = Z/2Z (that is, ‘coefficients modulo 2’) is called a
binary polynomial. The operations proceed as for usual polynomials except that the coefficients have to
be reduced modulo 2. To represent a binary polynomial in a binary computer we use words where the
bits are set at the positions where the polynomial coefficients are one. We use the convention that the
coefficient of xk appears at bit k, so the constant term lies at the least significant bit.

40.1 The basic arithmetical operations


Addition of binary polynomials is the XOR operation. Subtraction is the very same operation.
Multiplication of a binary polynomial by its independent variable x is simply a shift to the left.

40.1.1 Multiplication and squaring


Multiplication of two polynomials A and B is identical to the usual (binary algorithm for) multiplication,
except that no carry occurs [FXT: bpol/bitpol-arith.h]:
1 inline ulong bitpol_mult(ulong a, ulong b)
2 // Return A * B
3 {
4 ulong t = 0;
5 while ( b )
6 {
7 if ( b & 1 ) t ^= a;
8 b >>= 1;
9 a <<= 1;
10 }
11 return t;
12 }
As for integer multiplication with the C-type unsigned long, the result will silently overflow if
deg(A) + deg(B) is equal to or greater than the word length (BITS_PER_LONG). If the operation t^=a;
was replaced with t+=a; the ordinary (integer) product would be returned [FXT: gf2n/bitpolmult-
Pd k
demo.cc], see figure 40.1-A (top). When a binary polynomial p = k=0 ak x is squared, the result
d
equals p2 = k=0 ak x2k , figure 40.1-A (bottom). So we just have to move the bits from position k to
P
position 2k:
1 inline ulong bitpol_square(ulong a)
2 // Return A * A
3 {
4 ulong t = 0, m = 1UL;
5 while ( a )
6 {
7 if ( a&1 ) t ^= m;

J. Arndt, Matters Computational: Ideas, Algorithms, Source Code, 822


DOI 10.1007/978-3-642-14764-7_40, © Springer-Verlag Berlin Heidelberg 2011
40.1: The basic arithmetical operations 823

1..11.111 * 11.1.1
product as bitpol ordinary product
1..11.111 1 t= .....1..11.111 c= ......1..11.111
0
1..11.111.. 1 t= ...1.1111.1.11 c= ....11....1..11
0
1..11.111.... 1 t= .1.11.1..11.11 c= ..11..11.....11
1..11.111..... 1 t= 11.....1111.11 c= 1.......11...11

1..11.111 * 1..11.111
product as bitpol ordinary product
1..11.111 1 t= ........1..11.111 c= .........1..11.111
1..11.111. 1 t= .......11.1.11..1 c= ........111.1..1.1
1..11.111.. 1 t= ......1111....1.1 c= ......1...1......1
0
1..11.111.... 1 t= ....1.1..1111.1.1 c= .....11.111111...1
1..11.111..... 1 t= ...11..1....1.1.1 c= ...1....1.11.1...1
0
0
1..11.111........ 1 t= 1.....1.1...1.1.1 c= .1.1111..111.1...1

Figure 40.1-A: Multiplication (top) and squaring (bottom) of binary polynomials and numbers.

8 m <<= 2;
9 a >>= 1;
10 }
11 return t; // == bitpol_mult(a, a);
12 }

40.1.2 Optimization of the squaring and multiplication routines


The routines for multiplication and squaring can be optimized by partially unrolling which avoids
branches. As given, the function is compiled to:
0: 31 c9 xor %ecx,%ecx // t = 0
2: 48 85 ff test %rdi,%rdi // a
5: ba 01 00 00 00 mov $0x1,%edx // m = 1
a: 74 1b je 27 <_Z13bitpol_squarem+0x27> // a==0 ?
10: 48 89 c8 mov %rcx,%rax // tmp = t
13: 48 31 d0 xor %rdx,%rax // tmp ^= m
16: 40 f6 c7 01 test $0x1,%dil // if ( a&1 )
1a: 48 0f 45 c8 cmovne %rax,%rcx // then t = tmp
1e: 48 c1 e2 02 shl $0x2,%rdx // m <<= 2
22: 48 d1 ef shr %rdi // a >>= 1
25: 75 e9 jne 10 <_Z13bitpol_squarem+0x10> // a!=0 ?
27: 48 89 c8 mov %rcx,%rax
2a: c3 retq
The if-statement does not cause a branch so we unroll the contents of the loop 4-fold. We also move the
while() statement to the end of the loop to avoid the initial branch:
1 inline ulong bitpol_square(ulong a)
2 {
3 ulong t = 0, m = 1UL;
4 do
5 {
6 if ( a&1 ) t ^= m;
7 m <<= 2; a >>= 1;
8 if ( a&1 ) t ^= m;
9 m <<= 2; a >>= 1;
10 if ( a&1 ) t ^= m;
11 m <<= 2; a >>= 1;
12 if ( a&1 ) t ^= m;
13 m <<= 2; a >>= 1;
14 }
15 while ( a );
16 return t;
17 }
Now we obtain machine code that executes much faster:
0: 31 c9 xor %ecx,%ecx // t = 0
824 Chapter 40: Binary polynomials

2: ba 01 00 00 00 mov $0x1,%edx // m = 1
7: 48 89 c8 mov %rcx,%rax // tmp = t
a: 48 31 d0 xor %rdx,%rax // tmp ^= m
d: 40 f6 c7 01 test $0x1,%dil // if ( a&1 )
11: 48 0f 45 c8 cmovne %rax,%rcx // then t = tmp
15: 48 c1 e2 02 shl $0x2,%rdx // m <<= 2
19: 48 d1 ef shr %rdi // a >>= 1
1c: 48 89 c8 mov %rcx,%rax
1f: 48 31 d0 xor %rdx,%rax
22: 40 f6 c7 01 test $0x1,%dil
26: 48 0f 45 c8 cmovne %rax,%rcx
2a: 48 c1 e2 02 shl $0x2,%rdx
2e: 48 d1 ef shr %rdi
31: 48 89 c8 mov %rcx,%rax
[--snip--]
43: 48 d1 ef shr %rdi
46: 48 89 c8 mov %rcx,%rax
[--snip--]
58: 48 d1 ef shr %rdi
5b: 75 aa jne 7 <_Z13bitpol_squarem+0x7> // a!=0 ?
5d: 48 89 c8 mov %rcx,%rax
60: c3 retq
The multiplication algorithm is optimized in the same way. For squaring we can also use the bit-zip
function given in section 1.15 on page 39:
1 inline ulong bitpol_square(ulong a) { return bit_zip0( a ); }

The upper half of the bits of the argument must be zero.

40.1.3 Exponentiation
With a multiplication (and squaring) function at hand, it is straightforward (see section 28.5 on page 563)
to implement the algorithm for binary exponentiation [FXT: bpol/bitpol-arith.h]:
1 inline ulong bitpol_power(ulong a, ulong e)
2 // Return A ** e
3 {
4 if ( 0==e ) return 1;
5
6 ulong s = a;
7 while ( 0==(e&1) )
8 {
9 s = bitpol_square(s);
10 e >>= 1;
11 }
12
13 a = s;
14 while ( 0!=(e>>=1) )
15 {
16 s = bitpol_square(s);
17 if ( e & 1 ) a = bitpol_mult(a, s);
18 }
19 return a;
20 }
Note that overflow will occur even for moderate exponents.

40.1.4 Quotient and remainder


The remainder a modulo b can be computed by initializing A = a and subtracting B = xj · b with
deg(B) = deg(A) from A at each step. The computation is finished as soon as deg b > deg A. As C-code
[FXT: bpol/bitpol-arith.h]:
1 inline ulong bitpol_rem(ulong a, ulong b)
2 // Return R = A % B = A - (A/B)*B
3 // Must have: B!=0
4 {
5 const ulong db = highest_one_idx(b);
6 ulong da;
40.1: The basic arithmetical operations 825

7 while ( db <= (da=highest_one_idx(a)) )


8 {
9 if ( 0==a ) break; // needed because highest_one_idx(0)==highest_one_idx(1)
10 a ^= (b<<(da-db));
11 }
12 return a;
13 }
The function highest_one_idx() is given in section 1.6 on page 14. The following version may be
superior if the degree of a is small or if no fast version of the function highest_one_idx() is available:
1 while ( b <= a )
2 {
3 ulong t = b;
4 while ( (a^t) > t ) t <<= 1;
5 // =^= while ( highest_one(a) > highest_one(t) ) t <<= 1;
6 a ^= t;
7 }
8 return a;
The quotient and remainder of two polynomials is computed as follows:
1 inline void bitpol_divrem(ulong a, ulong b, ulong &q, ulong &r)
2 // Set R, Q so that A == Q * B + R.
3 // Must have B!=0.
4 {
5 const ulong db = highest_one_idx(b);
6 q = 0; // quotient
7 ulong da;
8 while ( db <= (da=highest_one_idx(a)) )
9 {
10 if ( 0==a ) break; // needed because highest_one_idx(0)==highest_one_idx(1)
11 a ^= (b<<(da-db));
12 q ^= (1UL<<(da-db));
13 }
14 r = a;
15 }
The division routine does the same computation but discards the remainder:
1 inline ulong bitpol_div(ulong a, ulong b)
2 // Return Q = A / B
3 // Must have B!=0.
4 {
5 [--snip--] // identical code
6 return q;
7 }

40.1.5 Greatest common divisor (GCD)


The polynomial greatest common divisor (GCD) can be computed with the Euclidean algorithm [FXT:
bpol/bitpol-gcd.h]:
1 inline ulong bitpol_gcd(ulong a, ulong b)
2 // Return polynomial gcd(A, B)
3 {
4 if ( a<b ) { ulong t=a; a=b; b=t; } // swap if deg(A)<deg(B)
5 // here: b<=a
6 while ( 0!=b )
7 {
8 ulong c = bitpol_rem(a, b);
9 a = b;
10 b = c;
11 }
12 return a;
13 }
Note that the comment
if ( a < b ) { ulong t=a; a=b; b=t; }; // swap if deg(A)<deg(B)

is not strictly correct as the swap can also happen with deg(a) = deg(b) but that does no harm.
The binary GCD algorithm can be implemented as follows:
826 Chapter 40: Binary polynomials

1 inline ulong bitpol_binary_gcd(ulong a, ulong b)


2 {
3 if ( a < b ) { ulong t=a; a=b; b=t; }; // swap if deg(A)<deg(B)
4 if ( b==0 ) return a;
5
6 ulong k = 0;
7 while ( !((a|b)&1) ) // both divisible by x
8 {
9 k++;
10 a >>= 1;
11 b >>= 1;
12 }
13 while ( !(a&1) ) a >>= 1;
14 while ( !(b&1) ) b >>= 1;
15
16 while ( a!=b )
17 {
18 if ( a < b ) { ulong t=a; a=b; b=t; }; // swap if deg(A)<deg(B)
19 ulong t = (a^b) >> 1;
20 while ( !(t&1) ) t >>= 1;
21 a = t;
22 }
23
24 return a << k;
25 }
With a fast bit-scan instruction we can optimize the function:
1 inline ulong bitpol_binary_gcd(ulong a, ulong b)
2 {
3 if ( (a==0) || (b==0) ) return a|b; // one (or both) of a, b zero?
4
5 ulong ka = lowest_one_idx(a);
6 a >>= ka;
7 ulong kb = lowest_one_idx(b);
8 b >>= kb;
9 ulong k = ( ka<kb ? ka : kb );
10
11 while ( a!=b )
12 {
13 if ( a < b ) { ulong t=a; a=b; b=t; } // swap if deg(A)<deg(B)
14 ulong t = (a^b) >> 1;
15 a = (t >> lowest_one_idx(t));
16 }
17 return a << k;
18 }

40.1.6 Exact division


Let C be a binary polynomial in x with constant term 1. We use the relation (for power series)
1 1 n n+1
= = (1 + Y ) (1 + Y 2 ) (1 + Y 4 ) (1 + Y 8 ) . . . (1 + Y 2 ) mod x2 (40.1-1)
C 1−Y
where Y = 1 − C. Now let Y = xe1 + xe2 + . . . + xek where ei ≥ 1 and ei+1 > ei . Then Y q =
xqe1 + xqe2 + . . . + xqek whenever q is a power of 2, and the multiplication by (1 − Y q ) is done by shifts
and subtractions. If A is an exact multiple of C, then R = A/C is a polynomial that can be computed
as follows. We assume that arrays of N bits are used for the polynomials.
1. Set R := A and let ei (for i = 1, 2, . . . , k) be the (ordered) positions of the nonzero coefficients of
C. Set q := 1.
2. If qe1 ≥ N , then return R.
3. Set T := 0. For j = 1, 2, . . . , k, set T := T + R xqej . The multiplications with xqej are left shifts by
qej positions. Set R := T .
4. Set q := 2 q and goto step 2.
The method is most efficient if k, the number of nonzero coefficients of C − 1, is small. Sometimes we can
reduce the work by dividing by C D and finally multiplying by D for some appropriate D. For example,
40.2: Multiplying binary polynomials of high degree 827

with all-ones polynomials C = 1 + x + x2 + . . . + xk and D = 1 + x, then C D = 1 + xk+1 . If C is of the


form xu (1 + . . . + xk ), then A/C can be computed as (A/xu )/(C/xu ).
The simplest example is C = 1 + x where the above procedure reduces to the inverse reversed Gray code
given in section 1.16.6 on page 45:
1 inline ulong bitpol_div_xp1(ulong a)
2 // Return power series A / (x+1)
3 // If A is a multiple of x+1, then the returned value
4 // is the exact division by x+1
5 {
6 a ^= a<<1; // rev_gray ** 1
7 a ^= a<<2; // rev_gray ** 2
8 a ^= a<<4; // rev_gray ** 4
9 a ^= a<<8; // rev_gray ** 8
10 a ^= a<<16; // rev_gray ** 16
11 #if BITS_PER_LONG >= 64
12 a ^= a<<32; // for 64bit words
13 #endif
14 return a;
15 }
For the division by x2 + 1 use the function
1 inline ulong bitpol_div_x2p1(ulong a)
2 // Return power series A / (x^2+1)
3 // If A is a multiple of x^2+1, then the returned value
4 // is the exact division by x^2+1
5 {
6 a ^= a<<2; // rev_gray ** 2
7 a ^= a<<4; // rev_gray ** 4
8 a ^= a<<8; // rev_gray ** 8
9 a ^= a<<16; // rev_gray ** 16
10 #if BITS_PER_LONG >= 64
11 a ^= a<<32; // for 64bit words
12 #endif
13 return a;
14 }
An algorithm for the exact division by C = 2k ± 1 (over Z) is given in section 1.21.2 on page 57.

40.2 Multiplying binary polynomials of high degree


We used the straightforward multiplication scheme which is O(N 2 ) for polynomials of degree N . This is
fine when working with polynomials of small degree. However, when working with polynomials of high
degree, the following splitting schemes should be used.

40.2.1 Karatsuba method: 2-way splitting


Let U and V be binary polynomials of (even) degree N . Write U = U0 + U1 xN/2 , V = V0 + V1 xN/2 and
use the scheme

UV = U0 · V0 (1 + xN/2 ) + (U1 − U0 ) · (V0 − V1 ) xN/2 + U1 · V1 (xN/2 + xN ) (40.2-1)

Only the three multiplications indicated by a dot are expensive, the multiplications by a power of x
are just shifts. The resulting scheme is the Karatsuba multiplication for polynomials, relation 28.1-3 on
page 550 interpreted for polynomials (set xN/2 = B). Recursive application of the scheme leads to the
asymptotic cost O(N log2 (3) ) ≈ O(N 1.585 ).

40.2.2 Splitting schemes that do not involve constants ‡


A generalization of the Karatsuba scheme is given in [347] (see also [348]). It does not lead to schemes
asymptotically better than O(N log2 (3) ) but has a simple structure and avoids all multiplications by
constants. As with 2-way splitting the method works for polynomials over any field.
828 Chapter 40: Binary polynomials

For the 3-way splitting scheme set

A = a2 x2 + a1 x + a0 (40.2-2a)
B = b2 x2 + b1 x + b0 (40.2-2b)
C = A B = c4 x4 + c3 x3 + c2 x2 + c1 x + c0 (40.2-2c)

Then the ck are

c0 = d0,0 (40.2-3a)
c1 = d0,1 − d0,0 − d1,1 (40.2-3b)
c2 = d0,2 − d0,0 − d2,2 + d1,1 (40.2-3c)
c3 = d1,2 − d1,1 − d2,2 (40.2-3d)
c4 = d2,2 (40.2-3e)

where

d0,0 = a0 b0 (40.2-4a)
d1,1 = a1 b1 (40.2-4b)
d2,2 = a2 b2 (40.2-4c)
d0,1 = (a0 + a1 ) (b0 + b1 ) (40.2-4d)
d0,2 = (a0 + a2 ) (b0 + b2 ) (40.2-4e)
d1,2 = (a1 + a2 ) (b1 + b2 ) (40.2-4f)

The scheme involves 6 multiplications and 13 additions. Recursive application leads to the asymptotic
cost (N log3 (6) ) ≈ O(N 1.6309 ) which is slightly worse than for the 2-term scheme. However, applying this
scheme first for a polynomial with N = 3 · 2n terms and then using the Karatsuba scheme recursively
can be advantageous.
We generalize the method for n-term polynomials and denote the scheme by KA-n. The 2-term scheme
KA-2 is the Karatsuba algorithm. With
n−1
X
A = ak xk (40.2-5a)
k=0
n−1
X
B = bk xk (40.2-5b)
k=0
2n−2
X
C = A B =: ck xk (40.2-5c)
k=0

define

ds,s := as bs for s = 0, 1, . . . , n − 1 (40.2-6a)


ds,t := (as + bs ) (at + bt ) for s + t = i, t > s ≥ 0, 1 ≤ i ≤ 2 n − 3 (40.2-6b)
X X
c∗i = ds,t − (ds,s + dt,t ) (40.2-6c)
s+t=i s+t=i
0≤s<t 0≤s<n−1

Then

c0 = d0,0 (40.2-7a)
c2 n−2 = dn−1,n−1 (40.2-7b)
40.2: Multiplying binary polynomials of high degree 829

and for 0 < i < 2 n − 2:

c∗i

if i odd
ci = (40.2-7c)
c∗i + di/2,i/2 otherwise

The Karatsuba scheme is obtained for n = 2.


We give GP code whose output is the KA-n algorithm for given n. We need to create symbols ‘ak’ (for
ak ), ‘bk’, and so on:
1 fa(k)=eval(Str("a" k))
2 fb(k)=eval(Str("b" k))
3 fc(k)=eval(Str("c" k))
4 fd(k,j)=eval(Str("d" k "" j))
For example, we can create a symbolic polynomial of degree 3:
? sum(k=0,3, fa(k) * x^k)
a3*x^3 + a2*x^2 + a1*x + a0
The next routine generates the definitions of all ds,t . It returns the number of multiplications involved:
1 D(n)=
2 {
3 local(mct);
4 mct = 0; \\ count multiplications
5 for (i=0, n-1, mct+=1; print(fd(i,i), " = ", fa(i), " * ", fb(i) ) );
6 for (t=1, n-1,
7 for (s=0, t-1,
8 mct += 1;
9 print(fd(s,t), " = (", fa(s)+fa(t), ") * (", fb(s)+fb(t), ")" ) ;
10 );
11 );
12 return(mct);
13 }
For n = 3 the output is
d00 = a0 * b0
d11 = a1 * b1
d22 = a2 * b2
d01 = (a0 + a1) * (b0 + b1)
d02 = (a0 + a2) * (b0 + b2)
d12 = (a1 + a2) * (b1 + b2)
The following routine prints ci , the coefficient of the product, in terms of several ds,t . It returns the
number of additions involved:
1 C(i, n)=
2 {
3 local(N, s, act);
4 act = -1; \\ count additions
5 print1(fc(i), " = ");
6 for (s=0, i-1,
7 t = i - s;
8 if ( (t>s) && (t<n),
9 act += 3;
10 print1(" + ", fd(s,t));
11 print1(" - ", fd(s,s));
12 print1(" - ", fd(t,t));
13 );
14 );
15 if ( 0==i%2, act+=1; print1(" + ", fd(i/2,i/2)) );
16 print();
17 return( act );
18 }
It has to be called for all i where 0 ≤ i ≤ 2n − 2. The algorithm is generated by the following routine:
1 KA(n)=
2 {
3 local(mct, act);
4 act = 0; \\ count additions
5 mct = 0; \\ count multiplications
6 mct = D(n); \\ generate definitions for the d_{s,t}
7 \\ generate rules for computation of c_i in terms of d_{s,t}:
8 for (i=0, 2*n-2, act+=C(i,n) );
830 Chapter 40: Binary polynomials

9 act += n*(n-1); \\ additions when setting up d(i,j) for i!=j


10 return( [mct, act] );
11 }
With n = 3 we find the relations 40.2-3a . . . 40.2-3e:
c0 = + d00
c1 = + d01 - d00 - d11
c2 = + d02 - d00 - d22 + d11
c3 = + d12 - d11 - d22
c4 = + d22

d00 = a0 * b0
d11 = a1 * b1
d22 = a2 * b2
d33 = a3 * b3
d44 = a4 * b4
d01 = (a0 + a1) * (b0 + b1)
d02 = (a0 + a2) * (b0 + b2)
d12 = (a1 + a2) * (b1 + b2)
d03 = (a0 + a3) * (b0 + b3)
d13 = (a1 + a3) * (b1 + b3)
d23 = (a2 + a3) * (b2 + b3)
d04 = (a0 + a4) * (b0 + b4)
d14 = (a1 + a4) * (b1 + b4)
d24 = (a2 + a4) * (b2 + b4)
d34 = (a3 + a4) * (b3 + b4)
c0 = + d00
c1 = + d01 - d00 - d11
c2 = + d02 - d00 - d22 + d11
c3 = + d03 - d00 - d33 + d12 - d11 - d22
c4 = + d04 - d00 - d44 + d13 - d11 - d33 + d22
c5 = + d14 - d11 - d44 + d23 - d22 - d33
c6 = + d24 - d22 - d44 + d33
c7 = + d34 - d33 - d44
c8 = + d44
Figure 40.2-A: Code for the algorithm KA-5.

Now we generate the definitions for the KA-5 algorithm:


n=5 /* n terms, degree=n-1 */
default(echo, 0);
KA(n);
We obtain the algorithm KA-5 shown in figure 40.2-A. The format is valid GP input, so we add a few
lines that print code to check the algorithm:
1 print("A=",sum(k=0,n-1, fa(k) * x^k))
2 print("B=",sum(k=0,n-1, fb(k) * x^k))
3 print("/* direct computation of the product: */")
4 print("C=A*B")
5 print("/* Karatsuba computation of the product: */")
6 print("K=",sum(k=0,2*n-2, fc(k) * x^k))
7 print("qq=K-C")
8 print("print( if(0==qq, \"OK.\", \" **** OUCH!\") )")
This gives for n = 5:
A=a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0
B=b4*x^4 + b3*x^3 + b2*x^2 + b1*x + b0
/* direct computation of the product: */
C=A*B
/* Karatsuba computation of the product: */
K=c8*x^8 + c7*x^7 + c6*x^6 + c5*x^5 + c4*x^4 + c3*x^3 + c2*x^2 + c1*x + c0
qq=K-C
print( if(0==qq, "OK.", " **** OUCH!") )
We can feed the output into another GP session to verify the algorithm:
gp -f -q < karatsuba-n.gp | gp
The output is (shortened and comments added)
/* definitions of d(s,t): */
b0*a0
b1*a1
b2*a2
b3*a3
40.2: Multiplying binary polynomials of high degree 831

b4*a4
(b0 + b1)*a0 + (a1*b0 + b1*a1)
(b0 + b2)*a0 + (a2*b0 + b2*a2)
[--snip--]
(b3 + b4)*a3 + (a4*b3 + b4*a4)
/* the c_i in terms of d(s,t), evaluated: */
b0*a0
b1*a0 + a1*b0
b2*a0 + (a2*b0 + b1*a1)
b3*a0 + (a3*b0 + (b2*a1 + a2*b1))
b4*a0 + (a4*b0 + (b3*a1 + (a3*b1 + b2*a2)))
b4*a1 + (a4*b1 + (b3*a2 + a3*b2))
b4*a2 + (a4*b2 + b3*a3)
b4*a3 + a4*b3
b4*a4
/* polynomials: */
a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0
b4*x^4 + b3*x^3 + b2*x^2 + b1*x + b0
/* direct computation of product: */
b4*a4*x^8 + (b4*a3 + a4*b3)*x^7 + (b4*a2 + (a4*b2 + b3*a3))*x^6 + [...]
/* Karatsuba computation of product: */
b4*a4*x^8 + (b4*a3 + a4*b3)*x^7 + (b4*a2 + (a4*b2 + b3*a3))*x^6 + [...]
/* difference: */
0
OK. /* looks good */
The number of multiplications with the KA-n splitting scheme is (n2 + n)/2 which is suboptimal except
for n = 2. However, recursive application can be worthwhile. One should start with the biggest prime
factors as the number of additions is then minimized. The number of multiplications does not depend
on the order of recursion (see [347] which also tabulates the number of additions and multiplications for
n ≤ 128).
With n just below a highly composite number one may append zeros as ‘dummy’ terms and recursively
use KA-n algorithms for small n. For example, for polynomials of degree 63 the recursion with KA-2
(and n = 64) will beat the scheme “KA-7, then KA-3”.
One can write code generators that create expanded versions of the recursions for n the product of
small primes. If the cost of multiplication is much higher than for addition (as for binary polynomial
multiplication on general purpose CPUs), then substantial savings can be expected.

40.2.3 Toom-Cook algorithms for binary polynomials


The 3-way and 4-way splitting schemes described in section 28.1 on page 550 cannot be used with binary
polynomials because constants other than 0 and 1 are used. We now give splitting schemes that use the
constants 0 and 1 only, they are given in [59]. The schemes are valid only for binary polynomials.

40.2.3.1 3-way splitting


For the multiplication of two polynomials A and B both of degree 3N write

A = a0 + a1 xN + a2 x2N =: a0 + a1 Y + a2 Y 2 (40.2-8)

and identically for B. A 3-way splitting scheme for multiplication is shown in figure 40.2-B. The multi-
plications and divisions by x are shifts and the exact divisions are linear operations if we use the method
of section 40.1.6 on page 826.

40.2.3.2 4-way splitting


For the multiplication of two polynomials A and B both of degree 4N write

A = a0 + a1 Y + a2 Y 2 + a3 Y 3 (40.2-9)

where Y := xN and identically for B. The 4-way splitting multiplication scheme is shown in figure 40.2-C.
832 Chapter 40: Binary polynomials

A = a2*Y^2 + a1*Y + a0
B = b2*Y^2 + b1*Y + b0
S3 = a2 + a1 + a0;
S2 = b2 + b1 + b0;
S1 = S3 * S2; \\ Mult (1)
S0 = a2*x^2 + a1*x;
S4 = b2*x^2 + b1*x;
S3 += S0;
S2 += S4;
S0 += a0;
S4 += b0;
S3 *= S2; \\ Mult (2)
S2 = S0 * S4; \\ Mult (3)
S4 = a2 * b2; \\ Mult (4)
S0 = a0 * b0; \\ Mult (5)
S3 += S2;
S2 += S0; S2 /= x; S2 += S3;
T = S4; T *= (x^3+1); \\ temporary variable
S2 += T; S2 /= (x+1); \\ exact division
S1 += S0;
S3 += S1; S3 /= x; S3 /= (x+1); \\ exact division
S1 += S4; S1 += S2;
S2 += S3;
P = S4*Y^4 + S3*Y^3 + S2*Y^2 + S1*Y + S0;
Mod(1,2)* (P - A*B) \\ == zero
(P - A*B) \\ NOT zero, the scheme only works over GF(2)
Figure 40.2-B: Implementation of the 3-way multiplication scheme for binary polynomials. The five
expensive multiplications are commented with ‘Mult (n)’.

40.2.4 FFT based methods


For polynomials of very high degree FFT-based algorithms can be used. The simplest method is to use
integer multiplication without the carry phase (which is polynomial multiplication!). We give an example
using decimal digits. The carry phase of the integer multiplication is replaced by a reduction modulo 2:
100110111 * 110101
== 11022223331211 // integer multiplication
== 11000001111011 // parity of digits
The scheme will work for polynomials of degree less than nine only. When using an FFT multiplication
scheme (see section 28.2 on page 558), we can multiply polynomials up to degree N as long as the integer
values 0, 1, 2 . . . N + 1 can be distinguished after computing the FFT. This is hardly a limitation at all:
with the C-type float (24 bit mantissa) polynomials up to degree one million can be multiplied assuming
at least 20 bits are correct after the FFT. With type double (53-bit mantissa) there is no practical limit.
While the algorithm is very easy to implement it is not competitive to well implemented splitting schemes
and the FFT method described in [303] or the multiplication algorithm given in [92]. An excellent source
for multiplication algorithms for binary polynomials is [85].

40.3 Modular arithmetic with binary polynomials


Here we consider arithmetic of binary polynomials modulo a binary polynomial. Addition and subtraction
are again the XOR operation and no modular reduction is required.

40.3.1 Multiplication and squaring


Multiplication of a polynomial A by x modulo (a polynomial) C can be done by shifting left and sub-
tracting C if the coefficient shifted out is one [FXT: bpol/bitpolmod-arith.h]:
1 static inline ulong bitpolmod_times_x(ulong a, ulong c, ulong h)
2 // Return (A * x) mod C
3 // where A and C represent polynomials over Z/2Z:
40.3: Modular arithmetic with binary polynomials 833

A = a3*Y^3 + a2*Y^2 + a1*Y + a0;


B = b3*Y^3 + b2*Y^2 + b1*Y + b0;
S1 = a3 + a2 + a1 + a0;
S2 = b3 + b2 + b1 + b0;
S3 = S1 * S2; \\ Mult (1)
S0 = a1 + x*(a2 + x*a3);
S6 = b1 + x*(b2 + x*b3);
S4 = (S0 + a3*(x+1))*x + S1;
S5 = (S6 + b3*(x+1))*x + S2;
S0 = S0*x + a0;
S6 = S6*x + b0;
S5 = S5 * S4; \\ Mult (2)
S4 = S0 * S6; \\ Mult (3)
S0 = a0*x^3 + a1*x^2 + a2*x;
S6 = b0*x^3 + b1*x^2 + b2*x;
S1 = S1 + S0 + a0*(x^2+x);
S2 = S2 + S6 + b0*(x^2+x);
S0 = S0 + a3;
S6 = S6 + b3;
S1 = S1 * S2; \\ Mult (4)
S2 = S0 * S6; \\ Mult (5)
S6 = a3 * b3; \\ Mult (6)
S0 = a0 * b0; \\ Mult (7)
S1 = S1 + S2 + S0*(x^4+x^2+1);
S5 = (S5 + S4 + S6*(x^4+x^2+1) + S1) \ (x^4+x);
S2 = S2 + S6 + S0*x^6;
S4 = S4 + S2 + S6*x^6 + S0;
S4 = (S4 + S5*(x^5+x)) \ (x^4+x^2);
S3 = S3 + S0 + S6;
S1 = S1 + S3;
S2 = S2 + S1*x + S3*x^2;
S3 = S3 + S4 + S5;
S1 = (S1 + S3*(x^2+x)) \ (x^4+x);
S5 = S5 + S1;
S2 = (S2 + S5*(x^2+x)) \ (x^4+x^2);
S4 = S4 + S2;
P = S6*Y^6 + S5*Y^5 + S4*Y^4 + S3*Y^3 + S2*Y^2 + S1*Y + S0;
Mod(1,2)*(P - A*B) \\ == zero
(P - A*B) \\ NOT zero, the scheme only works over GF(2)
Figure 40.2-C: Implementation of the 4-way multiplication scheme for binary polynomials. The seven
expensive multiplications are commented with ‘Mult (n)’.

4 // W = pol(w) =: \sum_k{ [bit_k(w)] * x^k}


5 //
6 // h needs to be a mask with one bit set:
7 // h == highest_one(c) >> 1 == 1UL << (degree(C)-1)
8 {
9 ulong s = a & h;
10 a <<= 1;
11 if ( s ) a ^= c;
12 return a;
13 }
To avoid the repeated computation of the highest set bit, we introduced the auxiliary variable h that has
to be initialized as described in the comment. Section 1.6 on page 14 gives algorithms for the function
highest_one(). Note that h needs to be recomputed only if the degree of the modulus C changes, which
is usually only once for a series of calculations. By using the variable h we can use the routine even if
the degree of C equals the number of bits in a word in which case C does not fit into a word.
The routine for the multiplication of two polynomials a and b modulo C is obtained by adding a reduction
step to the binary multiplication routine:
1 inline ulong bitpolmod_mult(ulong a, ulong b, ulong c, ulong h)
2 // Return (A * B) mod C
3 {
4 ulong t = 0;
5 while ( b )
6 {
834 Chapter 40: Binary polynomials

7 if ( b & 1 ) t ^= a;
8 b >>= 1;
9
10 ulong s = a & h;
11 a <<= 1;
12 if ( s ) a ^= c;
13 }
14 return t;
15 }

40.3.2 Optimization of the squaring and multiplication routines


Squaring a can be done by the multiplication a·a. If many squarings have to be done with a fixed modulus,
then the optimization using a precomputed table of the residues x2k mod C shown in section 42.1 on
Pd Pd
page 886 can be useful. Squaring of the polynomial k=0 ak xk is the computation of the sum k=0 ak x2k
modulo C. We use the auxiliary function
1 static inline ulong bitpolmod_times_x2(ulong a, ulong c, ulong h)
2 // Return (A * x * x) mod C
3 {
4 { ulong s=a&h; a<<=1; if (s) a^=c; }
5 { ulong s=a&h; a<<=1; if (s) a^=c; }
6 return a;
7 }
The squaring function, with a 4-fold unrolled loop, is
1 static inline ulong bitpolmod_square(ulong a, ulong c, ulong h)
2 // Return A*A mod C
3 {
4 ulong t = 0, s = 1;
5 do
6 {
7 if (a&1) t^=s; a>>=1; s=bitpolmod_times_x2(s, c, h);
8 if (a&1) t^=s; a>>=1; s=bitpolmod_times_x2(s, c, h);
9 if (a&1) t^=s; a>>=1; s=bitpolmod_times_x2(s, c, h);
10 if (a&1) t^=s; a>>=1; s=bitpolmod_times_x2(s, c, h);
11 }
12 while ( a );
13 return t;
14 }
Whether the unrolled code is used can be specified via the line
#define MULT_UNROLL // define to unroll loops 4-fold
The optimization used for the multiplication routine is also unrolling as described in section 40.1.2 on
page 823:
1 static inline ulong bitpolmod_mult(ulong a, ulong b, ulong c, ulong h)
2 {
3 ulong t = 0;
4 do
5 {
6 { if(b&1) t^=a; b>>=1; ulong s=a&h; a<<=1; if(s) a^=c; }
7 { if(b&1) t^=a; b>>=1; ulong s=a&h; a<<=1; if(s) a^=c; }
8 { if(b&1) t^=a; b>>=1; ulong s=a&h; a<<=1; if(s) a^=c; }
9 { if(b&1) t^=a; b>>=1; ulong s=a&h; a<<=1; if(s) a^=c; }
10 }
11 while ( b );
12 return t;
13 }
It turns out that squaring via multiplication is slightly faster than via the described sum computation.

40.3.3 Exponentiation
The following routine for modular exponentiation uses the right-to-left powering algorithm from sec-
tion 28.5.1 on page 563 [FXT: bpol/bitpolmod-arith.h]:
1 inline ulong bitpolmod_power(ulong a, ulong e, ulong c, ulong h)
2 // Return (A ** e) mod C
3 {
4 if ( 0==e ) return 1; // avoid hang with e==0 in next while()
40.3: Modular arithmetic with binary polynomials 835

5
6 ulong s = a;
7 while ( 0==(e&1) )
8 {
9 s = bitpolmod_square(s, c, h);
10 e >>= 1;
11 }
12
13 a = s;
14 while ( 0!=(e>>=1) )
15 {
16 s = bitpolmod_square(s, c, h);
17 if ( e & 1 ) a = bitpolmod_mult(a, s, c, h);
18 }
19 return a;
20 }
The left-to-right powering algorithm given in section 28.5.2 on page 564 can be implemented as:
1 inline ulong bitpolmod_power(ulong a, ulong e, ulong c, ulong h)
2 {
3 ulong s = a;
4 ulong b = highest_one(e);
5 while ( b>1 )
6 {
7 b >>= 1;
8 s = bitpolmod_square(s, c, h); // s *= s;
9 if ( e & b ) s = bitpolmod_mult(s, a, c, h); // s *= a;
10 }
11 return s;
12 }
Computing a power of x can be optimized with this scheme:
1 inline ulong bitpolmod_xpower(ulong e, ulong c, ulong h)
2 // Return (x ** e) mod C
3 {
4 ulong s = 2; // ’x’
5 ulong b = highest_one(e);
6 while ( b>1 )
7 {
8 b >>= 1;
9 s = bitpolmod_square(s, c, h); // s *= s;
10 if ( e & b ) s = bitpolmod_times_x(s, c, h); // s *= x;
11 }
12 return s;
13 }

40.3.4 Division by x
Division by x is possible if the modulus has a nonzero constant term (that is, gcd(C, x) = 1). The routine
is quite simple [FXT: bpol/bitpolmod-arith.h]:
1 static inline ulong bitpolmod_div_x(ulong a, ulong c, ulong h)
2 // Return (A / x) mod C
3 // C must have nonzero constant term: (c&1)==1
4 {
5 ulong s = a & 1;
6 a >>= 1;
7 if ( s )
8 {
9 a ^= (c>>1);
10 a |= h; // so it also works for n == BITS_PER_LONG
11 }
12 return a;
13 }
If we do not insist on correct results for the case that the degree of C equals the number of bits in a
word, we could simply use the following two-liner:
if ( a & 1 ) a ^= c;
a >> 1;
The operation needs only about two CPU cycles. The inverse of x can be computed with:
1 static inline ulong bitpolmod_inv_x(ulong c, ulong h)
2 // Return (1 / x) mod C
836 Chapter 40: Binary polynomials

3 // C must have nonzero constant term: (c&1)==1


4 {
5 ulong a = (c>>1);
6 a |= h; // so it also works for n == BITS_PER_LONG
7 return a;
8 }

40.3.5 Inversion and division


The method to compute the extended GCD (EGCD) is the same as given in section 39.1.4 on page 767
[FXT: bpol/bitpol-gcd.h]:
1 inline ulong bitpol_egcd(ulong u, ulong v, ulong &iu, ulong &iv)
2 // Return u3 and set u1,v1 so that gcd(u,v) == u3 == u*u1 + v*u2
3 {
4 ulong u1 = 1, u2 = 0;
5 ulong v1 = 0, v3 = v;
6 ulong u3 = u, v2 = 1;
7 while ( v3!=0 )
8 {
9 ulong q = bitpol_div(u3, v3); // == u3 / v3;
10
11 ulong t1 = u1 ^ bitpol_mult(v1, q); // == u1 - v1 * q;
12 u1 = v1; v1 = t1;
13
14 ulong t3 = u3 ^ bitpol_mult(v3, q); // == u3 - v3 * q;
15 u3 = v3; v3 = t3;
16
17 ulong t2 = u2 ^ bitpol_mult(v2, q); // == u2 - v2 * q;
18 u2 = v2; v2 = t2;
19 }
20
21 iu = u1; iv = u2;
22 return u3;
23 }
The routine can be optimized using bitpol_divrem(): remove the lines
ulong q = bitpol_div(u3, v3); // == u3 / v3;
[--snip--]
ulong t3 = u3 ^ bitpol_mult(v3, q); // == u3 - v3 * q;
and insert at the beginning of the body of the loop:
ulong q, t3;
bitpol_divrem(u3, v3, q, t3);
The routine computes the GCD g and two additional quantities iu and iv so that

g = u · iu + v · iv (40.3-1)

If g = 1, we have

1 ≡ u · iu mod v (40.3-2)

That is, iu is the inverse of u modulo v. The implementation is [FXT: bpol/bitpolmod-arith.h]


1 inline ulong bitpolmod_inverse(ulong a, ulong c)
2 // Returns the inverse of A modulo C if it exists, else zero.
3 // Must have deg(A) < deg(C)
4 {
5 ulong i, t; // t unused
6 ulong g = bitpol_egcd(a, c, i, t);
7 if ( g!=1 ) i = 0;
8 return i;
9 }
Modular division is done by multiplication with the inverse:
1 inline ulong bitpolmod_divide(ulong a, ulong b, ulong c, ulong h)
2 // Return a/b modulo c.
3 // Must have: gcd(b,c)==1
4 {
5 ulong i = bitpolmod_inverse(b, c);
40.4: Irreducible polynomials 837

6 a = bitpolmod_mult(a, i, c, h);
7 return a;
8 }
The inverse of a number a modulo a prime m can be computed as a−1 = am−2 (m − 1 is the maximal
order of an element in Z/mZ). With an irreducible (see section 40.4) polynomial C of degree n the inverse
n
modulo C of a polynomial A can be computed as A−1 = A2 −2 (2n − 1 is the maximal order modulo C,
see section 40.5 on page 841):
1 inline ulong bitpolmod_inverse_irred(ulong a, ulong c, ulong h)
2 // Return (A ** -1) mod C
3 // Must have: C irreducible.
4 {
5 ulong r1 = (h<<1) - 2; // max order minus one
6 ulong i = bitpolmod_power(a, r1, c, h);
7 return i;
8 }

40.4 Irreducible polynomials


A polynomial is called irreducible if it has no nontrivial factors (trivial factors are the constant polyno-
mial ‘1’ and the polynomial itself). A polynomial that has a nontrivial factorization is called reducible.
The irreducible polynomials are the ‘primes’ among the polynomials.
The factorization of a polynomial depends on its coefficient field: The polynomial x2 + 1 over R (or Z)
is irreducible. Over C it factors as (x2 + 1) = (x + i) (x − i). As a binary polynomial, the factorization
is (x2 + 1) = (x + 1)2 .
All polynomials with zero constant coefficient (except x) are reducible because they have the factor x. A
binary polynomial that is irreducible has at least one nonzero coefficient of odd degree (else it would be
a square). All binary polynomials except for x + 1 that have an even number of nonzero coefficients are
reducible because they have the factor x + 1.

40.4.1 Testing for irreducibility


n n
Irreducibility tests for binary polynomials use the fact that the polynomial x2 − x = x2 + x has all
irreducible polynomials whose degrees divide n as factors. For example, with n = 6 we get
6
x2 + x = x64 + x (40.4-1a)
= (x) · (x + 1) · (40.4-1b)
· x2 + x + 1 ·


· x3 + x + 1 · x3 + x2 + 1 ·
 

· x6 + x + 1 · x6 + x3 + 1 · x6 + x4 + x2 + x + 1 ·
  

· x6 + x4 + x3 + x + 1 · x6 + x5 + 1 · x6 + x5 + x2 + x + 1 ·
  

· x6 + x5 + x3 + x2 + 1 · x6 + x5 + x4 + x + 1 · x6 + x5 + x4 + x2 + 1
  

40.4.1.1 The Ben-Or test for irreducibility


k
A binary polynomial C of degree d is reducible if gcd(x2 − x mod C, C) 6= 1 for any k < d. We compute
k
uk = x2 (modulo C) for each k < d by successive squarings and test whether gcd(uk + x, C) = 1 for
all k. But as a factor of degree f implies another one of degree d − f it suffices to do the first bd/2c of the
tests. The algorithm is called the Ben-Or irreducibility test. A C++ implementation is given in [FXT:
bpol/bitpol-irred-ben-or.cc]:
1 bool bitpol_irreducible_q(ulong c, ulong h)
2 // Return whether C is irreducible (via the Ben-Or irreducibility test_;
3 // h needs to be a mask with one bit set:
4 // h == highest_one(C) >> 1 == 1UL << (degree(C)-1)
5 {
838 Chapter 40: Binary polynomials

6 if ( c<4 )
7 {
8 if ( c>=2 ) return true; // x, and 1+x are irreducible
9 else return false; // constant polynomials are reducible
10 }
11
12 if ( 0==(1&c) ) return false; // x is a factor
13
14 // if ( 0==(c & 0xaaaaaaaaUL ) ) return 0; // at least one odd degree term
15 // if ( 0==parity(c) ) return 0; // need odd number of nonzero coeff.
16 // if ( 0!=bitpol_test_squarefree(c) ) return 0; // must be square-free
17
18 ulong d = h >> 1;
19 ulong u = 2; // =^= x
20 while ( 0 != d ) // floor( degree/2 ) times
21 {
22 // Square r-times for coefficients of c in GF(2^r).
23 // We have r==1:
24 u = bitpolmod_square(u, c, h);
25
26 ulong upx = u ^ 2; // =^= u+x
27
28 ulong g = bitpol_binary_gcd(upx, c);
29
30 if ( 1!=g ) return false; // reducible
31
32 d >>= 2;
33 }
34 return true; // irreducible
35 }
Commented out at the beginning are a few tests for some necessary conditions for irreducibility. For the
test bitpol_test_squarefree() (for a square factor) see section 40.12.2 on page 860. The routine will
fail if deg c =BITS_PER_LONG, because the gcd-computation fails in this case.

40.4.1.2 Rabin’s test for irreducibility


A binary polynomial C of degree d is irreducible if and only if
d
x2 ≡ x mod C (40.4-2a)

and, for all prime divisors pi of d


 d/p 
i
gcd x2 − x mod C, C = 1 (40.4-2b)

The implied test is called Rabin’s algorithm for irreducibility testing, see [276, p.7]. The number of GCD
computations equals the number of prime divisors of d.
If the prime divisors are processed in decreasing order, the successive exponents are increasing and the
power of x can be updated via squarings. The total number of squarings equals d which is minimal.
A C++ implementation of Rabin’s test is given in [FXT: bpol/bitpol-irred-rabin.cc]. A table of auxiliary
bit-masks gives the number of squarings between the GCD computations:
1 static const ulong rabin_tab[] =
2 {
3 0UL, // x = 0 (bits: ...........) OPS:
4 0UL, // x = 1 (bits: ...........) OPS: finally sqr 1 times
5 0UL, // x = 2 (bits: ...........) OPS: finally sqr 2 times
6 0UL, // x = 3 (bits: ...........) OPS: finally sqr 3 times
7 4UL, // x = 4 (bits: ........1..) OPS: sqr 2 times, finally sqr 2 times
8 0UL, // x = 5 (bits: ...........) OPS: finally sqr 5 times
9 12UL, // x = 6 (bits: .......11..) OPS: sqr 2 times, sqr 1 times, finally sqr 3 times
10 0UL, // x = 7 (bits: ...........) OPS: finally sqr 7 times
11 16UL, // x = 8 (bits: ......1....) OPS: sqr 4 times, finally sqr 4 times
12 8UL, // x = 9 (bits: .......1...) OPS: sqr 3 times, finally sqr 6 times
13 36UL, // x = 10 (bits: .....1..1..) OPS: sqr 2 times, sqr 3 times, finally sqr 5 times
14 [--snip--]
The GCD computation for the divisor 1 can be avoided by noting that only the polynomial x2 + x =
(x + 1) x would wrongly pass the test, so we exclude the factor x explicitly. The testing routine is
40.4: Irreducible polynomials 839

1 inline bool bitpol_irreducible_rabin_q(ulong c, ulong h)


2 // Return whether C is irreducible (via Rabin’s irreducibility test).
3 // h needs to be a mask with one bit set:
4 // h == highest_one(C) >> 1 == 1UL << (degree(C)-1)
5 {
6 if ( c<4 ) // C is one of 0, 1, x, 1+x
7 {
8 if ( c>=2 ) return true; // x, and 1+x are irreducible
9 else return false; // constant polynomials are reducible
10 }
11
12 if ( 0==(1&c) ) return false; // x is a factor
13
14 ulong d = 1 + lowest_one_idx(h); // degree
15 ulong rt = rabin_tab[d];
16 ulong m = 2; // =^= ’x’
17
18 while ( rt > 1 )
19 {
20 do
21 {
22 --d;
23 m = bitpolmod_square(m, c, h);
24 rt >>= 1;
25 }
26 while ( 0 == (rt & 1) );
27
28 ulong g = bitpol_binary_gcd( m ^ 2UL, c );
29 if ( g!=1 ) return false;
30 }
31
32 do { m = bitpolmod_square(m, c, h); } while ( --d );
33 if ( m ^ 2UL ) return false;
34
35 return true;
36 }
Rabin’s test will be faster than the Ben-Or test if the polynomial is irreducible. If the polynomial is
reducible and has small factors (as often the case with ‘random’ polynomials), then the Ben-Or test will
be faster. A comparison of the tests is given in [150].

40.4.1.3 Testing for irreducibility without GCD computations


Call a binary polynomial C of degree d that has no linear factors and for which
d
x2 ≡ x mod C (40.4-3)

and, for all l < d,


l
x2 ≡ x mod C (40.4-4)

a strong pseudo irreducible (SPI). The test whether a polynomial is SPI does not involve any GCD
computation. The test for a polynomial C of degree d can be given as
1. If C has a linear factor (x or x + 1), then return false.
k
2. For k = 1, . . . , d compute sk := x2 mod C by successive squarings.
3. If sk = x for any k < d, then return false.
4. If sd 6= x, then return false.
5. Return true.
If d is a prime, the power of a prime, or the product of two primes, then strong pseudo irreducibility
implies irreducibility (see [23]). We list the degrees 1 < d < 63 where strong pseudo irreducibility does
not imply irreducibility (and GCDs are needed for irreducibility testing):
12, 18, 20, 24, 28, 30, 36, 40, 42, 44, 45, 48, 50, 52, 54, 56, 60, 63
840 Chapter 40: Binary polynomials

The sequence is entry A102467 in [312]. For the degrees 44 = 4 · 11 and 52 = 4 · 13 no GCDs are needed
e
because (see [23]) if d = re s where r and s are distinct primes and s > (2r − 2)/r. We have re = 4 so
we need s > (24 − 2)/2 = 7 which holds for primes s ≥ 11.
In the implementation of the SPI test an extra branch is needed if the polynomial C does not fit into a
word. In that case the parity must be even [FXT: bpol/bitpol-spi.cc]:
1 bool
2 bitpol_spi_q(ulong c, ulong h)
3 // Return whether C is a strong pseudo irreducible (SPI).
4 // A polynomial C of degree d is an SPI if
5 // it has no linear factors, x^(2^k)!=x for 0<k<d, and x^(2^d)==x.
6 // h needs to be a mask with one bit set:
7 // h == highest_one(C) >> 1 == 1UL << (degree(C)-1)
8 {
9 const bool md = (bool)((h<<1)==0); // whether degree == BITS_PER_LONG
10
11 if ( md )
12 {
13 if ( (c&1)==0 ) return false; // factor x
14 if ( 0 != parity(c) ) return false; // factor x+1
15 }
16 else
17 {
18 if ( c<4 ) // C is one of 0, 1, x, 1+x
19 {
20 if ( c>=2 ) return true; // x, and 1+x are irreducible
21 else return false; // constant polynomials are reducible
22 }
23
24 if ( (c&1)==0 ) return false; // factor x
25 if ( 0 == parity(c) ) return false; // factor x+1
26 }
27
28 ulong t = 1;
29 ulong m = 2; // x
30 m = bitpolmod_square(m, c, h);
31 do
32 {
33 if ( m==2 ) return false;
34 m = bitpolmod_square(m, c, h);
35 t <<= 1;
36 }
37 while ( t!=h );
38
39 if ( m!=2 ) return false;
40
41 return true;
42 }
An auxiliary function returns whether GCDs are needed with the irreducibility test (64-bit version):
1 bool bitpol_need_gcd(ulong h)
2 // Return whether GCDs are needed for irreducibility test.
3 {
4 // degrees where GCDs are needed:
5 // 12, 18, 20, 24, 28, 30, 36, 40, 42, 45, 48, 50, 54, 56, 60, 63
6 const ulong gn =
7 (1UL<<12)|(1UL<<18)|(1UL<<20)|(1UL<<24)|(1UL<<28)|(1UL<<30)|
8 (1UL<<36)|(1UL<<40)|(1UL<<42)|(1UL<<45)|(1UL<<48)|(1UL<<50)|
9 (1UL<<54)|(1UL<<56)|(1UL<<60)|(1UL<<63);
10 return 0 != ( h & (gn>>1) );
11 }
Now the irreducibility test can be implemented as follows:
1 inline bool bitpol_irreducible_q(ulong c, ulong h)
2 {
3 if ( bitpol_need_gcd(h) ) return bitpol_irreducible_ben_or_q(c, h);
4 else return bitpol_spi_q(c, h);
5 }
As the SPI test also works for polynomials not fitting into a word we can test those for irreducibility.
40.5: Primitive polynomials 841

40.5 Primitive polynomials


Let C be an irreducible polynomial. Then the sequence pk = xk mod (C), k = 1, 2, . . . is periodic and
the (smallest) period m of the sequence is the order of x modulo C. We call m the period (or order ) of
the polynomial C. For a binary polynomial of degree n the maximal period equals 2n − 1.
For the period m of C we have xm = 1 mod C, so xm − 1 = 0 mod C. That is, C divides xm − 1 but no
polynomial xk − 1 with k < m.
A polynomial is called primitive if its period is maximal. Then the powers of x generate all nonzero
binary polynomials of degree ≤ n − 1. The polynomial x is a generator (‘primitive root’) modulo C.
Primitivity implies irreducibility, the converse is not true.
The situation is somewhat parallel to the operations modulo an integer:
• Among those integers m that are prime some have the primitive root 2: the sequence 2k for
k = 1, 2, . . . , m − 1 contains all nonzero numbers modulo m (see chapter 26 on page 535).
• Among those polynomials C that are irreducible some are primitive: the sequence xk for k =
1, 2, . . . , 2n − 1 contains all nonzero polynomials modulo C.
Note that there is another notion of the term ‘primitive’, that of a polynomial for which the greatest
common divisor of all coefficients is one.

40.5.1 Roots of primitive polynomials have maximal order


A different characterization of primitivity is as follows. Suppose you want to do computations with
Pn−1
linear combinations A = k=0 ak αk (where ak ∈ GF(2)) of the powers of an (unknown!) root α of an
Pn−1
irreducible polynomial C = xn + k=0 ck xk .
When multiplying A with the root α we get a term αn which we want to get rid of. But we have
n−1
X
αn = − ck αk (40.5-1)
k=0

as α is a root of the polynomial C. Therefore we can use exactly the same modular reduction as with
polynomial computation modulo C. The same is true for the multiplication of two linear combinations
(of the powers of the same root α).
We see that the order of a polynomial p is the order of its root α modulo p and that a polynomial is
primitive if and only if its root has maximal order. An irreducible polynomial C of degree n has n distinct
k
roots, they are equal to α2 mod C for 0 ≤ k < n. The orders of all roots are identical.

40.5.2 Testing for primitivity


Checking a degree-d binary polynomial for primitivity by directly using the definition has complexity
O(2d ) which is prohibitive except for tiny d. A much better solution is a modification of the algorithm
to determine the order in a finite field given in section 39.7.1.2 on page 779. The implementation given
here uses the GP language:
1 polorder(p) =
2 /* Order of x modulo p (p irreducible over GF(2)) */
3 {
4 local(g, g1, te, tp, tf, tx);
5 g = ’x;
6 p *= Mod(1,2);
7 te = nn_;
8 for(i=1, np_,
9 tf = vf_[i]; tp = vp_[i]; tx = vx_[i];
10 te = te / tf;
11 g1 = Mod(g, p)^te;
12 while ( 1!=g1,
842 Chapter 40: Binary polynomials

13 g1 = g1^tp;
14 te = te * tp;
15 );
16 );
17 return( te );
18 }
The function uses the following global variables that must be set up before call:
1 nn_ = 0; /* max order = 2^n-1 */
2 np_ = 0; /* number of primes in factorization */
3 vp_ = []; /* vector of primes */
4 vf_ = []; /* vector of factors (prime powers) */
5 vx_ = []; /* vector of exponents */
As given, the algorithm will do np exponentiations modulo p where np is the number of different primes in
the factorization in m. A C++ implementation of the algorithm is given in [FXT: bpol/bitpol-order.cc].
A shortcut that makes the algorithm terminate as soon as the computed order drops below maximum is
1 polmaxorder_q(p) =
2 /* Whether order of x modulo p is maximal (p irreducible over GF(2)) */
3 /* Early-out variant */
4 {
5 local(g1, te, tp, tf, tx, ct);
6 p *= Mod(1,2);
7 te = nn_;
8 for(i=1, np_,
9 tf = vf_[i]; tp = vp_[i]; tx = vx_[i];
10 te = te / tf;
11 g1 = Mod(g, p)^te;
12 ct = 0;
13 while ( 1!=g1,
14 g1 = g1^tp;
15 te = te * tp;
16 ct = ct + 1;
17 );
18 if ( ct<tx, return(0) );
19 );
20 return(1);
21 }

With polmaxorder_q() and GP’s built-in polisirreducible() the search for the lexicographically min-
imal primitive polynomials up to degree n = 100 is a matter of about ten seconds. Extending the list
up to n = 200 takes three minutes. The computation of all polynomials up to degree n = 400 takes less
than an hour.
Again, the algorithm depends on precomputed factorizations. The table [FXT: data/mersenne-factors.txt]
taken from [89] was used to save computation time.
For prime m = 2n − 1 (that is, m is a Mersenne prime) irreducibility suffices for primality: The one-liner
n=607; for(k=1,n-1,if(polisirreducible(Mod(1,2)*(1+t^k+t^n)),print1(" ",k)))
finds all primitive trinomials xn +xk +1 whose degree is the Mersenne exponent n = 607. The computation
of the following list takes about two minutes.
89: 38 51
127: 1 7 15 30 63 64 97 112 120 126
521: 32 48 158 168 353 363 473 489
607: 105 147 273 334 460 502

Note we did not exploit the symmetry (reversed polynomials are also primitive). Techniques to find
primitive trinomials whose degrees are very big Mersenne exponents are described in [80] and [84].
Pd
Here is a surprising theorem: Let p(x) = k=0 ck xk be an irreducible binary polynomial and Lp (x) :=
2k
Pd d
k=0 ck x . Then all irreducible factors of Lp (x)/x (a polynomial of degree 2 − 1) are of degree equal
to ord(p) (the order of x modulo p(x)). Especially, if p(x) is primitive, then Lp (x)/x is irreducible. The
theorem is proved in [368] and also in [233, p.110]. An example: x7 + x + 1 is primitive, so x127 + x + 1
40.6: The number of irreducible and primitive polynomials 843

127
−1
is irreducible. But, as 2127 − 1 is prime, x127 + x + 1 is also primitive. Therefore x2 + x + 1 is
irreducible.

40.6 The number of irreducible and primitive polynomials

n: In n: In n: In n: In
1: 2 11: 186 21: 99858 31: 69273666
2: 1 12: 335 22: 190557 32: 134215680
3: 2 13: 630 23: 364722 33: 260300986
4: 3 14: 1161 24: 698870 34: 505286415
5: 6 15: 2182 25: 1342176 35: 981706806
6: 9 16: 4080 26: 2580795 36: 1908866960
7: 18 17: 7710 27: 4971008 37: 3714566310
8: 30 18: 14532 28: 9586395 38: 7233615333
9: 56 19: 27594 29: 18512790 39: 14096302710
10: 99 20: 52377 30: 35790267 40: 27487764474
Figure 40.6-A: The number of irreducible binary polynomials for degrees n ≤ 40.

n: Pn n: Pn n: Pn n: Pn
1: 1 11: 176 21: 84672 31: 69273666
2: 1 12: 144 22: 120032 32: 67108864
3: 2 13: 630 23: 356960 33: 211016256
4: 2 14: 756 24: 276480 34: 336849900
5: 6 15: 1800 25: 1296000 35: 929275200
6: 6 16: 2048 26: 1719900 36: 725594112
7: 18 17: 7710 27: 4202496 37: 3697909056
8: 16 18: 7776 28: 4741632 38: 4822382628
9: 48 19: 27594 29: 18407808 39: 11928047040
10: 60 20: 24000 30: 17820000 40: 11842560000
Figure 40.6-B: The number of primitive binary polynomials for degrees n ≤ 40.

The number of irreducible binary polynomials of degree n is


1 X 1 X
In = µ(d) 2n/d = µ(n/d) 2d (40.6-1)
n n
d\n d\n

The Möbius function µ is defined by relation 37.1-6 on page 705. The expression is identical to the
n
formula for the number of Lyndon words (relation 18.3-2 on page 380). If n is prime, then In = 2 n−2 .
Figure 40.6-A gives In for n ≤ 40, the sequence is entry A001037 in [312]. The list of all irreducible
polynomials up to degree 11 is given in [FXT: data/all-irredpoly.txt].
For large degrees n the probability that a randomly chosen polynomial is irreducible is about 1/n. With
polynomials in two or more variables the situation is very different: the probability that a random
polynomial is irreducible tends to 1 for large n, see [58].
The number of primitive binary polynomials of degree n equals

ϕ(2n − 1)
Pn = (40.6-2)
n
n
If n is the exponent of a Mersenne prime we have Pn = 2 n−2 = In . The values of Pn for n ≤ 40 are
shown in figure 40.6-B. The sequence is entry A011260 in [312]. The list of all primitive polynomials up
to degree 11 is given in [FXT: data/all-primpoly.txt].
844 Chapter 40: Binary polynomials

n: Dn n: Dn n: Dn n: Dn
1: 1 11: 10 21: 15186 31: 0
2: 0 12: 191 22: 70525 32: 67106816
3: 0 13: 0 23: 7762 33: 49284730
4: 1 14: 405 24: 422390 34: 168436515
5: 0 15: 382 25: 46176 35: 52431606
6: 3 16: 2032 26: 860895 36: 1183272848
7: 0 17: 0 27: 768512 37: 16657254
8: 14 18: 6756 28: 4844763 38: 2411232705
9: 8 19: 0 29: 104982 39: 2168255670
10: 39 20: 28377 30: 17970267 40: 15645204474
Figure 40.6-C: The number of irreducible non-primitive binary polynomials for degrees n ≤ 40.

n: Pn /In n: Pn /In n: Pn /In n: Pn /In


1: 0.50000000 26: 0.66642256 51: 0.84834222 76: 0.52983738
2: 1.0 27: 0.84540117 52: 0.51936149 77: 0.93832726
3: 1.0 28: 0.49462097 53: 0.99982834 78: 0.56391518
4: 0.66666667 29: 0.99432922 54: 0.53392943 79: 0.99962783
5: 1.0 30: 0.49790073 55: 0.91393553 80: 0.42915344
6: 0.66666667 31: 1.0 56: 0.46549716 81: 0.84506003
7: 1.0 32: 0.50000763 57: 0.85711404 82: 0.65858526
8: 0.53333333 33: 0.81066253 58: 0.65165057 83: 0.99401198
9: 0.85714286 34: 0.66665141 59: 0.99999444 84: 0.38979140
10: 0.60606061 35: 0.94659138 60: 0.35255399 85: 0.96773455
11: 0.94623656 36: 0.38011770 61: 1.0 86: 0.66505112
12: 0.42985075 37: 0.99551569 62: 0.66666667 87: 0.85207814
13: 1.0 38: 0.66666285 63: 0.83624531 88: 0.47128978
14: 0.65116279 39: 0.84618267 64: 0.49921989 89: 1.0
15: 0.82493126 40: 0.43083023 65: 0.96762379 90: 0.46446197
16: 0.50196078 41: 0.99992518 66: 0.53157031 91: 0.99091593
17: 1.0 42: 0.55199996 67: 0.99999999 92: 0.51925414
18: 0.53509496 43: 0.99757669 68: 0.52884860 93: 0.85714286
19: 1.0 44: 0.50216809 69: 0.83890107 94: 0.66388120
20: 0.45821639 45: 0.81138931 70: 0.55834947 95: 0.96267339
21: 0.84792405 46: 0.65247846 71: 0.99999560 96: 0.38730483
22: 0.62990076 47: 0.99935309 72: 0.35544000 97: 0.99991264
23: 0.97871804 48: 0.38932803 73: 0.99772166 98: 0.64603552
24: 0.39561006 49: 0.99212598 74: 0.66330362 99: 0.79553432
25: 0.96559617 50: 0.58273388 75: 0.82216371 100: 0.45025627
Figure 40.6-D: Ratios Pn /In for degrees n ≤ 100: a random irreducible binary polynomial of prime
degree n is likely primitive even if n is not a Mersenne exponent.
40.7: Transformations that preserve irreducibility 845

The difference Dn := In − Pn is the number of irreducible non-primitive polynomials (see figure 40.6-C).
If n is the exponent of a Mersenne prime, we have Dn = 0. The complete list of these polynomials up to
degree 12 inclusive is given in [FXT: data/all-nonprim-irredpoly.txt].
Figure 40.6-D gives the probability that a randomly chosen irreducible polynomial of degree n is primitive.
A polynomial of prime degree is very likely primitive, so any conjecture suggesting that polynomials of
a certain type are always primitive for prime degree is dubious: if we take one random irreducible
polynomial for each prime degree n, then chances are that all of them are primitive.

40.7 Transformations that preserve irreducibility


40.7.1 The reciprocal polynomial
The reciprocal of a polynomial F (x) is the polynomial

F ∗ (x) = xdeg F F (1/x) (40.7-1)

The roots of F ∗ (x) are the inverses of the roots of F (x). The reciprocal of a binary polynomial is the
reversed binary word:
1 inline ulong bitpol_recip(ulong c)
2 // Return x^deg(C) * C(1/x) (the reciprocal polynomial)
3 {
4 ulong t = 0;
5 while ( c )
6 {
7 t <<= 1;
8 t |= (c & 1);
9 c >>= 1;
10 }
11 return t;
12 }

Alternatively, we can use the bit-reversal routines given in section 1.14 on page 33. The reciprocal
of an irreducible polynomial is again irreducible. The order of the polynomial is preserved under the
transformation.

40.7.2 The polynomial p(x + 1)


If a polynomial p(x) is irreducible, then p(x + 1), the composition with x + 1, is also irreducible. The
composition with x+1 does not in general preserve order: the simplest example is the primitive polynomial
p(x) = x4 + x3 + 1 where p(x + 1) = x4 + x3 + x2 + x + 1 has the order 5. The order of x modulo p(x)
equals the order of x + 1 modulo p(x + 1). The composition with x + 1 can be computed by [FXT:
bpol/bitpol-irred.h]:
1 inline ulong bitpol_compose_xp1(ulong c)
2 // Return C(x+1).
3 // Self-inverse.
4 {
5 ulong z = 1;
6 ulong r = 0;
7 while ( c )
8 {
9 if ( c & 1 ) r ^= z;
10 c >>= 1;
11 z ^= (z<<1);
12 }
13 return r;
14 }

A faster routine that finishes in time log2 (b) (where b = bits per word) is the blue_code() from sec-
tion 1.19 on page 49.
In general the sequence of successive ‘compose’ and ‘reverse’ operations leads to six different polynomials:
C= [11, 10, 4, 3, 0]
[11, 10, 4, 3, 0] -- recip (C=bitpol_recip(C)) -->
846 Chapter 40: Binary polynomials

[11, 8, 7, 1, 0] -- compose (C=bitpol_compose_xp1(C)) -->


[11, 10, 9, 7, 6, 5, 4, 1, 0] -- recip -->
[11, 10, 7, 6, 5, 4, 2, 1, 0] -- compose -->
[11, 9, 7, 2, 0] -- recip -->
[11, 9, 4, 2, 0] -- compose -->
[11, 10, 4, 3, 0] == initial value

40.8 Self-reciprocal polynomials

irred. poly irred. SRP


1: 11...1..11 111..1..111..1..111
2: 1..111.111 1.11111.111.11111.1
3: 1.11.11.11 1..111.11111.111..1
4: 11111...11 11.1...1.1.1...1.11
5: 1....1.111 1.1..1.11111.1..1.1
6: 11.11.1.11 11111..1.1.1..11111
7: 111...1111 11..1..11111..1..11
8: 1....11.11 1.1..11..1..11..1.1
9: 11.111..11 1111111111111111111
10: 1..11.1111 1.111....1....111.1
11: 1..1.11111 1.11.11..1..11.11.1
12: 1111..1.11 11.11..11111..11.11
13: 1.11..1111 1..11...111...11..1
14: 11.1.11.11 1111.111.1.111.1111
15: 1111111.11 11.1.111111111.1.11
16: 1111...111 11.11.1..1..1.11.11
17: 1.1.11.111 1....1.1.1.1.1....1
18: 11.1..1111 1111..1..1..1..1111
19: 11.1111111 111111...1...111111
20: 1.1.1.1111 1.....1111111.....1
21: 1.1.1...11 1........1........1
22: 1..1..1.11 1.11..11.1.11..11.1
23: 1.1....111 1...1.11.1.11.1...1
24: 1.......11 1.1.....111.....1.1
25: 11...11111 111..111.1.111..111
26: 11..111.11 111.11...1...11.111
27: 1...11..11 1.1.111.111.111.1.1
28: 11..1...11 111.1.1.111.1.1.111

Figure 40.8-A: All irreducible self-reciprocal binary polynomials of degree 18 (right) and the corre-
sponding irreducible polynomials of degree 9 with constant linear coefficient (left).

A polynomial is called self-reciprocal if it is its own reciprocal. The irreducible self-reciprocal polynomials
(SRPs), except for 1 + x, are of even degree 2 d. They can be computed from the irreducible polynomials
Pd
of degree d with nonzero linear coefficient. Let F (x) = j=0 fj xj and SF (x) the corresponding SRP,
then
d
X
d
SF (x) = x F (x + 1/x) = Fj xd−j (1 + x2 )j (40.8-1)
j=0

The irreducible SRPs of degree 18 and their corresponding polynomials are shown in figure 40.8-A [FXT:
gf2n/bitpol-srp-demo.cc]. The conversion can be implemented as [FXT: bpol/bitpol-srp.h]:
1 inline ulong bitpol_pol2srp(ulong f, ulong d)
2 // Return the self-reciprocal polynomial S=x^d*F(x+1/x) where d=deg(f).
3 // W = sum(j=0, d, F(j)*x^(d-j)*(1+x^2)^j ) where
4 // F(j) is the j-th coefficient of F.
5 // Must have: d==degree(F)
6 {
7 ulong w = 1; // == (x^2+1)^j
8 ulong s = 0;
9 do // for j = 0 ... d:
10 {
11 if ( f & 1 ) s ^= (w << d); // S += F(j)*x^(d-j)*(1+x^2)^j
12 w ^= (w<<2); // w *= (1+x^2)
13 f >>= 1; // next coefficient to low end
14 }
15 while ( d-- );
16 return s;
17 }
40.8: Self-reciprocal polynomials 847

The inverse function is given in [244]:


1. Set F := 0 and j := 0.
2. If S mod (x2 + 1) ≡ 0, then set fj := 0, else set fj := 1.
3. Set S := (S − fj xd−j )/(x2 + 1) [the division is exact].
4. Set j := j + 1. If j ≤ d goto step 2.
Pd
5. Return F (= j=0 fj xj ).
The computation of S mod (x2 + 1) can be omitted because the quantity is 0 if and only if the central
coefficient of S equals 0. The assignment S := (S − fj xd−j )/(x2 + 1) can be replaced by S := S/(x2 + 1)
(as power series) because no coefficient beyond the position d − j is needed by the following steps. We
use the power series division shown in section 40.1.6 on page 826 for this computation:
1 inline ulong bitpol_srp2pol(ulong s, ulong hd)
2 // Inverse of bitpol_pol2srp().
3 // Must have: hd = degree(s)/2 (note: _half_ of the degree).
4 // Only the lower half coefficients are accessed, i.e.
5 // the routine works for degree(S) <= 2*BITS_PER_LONG-2.
6 {
7 ulong f = 0;
8 ulong mh = 1UL << hd;
9 ulong ml = 1;
10 do
11 {
12 ulong b = s & mh; // central coefficient
13 // s ^= b; // set central coefficient to zero (not needed)
14 if ( b ) f |= ml; // positions 0,1,...,hd
15 ml <<= 1;
16 s = bitpol_div_x2p1(s); // exact division by (x^2+1)
17 }
18 while ( (mh>>=1) );
19 return f;
20 }
n
The self-reciprocal polynomials of degree 2n are factors of the polynomial x2 +1
− 1 (see [251]). For
example, for n = 5 we find
? lift(factormod(x^(2^5+1)-1,2))
[x + 1 1]
[x^2 + x + 1 1]
[x^10 + x^7 + x^5 + x^3 + 1 1]
[x^10 + x^9 + x^5 + x + 1 1]
[x^10 + x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1 1]

The order of a self-reciprocal polynomial of degree 2n is a divisor of 2n + 1. The list of all irreducible
SRP up to degree 22 is given in [FXT: data/all-irred-srp.txt].

n: Sn n: Sn n: Sn n: Sn
1: 1 11: 93 21: 49929 31: 34636833
2: 1 12: 170 22: 95325 32: 67108864
3: 1 13: 315 23: 182361 33: 130150493
4: 2 14: 585 24: 349520 34: 252645135
5: 3 15: 1091 25: 671088 35: 490853403
6: 5 16: 2048 26: 1290555 36: 954437120
7: 9 17: 3855 27: 2485504 37: 1857283155
8: 16 18: 7280 28: 4793490 38: 3616814565
9: 28 19: 13797 29: 9256395 39: 7048151355
10: 51 20: 26214 30: 17895679 40: 13743895344
Figure 40.8-B: Number of irreducible self-reciprocal polynomials of degree 2n.
848 Chapter 40: Binary polynomials

n: Tn n: Tn n: Tn n: Tn
1: 1 11: 62 21: 32508 31: 23091222
2: 1 12: 160 22: 76032 32: 67004160
3: 1 13: 210 23: 121574 33: 85342752
4: 2 14: 448 24: 344064 34: 200422656
5: 2 15: 660 25: 405000 35: 289531200
6: 4 16: 2048 26: 1005888 36: 892477440
7: 6 17: 2570 27: 1569780 37: 1237491936
8: 16 18: 5184 28: 4511520 38: 2874507264
9: 18 19: 9198 29: 6066336 39: 4697046900
10: 40 20: 24672 30: 12672000 40: 13690417152
Figure 40.8-C: Number of primitive self-reciprocal polynomials of degree 2n.

The number Sn of irreducible SRPs of degree 2n is


1 X
Sn = µ(d) 2n/d (40.8-2)
2n
d\n, d odd

Values of Sn for n ≤ 40 are shown in figure 40.8-B. The sequence of values Sn is entry A000048 in [312].
The number of irreducible polynomials of degree n with linear coefficient one is also Sn .
The number S̃n of irreducible SRPs of degree n is
−1 X
S̃n = µ(d) 2n/d (40.8-3)
n
d\n, d even

We have S̃n = 0 for n odd and S̃n = Sn/2 for n even. The number Tn of primitive SRPs of degree 2n is

ϕ (2n + 1)
Tn = (40.8-4)
2n
The sequence of values Tn is entry A069925 in [312], values for n ≤ 40 are shown in figure 40.8-C.

40.9 Irreducible and primitive polynomials of special forms ‡


We give lists of irreducible and primitive polynomials of special forms. The abbreviation ‘PP’ is used for
‘primitive polynomial’ in what follows. The weight of a binary polynomial is the sum of its coefficients.
Polynomials of low weight allow for cheap modular reduction.

40.9.1 All irreducible and primitive polynomials for low degrees


For degrees n ≤ 8 the complete list of irreducible polynomials is shown in figure 40.9-A. The list up to
degree n = 11 is given in [FXT: data/all-irredpoly.txt]. The list of PPs for n ≤ 11 is given in [FXT:
data/all-primpoly.txt]. The list of all irreducible polynomials that are not primitive for n ≤ 12 is given
in [FXT: data/all-nonprim-irredpoly.txt].

40.9.2 All irreducible and primitive trinomials for low degrees


A trinomial is a polynomial with exactly three nonzero coefficients. The irreducible binary trinomials for
degrees n ≤ 49 are shown in figure 40.9-B (there are no irreducible trinomials for degrees 50 and 51). A
list of all irreducible trinomials up to degree n = 400 is given in [FXT: data/all-trinomial-irredpoly.txt].
A more compact form of the list can is given in [FXT: data/all-trinomial-irredpoly-short.txt]:
2: 1
3: 1 2
4: 1 3
5: 2 3
40.9: Irreducible and primitive polynomials of special forms ‡ 849

2,1,0 7,1,0 8,4,3,2,0


7,3,0 8,5,3,1,0
3,1,0 7,3,2,1,0 8,5,3,2,0
3,2,0 7,4,0 8,6,3,2,0
7,4,3,2,0 8,6,4,3,2,1,0
4,1,0 7,5,2,1,0 8,6,5,1,0
4,3,0 7,5,3,1,0 8,6,5,2,0
# non-primitive: 7,5,4,3,0 8,6,5,3,0
4,3,2,1,0 7,5,4,3,2,1,0 8,6,5,4,0
7,6,0 8,7,2,1,0
5,2,0 7,6,3,1,0 8,7,3,2,0
5,3,0 7,6,4,1,0 8,7,5,3,0
5,3,2,1,0 7,6,4,2,0 8,7,6,1,0
5,4,2,1,0 7,6,5,2,0 8,7,6,3,2,1,0
5,4,3,1,0 7,6,5,3,2,1,0 8,7,6,5,2,1,0
5,4,3,2,0 7,6,5,4,0 8,7,6,5,4,2,0
7,6,5,4,2,1,0 # non-primitive:
6,1,0 7,6,5,4,3,2,0 8,4,3,1,0
6,4,3,1,0 8,5,4,3,0
6,5,0 8,5,4,3,2,1,0
6,5,2,1,0 8,6,5,4,2,1,0
6,5,3,2,0 8,6,5,4,3,1,0
6,5,4,1,0 8,7,3,1,0
# non-primitive: 8,7,4,3,2,1,0
6,3,0 8,7,5,1,0
6,4,2,1,0 8,7,5,4,0
6,5,4,2,0 8,7,5,4,3,2,0
8,7,6,4,2,1,0
8,7,6,4,3,2,0
8,7,6,5,4,1,0
8,7,6,5,4,3,0
Figure 40.9-A: All binary irreducible polynomials up to degree 8.

2,1 10,3 17,3 22,1 -30,1 35,2 -42,7


3,1 10,7 17,5 22,21 -30,9 35,33 -42,35
3,2 11,2 17,6 23,5 -30,21 -36,9 -44,5
4,1 11,9 17,11 23,9 -30,29 36,11 -44,39
4,3 -12,3 17,12 23,14 31,3 -36,15 -46,1
5,2 -12,5 17,14 23,18 31,6 -36,21 -46,45
5,3 -12,7 -18,3 25,3 31,7 36,25 47,5
6,1 -12,9 18,7 25,7 31,13 -36,27 47,14
-6,3 -14,5 -18,9 25,18 31,18 39,4 47,20
6,5 -14,9 18,11 25,22 31,24 39,8 47,21
7,1 15,1 -18,15 -28,1 31,25 39,14 47,26
7,3 15,4 20,3 28,3 31,28 39,25 47,27
7,4 15,7 -20,5 28,9 -33,10 39,31 47,33
7,6 15,8 -20,15 28,13 33,13 39,35 47,42
-9,1 15,11 20,17 28,15 33,20 41,3 49,9
9,4 15,14 21,2 28,19 -33,23 41,20 49,12
9,5 -21,7 28,25 -34,7 41,21 49,15
-9,8 -21,14 -28,27 -34,27 41,38 49,22
21,19 29,2 49,27
29,27 49,34
49,37
49,40

Figure 40.9-B: All irreducible trinomials xn + xk + 1 for degrees n ≤ 49. The format of the entries is
n,k for primitive trinomials and -n,k for non-primitive trinomials.

6: 1 5
7: 1 3 4 6
9: 4 5
10: 3 7
11: 2 9
15: 1 4 7 8 11 14

A line starts with the entry for the degree followed by all possible positions of the middle coefficient.
The corresponding files giving primitive trinomials only are [FXT: data/all-trinomial-primpoly.txt] and
[FXT: data/all-trinomial-primpoly-short.txt]. A list of irreducible trinomials that are not primitive is
[FXT: data/all-trinomial-nonprimpoly.txt].
Values of n such that an irreducible trinomial of degree n exists are given in sequence A073571 in [312].
Values such that at least one primitive trinomial exists are given in entry A073726. The values n, k for
primitive polynomials of the form (x + 1)n + (x + 1)k + 1 are listed in [FXT: data/all-t1-primpoly.txt].
850 Chapter 40: Binary polynomials

Polynomials of that form are irreducible whenever xn + xk + 1 is irreducible. The list is not the same as
for primitive trinomials as the transformation p(x) 7→ p(x+1) does in general not preserve the order. The
sequence of degrees n such that there is a primitive polynomial (x + 1)n + (x + 1)k + 1 where 0 < k < n
is entry A136416 in [312].
Regarding trinomials, there is a theorem by Swan (given in [327]): The trinomial xn + xk + 1 over GF(2)
has an even number of irreducible factors (and therefore is reducible) if
1. n is even, k is odd, n 6= 2k, and either nk/2 ≡ 0 mod 4 or nk/2 ≡ 1 mod 4,
2. n is odd, k is even and does not divide 2n, and n ≡ ±3 mod 8,
3. n is even, k is odd and does divide 2n, and n ≡ ±1 mod 8,
4. any of the above holds for k replaced by n − k (that is, for the reciprocal trinomial).
The first condition implies that no irreducible trinomial for n a multiple of 8 exists (as n is even, k
must be odd, else the trinomial is a perfect square; and nk/2 ≡ 0 mod 4). Further, if n is a prime with
n ≡ ±3 mod 8, then the trinomial can be irreducible only if k = 2 (or n − k = 2). In the note [106] it is
shown that no irreducible trinomial exists for n a prime such that n ≡ 13 mod 24 or n ≡ 19 mod 24.
For some applications one may want to use reducible trinomials whose period is close to that of a primitive
one. For example, the trinomial

x32 + x15 + 1 = (40.9-1)


x + x + x + x + 1 · x + x + x + x + x + x + x + x + x + x + x + x2 + 1
11 9 7 2 21 19 15 13 12 10 9 8 7 6 4
 

has the period p = 4, 292, 868, 097 which is very close to 232 − 1 = 4, 294, 967, 295. Note that the degree
is a multiple of 8, so no irreducible trinomial of that degree exists. See [82], [126], and [107].

40.9.3 Irreducible trinomials of the form 1 + xk + xd


With each sequence, we give its number as entry in [312].
k=1: The trinomial p = 1 + x + xd is irreducible for the following 2 ≤ d ≤ 34353 (sequence A002475):
2, 3, 4, 6, 7, 9, 15, 22, 28, 30, 46, 60, 63,
127, 153, 172, 303, 471, 532, 865, 900,
1366, 2380, 3310, 4495, 6321, 7447,
10198, 11425, 21846, 24369, 27286, 28713, 32767, 34353
The trinomials are primitive for the following d ≤ 4400 (sequence A073639):
2, 3, 4, 6, 7, 15, 22, 60, 63, 127, 153, 471, 532, 865, 900, 1366
k=2: p = 1 + x2 + xd is irreducible for the following 3 ≤ d ≤ 57341 (sequence A057460):
3, 5, 11, 21, 29, 35, 93, 123, 333, 845, 4125,
10437, 10469, 14211, 20307, 34115, 47283, 50621, 57341

The trinomials are primitive for all n ≤ 845 (sequence A074710).


k=3: p = 1 + x3 + xd is irreducible for the following 4 ≤ d ≤ 1000 (sequence A057461):
4, 5, 6, 7, 10, 12, 17, 18, 20, 25, 28, 31, 41, 52, 66,
130, 151, 180, 196, 503, 650, 761, 986
The trinomials are primitive for the following n ≤ 400:
4, 5, 7, 10, 17, 20, 25, 28, 31, 41, 52, 130, 151,
k=4: p = 1 + x4 + xd is irreducible for the following 5 ≤ d ≤ 1000 (sequence A057463):
7, 9, 15, 39, 57, 81, 105

The trinomials are primitive for the following n ≤ 400: 7, 9, 15, 39, 81.
k=5: p = 1 + x5 + xd is irreducible for the following 6 ≤ d ≤ 1000 (sequence A057474):
40.9: Irreducible and primitive polynomials of special forms ‡ 851

6, 9, 12, 14, 17, 20, 23, 44, 47, 63, 84,


129, 236, 278, 279, 297, 300, 647, 726, 737,
The trinomials are primitive for the following n ≤ 400:
6, 9, 17, 23, 47, 63, 129, 236, 278, 279, 297

40.9.4 Irreducible trinomials of the form 1 + xd + xk d


The trinomial p = 1 + xd + x2d is irreducible whenever d is a power of 3:
1: x^2 + x + 1
3: x^6 + x^3 + 1
9: x^18 + x^9 + 1
27: x^54 + x^27 + 1
81: x^162 + x^81 + 1
243: x^486 + x^243 + 1
...

The trinomial p = 1 + xd + x3d is irreducible whenever d is a power of 7, and p = 1 + xd + x4d is irreducible


whenever d = 3i 5j , i, j ∈ N. Similar regularities can be observed for other forms, see [55].

40.9.5 Primitive pentanomials

15,4,2,1,0 30,6,4,1,0 45,4,3,1,0 60,5,4,2,0 75,6,3,1,0


16,5,3,2,0 31,3,2,1,0 46,8,7,6,0 61,5,2,1,0 76,5,4,2,0
17,3,2,1,0 32,7,6,2,0 47,5,4,1,0 62,6,5,3,0 77,6,5,2,0
18,5,2,1,0 33,6,4,1,0 48,9,7,4,0 63,5,4,1,0 78,7,2,1,0
19,5,2,1,0 34,8,4,3,0 49,6,5,4,0 64,4,3,1,0 79,4,3,2,0
5,3,2,1,0 20,6,4,1,0 35,8,7,1,0 50,4,3,2,0 65,4,3,1,0 80,9,4,2,0
6,4,3,1,0 21,5,2,1,0 36,8,7,1,0 51,6,3,1,0 66,9,8,6,0 81,6,3,2,0
7,3,2,1,0 22,5,4,3,0 37,6,4,1,0 52,6,3,1,0 67,5,2,1,0 82,9,6,4,0
8,4,3,2,0 23,5,3,1,0 38,6,5,1,0 53,6,2,1,0 68,7,5,1,0 83,7,4,2,0
9,4,3,1,0 24,4,3,1,0 39,7,4,1,0 54,8,6,3,0 69,6,5,2,0 84,9,7,1,0
10,4,3,1,0 25,3,2,1,0 40,5,4,3,0 55,6,2,1,0 70,5,3,1,0 85,8,2,1,0
11,4,2,1,0 26,6,2,1,0 41,3,2,1,0 56,7,4,2,0 71,5,3,1,0 86,6,5,2,0
12,6,4,1,0 27,5,2,1,0 42,7,4,3,0 57,5,3,2,0 72,10,9,3,0 87,7,5,1,0
13,4,3,1,0 28,6,4,1,0 43,6,4,3,0 58,6,5,1,0 73,4,3,2,0 88,11,9,8,0
14,5,3,1,0 29,4,2,1,0 44,6,5,2,0 59,7,4,2,0 74,7,4,3,0 89,6,5,3,0

Figure 40.9-C: The first (in lexicographic order) primitive pentanomials for n ≤ 89.

A pentanomial is a polynomial that has exactly five nonzero coefficients. PPs that are pentanomials
are given in [FXT: data/pentanomial-primpoly.txt]. For all degrees n ≥ 5 an irreducible (and primitive)
pentanomial seems to exist, but this has not been proved so far. Pentanomials of the form xn + x3 + x2 +
x + 1 are primitive for n ∈ {5, 7, 17, 25, 31, 41, 151} (and n ≤ 400), and irreducible for
5, 7, 10, 17, 20, 25, 28, 31, 41, 52, 130, 151, 196, 503, 650, 761, 986, 1391, 2047,
6172, 6431, 6730, 8425, 10162, 11410, 12071, 13151, 14636, 17377, 18023, 32770, ...

This is sequence A057496 in [312].

40.9.6 Primitive minimum-weight and low-bit polynomials

[1,0] 17,3,0 33,13,0 49,9,0


2,1,0 18,7,0 34,8,4,3,0 50,4,3,2,0
3,1,0 19,5,2,1,0 35,2,0 51,6,3,1,0
4,1,0 20,3,0 36,11,0 52,3,0
5,2,0 21,2,0 37,6,4,1,0 53,6,2,1,0
6,1,0 22,1,0 38,6,5,1,0 54,8,6,3,0
7,1,0 23,5,0 39,4,0 55,24,0
8,4,3,2,0 24,4,3,1,0 40,5,4,3,0 56,7,4,2,0
9,4,0 25,3,0 41,3,0 57,7,0
10,3,0 26,6,2,1,0 42,7,4,3,0 58,19,0
11,2,0 27,5,2,1,0 43,6,4,3,0 59,7,4,2,0
12,6,4,1,0 28,3,0 44,6,5,2,0 60,1,0
13,4,3,1,0 29,2,0 45,4,3,1,0 61,5,2,1,0
14,5,3,1,0 30,6,4,1,0 46,8,7,6,0 62,6,5,3,0
15,1,0 31,3,0 47,5,0 63,1,0
16,5,3,2,0 32,7,6,2,0 48,9,7,4,0 64,4,3,1,0
Figure 40.9-D: Binary primitive polynomials of minimum weight.
852 Chapter 40: Binary polynomials

[1,0] 17,3,0 33,6,4,1,0 49,6,5,4,0


2,1,0 18,5,2,1,0 34,7,6,5,2,1,0 50,4,3,2,0
3,1,0 19,5,2,1,0 35,2,0 51,6,3,1,0
4,1,0 20,3,0 36,6,5,4,2,1,0 52,3,0
5,2,0 21,2,0 37,5,4,3,2,1,0 53,6,2,1,0
6,1,0 22,1,0 38,6,5,1,0 54,6,5,4,3,2,0
7,1,0 23,5,0 39,4,0 55,6,2,1,0
8,4,3,2,0 24,4,3,1,0 40,5,4,3,0 56,7,4,2,0
9,4,0 25,3,0 41,3,0 57,5,3,2,0
10,3,0 26,6,2,1,0 42,5,4,3,2,1,0 58,6,5,1,0
11,2,0 27,5,2,1,0 43,6,4,3,0 59,6,5,4,3,1,0
12,6,4,1,0 28,3,0 44,6,5,2,0 60,1,0
13,4,3,1,0 29,2,0 45,4,3,1,0 61,5,2,1,0
14,5,3,1,0 30,6,4,1,0 46,8,5,3,2,1,0 62,6,5,3,0
15,1,0 31,3,0 47,5,0 63,1,0
16,5,3,2,0 32,7,5,3,2,1,0 48,7,5,4,2,1,0 64,4,3,1,0
Figure 40.9-E: Binary primitive polynomials of small weight and nonzero coefficient at low indices.

The data in [FXT: data/minweight-primpoly.txt] lists minimal-weight PPs where in addition the coef-
ficients are as close to the low end as possible. The first entries are shown in figure 40.9-D A list of
minimal-weight PPs that fit into a machine word is given in [FXT: bpol/primpoly-minweight.cc].
By choosing those PPs where the highest nonzero coefficient is as low as possible one obtains the list in
[FXT: data/lowbit-primpoly.txt]. It starts as shown in figure 40.9-E. The corresponding extract for small
degrees is given in [FXT: bpol/primpoly-lowbit.cc]. The index (position) of the second highest nonzero
coefficient (the subdegree of the polynomial) grows slowly with n and is ≤ 12 for all n ≤ 400. So we can
store the list compactly as an array of 16-bit words.

40.9.7 All primitive low-bit polynomials for certain degrees


Pk
A list of all PPs xn + j=0 cj xj for degree n = 256 with the second-highest order k ≤ 15 (and the first
few polynomials for k = 16) is given in [FXT: data/lowbit256-primpoly.txt]. The first few are
256,10,5,2,0
256,10,8,5,4,1,0
256,10,9,8,7,4,2,1,0
256,11,8,4,3,2,0
256,11,8,6,4,3,0
256,11,10,9,4,2,0
256,11,10,9,7,4,0
256,12,7,5,4,2,0
256,12,8,7,6,3,0

Equivalent tables for degrees DEG= 63, 64, 127, 128, 256, 512, 521, 607, 1000, and 1024, can be found in
the files data/lowbitDEG-primpoly.txt (where DEG has to be replaced by the number).

40.9.8 Primitive low-block polynomials


Pk
A low-block polynomial has the special form xn + j=0 xj . Such PPs exist for 218 degrees n ≤ 400.
These are especially easy to store in an array (saving the index of the second highest nonzero coefficient
in array element n). A complete list of all low-block PPs with degree n ≤ 400 is given in [FXT: data/all-
lowblock-primpoly.txt]. A short form of the list is [FXT: data/all-lowblock-primpoly-short.txt]. Among
the low-block PPs are a few where just one bit (the coefficient after the leading coefficient) is not set.
For n ≤ 400 this is for the following degrees:
3, 5, 7, 13, 15, 23, 37, 47, 85, 127, 183, 365, 383

The PPs listed in [FXT: data/lowblock-primpoly.txt] have the smallest possible block of set bits.

40.9.9 Irreducible all-ones polynomials


Irreducible polynomials of the form xn + xn−1 + xn−2 + . . . + x + 1 (all-ones polynomials) exist whenever
n + 1 is a prime number for which 2 is a primitive root. The list of such primes up to 2000 is shown in
figure 41.7-B on page 878. The all-ones polynomials are irreducible for the following s < 400:
1, 2, 4, 10, 12, 18, 28, 36, 52, 58, 60, 66, 82, 100, 106, 130, 138, 148,
40.9: Irreducible and primitive polynomials of special forms ‡ 853

162, 172, 178, 180, 196, 210, 226, 268, 292, 316, 346, 348, 372, 378, 388

The sequence is entry A071642 in [312].


With the exception of x2 +x+1, none of the all-ones polynomials is primitive. In fact, the order of x equals
n+1, which is immediate when printing the powers of x (example using n+1 = 5, p = x4 +x3 +x2 +x+1):
k x^k
0 ...1
1 ..1.
2 .1..
3 1...
4 1111
5 ...1 == x^5 == 1

For computations modulo all-ones polynomials it is advisable to use the redundant polynomial xn+1 + 1
during the calculations:

1 + x + x2 + x3 + . . . + xn · (1 + x) = 1 + xn+1

(40.9-2)

One does all computations modulo the product (with cheap reductions) and only reduces the final result
modulo the all-ones polynomial.
The all-ones polynomials are a special case for the factorization of cyclotomic polynomials, see sec-
tion 40.11 on page 857. Irreducible polynomials of high weight are considered in [6] where irreducible
polynomials of the form (xn+1 + 1)/(x + 1) + xk up to degree 340 are given.

40.9.10 Irreducible alternating polynomials


Pd
The ‘alternating’ polynomial 1 + k=0 x2 k+1 = 1 + x + x3 + x5 . . . + x2d+1 can be irreducible only if d
is odd:
d: (irred. poly.)
1: x^3 + x + 1
3: x^7 + x^5 + x^3 + x + 1
5: x^11 + x^9 + x^7 + x^5 + x^3 + x + 1
The list up to d = 1000 (sequence A107220 in [312]) is
1, 3, 5, 7, 9, 13, 23, 27, 31, 37, 63, 69, 117, 119, 173, 219, 223,
247, 307, 363, 383, 495, 695, 987,
It can be computed (within about ten minutes) via
for(d=1,1000, p=(1+sum(t=0,d,x^(2*t+1))); if(polisirreducible(Mod(1,2)*p),print1(d,", ")))

Similar to the all-ones polynomials, a speedup can be achieved by using the redundant modulus

1 + x + x3 + x5 + . . . + xn · 1 + x2 = 1 + x + x2 + xn+2
 
(40.9-3)

40.9.11 Primitive polynomials with uniformly distributed coefficients


Primitive polynomials with (roughly) equally spaced coefficients are given in [278] for degrees from 9
to 660. Polynomials with weight 5 (pentanomials) are given in [FXT: data/eq-primpoly-w5.txt], the
polynomials around degree 500 are
498 372 247 124 0, 499 380 253 125 0, 500 378 250 127 0,
501 375 255 125 0, 502 370 240 121 0
The polynomials with weight 7 are given in [FXT: data/eq-primpoly-w7.txt], the list for weight 9 is [FXT:
data/eq-primpoly-w9.txt].

40.9.12 Irreducible self-reciprocal polynomials


A list of all irreducible self-reciprocal polynomials (see section 40.8 on page 846) up to degree 22 is given in
[FXT: data/all-irred-srp.txt]. These polynomials have even degree and none of them (with the exception
of x2 + x + 1) is primitive. The number after the percent sign with each entry in figure 40.9-F equals
(2n/2 + 1)/r where r is the order of the polynomial with degree n.
854 Chapter 40: Binary polynomials

2,1,0 % 1 14,9,7,5,0 % 1
14,10,8,7,6,4,0 % 1
14,11,10,9,8,7,6,5,4,3,0 % 3
4,3,2,1,0 % 1 14,12,10,7,4,2,0 % 3
14,12,9,8,7,6,5,2,0 % 1
14,13,10,8,7,6,4,1,0 % 1
6,3,0 % 1 14,13,11,7,3,1,0 % 3
14,13,12,11,10,9,7,5,4,3,2,1,0 % 1
14,13,12,9,8,7,6,5,2,1,0 % 1
8,5,4,3,0 % 1
8,7,6,4,2,1,0 % 1 16,15,8,1,0 % 1
16,12,11,8,5,4,0 % 1
16,13,12,10,8,6,4,3,0 % 1
10,7,5,3,0 % 1 16,13,8,3,0 % 1
10,9,5,1,0 % 1 16,14,12,11,8,5,4,2,0 % 1
10,9,8,7,6,5,4,3,2,1,0 % 3 16,14,13,11,10,9,8,7,6,5,3,2,0 % 1
16,14,13,12,10,8,6,4,3,2,0 % 1
16,14,13,12,11,9,8,7,5,4,3,2,0 % 1
12,10,7,6,5,2,0 % 1 16,15,13,11,10,8,6,5,3,1,0 % 1
12,10,9,8,6,4,3,2,0 % 1 16,15,13,12,10,9,8,7,6,4,3,1,0 % 1
12,11,10,9,8,7,6,5,4,3,2,1,0 % 5 16,15,13,9,8,7,3,1,0 % 1
12,11,9,7,6,5,3,1,0 % 1 16,15,14,12,10,8,6,4,2,1,0 % 1
12,8,7,6,5,4,0 % 1 16,15,14,13,11,10,8,6,5,3,2,1,0 % 1
16,15,14,13,12,11,8,5,4,3,2,1,0 % 1
16,15,14,13,9,8,7,3,2,1,0 % 1
16,15,14,8,2,1,0 % 1
Figure 40.9-F: Irreducible self-reciprocal polynomials up to degree 16.

m: deg polynomial fm
0: 1 11 == x + 1
1: 2 111 == x^2 + x + 1
2: 4 11111 == x^4 + x^3 + x^2 + x + 1
3: 8 111.1.111 == x^8 + x^7 + x^6 + x^4 + x^2 + x + 1
4: 16 111111..1..111111
5: 32 111.111.1.1....111....1.1.111.111
6: 64 11111...1.1.11..11..11.1.1...1111111...1.1.11..11..11.1.1...11111
7: 128 111.1.1111...1..11..1...1111.1.11.11.1.1111...1..11..1...1111.1.1 \
.1.1111...1..11..1...1111.1.11.11.1.1111...1..11..1...1111.1.111

........1.......
.........1...... == M4
..........1.....
...........1....
............1...
.............1..
..............1.
...............1
1...........1... ....1...
.1...........1.. .....1.. == M3
..1...........1. ......1.
...1...........1 .......1
....1...1.....1. 1.....1. ..1. == M2
.....1...1.....1 .1.....1 ...1
......1...1.1..1 ..1.1..1 1..1 .1 == M1
.......1...1.111 ...1.111 .111 11

Figure 40.9-G: A family fm of irreducible self-reciprocal binary polynomials (top) and matrices Mm
whose characteristic polynomials are fm (bottom).
40.9: Irreducible and primitive polynomials of special forms ‡ 855

Pn
Given an irreducible polynomial f0 (x) = k=0 ck xk where c1 = 1 and cn−1 = 1 an infinite family of
irreducible polynomials fm (x) of degrees n 2m can be given as follows [113]: for m > 0 set fm (x) =
S (fm−1 (x)) where S (p(x)) = xd p(x + 1/x) and d is the degree of p (relation 40.8-1 on page 846). The
polynomials fm are self-reciprocal for m ≥ 1. A formula for the number of degree-n polynomials suitable
as f0 is given in [260], see sequence A175390 in [312].
Starting with f0 = x + 1 we obtain the polynomials shown in figure 40.9-G. The matrices Mm whose
characteristic polynomials are fm have a simple structure.
The polynomials fm can be computed in a different way [149, p.63]: set a0 = x, b0 = 1, am+1 = am bm ,
2
and bm+1 = a2m + b2m = (am + bm ) , then fm = am + bm .

40.9.13 Irreducible normal polynomials

2,1,0 8,7,2,1,0 -9,8,0


-8,7,3,1,0 9,8,4,1,0
3,2,0 8,7,3,2,0 9,8,4,2,0
-8,7,4,3,2,1,0 9,8,4,3,2,1,0
4,3,0 -8,7,5,1,0 9,8,5,4,0
-4,3,2,1,0 8,7,5,3,0 9,8,5,4,3,1,0
-8,7,5,4,0 -9,8,6,3,0
5,4,2,1,0 -8,7,5,4,3,2,0 9,8,6,3,2,1,0
5,4,3,1,0 8,7,6,1,0 9,8,6,4,3,1,0
5,4,3,2,0 8,7,6,3,2,1,0 9,8,6,5,3,1,0
-8,7,6,4,2,1,0 9,8,6,5,3,2,0
6,5,0 -8,7,6,4,3,2,0 9,8,6,5,4,1,0
6,5,2,1,0 8,7,6,5,2,1,0 9,8,7,2,0
6,5,4,1,0 -8,7,6,5,4,1,0 9,8,7,3,2,1,0
-6,5,4,2,0 8,7,6,5,4,2,0 9,8,7,5,4,3,0
-8,7,6,5,4,3,0 9,8,7,6,2,1,0
7,6,0 9,8,7,6,3,1,0
7,6,3,1,0 9,8,7,6,4,2,0
7,6,4,1,0 9,8,7,6,4,3,0
7,6,4,2,0 9,8,7,6,5,1,0
7,6,5,2,0 9,8,7,6,5,4,3,1,0
7,6,5,3,2,1,0
7,6,5,4,2,1,0
Figure 40.9-H: All normal irreducible polynomials up to degree n = 9.

2,1,0 9,8,6,5,4,1,0 13,12,10,6,0


-9,8,6,3,0 13,12,10,7,4,3,0
3,2,0 9,8,6,3,2,1,0 13,12,10,9,8,3,2,1,0
13,12,10,9,8,6,4,1,0
10,9,8,6,3,2,0 13,12,10,9,8,7,6,4,3,2,0
5,4,2,1,0 10,9,8,5,4,3,0
-10,9,8,5,3,1,0 14,13,12,10,6,3,2,1,0
-6,5,4,2,0 10,9,8,6,4,3,0 -14,13,12,9,7,5,3,2,0
6,5,4,1,0 -14,13,12,9,8,6,5,2,0
11,10,8,7,6,5,0 14,13,12,10,8,6,5,4,2,1,0
7,6,4,1,0 11,10,8,5,2,1,0 -14,13,12,9,5,3,2,1,0
11,10,8,4,3,2,0 14,13,12,10,7,5,4,1,0
-14,13,12,10,8,4,2,1,0
14,13,12,9,8,1,0
Figure 40.9-I: All normal polynomials whose roots form a self-dual basis up to degree n = 14.

The normal irreducible polynomials are those whose roots are linearly independent (see section 42.6 on
page 900). A complete list up to degree n = 13 is given in [FXT: data/all-normalpoly.txt], figure 40.9-H
shows the polynomials up to degree n = 9 (polynomials that are not primitive are marked with a ‘-’).
Normal polynomials must have subdegree n − 1, that is, they are of the form xn + xn−1 + . . .. The
condition is necessary but not sufficient: not all irreducible polynomials of subdegree n − 1 are normal. A
list of primitive normal polynomials xn + xn−1 + . . . + xw + 1 with w as big as possible is given in [FXT:
data/highbit-normalpoly.txt]. Primitive normal polynomials xn + xn−1 + xw + . . . + 1 where w is as small
as possible are given in [FXT: data/lowbit-normalprimpoly.txt]. Every irreducible all-ones polynomial is
normal.
The polynomials fm (see figure 40.9-G) are normal for all m, they are primitve only for m = 0 and m = 1.
856 Chapter 40: Binary polynomials

All normal polynomials whose roots form a self-dual basis (see section 42.6.4 on page 908) up to degree
n = 19 are given in [FXT: data/all-irred-self-dual.txt]. The list, up to degree n = 14 is shown in figure
40.9-I. No such polynomials exist for n a multiple of 4.

40.10 Generating irreducible polynomials from Lyndon words


It is not a coincidence that the number of length-n Lyndon words (see section 18.3 on page 379) is equal to
the number of degree-n irreducible polynomials. Indeed, [95] gives an algorithm that, given one primitive
polynomial, generates an irreducible polynomial from a Lyndon word: Let b be a Lyndon word, c an
irreducible polynomial of degree n and a an element of maximal order modulo c. Set e = ab and compute
the polynomial pe (x) over GF(2n ), defined as
n−1 
x − e2 x − e4 x − e8 · · · x − e2
   
pe (x) := x−e (40.10-1)

Then all coefficients of pe (x) are either zero or one and the polynomial is irreducible over GF(2).

b e p b e p
....1 4 m ...1. .11..1 P ....1 4 m ...1. .11..1 P
...1. 4 ..1.. .11..1 P ...11 4 m .1... .11111
...11 4 m .1... .11111 ..1.1 2 m .1.11 .1.1.1 red.
..1.. 4 .1..1 .11..1 P ..111 4 m ..111 .1..11 P
..1.1 2 m .1.11 .1.1.1 red. .1111 1 m ....1 .1...1 red.
..11. 4 .1111 .11111
..111 4 m ..111 .1..11 P
.1... 4 .111. .11..1 P
.1..1 4 ..1.1 .11111
.1.1. 2 .1.1. .1.1.1 red.
.1.11 4 .11.1 .1..11 P
.11.. 4 ...11 .11111
.11.1 4 ..11. .1..11 P
.111. 4 .11.. .1..11 P
.1111 1 m ....1 .1...1 red.

Figure 40.10-A: Polynomials pe (x) for the powers e = xb of the primitive element x modulo c =
x4 + x3 + 1 (left). If only necklaces are used as exponents b, each polynomial is found only once (right).
Irreducible polynomials are obtained for aperiodic necklaces.

An implementation in C++ is given in [FXT: class necklace2bitpol in bpol/necklace2bitpol.h]:


1 class necklace2bitpol
2 {
3 public:
4 ulong p_[BITS_PER_LONG+1]; // polynomial over GF(2**n_)
5 ulong n_; // degree of c_
6 ulong c_; // modulus (irreducible polynomial)
7 ulong h_; // mask used for computation
8 ulong a_; // generator modulo c
9 ulong e_; // a^b
10
11 public:
12 necklace2bitpol(ulong n, ulong c=0, ulong a=0)
13 : n_(n), c_(c), a_(a)
14 {
15 if ( 0==c ) c_ = lowbit_primpoly[n];
16 if ( 0==a ) a_ = 2UL; // ’x’
17 h_ = (highest_one(c_) >> 1);
18 }
19
20 ~necklace2bitpol() { ; }
21
22 ulong poly(ulong b)
23 {
24 const ulong e = bitpolmod_power(a_, b, c_, h_);
25 e_ = e;
26 const ulong x = 2; // a root of the C
27 ulong s = e;
28 ulong m = 1; // minpoly
29 for (ulong j=0; j<n_; ++j)
40.11: Irreducible and cyclotomic polynomials ‡ 857

30 {
31 ulong t = x ^ s;
32 m = bitpolmod_mult(m, t, c_, h_);
33 s = bitpolmod_square(s, c_, h_);
34 }
35 bp_ = m ^ c_;
36 return bp_;
37 }
38 };
The computation of the polynomials is a variant of the second algorithm in section 42.2 on page 892.
Figure 40.10-A (left) shows all polynomials that are generated with c = x4 + x3 + 1 and the generator
a = x. This is the output of [FXT: gf2n/necklace2irred-demo.cc]. The columns are: b and its cyclic
period (symbol ‘m’ appended if the word is the cyclic minimum), e and p where a ‘P’ indicates that p is
primitive. Observe that cyclic shifts of the same word give identical polynomials p. Further, if the period
is not maximal, then p is reducible. Restricting our attention to the necklaces b we obtain each polynomial
just once (right of figure 40.10-A). The Lyndon words b give all degree-n irreducible polynomials. The
primitive polynomials are exactly those where gcd(b, 2n − 1) = 1.

degree: necklaces search


24: 276 k/sec 147 k/sec
35: 124 k/sec 64 k/sec
45: 73 k/sec 36 k/sec
63: 38 k/sec 18 k/sec
Figure 40.10-B: Rate of generation of irreducible polynomials via necklaces and with exhaustive search.

To generate all irreducible binary polynomials of fixed degree use [FXT: class all irredpoly in
bpol/all-irredpoly.h]. The usage is shown in [FXT: gf2n/all-irredpoly-demo.cc]. It turns out that the gen-
eration via exhaustive search [FXT: gf2n/bitpol-search-irred-demo.cc] is not much slower, figure 40.10-B
gives the rates of generation for various degrees and both methods.

40.11 Irreducible and cyclotomic polynomials ‡


The primitive binary polynomials of degree n can be obtained by factoring the cyclotomic polynomial
(see section 37.1.1 on page 704) YN over GF(2) where N = 2n − 1. For example, with n = 6,
? n=6; N=2^n-1; lift( factormod(polcyclo(N),2) )
[x^6 + x + 1 1]
[x^6 + x^4 + x^3 + x + 1 1]
[x^6 + x^5 + 1 1]
[x^6 + x^5 + x^2 + x + 1 1]
[x^6 + x^5 + x^3 + x^2 + 1 1]
[x^6 + x^5 + x^4 + x + 1 1]
We use a routine (pcfprint(N)) that prints the N -th cyclotomic polynomial and its factors in symbolic
form. With n = 6, N = 2n − 1 = 63 we obtain
? n=6; N=2^n-1;
? pcfprint(N)
63: [ 36 33 27 24 18 12 9 3 0 ]
[ 6 1 0 ]
[ 6 4 3 1 0 ]
[ 6 5 0 ]
[ 6 5 2 1 0 ]
[ 6 5 3 2 0 ]
[ 6 5 4 1 0 ]
The irreducible but non-primitive binary polynomials are factors of cyclotomic polynomials Yd where
d\N , d < N and the order of 2 modulo d equals n:
? fordiv(N,d,if(n==znorder(Mod(2,d)) && (d<N), pcfprint(d) ));
9: [ 6 3 0 ]
[ 6 3 0 ]
21: [ 12 11 9 8 6 4 3 1 0 ]
[ 6 4 2 1 0 ]
[ 6 5 4 2 0 ]
858 Chapter 40: Binary polynomials

The number of factors of Yd equals ϕ(d)/n so we can count how many degree-n irreducible polynomials
correspond to which divisor of N = 2n − 1:
1: [1:1] 1
2: [3:1] 1
3: [7:2] 2
4: [5:1] [15:2] 3
5: [31:6] 6
6: [9:1] [21:2] [63:6] 9
7: [127:18] 18
8: [17:2] [51:4] [85:8] [255:16] 30
9: [73:8] [511:48] 56
10: [11:1] [33:2] [93:6] [341:30] [1023:60] 99
11: [23:2] [89:8] [2047:176] 186
Line 6 tells us that one irreducible polynomial of degree 6 is due to the factor 9, two are due to the
factor 21, and the 6 primitive polynomials correspond to N = 63 itself, which we have verified a moment
ago. Further, the a polynomials corresponding to an entry [d:a] all have order d. The list was produced
using
1 { for (n=1, 11,
2 print1(n,": ");
3 s = 0;
4 N = 2^n-1;
5 fordiv (N, d,
6 if ( n==znorder(Mod(2,d)) ,
7 a = eulerphi(d)/n;
8 print1(" [",d,":",a,"] ");
9 s += a;
10 );
11 );
12 print(" ",s);
13 ); }

40.12 Factorization of binary polynomials


We give a method for the factorization of binary polynomials. The first part describes how to factorize
polynomials that do not contain a square factor. The second part gives algorithms to detect and remove
square factors. Finally, an algorithm to factorize arbitrary binary polynomials is given.

40.12.1 Factorization of square-free polynomials


A polynomial that does not contain a nontrivial square factor is called square-free. To factorize a square-
free polynomial, we will use Berlekamp’s Q-matrix algorithm described in [46]. The algorithm consists
of two main steps: the computation of the nullspace of a matrix and a refinement phase that finds the
distinct irreducible factors.
Let c be a binary polynomial of degree d. The Q-matrix is a d × d matrix whose n-th column can be
computed as the binary polynomial x2 n (mod c). The algorithm will use the nullspace of Q − id.
The routine to compute the Q-matrix is [FXT: bpol/berlekamp.cc]:
1 void
2 setup_q_matrix(ulong c, ulong d, ulong *ss)
3 // Compute the Q-matrix for the degree-d polynomial c.
4 // Used in Berlekamp’s factorization algorithm.
5 {
6 ulong h = 1UL << (d-1);
7 {
8 ulong x2 = 2UL; // == ’x’
9 ulong q = 1UL;
10 x2 = bitpolmod_mult(x2, x2, c, h);
11 for (ulong k=0; k<d; ++k)
12 {
13 ss[k] = q;
14 q = bitpolmod_mult(q, x2, c, h);
15 }
16 bitmat_transpose(ss, d, ss);
17 }
18 }
40.12: Factorization of binary polynomials 859

c = x7 + x + 1 (irreducible):
Q= Q-id= nullspace=
1...... ....... 1......
....1.. .1..1..
.1..1.. .11.1..
.....1. ...1.1.
..1..1. ..1.11.
......1 .....11
...1..1 ...1...

c = x7 + x3 + x + 1 = (x + 1) (x2 + x + 1) (x4 + x + 1) (reducible but square-free):


Q= Q-id= nullspace=
1...... ....... 1......
....1.1 .1..1.1 .1..1..
.1..1.1 .11.1.1 .1.1.11
.....1. ...1.1.
..1.111 ..1..11
......1 .....11
...1.11 ...1.1.

c = (1 + x)7 = x7 + x6 + x5 + x4 + x3 + x2 + x + 1 (not square-free):


Q= Q-id=
1...1.. ....1.. nullspace=
....... .1..... 1......
.1...1. .11..1.
....... ...1...
..1...1 ..1.1.1
....... .....1.
...1... ...1..1
Figure 40.12-A: The Q-matrices for three binary polynomials and the nullspaces of Q − id.

The Q-matrix and nullspace of Q − id for the irreducible binary polynomial c = x7 + x + 1 are shown at
the top of figure 40.12-A. The vector n0 = [1, 0, . . . , 0] lies in the nullspace of Q − id for every polynomial.
For c = x7 + x3 + x + 1 = (x + 1) (x2 + x + 1) (x4 + x + 1) the nullspace has rank three (middle of
figure 40.12-A). the rank of the nullspace equals the number of distinct irreducible factors if c is square-
free. For polynomials containing a square factor we do not get the total number of factors, the data for
c = (1 + x)7 = x7 + x6 + x5 + x4 + x3 + x2 + x + 1 is shown at the bottom of figure 40.12-A. The figure
was created with the program [FXT: gf2n/qmatrix-demo.cc].
To find the irreducible factors of c, the vectors spanning the nullspace must be post-processed. The
algorithm can be described as follows: let F be a set of binary polynomials whose product equals c, the
refinement step Ri proceeds as follows:
Let t be the i-th element of the nullspace. For each element f ∈ F do the following: if the degree of f
equals 1, keep it in the set, else remove f from the set and add from the set X = {gcd(f, t), gcd(f, t + 1)}
those elements whose degrees are greater than or equal to 1.
One starts with F = {c} and does the refinement steps R0 , R1 , . . . Rr−1 corresponding to the vectors of
the nullspace. Afterwards the set F will contain exactly the distinct irreducible factors of c. This is done
in the following routine [FXT: bpol/berlekamp.cc]:
1 ulong
2 bitpol_refine_factors(ulong *f, ulong nf, const ulong *nn, ulong r)
3 // Given the nullspace nn[0,...,r-1] of (Q-id)
4 // and nf factors f[0,...,nf-1] whose product equals c
5 // (typically nf=1 and f[0]==c)
6 // then get all r irreducible factors of c.
7 {
8 ulong ss[r];
9 for (ulong j=0; j<r; ++j) // for all elements t in nullspace
10 {
11 ulong t = nn[j];
12
13 // skip trivial elements in nullspace:
14 if ( bitpol_deg(t)==0 ) continue;
15
16 ulong sc = 0;
860 Chapter 40: Binary polynomials

17 for (ulong b=0; b<nf; ++b) // for all elements bv in set


18 {
19 ulong bv = f[b];
20 ulong db = bitpol_deg(bv);
21 if ( db <= 1 ) // bv cannot be reduced
22 {
23 ss[sc++] = bv;
24 }
25 else
26 {
27 for (ulong s=0; s<2; ++s) // for all elements in GF(2)
28 {
29 ulong ti = t ^ s;
30 ulong g = bitpol_gcd(bv, ti);
31 if ( bitpol_deg(g) >= 1 ) ss[sc++] = g;
32 }
33 }
34 }
35
36 nf = sc;
37 for (ulong k=0; k<nf; ++k) f[k] = ss[k];
38
39 if ( nf>=r ) break; // done
40 }
41
42 return nf;
43 }
We skip elements corresponding to constant polynomials. Further, as soon as the set F contains r
elements, all factors are found and the algorithm terminates.
Now Berlekamp’s algorithm can be implemented as
1 ulong
2 bitpol_factor_squarefree(ulong c, ulong *f)
3 // Fill irreducible factors of square-free polynomial c into f[]
4 // Return number of factors.
5 {
6 ulong d = bitpol_deg(c);
7
8 if ( d<=1 ) // trivial cases: 0, 1, x, x+1
9 {
10 f[0] = c;
11 if ( 0==c ) d = 1; // 0==0^1
12 return d;
13 }
14
15 ulong ss[d];
16 setup_q_matrix(c, d, ss);
17 bitmat_add_unit(ss, d);
18
19 ulong nn[d];
20 ulong r = bitmat_nullspace(ss, d, nn);
21
22
23 f[0] = c;
24 ulong nf = 1;
25 if ( r>1 ) nf = bitpol_refine_factors(f, nf, nn, r);
26
27 return r;
28 }
The algorithm for the computation of the nullspace was taken from [213], find the implementation in
[FXT: bmat/bitmat-nullspace.cc].
Berlekamp’s algorithm is given in [110] in a more general form: to factorize a polynomial with coefficients
in the finite field GF(q), set up the Q-matrix with columns xq i and set X = {gcd(f, t + 0), gcd(f, t +
1), . . . , gcd(f, t + (q − 1))} in the refinement step. The algorithm is efficient only if q is small.

40.12.2 Extracting the square-free part of a polynomial


To test whether a polynomial c has a square factor one computes g = gcd(c, c0 ) where c0 is the derivative.
If g 6= 1, then c has the square factor g: let c = a · b2 , then c0 = a0 b2 + a 2 b b0 = a0 b2 , so gcd(c, c0 ) = b2 .
The corresponding routine for binary polynomials is given in [FXT: bpol/bitpol-squarefree.h]:
40.12: Factorization of binary polynomials 861

1 inline ulong bitpol_test_squarefree(ulong c)


2 // Return 0 if polynomial is square-free
3 // else return square factor != 0
4 {
5 ulong d = bitpol_deriv(c);
6 if ( 0==d ) return (1==c ? 0 : c);
7 ulong g = bitpol_gcd(c, d);
8 return (1==g ? 0 : g);
9 }
The derivative of a binary polynomial can be computed easily [FXT: bpol/bitpol-deriv.h] (64-bit version):
1 inline ulong bitpol_deriv(ulong c)
2 // Return derivative of polynomial c
3 {
4 c &= 0xaaaaaaaaaaaaaaaaUL;
5 return (c>>1);
6 }

The coefficients at the even powers have to be cleared because derivation multiplies them with an even
factor which equals 0 modulo 2.
If the derivative of a binary polynomial is zero, then it is a perfect square or a constant polynomial:
1 inline ulong bitpol_pure_square_q(ulong c)
2 // Return whether polynomial is a pure square != 1
3 {
4 if ( 1UL==c ) return 0;
5 c &= 0xaaaaaaaaaaaaaaaaUL;
6 return (0==c);
7 }
The following routine returns zero if c is square-free. If c is has a square factor s 6= 1, then s is returned:
1 inline ulong bitpol_test_squarefree(ulong c)
2 {
3 ulong d = bitpol_deriv(c);
4 if ( 0==d ) return (1==c ? 0 : c);
5 ulong g = bitpol_gcd(c, d);
6 return (1==g ? 0 : g);
7 }
If a polynomial is a perfect square, then its square root can be computed as
1 inline ulong bitpol_pure_sqrt(ulong c)
2 {
3 ulong t = 0;
4 for (ulong mc=1,mt=1; mc; mc<<=2,mt<<=1)
5 {
6 if ( mc & c ) t |= mt;
7 }
8 return t;
9 }
A faster way to do the computation is to use the function bit_unzip0() from section 1.15 on page 38.
For the factorization algorithm for general polynomials we have to extract the product of all distinct
irreducible factors (the square-free part) from a polynomial. The following routine returns a polynomial
where the even exponents in the factorization are reduced [FXT: bpol/bitpol-squarefree.cc]:
1 ulong
2 bitpol_sreduce(ulong c)
3 {
4 ulong s = bitpol_test_squarefree(c);
5 if ( 0==s ) return c; // c is square-free
6
7 ulong f = bitpol_div(c, s);
8
9 do // here s is a pure square and s>1
10 {
11 s = bitpol_pure_sqrt(s);
12 }
13 while ( bitpol_pure_square_q(s) );
14
15 ulong g = bitpol_gcd(s, f);
16 s = bitpol_div(s, g);
862 Chapter 40: Binary polynomials

17 f = bitpol_mult(f, s);
18
19 return f;
20 }
t
With c = f · sk 2 (k odd, the factors of f and s not necessarily distinct) the returned polynomial equals
f · sk . Some examples:

a2 7→ a (40.12-1a)
a4 7 → a (40.12-1b)
a3 = a a2 7 → aa (40.12-1c)
a5 = a a4 7 → aa (40.12-1d)
a b2 7 → ab (40.12-1e)
a b b2 7 → a b b = a b2 7→ a b (40.12-1f)
t
f · sk 2 7→ f · sk (40.12-1g)

To extract the square-free part of a polynomial call the routine repeatedly until the returned polynomial
equals the input:
1 inline ulong bitpol_make_squarefree(ulong c)
2 {
3 ulong z = c, t;
4 while ( z!=(t=bitpol_sreduce(z)) ) z = t;
5 return z;
6 }
The reduction routine will be called at most log2 (n) times for a polynomial of degree n: the worst case
k
is a perfect power p = a2 −1 where 2k − 1 ≤ n. Observe that (2k − 1) = 1 + 2 (2k−1 − 1), so the reduction
k−1
routine will split p as p = a s2 7→ a s where s = a2 −1 is of the same form.

40.12.3 Factorization of arbitrary polynomials


The factorization routine for arbitrary binary polynomials extracts the square-free part f of its input c,
uses Berlekamp’s algorithm to factor f and updates the exponents according to the polynomial s = c/f .
There is just one call to the routine that computes a nullspace [FXT: bpol/bitpol-factor.cc]:
1 ulong
2 bitpol_factor(ulong c, ulong *f, ulong *e)
3 // Factorize the binary polynomial c:
4 // c = \prod_{i=0}^{fct-1}{f[i]^e[i]}
5 // The number of factors (fct) is returned.
6 {
7 ulong d = bitpol_deg(c);
8 if ( d<=1 ) // trivial cases: 0, 1, x, x+1
9 {
10 f[0] = c;
11 if ( 0==c ) d = 1; // 0==0^1
12 return d;
13 }
14
15 // get square-free part:
16 ulong cf = bitpol_make_squarefree(c);
17
18 // ... and factor it:
19 ulong fct = bitpol_factor_squarefree(cf, f);
20
21 // All exponents are one:
22 for (ulong j=0; j<fct; ++j) { e[j] = 1; }
23
24 // Here f[],e[] is a valid factorization of the square-free part cf
25
26 // Update exponents with square part:
27 ulong cs = bitpol_div(c, cf);
28 for (ulong j=0; j<fct; ++j)
29 {
30 if ( 1==cs ) break;
40.12: Factorization of binary polynomials 863

31 ulong fj = f[j];
32 ulong g = bitpol_gcd(cs, fj);
33 while ( 1!=g )
34 {
35 ++e[j];
36 cs = bitpol_div(cs, fj);
37 if ( 1==cs ) break;
38 g = bitpol_gcd(cs, fj);
39 }
40 }
41
42 return fct;
43 }

0: x^5 == (x)^5
1: x^5 +1 == (x+1) * (x^4+x^3+x^2+x+1)
2: x^5 +x == (x) * (x+1)^4
3: x^5 +x+1 == (x^2+x+1) * (x^3+x^2+1)
4: x^5 +x^2 == (x)^2 * (x+1) * (x^2+x+1)
5: x^5 +x^2 +1 == (x^5+x^2+1)
6: x^5 +x^2+x == (x) * (x^4+x+1)
7: x^5 +x^2+x+1 == (x+1)^2 * (x^3+x+1)
8: x^5 +x^3 == (x)^3 * (x+1)^2
9: x^5 +x^3 +1 == (x^5+x^3+1)
10: x^5 +x^3 +x == (x) * (x^2+x+1)^2
11: x^5 +x^3 +x+1 == (x+1) * (x^4+x^3+1)
12: x^5 +x^3+x^2 == (x)^2 * (x^3+x+1)
13: x^5 +x^3+x^2 +1 == (x+1)^3 * (x^2+x+1)
14: x^5 +x^3+x^2+x == (x) * (x+1) * (x^3+x^2+1)
15: x^5 +x^3+x^2+x+1 == (x^5+x^3+x^2+x+1)
16: x^5+x^4 == (x)^4 * (x+1)
17: x^5+x^4 +1 == (x^2+x+1) * (x^3+x+1)
18: x^5+x^4 +x == (x) * (x^4+x^3+1)
19: x^5+x^4 +x+1 == (x+1)^5
20: x^5+x^4 +x^2 == (x)^2 * (x^3+x^2+1)
21: x^5+x^4 +x^2 +1 == (x+1) * (x^4+x+1)
22: x^5+x^4 +x^2+x == (x) * (x+1)^2 * (x^2+x+1)
23: x^5+x^4 +x^2+x+1 == (x^5+x^4+x^2+x+1)
24: x^5+x^4+x^3 == (x)^3 * (x^2+x+1)
25: x^5+x^4+x^3 +1 == (x+1)^2 * (x^3+x^2+1)
26: x^5+x^4+x^3 +x == (x) * (x+1) * (x^3+x+1)
27: x^5+x^4+x^3 +x+1 == (x^5+x^4+x^3+x+1)
28: x^5+x^4+x^3+x^2 == (x)^2 * (x+1)^3
29: x^5+x^4+x^3+x^2 +1 == (x^5+x^4+x^3+x^2+1)
30: x^5+x^4+x^3+x^2+x == (x) * (x^4+x^3+x^2+x+1)
31: x^5+x^4+x^3+x^2+x+1 == (x+1) * (x^2+x+1)^2
Figure 40.12-B: Factorizations of the binary polynomials of degree 5.

Figure 40.12-B shows the factorizations of the binary polynomials of degree 5. It was created with the
program [FXT: gf2n/bitpolfactor-demo.cc]. Factoring the first million polynomials of degrees 20, 30, 40
and 60 takes about 5, 10, 15 and 30 seconds, respectively.
A variant of the factorization algorithm often given uses the square-free factorization c = i aii where
Q
the polynomials ai are square-free and pair-wise coprime. Given the square-free factorization one has to
call the core routine for each nontrivial ai .
As noted, the refinement step becomes expensive if the coefficients are in a field GF(q) where q is not
small because q computations of the polynomial gcd are involved. For an algorithm that is efficient also
for large values of q see [110] or [154, ch.14]. A ‘baby step/giant step’ method is given in [308].

You might also like