@@ -44,7 +44,7 @@ function AlgebraicNumber(a::Complex)
4444 id = 2
4545 ca = conj (ca)
4646 end
47- AlgebraicNumber (x^ 2 - 2 * ra * x + ia^ 2 + ra^ 2 , [ca, conj (ca)], id, a, NOCHECK)
47+ AlgebraicNumber (x^ 2 - 2 * ra * x + ia^ 2 + ra^ 2 , [ca, conj (ca)], id, a, NOCHECK)
4848end
4949
5050function AlgebraicNumber (p:: UnivariatePolynomial , a = - Inf )
@@ -215,7 +215,7 @@ function lincomb(a::T, b::T, aa, bb) where T<:UnivariatePolynomial
215215 lincomb (a, aa)
216216 elseif iszero (aa)
217217 lincomb (b, bb)
218- elseif a == b
218+ elseif a == b # there should be better performance possible in this case - also check if a and b are collinear
219219 ca = companion (a)
220220 ea = I (deg (a))
221221 characteristic_polynomial (kron (ca, ea * aa) + kron (ea * bb, ca))
231231function lincomb (p:: T , aa) where T<: UnivariatePolynomial
232232 if isone (aa)
233233 p
234+ elseif iszero (aa)
235+ monom (T)
234236 else
235237 q = copy (p)
236238 qq = q. coeff
@@ -465,8 +467,15 @@ function rationalconst(expr::Expr)
465467 p = rationalconst (args[2 ])
466468 isnothing (p) && return p
467469 return inv (p)
470+ elseif fun == :sqrt
471+ p = rationalconst (args[2 ])
472+ isnothing (p) && return p
473+ sn = isqrt (abs (numerator (p)))
474+ sd = isqrt (denominator (p))
475+ q = sn // sd
476+ return q^ 2 == p ? q : nothing
468477 end
469- if fun ∉ (:(+ ), :(- ), :(* ), :(// ), :(inv), ( :sqrt ) )
478+ if fun ∉ (:(+ ), :(- ), :(* ), :(// ))
470479 return false
471480 end
472481 n = length (args)
@@ -516,21 +525,26 @@ function isalgebraic(expr::Expr)
516525 end
517526end
518527
519- function AlgebraicNumber (expr:: Expr )
528+ AlgebraicNumber (expr:: Expr ) = AlgebraicNumber (to_algebraic_or_rational (expr))
529+
530+ function to_algebraic_or_rational (expr:: Expr )
531+ x = rationalconst (expr)
532+ ! isnothing (x) && return x
520533 isalgebraic (expr) || throw (ArgumentError (" expression is not an algebraic number" ))
521534 head = expr. head
522535 if head == :call
523536 args = expr. args
524537 fun = args[1 ]
525538 if fun == :(^ )
526- a = AlgebraicNumber (args[2 ])
539+ a = to_algebraic_or_rational (args[2 ])
527540 q = rationalconst (args[3 ])
541+ denominator (q) != 1 && (a = AlgebraicNumber (a))
528542 return a^ q
529543 elseif fun ∈ (:(+ ), :(- ), :(* ), :(// ), :(/ ), :inv , :sqrt )
530544 n = length (args)
531545 eargs = Vector {Any} (undef, n - 1 )
532546 for j = 2 : n
533- eargs[j- 1 ] = AlgebraicNumber (args[j])
547+ eargs[j- 1 ] = to_algebraic_or_rational (args[j])
534548 end
535549 return evaluate (Val (fun), eargs)
536550 end
@@ -539,11 +553,58 @@ function AlgebraicNumber(expr::Expr)
539553 throw (ArgumentError (" no call, but $head " ))
540554 end
541555end
556+ to_algebraic_or_rational (a:: Integer ) = a
542557
543558evaluate (:: Val{:(+)} , args) = + (args... )
544559evaluate (:: Val{:(-)} , args) = - (args... )
545560evaluate (:: Val{:(*)} , args) = * (args... )
546- evaluate (:: Val{:(/)} , args) = // (args... )
547- evaluate (:: Val{:(//)} , args) = // (args... )
561+ evaluate (:: Val{:(/)} , args) = / (args... )
562+ evaluate (:: Val{:(//)} , args) = / (args... )
548563evaluate (:: Val{:(inv)} , args) = inv (args... )
549- evaluate (:: Val{:(sqrt)} , args) = sqrt (args... )
564+ evaluate (:: Val{:(sqrt)} , args) = sqrt (AlgebraicNumber (args[1 ]))
565+
566+ """
567+ com2(p, q)
568+
569+ calculates `mod(q^i, p)` for i = 0:n and stores coeffs in n*n matrix M and vector V.
570+ The solution of the linear sytem of equations delivers the coefficients of
571+ the field polynomial of `q(a)` when p is the minimal polynomial of `a`.
572+
573+ Is an alternative to `det(x - companion(p, q))` which is faster sometimes.
574+ """
575+ function com2 (p:: UnivariatePolynomial{T} , q) where T
576+ n = deg (p)
577+ S = typeof (value (p[0 ]))
578+ M = zeros (S, n, n)
579+ s = q^ 0
580+ for i = 0 : n- 1
581+ k = deg (s)
582+ for k = 0 : k
583+ M[k+ 1 , i+ 1 ] = s[k]
584+ end
585+ s = mod (s * q, p)
586+ end
587+ V = zeros (S, n)
588+ k = deg (s)
589+ for k = 0 : k
590+ V[k+ 1 ] = s[k]
591+ end
592+ M, V
593+ end
594+
595+ """
596+ evaluate2(q::UnivariatePolynomial, a::AlgebraicNumber)
597+
598+ Evaluates polynomial `q` for an algebraic number `a` using algorithm `com2`.
599+ """
600+ function evaluate2 (q:: P , a:: AlgebraicNumber ) where P<: UnivariatePolynomial
601+ p = minimal_polynomial (a)
602+ M, V = com2 (p, q)
603+ m = - P (M \ V) + monom (P, deg (a))
604+ AlgebraicNumber (m, q (approx (a)))
605+ end
606+
607+ field_matrix (a:: AlgebraicNumber ) = companion (minimal_polynomial (a))
608+ norm (a:: AlgebraicNumber ) = minimal_polynomial (a)[0 ] * (- 1 )^ deg (a)
609+ tr (a:: AlgebraicNumber ) = - minimal_polynomial (a)[deg (a)- 1 ]
610+ discriminant (a:: AlgebraicNumber ) = discriminant (minimal_polynomial (a))
0 commit comments