:: Primitive Roots of Unity and Cyclotomic Polynomials
:: by Broderick Arneson and Piotr Rudnicki
::
:: Copyright (c) 2003-2021 Association of Mizar Users

Lm1: for k being Element of NAT holds
( not k is zero iff 1 <= k )

proof end;

scheme :: UNIROOTS:sch 1
CompIndNE{ P1[ non zero Nat] } :
for k being non zero Element of NAT holds P1[k]
provided
A1: for k being non zero Element of NAT st ( for n being non zero Element of NAT st n < k holds
P1[n] ) holds
P1[k]
proof end;

theorem Th1: :: UNIROOTS:1
for f being FinSequence st 1 <= len f holds
f | (Seg 1) = <*(f . 1)*>
proof end;

Lm2: for f being FinSequence
for n, i being Element of NAT st i <= n holds
(f | (Seg n)) | (Seg i) = f | (Seg i)

by ;

theorem Th2: :: UNIROOTS:2
for f being FinSequence of F_Complex
for g being FinSequence of REAL st len f = len g & ( for i being Element of NAT st i in dom f holds
|.(f /. i).| = g . i ) holds
|.().| = Product g
proof end;

theorem Th3: :: UNIROOTS:3
for s being non empty finite Subset of F_Complex
for x being Element of F_Complex
for r being FinSequence of REAL st len r = card s & ( for i being Element of NAT
for c being Element of F_Complex st i in dom r & c = () . i holds
r . i = |.(x - c).| ) holds
|.(eval ((poly_with_roots ((s,1) -bag)),x)).| = Product r
proof end;

theorem Th4: :: UNIROOTS:4
for f being FinSequence of F_Complex st ( for i being Element of NAT st i in dom f holds
f . i is integer ) holds
Sum f is integer
proof end;

theorem :: UNIROOTS:5
for x, y being Element of F_Complex
for r1, r2 being Real st r1 = x & r2 = y holds
( r1 * r2 = x * y & r1 + r2 = x + y ) ;

theorem Th6: :: UNIROOTS:6
for q being Real st q > 0 holds
for r being Element of F_Complex st |.r.| = 1 & r <> [**1,0**] holds
|.([**q,0**] - r).| > q - 1
proof end;

theorem Th7: :: UNIROOTS:7
for ps being non empty FinSequence of REAL
for x being Real st x >= 1 & ( for i being Element of NAT st i in dom ps holds
ps . i > x ) holds
Product ps > x
proof end;

theorem Th8: :: UNIROOTS:8
for n being Element of NAT holds 1_ F_Complex = . ((),n)
proof end;

theorem Th9: :: UNIROOTS:9
for n, i being Nat holds
( cos (((2 * PI) * i) / n) = cos (((2 * PI) * (i mod n)) / n) & sin (((2 * PI) * i) / n) = sin (((2 * PI) * (i mod n)) / n) )
proof end;

theorem Th10: :: UNIROOTS:10
for n, i being Nat holds [**(cos (((2 * PI) * i) / n)),(sin (((2 * PI) * i) / n))**] = [**(cos (((2 * PI) * (i mod n)) / n)),(sin (((2 * PI) * (i mod n)) / n))**]
proof end;

theorem Th11: :: UNIROOTS:11
for n, i, j being Element of NAT holds [**(cos (((2 * PI) * i) / n)),(sin (((2 * PI) * i) / n))**] * [**(cos (((2 * PI) * j) / n)),(sin (((2 * PI) * j) / n))**] = [**(cos (((2 * PI) * ((i + j) mod n)) / n)),(sin (((2 * PI) * ((i + j) mod n)) / n))**]
proof end;

theorem Th12: :: UNIROOTS:12
for L being non empty unital associative multMagma
for x being Element of L
for n, m being Nat holds () . (x,(n * m)) = () . ((() . (x,n)),m)
proof end;

theorem Th13: :: UNIROOTS:13
for n being Element of NAT
for x being Element of F_Complex st x is Integer holds
. (x,n) is Integer
proof end;

theorem Th14: :: UNIROOTS:14
for F being FinSequence of F_Complex st ( for i being Element of NAT st i in dom F holds
F . i is Integer ) holds
Sum F is Integer
proof end;

Lm3:
by MOD_2:def 20;

registration
existence
ex b1 being Field st b1 is finite
by ;
existence
ex b1 being Skew-Field st b1 is finite
by ;
end;

definition
let R be Skew-Field;
func MultGroup R -> strict Group means :Def1: :: UNIROOTS:def 1
( the carrier of it = NonZero R & the multF of it = the multF of R || the carrier of it );
existence
ex b1 being strict Group st
( the carrier of b1 = NonZero R & the multF of b1 = the multF of R || the carrier of b1 )
proof end;
uniqueness
for b1, b2 being strict Group st the carrier of b1 = NonZero R & the multF of b1 = the multF of R || the carrier of b1 & the carrier of b2 = NonZero R & the multF of b2 = the multF of R || the carrier of b2 holds
b1 = b2
;
end;

:: deftheorem Def1 defines MultGroup UNIROOTS:def 1 :
for R being Skew-Field
for b2 being strict Group holds
( b2 = MultGroup R iff ( the carrier of b2 = NonZero R & the multF of b2 = the multF of R || the carrier of b2 ) );

theorem :: UNIROOTS:15
for R being Skew-Field holds the carrier of R = the carrier of () \/ {(0. R)}
proof end;

theorem Th16: :: UNIROOTS:16
for R being Skew-Field
for a, b being Element of R
for c, d being Element of () st a = c & b = d holds
c * d = a * b
proof end;

theorem Th17: :: UNIROOTS:17
for R being Skew-Field holds 1_ R = 1_ ()
proof end;

registration
let R be finite Skew-Field;
correctness
coherence ;
proof end;
end;

theorem :: UNIROOTS:18
for R being finite Skew-Field holds card () = (card R) - 1
proof end;

theorem Th19: :: UNIROOTS:19
for R being Skew-Field
for s being set st s in the carrier of () holds
s in the carrier of R
proof end;

theorem :: UNIROOTS:20
for R being Skew-Field holds the carrier of () c= the carrier of R
proof end;

definition
let n be non zero Element of NAT ;
func n -roots_of_1 -> Subset of F_Complex equals :: UNIROOTS:def 2
{ x where x is Element of F_Complex : x is CRoot of n, 1_ F_Complex } ;
coherence
{ x where x is Element of F_Complex : x is CRoot of n, 1_ F_Complex } is Subset of F_Complex
proof end;
end;

:: deftheorem defines -roots_of_1 UNIROOTS:def 2 :
for n being non zero Element of NAT holds n -roots_of_1 = { x where x is Element of F_Complex : x is CRoot of n, 1_ F_Complex } ;

theorem Th21: :: UNIROOTS:21
for n being non zero Element of NAT
for x being Element of F_Complex holds
( x in n -roots_of_1 iff x is CRoot of n, 1_ F_Complex )
proof end;

theorem Th22: :: UNIROOTS:22
for n being non zero Element of NAT holds 1_ F_Complex in n -roots_of_1
proof end;

theorem Th23: :: UNIROOTS:23
for n being non zero Element of NAT
for x being Element of F_Complex st x in n -roots_of_1 holds
|.x.| = 1
proof end;

theorem Th24: :: UNIROOTS:24
for n being non zero Element of NAT
for x being Element of F_Complex holds
( x in n -roots_of_1 iff ex k being Element of NAT st x = [**(cos (((2 * PI) * k) / n)),(sin (((2 * PI) * k) / n))**] )
proof end;

theorem Th25: :: UNIROOTS:25
for n being non zero Element of NAT
for x, y being Element of COMPLEX st x in n -roots_of_1 & y in n -roots_of_1 holds
x * y in n -roots_of_1
proof end;

theorem Th26: :: UNIROOTS:26
for n being non zero Element of NAT holds n -roots_of_1 = { [**(cos (((2 * PI) * k) / n)),(sin (((2 * PI) * k) / n))**] where k is Element of NAT : k < n }
proof end;

theorem Th27: :: UNIROOTS:27
for n being non zero Element of NAT holds card () = n
proof end;

registration
let n be non zero Element of NAT ;
cluster n -roots_of_1 -> non empty ;
correctness
coherence
not n -roots_of_1 is empty
;
by Th22;
correctness
coherence ;
proof end;
end;

theorem Th28: :: UNIROOTS:28
for n, ni being non zero Element of NAT st ni divides n holds
ni -roots_of_1 c= n -roots_of_1
proof end;

theorem Th29: :: UNIROOTS:29
for R being Skew-Field
for x being Element of ()
for y being Element of R st y = x holds
for k being Nat holds (power ()) . (x,k) = () . (y,k)
proof end;

theorem Th30: :: UNIROOTS:30
for n being non zero Element of NAT
for x being Element of st x in n -roots_of_1 holds
not x is being_of_order_0
proof end;

theorem Th31: :: UNIROOTS:31
for n being non zero Element of NAT
for k being Element of NAT
for x being Element of st x = [**(cos (((2 * PI) * k) / n)),(sin (((2 * PI) * k) / n))**] holds
ord x = n div (k gcd n)
proof end;

theorem Th32: :: UNIROOTS:32
for n being non zero Element of NAT holds n -roots_of_1 c= the carrier of
proof end;

theorem :: UNIROOTS:33
for n being non zero Element of NAT ex x being Element of st ord x = n
proof end;

theorem Th34: :: UNIROOTS:34
for n being non zero Element of NAT
for x being Element of holds
( ord x divides n iff x in n -roots_of_1 )
proof end;

theorem Th35: :: UNIROOTS:35
for n being non zero Element of NAT holds n -roots_of_1 = { x where x is Element of : ord x divides n }
proof end;

theorem Th36: :: UNIROOTS:36
for n being non zero Element of NAT
for x being set holds
( x in n -roots_of_1 iff ex y being Element of st
( x = y & ord y divides n ) )
proof end;

definition
let n be non zero Element of NAT ;
func n -th_roots_of_1 -> strict Group means :Def3: :: UNIROOTS:def 3
( the carrier of it = n -roots_of_1 & the multF of it = the multF of F_Complex || () );
existence
ex b1 being strict Group st
( the carrier of b1 = n -roots_of_1 & the multF of b1 = the multF of F_Complex || () )
proof end;
uniqueness
for b1, b2 being strict Group st the carrier of b1 = n -roots_of_1 & the multF of b1 = the multF of F_Complex || () & the carrier of b2 = n -roots_of_1 & the multF of b2 = the multF of F_Complex || () holds
b1 = b2
;
end;

:: deftheorem Def3 defines -th_roots_of_1 UNIROOTS:def 3 :
for n being non zero Element of NAT
for b2 being strict Group holds
( b2 = n -th_roots_of_1 iff ( the carrier of b2 = n -roots_of_1 & the multF of b2 = the multF of F_Complex || () ) );

theorem :: UNIROOTS:37
for n being non zero Element of NAT holds n -th_roots_of_1 is Subgroup of MultGroup F_Complex
proof end;

definition
let n be non zero Nat;
let L be non empty left_unital doubleLoopStr ;
func unital_poly (L,n) -> Polynomial of L equals :: UNIROOTS:def 4
((0_. L) +* (0,(- (1_ L)))) +* (n,(1_ L));
coherence
((0_. L) +* (0,(- (1_ L)))) +* (n,(1_ L)) is Polynomial of L
proof end;
end;

:: deftheorem defines unital_poly UNIROOTS:def 4 :
for n being non zero Nat
for L being non empty left_unital doubleLoopStr holds unital_poly (L,n) = ((0_. L) +* (0,(- (1_ L)))) +* (n,(1_ L));

Lm4: unital_poly (F_Complex,1) = <%(- ()),()%>
;

theorem Th38: :: UNIROOTS:38
for L being non empty left_unital doubleLoopStr
for n being non zero Element of NAT holds
( (unital_poly (L,n)) . 0 = - (1_ L) & (unital_poly (L,n)) . n = 1_ L )
proof end;

theorem Th39: :: UNIROOTS:39
for L being non empty left_unital doubleLoopStr
for n being non zero Nat
for i being Nat st i <> 0 & i <> n holds
(unital_poly (L,n)) . i = 0. L
proof end;

theorem Th40: :: UNIROOTS:40
for L being non empty non degenerated well-unital doubleLoopStr
for n being non zero Element of NAT holds len (unital_poly (L,n)) = n + 1
proof end;

registration
let L be non empty non degenerated well-unital doubleLoopStr ;
let n be non zero Element of NAT ;
cluster unital_poly (L,n) -> non-zero ;
correctness
coherence
unital_poly (L,n) is non-zero
;
proof end;
end;

theorem Th41: :: UNIROOTS:41
for n being non zero Element of NAT
for x being Element of F_Complex holds eval ((),x) = ( . (x,n)) - 1
proof end;

theorem Th42: :: UNIROOTS:42
for n being non zero Element of NAT holds Roots () = n -roots_of_1
proof end;

theorem Th43: :: UNIROOTS:43
for n being Element of NAT
for z being Element of F_Complex st z is Real holds
ex x being Real st
( x = z & . (z,n) = x |^ n )
proof end;

theorem Th44: :: UNIROOTS:44
for n being non zero Element of NAT
for x being Real ex y being Element of F_Complex st
( y = x & eval ((),y) = (x |^ n) - 1 )
proof end;

theorem Th45: :: UNIROOTS:45
for n being non zero Element of NAT holds BRoots () = ((),1) -bag
proof end;

theorem Th46: :: UNIROOTS:46
for n being non zero Element of NAT holds unital_poly (F_Complex,n) = poly_with_roots (((),1) -bag)
proof end;

theorem Th47: :: UNIROOTS:47
for n being non zero Element of NAT
for i being Element of F_Complex st i is Integer holds
eval ((),i) is Integer
proof end;

definition
let d be non zero Nat;
func cyclotomic_poly d -> Polynomial of F_Complex means :Def5: :: UNIROOTS:def 5
ex s being non empty finite Subset of F_Complex st
( s = { y where y is Element of : ord y = d } & it = poly_with_roots ((s,1) -bag) );
existence
ex b1 being Polynomial of F_Complex ex s being non empty finite Subset of F_Complex st
( s = { y where y is Element of : ord y = d } & b1 = poly_with_roots ((s,1) -bag) )
proof end;
uniqueness
for b1, b2 being Polynomial of F_Complex st ex s being non empty finite Subset of F_Complex st
( s = { y where y is Element of : ord y = d } & b1 = poly_with_roots ((s,1) -bag) ) & ex s being non empty finite Subset of F_Complex st
( s = { y where y is Element of : ord y = d } & b2 = poly_with_roots ((s,1) -bag) ) holds
b1 = b2
;
end;

:: deftheorem Def5 defines cyclotomic_poly UNIROOTS:def 5 :
for d being non zero Nat
for b2 being Polynomial of F_Complex holds
( b2 = cyclotomic_poly d iff ex s being non empty finite Subset of F_Complex st
( s = { y where y is Element of : ord y = d } & b2 = poly_with_roots ((s,1) -bag) ) );

theorem Th48: :: UNIROOTS:48
cyclotomic_poly 1 = <%(- ()),()%>
proof end;

theorem Th49: :: UNIROOTS:49
for n being non zero Element of NAT
for f being FinSequence of the carrier of st len f = n & ( for i being non zero Element of NAT st i in dom f holds
( ( not i divides n implies f . i = ) & ( i divides n implies f . i = cyclotomic_poly i ) ) ) holds
unital_poly (F_Complex,n) = Product f
proof end;

theorem Th50: :: UNIROOTS:50
for n being non zero Element of NAT ex f being FinSequence of the carrier of ex p being Polynomial of F_Complex st
( p = Product f & dom f = Seg n & ( for i being non zero Element of NAT st i in Seg n holds
( ( ( not i divides n or i = n ) implies f . i = ) & ( i divides n & i <> n implies f . i = cyclotomic_poly i ) ) ) & unital_poly (F_Complex,n) = () *' p )
proof end;

theorem Th51: :: UNIROOTS:51
for d being non zero Element of NAT
for i being Element of NAT holds
( ( () . 0 = 1 or () . 0 = - 1 ) & () . i is integer )
proof end;

theorem Th52: :: UNIROOTS:52
for d being non zero Element of NAT
for z being Element of F_Complex st z is Integer holds
eval ((),z) is Integer
proof end;

theorem Th53: :: UNIROOTS:53
for n, ni being non zero Element of NAT
for f being FinSequence of the carrier of
for s being finite Subset of F_Complex st s = { y where y is Element of : ( ord y divides n & not ord y divides ni & ord y <> n ) } & dom f = Seg n & ( for i being non zero Element of NAT st i in dom f holds
( ( ( not i divides n or i divides ni or i = n ) implies f . i = ) & ( i divides n & not i divides ni & i <> n implies f . i = cyclotomic_poly i ) ) ) holds
Product f = poly_with_roots ((s,1) -bag)
proof end;

theorem Th54: :: UNIROOTS:54
for n, ni being non zero Element of NAT st ni < n & ni divides n holds
ex f being FinSequence of the carrier of ex p being Polynomial of F_Complex st
( p = Product f & dom f = Seg n & ( for i being non zero Element of NAT st i in Seg n holds
( ( ( not i divides n or i divides ni or i = n ) implies f . i = ) & ( i divides n & not i divides ni & i <> n implies f . i = cyclotomic_poly i ) ) ) & unital_poly (F_Complex,n) = ((unital_poly (F_Complex,ni)) *' ()) *' p )
proof end;

theorem Th55: :: UNIROOTS:55
for i being Integer
for c being Element of F_Complex
for f being FinSequence of the carrier of
for p being Polynomial of F_Complex st p = Product f & c = i & ( for i being non zero Element of NAT holds
( not i in dom f or f . i = or f . i = cyclotomic_poly i ) ) holds
eval (p,c) is integer
proof end;

theorem Th56: :: UNIROOTS:56
for n being non zero Element of NAT
for j, k, q being Integer
for qc being Element of F_Complex st qc = q & j = eval ((),qc) & k = eval ((),qc) holds
j divides k
proof end;

theorem Th57: :: UNIROOTS:57
for n, ni being non zero Element of NAT
for q being Integer st ni < n & ni divides n holds
for qc being Element of F_Complex st qc = q holds
for j, k, l being Integer st j = eval ((),qc) & k = eval ((),qc) & l = eval ((unital_poly (F_Complex,ni)),qc) holds
j divides k div l
proof end;

theorem :: UNIROOTS:58
for n, q being non zero Element of NAT
for qc being Element of F_Complex st qc = q holds
for j being Integer st j = eval ((),qc) holds
j divides (q |^ n) - 1
proof end;

theorem :: UNIROOTS:59
for n, ni, q being non zero Element of NAT st ni < n & ni divides n holds
for qc being Element of F_Complex st qc = q holds
for j being Integer st j = eval ((),qc) holds
j divides ((q |^ n) - 1) div ((q |^ ni) - 1)
proof end;

theorem :: UNIROOTS:60
for n being non zero Element of NAT st 1 < n holds
for q being Element of NAT st 1 < q holds
for qc being Element of F_Complex st qc = q holds
for i being Integer st i = eval ((),qc) holds
|.i.| > q - 1
proof end;