Ask Your Question

Revision history [back]

A shortcut for the first line is:

sage: x = polygen(QQ)

Then it's a matter of taste which is more elegant: your code, or

sage: p = x^6 - 3*x^4 + 5*x^2 - 9
sage: assert not any(p.list()[1::2])
sage: p.parent(p.list()[::2])
x^3 - 3*x^2 + 5*x - 9

This code is shorter, but yours iterates instead of constructing a list.

Sadly, p[1::2] and p[::2] don't give the expected result, the final :2 is silently ignored. The code for that is in the __getitem__ method of the class Polynomial_rational_flint, which is the class of p. Inspecting this method:

sage: from sage.rings.polynomial.polynomial_rational_flint import Polynomial_rational_flint
sage: Polynomial_rational_flint.__getitem__??

gives

def __getitem__(self, n):
    """
    Returns coefficient of the monomial of degree `n` if `n` is an integer,
    returns the monomials of self of degree in slice `n` if `n` is a slice.

    INPUT:

    - ``n`` - Degree of the monomial whose coefficient is to be returned
              or a slice.

    EXAMPLES::

        sage: R.<t> = QQ[]
        sage: f = 1 + t + t^2/2 + t^3/3 + t^4/4
        sage: f[-1], f[0], f[3], f[5]            # indirect doctest
        (0, 1, 1/3, 0)
        sage: f[1:3]                             # indirect doctest
        1/2*t^2 + t
    """
    cdef Rational z = PY_NEW(Rational)
    cdef Polynomial_rational_flint res = self._new()
    cdef bint do_sig = _do_sig(self.__poly)
    if isinstance(n, slice):
        start, stop, step = n.indices(self.degree() + 1)
        if do_sig: sig_on()
        fmpq_poly_get_slice(res.__poly, self.__poly, start, stop)
        if do_sig: sig_off()
        return res
    else:
        if 0 <= n and n < fmpq_poly_length(self.__poly):
            fmpq_poly_get_coeff_mpq(z.value, self.__poly, n)
        return z

in which we see that in the case where n is an instance of the type slice, it is split into start, stop, step, and then step is silently dropped when calling fmpq_poly_get_slice(res.__poly, self.__poly, start, stop).

Fixing this is not immediate since the flint function fmpq_poly_get_slice only takes start and stop arguments, not a step, see flint source code. Maybe this could be a feature request for Flint, and then we could make the __get_item__ method above work!

In the meantime, I wonder if a warning, or a "not implemented" error should be raised when calling __get_item__ with a step other than 1, since the result is likely to be wrong with respect to the user's expectation.

Going beyond this exploration of your simple example: of course if you wanted to deal with very general polynomials, including sparse polynomials or multivariate polynomials, you would need to deal differently with different flavours of polynomials, since they have different implementations.