1+
2+ function HermiteReduce (f:: AbstractAlgebra.ResFieldElem{P} , DE:: AlgebraicExtensionDerivation ) where
3+ {T<: FieldElement , P<: PolyElem{T} }
4+ iscompatible (f, DE) || error (" rational function f must be in the domain of derivation D" )
5+
6+ E = parent (f)
7+ F = base_ring (base_ring (E))
8+ y = E (gen (base_ring (E)))
9+ p = modulus (E)
10+ n = degree (p)
11+ M_n_n = MatrixSpace (F, n, n)
12+ M_n = MatrixSpace (F, n, 1 )
13+
14+ g = zero (E)
15+
16+ if all ([iszero (coeff (p, j)) for j= 1 : n- 1 ]) # simple radical extension
17+ @assert isone (leading_coefficient (p))
18+ a = constant_coefficient (p)
19+ A = numerator (a)
20+ D = denominator (a)
21+ As = Squarefree (A* D^ (n- 1 ))
22+ k = length (As)
23+ qrs = [divrem (i, n) for i= 1 : k]
24+ qs = [q for (q, r) in qrs]
25+ rs = [r for (q, r) in qrs]
26+ F = prod ([As[i]^ qs[i] for i= 1 : k])
27+ H = prod ([As[i]^ rs[i] for i= 1 : k])
28+ z = y* D// F
29+ Hs = Squarefree (H)
30+ m = length (Hs)
31+ ws = [z^ (i- 1 )* 1 // prod ([Hs[j]^ div ((i- 1 )* j, n) for j= 1 : m]) for i= 1 : n]
32+ Ds = [prod ([Hs[j]^ div ((i- 1 )* j, n) for j= 1 : m]) for i= 1 : n] # note: index shift in i
33+ dDs_over_Ds = [derivative (D)// D for D in Ds]
34+ dH_over_H = derivative (H)// H
35+ Winv = inv (M_n_n ([coeff (data (w), j) for j= 0 : n- 1 , w in ws]))
36+ while true
37+ fs = Winv* M_n ([coeff (data (f), i) for i= 0 : n- 1 ])
38+ D = lcm (denominator .(fs)[:,1 ])
39+ As = [numerator (f* D) for f in fs]
40+ if degree (gcd (D, derivative (D)))<= 0 # D squarefree?
41+ return g, f, ws, As, D
42+ end
43+
44+ Ds1 = Squarefree (D) # "Ds1" because "Ds" already in use and needed below
45+ m = length (Ds1)
46+ V = Ds1[m]
47+ U = divexact (D, V^ m)
48+ dV = derivative (V)
49+
50+ fs = [As[i]// (U* (V* ((i- 1 )// n* dH_over_H - dDs_over_Ds[i]) - (m- 1 )* dV)) for i= 1 : n]
51+ Q = lcm (denominator .(fs)[:,1 ])
52+ Ts = [numerator (f* Q) for f in fs]
53+ _, _, R = gcdx (V, Q)
54+ B = sum ([rem (R* Ts[i], V)* ws[i] for i= 1 : n])* 1 // V^ (m - 1 )
55+ g += B
56+ f -= DE (B)
57+ end
58+ end
59+
60+ ws = [y^ j for j= 0 : n- 1 ]
61+ Winv = M_n_n (1 )
62+
63+ while true
64+ fs = Winv* M_n ([coeff (data (f), i) for i= 0 : n- 1 ])
65+ D = lcm (denominator .(fs)[:,1 ])
66+ As = [numerator (f* D) for f in fs]
67+ if degree (gcd (D, derivative (D)))<= 0 # D squarefree?
68+ return g, f, ws, As, D
69+ end
70+
71+ Ds = Squarefree (D)
72+ m = length (Ds)
73+ V = Ds[m]
74+ U = divexact (D, V^ m)
75+
76+ Ss = [U* V^ m* DE (w* 1 // V^ (m- 1 )) for w in ws]
77+
78+ SM = M_n_n ([coeff (data (S), j) for j= 0 : n- 1 , S in Ss])
79+ d, N = nullspace (SM)
80+ if d> 0 # Theorem 1
81+ _, N = nullspace (SM)
82+ w0 = U// V* sum (N[i,1 ]* ws[i] for i= 1 : n)
83+ else
84+ fs = solve (SM, M_n (As))
85+ Q = lcm (denominator .(fs)[:,1 ])
86+ Ts = [numerator (f* Q) for f in fs]
87+ w0 = zero (parent (f))
88+ gcdVQ = gcd (V, Q)
89+ if degree (gcdVQ)>= 1 # Theorem 2
90+ w0 = U* divexact (V, gcdVQ)// gcdVQ* sum ([Ts[i]* ws[i] for i= 1 : n])
91+ else
92+ j = 1
93+ while j<= n
94+ dw = DE (ws[j])
95+ dws = Winv* M_n ([coeff (data (dw), i) for i= 0 : n- 1 ])
96+ F = lcm (denominator .(dws)[:,1 ])
97+ if degree (gcd (F, derivative (F)))>= 1 # denominator F of ws[j]' not squarefree, apply Theorem 3
98+ w0 = prod (Squarefree (F))* dw
99+ break
100+ end
101+ j += 1
102+ end
103+ if j> n # all denominators of the ws[j]' squarefree, do the reduction
104+ _, _, R = gcdx (V, Q)
105+ B = sum ([rem (R* Ts[i], V)* ws[i] for i= 1 : n])* 1 // V^ (m - 1 )
106+ g += B
107+ f -= DE (B)
108+ ws = [y^ j for j= 0 : n- 1 ]
109+ Winv = M_n_n (1 )
110+ continue
111+ end
112+ end
113+ end
114+
115+ C0s = solve (M_n_n ([coeff (data (w), j) for j= 0 : n- 1 , w in ws]), M_n ([coeff (data (w0), i) for i= 0 : n- 1 ]))
116+ F = lcm (denominator .(C0s)[:,1 ])
117+ Cs = [numerator (C0* F) for C0 in C0s]
118+
119+ C = zero_matrix (parent (F), n+ 1 , n)
120+ for j= 1 : n
121+ C[j,j] = F
122+ end
123+ for j= 1 : n
124+ C[n+ 1 ,j] = Cs[j]
125+ end
126+ C = hnf (C)
127+
128+ ws = [sum ([C[i,j]* ws[j] for j= 1 : n])* 1 // F for i= 1 : n]
129+ Winv = inv (M_n_n ([coeff (data (w), j) for j= 0 : n- 1 , w in ws]))
130+ end
131+ end
0 commit comments