@@ -2612,19 +2612,28 @@ cdef class Polynomial(CommutativePolynomial):
2612
2612
# would work with the smallest possible extension.
2613
2613
# However, if we have some element of GF(p^k) and we try and coerce this to
2614
2614
# some element GF(p^(k*n)) this can fail, even though mathematically it
2615
- # should be fine. As a result, we simply coerce straight to the user supplied
2616
- # ring and find a root here.
2615
+ # should be fine.
2617
2616
# TODO: Additionally, if the above was solved, it would be faster to extend the base
2618
2617
# ring with the irreducible factor however, if the base ring is an extension
2619
2618
# then the type of self.base_ring().extension(f) is a Univariate Quotient Polynomial Ring
2620
- # and not a finite field. So we do the slower option here to ensure the type is
2621
- # maintained.
2622
- if not f.degree().is_one():
2623
- f = f.change_ring(ring)
2624
-
2625
- # Now we find the root of this irreducible polynomial over this extension
2626
- root = f.any_root()
2627
- return ring(root)
2619
+ # and not a finite field.
2620
+
2621
+ # When f has degree one we simply return the roots
2622
+ # TODO: should we write something fast for degree two using
2623
+ # the quadratic formula?
2624
+ if f.degree().is_one():
2625
+ root = - f[0 ] / f[1 ]
2626
+ return ring(root)
2627
+
2628
+ # TODO: The proper thing to do here would be to call
2629
+ # return f.change_ring(ring).any_root()
2630
+ # but as we cannot work in the minimal extension (see above) working
2631
+ # in the extension for f.change_ring(ring).any_root() is almost always
2632
+ # much much much slower than using the call for roots() which uses
2633
+ # C library bindings for all finite fields.
2634
+ # Until the coercion system for finite fields works better,
2635
+ # this will be the most performant
2636
+ return f.roots(ring, multiplicities = False )[0 ]
2628
2637
2629
2638
# The old version of `any_root()` allowed degree < 0 to indicate that the input polynomial
2630
2639
# had a distinct degree factorisation, we pass this to any_irreducible_factor as a bool and
@@ -2668,11 +2677,15 @@ cdef class Polynomial(CommutativePolynomial):
2668
2677
# over explicitly a FiniteField type.
2669
2678
ring = self .base_ring().extension(degree, names = " a" )
2670
2679
2671
- # Now we look for a linear root of this irreducible polynomial of degree `degree`
2672
- # over the user supplied ring or the extension we just computed. If the user sent
2673
- # a bad ring here of course there may be no root found.
2674
- f = f.change_ring(ring)
2675
- return f.any_root()
2680
+ # TODO: The proper thing to do here would be to call
2681
+ # return f.change_ring(ring).any_root()
2682
+ # but as we cannot work in the minimal extension (see above) working
2683
+ # in the extension for f.change_ring(ring).any_root() is almost always
2684
+ # much much much slower than using the call for roots() which uses
2685
+ # C library bindings for all finite fields.
2686
+ # Until the coercion system for finite fields works better,
2687
+ # this will be the most performant
2688
+ return f.roots(ring, multiplicities = False )[0 ]
2676
2689
2677
2690
def __truediv__ (left , right ):
2678
2691
r """
0 commit comments