11
22function HermiteReduce (f:: AbstractAlgebra.ResFieldElem{P} , DE:: AlgebraicExtensionDerivation ) where
3- {T<: FieldElement , P<: PolyElem{T} }
3+ {T<: FieldElement , P<: PolyElem{T} }
4+ # "Lazy" Hermite reduction, see Section 2.1 of:
5+ # Manuel Bronstein. Symbolic integration tutorial. ISSAC’98, 1998.
46 iscompatible (f, DE) || error (" rational function f must be in the domain of derivation D" )
57
68 E = parent (f)
@@ -10,10 +12,10 @@ function HermiteReduce(f::AbstractAlgebra.ResFieldElem{P}, DE::AlgebraicExtensio
1012 n = degree (p)
1113 M_n_n = MatrixSpace (F, n, n)
1214 M_n = MatrixSpace (F, n, 1 )
13-
1415 g = zero (E)
1516
1617 if all ([iszero (coeff (p, j)) for j= 1 : n- 1 ]) # simple radical extension
18+ # Simpler method for simple radical extensions, see Section 2.2. of Bronstein's tutorial.
1719 @assert isone (leading_coefficient (p))
1820 a = constant_coefficient (p)
1921 A = numerator (a)
@@ -128,4 +130,73 @@ function HermiteReduce(f::AbstractAlgebra.ResFieldElem{P}, DE::AlgebraicExtensio
128130 ws = [sum ([C[i,j]* ws[j] for j= 1 : n])* 1 // F for i= 1 : n]
129131 Winv = inv (M_n_n ([coeff (data (w), j) for j= 0 : n- 1 , w in ws]))
130132 end
133+ end
134+
135+
136+ function IntegralBasis (E:: AbstractAlgebra.ResField{P} ) where {T<: FieldElement , P<: PolyElem{T} }
137+ # Trager's algorithm, see Chapter 2 of
138+ # B.M. Trager. On the integration of algebraic functions. PhD thesis, MIT, Computer Science, 1984.
139+ Ky = base_ring (E)
140+ K = base_ring (Ky)
141+ y = E (gen (Ky))
142+ f = modulus (E)
143+ n = degree (f)
144+ M_n_n = MatrixSpace (K, n, n)
145+ MP_n_n = MatrixSpace (base_ring (K), n, n)
146+ D = resultant (f, derivative (f))
147+ println ()
148+ @assert isone (denominator (D))
149+ D = numerator (D)
150+ D = 1 // leading_coefficient (D) * D
151+ k = D
152+ bs = [y^ j for j= 0 : n- 1 ]
153+ B = M_n_n ([coeff (data (bs[j]), i) for i= 0 : n- 1 , j= 1 : n])
154+ while true
155+ Ds = SI. Squarefree (D)
156+ if length (Ds)< 2
157+ return bs
158+ end
159+ Q = gcd (prod (SI. Squarefree (D)[2 : end ]), k)
160+ if degree (Q)<= 0
161+ return bs
162+ end
163+
164+ # Compute J, the Q-trace radical of V
165+ ZE = zero (E)
166+ S = [p<= q ? bs[p]* bs[q] : ZE for p= 1 : n, q= 1 : n] # only upper triangle needed
167+ ZK = zero (K)
168+ # TODO : optimize computation of TM, which is one of the bottlenecks.
169+ # Compute only upper triangle of TM, lower triangle by symmetry:
170+ TM = [p<= q ? numerator (sum ([coeff (data (S[p,q]* y^ j), j) for j= 0 : n- 1 ])) : ZK for p= 1 : n, q= 1 : n]
171+ for p= 1 : n
172+ for q= 1 : p- 1
173+ TM[p,q]= TM[q,p]
174+ end
175+ end
176+ H = hnf (vcat (MP_n_n (TM), MP_n_n (Q)))[1 : n,:] # Hermite normal form
177+ J = inv (map (x-> x// 1 , H)) # map(x->x/1, H) is H as element in FractionField
178+
179+ # Compute the idealizer of J
180+ JB = J* B
181+ ms = [E (Ky (reshape (Matrix (JB[:,k]), n))) for k= 1 : n]
182+ Minv = inv (M_n_n ([coeff (data (m), i) for i= 0 : n- 1 , m in ms]))
183+ MM = 0
184+ for k= 1 : n
185+ mbs = [data (ms[k]* b) for b in bs]
186+ Mk = Minv* M_n_n ([coeff (mbs[j], i) for i= 0 : n- 1 , j= 1 : n])
187+ MM = k== 1 ? Mk : vcat (MM, Mk)
188+ end
189+ Mhat = hnf (map (x-> numerator (x), MM))[1 : n,:] # Hermite normal form
190+ Mhatinv = inv (map (x-> x// 1 , Mhat))
191+ k = det (Mhat)
192+
193+ if degree (k)<= 0 # is k a unit ?
194+ return bs
195+ end
196+
197+ # Update bs by applying the change of basis
198+ B = transpose (Mhatinv)* B
199+ bs = [E (Ky (reshape (Matrix (B[:,k]), n))) for k= 1 : n]
200+ D = divexact (D, k^ 2 )
201+ end
131202end
0 commit comments