# HG changeset patch
# User Julian Rueth <julian.rueth@gmail.com>
Trac 12404: Distinguish zero and non-zero characteristic in is_squarefree for univariate polynomials.
More could be done for polynomials defined over perfect rings but this will go into another patch.
diff --git a/sage/rings/polynomial/polynomial_element.pyx b/sage/rings/polynomial/polynomial_element.pyx
index e5a7011..d25c3df 100644
a
|
b
|
AUTHORS: |
9 | 9 | |
10 | 10 | - Robert Bradshaw: Move Polynomial_generic_dense to Cython. |
11 | 11 | |
12 | | - Miguel Marco: Implemented resultant in the case where PARI fails. |
| 12 | - Miguel Marco: Implemented resultant in the case where PARI fails. |
13 | 13 | |
14 | 14 | - Simon King: Use a faster way of conversion from the base ring. |
15 | 15 | |
| 16 | - Julian Rueth (2012-05-25): Fixed is_squarefree() for imperfect fields. |
16 | 17 | |
17 | 18 | TESTS:: |
18 | 19 | |
… |
… |
cdef class Polynomial(CommutativeAlgebraElement): |
5616 | 5617 | |
5617 | 5618 | def is_squarefree(self): |
5618 | 5619 | """ |
5619 | | Return True if this polynomial is square free. |
5620 | | |
| 5620 | Return False if this polynomial is not square-free, i.e., if there is a |
| 5621 | non-unit `g` in the polynomial ring such that `g^2` divides ``self``. |
| 5622 | |
5621 | 5623 | EXAMPLES:: |
5622 | 5624 | |
5623 | | sage: x = polygen(QQ) |
| 5625 | sage: R.<x> = QQ[] |
5624 | 5626 | sage: f = (x-1)*(x-2)*(x^2-5)*(x^17-3); f |
5625 | 5627 | x^21 - 3*x^20 - 3*x^19 + 15*x^18 - 10*x^17 - 3*x^4 + 9*x^3 + 9*x^2 - 45*x + 30 |
5626 | 5628 | sage: f.is_squarefree() |
5627 | 5629 | True |
5628 | 5630 | sage: (f*(x^2-5)).is_squarefree() |
5629 | 5631 | False |
| 5632 | |
| 5633 | A generic implementation is available for polynomials defined over |
| 5634 | principal ideal domains of characteristic 0; the algorithm relies on |
| 5635 | gcd computations:: |
| 5636 | |
5630 | 5637 | sage: R.<x> = ZZ[] |
5631 | | sage: f = 2*x; g = 4*x; h = 2*x^2 |
5632 | | sage: f.is_squarefree() |
| 5638 | sage: (2*x).is_squarefree() |
5633 | 5639 | True |
5634 | | sage: g.is_squarefree() |
| 5640 | sage: (4*x).is_squarefree() |
| 5641 | False |
| 5642 | sage: (2*x^2).is_squarefree() |
| 5643 | False |
| 5644 | sage: R(0).is_squarefree() |
| 5645 | False |
| 5646 | |
| 5647 | sage: S.<y> = QQ[] |
| 5648 | sage: R.<x> = S[] |
| 5649 | sage: (2*x*y).is_squarefree() # R does not provide a gcd implementation |
| 5650 | Traceback (most recent call last): |
| 5651 | ... |
| 5652 | AttributeError: 'sage.rings.polynomial.polynomial_element.Polynomial_generic_dense' object has no attribute 'gcd' |
| 5653 | sage: (2*x*y^2).is_squarefree() |
5635 | 5654 | False |
5636 | | sage: h.is_squarefree() |
| 5655 | |
| 5656 | Over principal ideal domains of positive characteristic, we compute the |
| 5657 | square-free decomposition or a full factorization depending on which is |
| 5658 | available:: |
| 5659 | |
| 5660 | sage: K.<t> = FunctionField(GF(3)) |
| 5661 | sage: R.<x> = K[] |
| 5662 | sage: (x^3+2*x).is_squarefree() |
| 5663 | True |
| 5664 | sage: (x^3+2).is_squarefree() |
5637 | 5665 | False |
| 5666 | sage: (x^3+t).is_squarefree() |
| 5667 | True |
| 5668 | sage: R(t^2).is_squarefree() |
| 5669 | True |
| 5670 | |
5638 | 5671 | """ |
5639 | | if self.parent().base_ring().is_field(): |
5640 | | return self.derivative().gcd(self).degree() <= 0 |
5641 | | return self.derivative().gcd(self).degree() <= 0 and self.content().is_squarefree() |
| 5672 | if self.parent().base_ring() not in sage.categories.principal_ideal_domains.PrincipalIdealDomains(): |
| 5673 | raise NotImplementedError("is_squarefree() is only implemented for polynomials over principal ideal domains") |
| 5674 | |
| 5675 | # a square-free polynomial has a square-free content |
| 5676 | if not self.parent().base_ring().is_field(): |
| 5677 | content = self.content() |
| 5678 | if content not in self.parent().base_ring(): |
| 5679 | content = content.gen() |
| 5680 | if not content.is_squarefree(): |
| 5681 | return False |
| 5682 | |
| 5683 | # separable polynomials are square-free |
| 5684 | if self.derivative().gcd(self).is_constant(): |
| 5685 | return True |
| 5686 | |
| 5687 | # for characteristic zero rings, square-free polynomials have to be separable |
| 5688 | if self.parent().characteristic().is_zero(): |
| 5689 | return False |
| 5690 | |
| 5691 | # over rings of positive characteristic, we rely on the square-free decomposition if available |
| 5692 | try: |
| 5693 | F = self.squarefree_decomposition() |
| 5694 | except NotImplementedError: |
| 5695 | F = self.factor() |
| 5696 | return all([e<=1 for (f,e) in F]) |
5642 | 5697 | |
5643 | 5698 | def radical(self): |
5644 | 5699 | """ |