# This file is auto-generated by autogen/generator.py

cdef class Pari_auto:
    """
    Part of the :class:`Pari` class containing auto-generated functions.

    You must never use this class directly (in fact, Python may crash
    if you do), use the derived class :class:`Pari` instead.
    """
    def Catalan(self, long precision=DEFAULT_BITPREC):
        r'''
        Catalan's constant :math:`G = \sum_{n >= 0}((-1)^n)/((2n+1)^2) = 0.91596...`.
        Note that :literal:`Catalan` is one of the few reserved names which cannot be
        used for user variables.
        '''
        sig_on()
        precision = nbits2prec(precision)
        cdef GEN _ret = mpcatalan(precision)
        return new_gen(_ret)

    def Col(self, x, long n=0):
        r'''
        Transforms the object :math:`x` into a column vector. The dimension of the
        resulting vector can be optionally specified via the extra parameter :math:`n`.

        If :math:`n` is omitted or :math:`0`, the dimension depends on the type of :math:`x`; the
        vector has a single component, except when :math:`x` is

        - a vector or a quadratic form (in which case the resulting vector
        is simply the initial object considered as a row vector),

        - a polynomial or a power series. In the case of a polynomial, the
        coefficients of the vector start with the leading coefficient of the
        polynomial, while for power series only the significant coefficients are
        taken into account, but this time by increasing order of degree.
        In this last case, :literal:`Vec` is the reciprocal function of :literal:`Pol` and
        :literal:`Ser` respectively,

        - a matrix (the column of row vector comprising the matrix is returned),

        - a character string (a vector of individual characters is returned).

        In the last two cases (matrix and character string), :math:`n` is meaningless and
        must be omitted or an error is raised. Otherwise, if :math:`n` is given, :math:`0`
        entries are appended at the end of the vector if :math:`n > 0`, and prepended at
        the beginning if :math:`n < 0`. The dimension of the resulting vector is :math:`\|n\|`.

        See ??Vec for examples.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gtocol0(_x, n)
        return new_gen(_ret)

    def Colrev(self, x, long n=0):
        r'''
        As :math:`Col (x, -n)`, then reverse the result. In particular,
        :literal:`Colrev` is the reciprocal function of :literal:`Polrev`: the
        coefficients of the vector start with the constant coefficient of the
        polynomial and the others follow by increasing degree.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gtocolrev0(_x, n)
        return new_gen(_ret)

    def Euler(self, long precision=DEFAULT_BITPREC):
        r'''
        Euler's constant :math:`\gamma = 0.57721...`. Note that
        :literal:`Euler` is one of the few reserved names which cannot be used for
        user variables.
        '''
        sig_on()
        precision = nbits2prec(precision)
        cdef GEN _ret = mpeuler(precision)
        return new_gen(_ret)

    def I(self):
        r'''
        The complex number :math:`\sqrt{-1}`.
        '''
        sig_on()
        cdef GEN _ret = gen_I()
        return new_gen(_ret)

    def List(self, x=None):
        r'''
        Transforms a (row or column) vector :math:`x` into a list, whose components are
        the entries of :math:`x`. Similarly for a list, but rather useless in this case.
        For other types, creates a list with the single element :math:`x`.
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _ret = gtolist(_x)
        return new_gen(_ret)

    def Map(self, x=None):
        r'''
        A "Map" is an associative array, or dictionary: a data
        type composed of a collection of (:emphasis:`key`, :emphasis:`value`) pairs, such that
        each key appears just once in the collection. This function
        converts the matrix :math:`[a_1,b_1;a_2,b_2;...;a_n,b_n]` to the map :math:`a_i:--->
        b_i`.

        ::

        ? M = Map(factor(13!));
        ? mapget(M,3)
        %2 = 5

        If the argument :math:`x` is omitted, creates an empty map, which
        may be filled later via :literal:`mapput`.
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _ret = gtomap(_x)
        return new_gen(_ret)

    def Mat(self, x=None):
        r'''
        Transforms the object :math:`x` into a matrix.
        If :math:`x` is already a matrix, a copy of :math:`x` is created.
        If :math:`x` is a row (resp. column) vector, this creates a 1-row (resp.
        1-column) matrix, :emphasis:`unless` all elements are column (resp. row) vectors
        of the same length, in which case the vectors are concatenated sideways
        and the attached big matrix is returned.
        If :math:`x` is a binary quadratic form, creates the attached :math:`2 x 2`
        matrix. Otherwise, this creates a :math:`1 x 1` matrix containing :math:`x`.

        ::

        ? Mat(x + 1)
        %1 =
        [x + 1]
        ? Vec( matid(3) )
        %2 = [[1, 0, 0]~, [0, 1, 0]~, [0, 0, 1]~]
        ? Mat(%)
        %3 =
        [1 0 0]
        
        [0 1 0]
        
        [0 0 1]
        ? Col( [1,2; 3,4] )
        %4 = [[1, 2], [3, 4]]~
        ? Mat(%)
        %5 =
        [1 2]
        
        [3 4]
        ? Mat(Qfb(1,2,3))
        %6 =
        [1 1]
        
        [1 3]
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _ret = gtomat(_x)
        return new_gen(_ret)

    def Mod(self, a, b):
        r'''
        In its basic form, creates an intmod or a polmod :math:`(a mod b)`; :math:`b` must
        be an integer or a polynomial. We then obtain a :literal:`t_INTMOD` and a
        :literal:`t_POLMOD` respectively:

        ::

        ? t = Mod(2,17); t^8
        %1 = Mod(1, 17)
        ? t = Mod(x,x^2+1); t^2
        %2 = Mod(-1, x^2+1)

        If :math:`a \% b` makes sense and yields a result of the
        appropriate type (:literal:`t_INT` or scalar/:literal:`t_POL`), the operation succeeds as
        well:

        ::

        ? Mod(1/2, 5)
        %3 = Mod(3, 5)
        ? Mod(7 + O(3^6), 3)
        %4 = Mod(1, 3)
        ? Mod(Mod(1,12), 9)
        %5 = Mod(1, 3)
        ? Mod(1/x, x^2+1)
        %6 = Mod(-1, x^2+1)
        ? Mod(exp(x), x^4)
        %7 = Mod(1/6*x^3 + 1/2*x^2 + x + 1, x^4)

        If :math:`a` is a complex object, "base change" it to :math:`\mathbb{Z}/b\mathbb{Z}` or :math:`K[x]/(b)`,
        which is equivalent to, but faster than, multiplying it by :literal:`Mod(1,b)`:

        ::

        ? Mod([1,2;3,4], 2)
        %8 =
        [Mod(1, 2) Mod(0, 2)]
        
        [Mod(1, 2) Mod(0, 2)]
        ? Mod(3*x+5, 2)
        %9 = Mod(1, 2)*x + Mod(1, 2)
        ? Mod(x^2 + y*x + y^3, y^2+1)
        %10 = Mod(1, y^2 + 1)*x^2 + Mod(y, y^2 + 1)*x + Mod(-y, y^2 + 1)

        This function is not the same as :math:`x` :literal:`\%` :math:`y`, the result of which
        has no knowledge of the intended modulus :math:`y`. Compare

        ::

        ? x = 4 % 5; x + 1
        %1 = 5
        ? x = Mod(4,5); x + 1
        %2 = Mod(0,5)

        Note that such "modular" objects can be lifted via :literal:`lift` or
        :literal:`centerlift`. The modulus of a :literal:`t_INTMOD` or :literal:`t_POLMOD` :math:`z` can
        be recovered via :literal:`:math:`z`.mod`.
        '''
        a = objtogen(a)
        b = objtogen(b)
        sig_on()
        cdef GEN _a = (<Gen>a).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _ret = gmodulo(_a, _b)
        return new_gen(_ret)

    def Pi(self, long precision=DEFAULT_BITPREC):
        r'''
        The constant :math:`\pi` (:math:`3.14159...`). Note that :literal:`Pi` is one of the few
        reserved names which cannot be used for user variables.
        '''
        sig_on()
        precision = nbits2prec(precision)
        cdef GEN _ret = mppi(precision)
        return new_gen(_ret)

    def Pol(self, t, v=None):
        r'''
        Transforms the object :math:`t` into a polynomial with main variable :math:`v`. If :math:`t`
        is a scalar, this gives a constant polynomial. If :math:`t` is a power series with
        non-negative valuation or a rational function, the effect is similar to
        :literal:`truncate`, i.e. we chop off the :math:`O(X^k)` or compute the Euclidean
        quotient of the numerator by the denominator, then change the main variable
        of the result to :math:`v`.

        The main use of this function is when :math:`t` is a vector: it creates the
        polynomial whose coefficients are given by :math:`t`, with :math:`t[1]` being the leading
        coefficient (which can be zero). It is much faster to evaluate
        :literal:`Pol` on a vector of coefficients in this way, than the corresponding
        formal expression :math:`a_n X^n +...+ a_0`, which is evaluated naively exactly
        as written (linear versus quadratic time in :math:`n`). :literal:`Polrev` can be used if
        one wants :math:`x[1]` to be the constant coefficient:

        ::

        ? Pol([1,2,3])
        %1 = x^2 + 2*x + 3
        ? Polrev([1,2,3])
        %2 = 3*x^2 + 2*x + 1

        The reciprocal function of :literal:`Pol` (resp. :literal:`Polrev`) is :literal:`Vec` (resp.
        :literal:`Vecrev`).

        ::

        ? Vec(Pol([1,2,3]))
        %1 = [1, 2, 3]
        ? Vecrev( Polrev([1,2,3]) )
        %2 = [1, 2, 3]

        :strong:`Warning.` This is :emphasis:`not` a substitution function. It will not
        transform an object containing variables of higher priority than :math:`v`.

        ::

        ? Pol(x + y, y)
        *** at top-level: Pol(x+y,y)
        *** ^----------
        *** Pol: variable must have higher priority in gtopoly.
        '''
        t = objtogen(t)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _t = (<Gen>t).g
        cdef GEN _ret = gtopoly(_t, _v)
        return new_gen(_ret)

    def Polrev(self, t, v=None):
        r'''
        Transform the object :math:`t` into a polynomial
        with main variable :math:`v`. If :math:`t` is a scalar, this gives a constant polynomial.
        If :math:`t` is a power series, the effect is identical to :literal:`truncate`, i.e. it
        chops off the :math:`O(X^k)`.

        The main use of this function is when :math:`t` is a vector: it creates the
        polynomial whose coefficients are given by :math:`t`, with :math:`t[1]` being the
        constant term. :literal:`Pol` can be used if one wants :math:`t[1]` to be the leading
        coefficient:

        ::

        ? Polrev([1,2,3])
        %1 = 3*x^2 + 2*x + 1
        ? Pol([1,2,3])
        %2 = x^2 + 2*x + 3

        The reciprocal function of :literal:`Pol` (resp. :literal:`Polrev`) is :literal:`Vec` (resp.
        :literal:`Vecrev`).
        '''
        t = objtogen(t)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _t = (<Gen>t).g
        cdef GEN _ret = gtopolyrev(_t, _v)
        return new_gen(_ret)

    def Qfb(self, a, b, c, D=None, long precision=DEFAULT_BITPREC):
        r'''
        Creates the binary quadratic form
        :math:`ax^2+bxy+cy^2`. If :math:`b^2-4ac > 0`, initialize Shanks' distance
        function to :math:`D`. Negative definite forms are not implemented,
        use their positive definite counterpart instead.
        '''
        a = objtogen(a)
        b = objtogen(b)
        c = objtogen(c)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _a = (<Gen>a).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _c = (<Gen>c).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        precision = nbits2prec(precision)
        cdef GEN _ret = Qfb0(_a, _b, _c, _D, precision)
        return new_gen(_ret)

    def Ser(self, s, v=None, d=None, long serprec=-1):
        r'''
        Transforms the object :math:`s` into a power series with main variable :math:`v`
        (:math:`x` by default) and precision (number of significant terms) equal to
        :math:`d >= 0` (:math:`d = seriesprecision` by default). If :math:`s` is a
        scalar, this gives a constant power series in :math:`v` with precision :literal:`d`.
        If :math:`s` is a polynomial, the polynomial is truncated to :math:`d` terms if needed

        ::

        ? \ps
        seriesprecision = 16 significant terms
        ? Ser(1) \\ 16 terms by default
        %1 = 1 + O(x^16)
        ? Ser(1, 'y, 5)
        %2 = 1 + O(y^5)
        ? Ser(x^2,, 5)
        %3 = x^2 + O(x^7)
        ? T = polcyclo(100)
        %4 = x^40 - x^30 + x^20 - x^10 + 1
        ? Ser(T, 'x, 11)
        %5 = 1 - x^10 + O(x^11)

        The function is more or less equivalent with multiplication by
        :math:`1 + O(v^d)` in theses cases, only faster.

        For the remaining types, vectors and power series, we first explain what
        occurs if :math:`d` is omitted. In this case, the function uses exactly the amount
        of information given in the input:

        - If :math:`s` is already a power series in :math:`v`, we return it verbatim;

        - If :math:`s` is a vector, the coefficients of the vector are
        understood to be the coefficients of the power series starting from the
        constant term (as in :literal:`Polrev`:math:`(x)`); in other words we convert
        :literal:`t_VEC` / :literal:`t_COL` to the power series whose significant terms are exactly
        given by the vector entries.

        On the other hand, if :math:`d` is explicitly given, we abide by its value
        and return a series, truncated or extended with zeros as needed, with
        :math:`d` significant terms.

        ::

        ? v = [1,2,3];
        ? Ser(v, t) \\ 3 terms: seriesprecision is ignored!
        %7 = 1 + 2*t + 3*t^2 + O(t^3)
        ? Ser(v, t, 7) \\ 7 terms as explicitly requested
        %8 = 1 + 2*t + 3*t^2 + O(t^7)
        ? s = 1+x+O(x^2);
        ? Ser(s)
        %10 = 1 + x + O(x^2) \\ 2 terms: seriesprecision is ignored
        ? Ser(s, x, 7) \\ extend to 7 terms
        %11 = 1 + x + O(x^7)
        ? Ser(s, x, 1) \\ truncate to 1 term
        %12 = 1 + O(x)

        The warning given for :literal:`Pol` also applies here: this is not a substitution
        function.
        '''
        s = objtogen(s)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        cdef bint _have_d = (d is not None)
        if _have_d:
            d = objtogen(d)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        cdef GEN _d = NULL
        if _have_d:
            _d = (<Gen>d).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = Ser0(_s, _v, _d, serprec)
        return new_gen(_ret)

    def Set(self, x=None):
        r'''
        Converts :math:`x` into a set, i.e. into a row vector, with strictly increasing
        entries with respect to the (somewhat arbitrary) universal comparison function
        :literal:`cmp`. Standard container types :literal:`t_VEC`, :literal:`t_COL`, :literal:`t_LIST` and
        :literal:`t_VECSMALL` are converted to the set with corresponding elements. All
        others are converted to a set with one element.

        ::

        ? Set([1,2,4,2,1,3])
        %1 = [1, 2, 3, 4]
        ? Set(x)
        %2 = [x]
        ? Set(Vecsmall([1,3,2,1,3]))
        %3 = [1, 2, 3]
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _ret = gtoset(_x)
        return new_gen(_ret)

    def Strchr(self, x):
        r'''
        Converts :math:`x` to a string, translating each integer
        into a character.

        ::

        ? Strchr(97)
        %1 = "a"
        ? Vecsmall("hello world")
        %2 = Vecsmall([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100])
        ? Strchr(%)
        %3 = "hello world"
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = Strchr(_x)
        return new_gen(_ret)

    def Vec(self, x, long n=0):
        r'''
        Transforms the object :math:`x` into a row vector. The dimension of the
        resulting vector can be optionally specified via the extra parameter :math:`n`.
        If :math:`n` is omitted or :math:`0`, the dimension depends on the type of :math:`x`; the
        vector has a single component, except when :math:`x` is

        - a vector or a quadratic form: returns the initial object considered as a
        row vector,

        - a polynomial or a power series: returns a vector consisting of the
        coefficients. In the case of a polynomial, the coefficients of the vector
        start with the leading coefficient of the polynomial, while for power series
        only the significant coefficients are taken into account, but this time by
        increasing order of degree. In particular the valuation is ignored
        (which makes the function useful for series of negative valuation):

        ::

        ? Vec(3*x^2 + x)
        %1 = [3, 1, 0]
        ? Vec(x^2 + 3*x^3 + O(x^5))
        %2 = [1, 3, 0]
        ? Vec(x^-2 + 3*x^-1 + O(x))
        %3 = [1, 3, 0]

        :literal:`Vec` is the reciprocal function of :literal:`Pol` for a
        polynomial and of :literal:`Ser` for power series of valuation :math:`0`.

        - a matrix: returns the vector of columns comprising the matrix,

        ::

        ? m = [1,2,3;4,5,6]
        %4 =
        [1 2 3]
        
        [4 5 6]
        ? Vec(m)
        %5 = [[1, 4]~, [2, 5]~, [3, 6]~]

        - a character string: returns the vector of individual characters,

        ::

        ? Vec("PARI")
        %6 = ["P", "A", "R", "I"]

        - a map: returns the vector of the domain of the map,

        - an error context (:literal:`t_ERROR`): returns the error components, see
        :literal:`iferr`.

        In the last four cases (matrix, character string, map, error), :math:`n` is
        meaningless and must be omitted or an error is raised. Otherwise, if :math:`n` is
        given, :math:`0` entries are appended at the end of the vector if :math:`n > 0`, and
        prepended at the beginning if :math:`n < 0`. The dimension of the resulting vector
        is :math:`\|n\|`. This allows to write a conversion function for series that
        takes positive valuations into account:

        ::

        ? serVec(s) = Vec(s, -serprec(s,variable(s)));
        ? Vec(x^2 + 3*x^3 + O(x^5))
        %2 = [0, 0, 1, 3, 0]

        (That function is not intended for series of negative valuation.)
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gtovec0(_x, n)
        return new_gen(_ret)

    def Vecrev(self, x, long n=0):
        r'''
        As :math:`Vec (x, -n)`, then reverse the result. In particular,
        :literal:`Vecrev` is the reciprocal function of :literal:`Polrev`: the
        coefficients of the vector start with the constant coefficient of the
        polynomial and the others follow by increasing degree.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gtovecrev0(_x, n)
        return new_gen(_ret)

    def Vecsmall(self, x, long n=0):
        r'''
        Transforms the object :math:`x` into a row vector of type :literal:`t_VECSMALL`. The
        dimension of the resulting vector can be optionally specified via the extra
        parameter :math:`n`.

        This acts as :literal:`Vec`:math:`(x,n)`, but only on a limited set of objects:
        the result must be representable as a vector of small integers.
        If :math:`x` is a character string, a vector of individual characters in ASCII
        encoding is returned (:literal:`Strchr` yields back the character string).
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gtovecsmall0(_x, n)
        return new_gen(_ret)

    def abs(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Absolute value of :math:`x` (modulus if :math:`x` is complex).
        Rational functions are not allowed. Contrary to most transcendental
        functions, an exact argument is :emphasis:`not` converted to a real number before
        applying :literal:`abs` and an exact result is returned if possible.

        ::

        ? abs(-1)
        %1 = 1
        ? abs(3/7 + 4/7*I)
        %2 = 5/7
        ? abs(1 + I)
        %3 = 1.414213562373095048801688724

        If :math:`x` is a polynomial, returns :math:`-x` if the leading coefficient is
        real and negative else returns :math:`x`. For a power series, the constant
        coefficient is considered instead.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gabs(_x, precision)
        return new_gen(_ret)

    def acos(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of :math:`\cos^{-1}(x) = -i \log (x + i\sqrt{1-x^2})`.
        In particular, :math:`\Re (acos(x))\in [0,\pi]` and if :math:`x\in \mathbb{R}` and :math:`\|x\| > 1`,
        then :math:`acos(x)` is complex. The branch cut is in two pieces:
        :math:`]- oo ,-1]` , continuous with quadrant II, and :math:`[1,+ oo [`, continuous
        with quadrant IV. We have :math:`acos(x) = \pi/2 - asin(x)` for all
        :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gacos(_x, precision)
        return new_gen(_ret)

    def acosh(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of :math:`\cosh^{-1}(x) = 2
        \log (\sqrt{(x+1)/2} + \sqrt{(x-1)/2})`. In particular,
        :math:`\Re (acosh(x)) >= 0` and
        :math:`\Im (acosh(x))\in ]-\pi,\pi]`; if :math:`x\in \mathbb{R}` and :math:`x < 1`, then
        :math:`acosh(x)` is complex.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gacosh(_x, precision)
        return new_gen(_ret)

    def addhelp(self, sym, str):
        r'''
        Changes the help message for the symbol :literal:`sym`. The string :emphasis:`str`
        is expanded on the spot and stored as the online help for :literal:`sym`. It is
        recommended to document global variables and user functions in this way,
        although :literal:`gp` will not protest if you don't.

        You can attach a help text to an alias, but it will never be
        shown: aliases are expanded by the :literal:`?` help operator and we get the help
        of the symbol the alias points to. Nothing prevents you from modifying the
        help of built-in PARI functions. But if you do, we would like to hear why you
        needed it!

        Without :literal:`addhelp`, the standard help for user functions consists of its
        name and definition.

        ::

        gp> f(x) = x^2;
        gp> ?f
        f =
        (x)->x^2
        

        Once addhelp is applied to :math:`f`, the function code is no
        longer included. It can still be consulted by typing the function name:

        ::

        gp> addhelp(f, "Square")
        gp> ?f
        Square
        
        gp> f
        %2 = (x)->x^2
        '''
        sym = to_bytes(sym)
        cdef char* _sym = <bytes>sym
        str = to_bytes(str)
        cdef char* _str = <bytes>str
        sig_on()
        addhelp(_sym, _str)
        clear_stack()

    def addprimes(self, x=None):
        r'''
        Adds the integers contained in the
        vector :math:`x` (or the single integer :math:`x`) to a special table of
        "user-defined primes", and returns that table. Whenever :literal:`factor` is
        subsequently called, it will trial divide by the elements in this table.
        If :math:`x` is empty or omitted, just returns the current list of extra
        primes.

        The entries in :math:`x` must be primes: there is no internal check, even if
        the :literal:`factor_proven` default is set. To remove primes from the list use
        :literal:`removeprimes`.
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _ret = addprimes(_x)
        return new_gen(_ret)

    def agm(self, x, y, long precision=DEFAULT_BITPREC):
        r'''
        Arithmetic-geometric mean of :math:`x` and :math:`y`. In the
        case of complex or negative numbers, the optimal AGM is returned
        (the largest in absolute value over all choices of the signs of the square
        roots). :math:`p`-adic or power series arguments are also allowed. Note that
        a :math:`p`-adic agm exists only if :math:`x/y` is congruent to 1 modulo :math:`p` (modulo
        16 for :math:`p = 2`). :math:`x` and :math:`y` cannot both be vectors or matrices.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        precision = nbits2prec(precision)
        cdef GEN _ret = agm(_x, _y, precision)
        return new_gen(_ret)

    def algadd(self, al, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in :emphasis:`al`, computes their sum :math:`x+y` in
        the algebra :emphasis:`al`.

        ::

        ? A = alginit(nfinit(y),[-1,1]);
        ? algadd(A,[1,0]~,[1,2]~)
        %2 = [2, 2]~

        Also accepts matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = algadd(_al, _x, _y)
        return new_gen(_ret)

    def algalgtobasis(self, al, x):
        r'''
        Given an element :emphasis:`x` in the central simple algebra :emphasis:`al` output
        by :literal:`alginit`, transforms it to a column vector on the integral basis of
        :emphasis:`al`. This is the inverse function of :literal:`algbasistoalg`.

        ::

        ? A = alginit(nfinit(y^2-5),[2,y]);
        ? algalgtobasis(A,[y,1]~)
        %2 = [0, 2, 0, -1, 2, 0, 0, 0]~
        ? algbasistoalg(A,algalgtobasis(A,[y,1]~))
        %3 = [Mod(Mod(y, y^2 - 5), x^2 - 2), 1]~
        '''
        al = objtogen(al)
        x = objtogen(x)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = algalgtobasis(_al, _x)
        return new_gen(_ret)

    def algaut(self, al):
        r'''
        Given a cyclic algebra :math:`al = (L/K,\sigma,b)` output by
        :literal:`alginit`, returns the automorphism :math:`\sigma`.

        ::

        ? nf = nfinit(y);
        ? p = idealprimedec(nf,7)[1];
        ? p2 = idealprimedec(nf,11)[1];
        ? A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]);
        ? algaut(A)
        %5 = -1/3*x^2 + 1/3*x + 26/3
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algaut(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algb(self, al):
        r'''
        Given a cyclic algebra :math:`al = (L/K,\sigma,b)` output by
        :literal:`alginit`, returns the element :math:`b\in K`.

        ::

        nf = nfinit(y);
        ? p = idealprimedec(nf,7)[1];
        ? p2 = idealprimedec(nf,11)[1];
        ? A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]);
        ? algb(A)
        %5 = Mod(-77, y)
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algb(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algbasis(self, al):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, returns
        a :math:`\mathbb{Z}`-basis of the order :math:`O_0` stored in :emphasis:`al` with respect to the
        natural order in :emphasis:`al`. It is a maximal order if one has been computed.

        ::

        A = alginit(nfinit(y), [-1,-1]);
        ? algbasis(A)
        %2 =
        [1 0 0 1/2]
        
        [0 1 0 1/2]
        
        [0 0 1 1/2]
        
        [0 0 0 1/2]
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algbasis(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algbasistoalg(self, al, x):
        r'''
        Given an element :emphasis:`x` in the central simple algebra :emphasis:`al` output
        by :literal:`alginit`, transforms it to its algebraic representation in :emphasis:`al`.
        This is the inverse function of :literal:`algalgtobasis`.

        ::

        ? A = alginit(nfinit(y^2-5),[2,y]);
        ? z = algbasistoalg(A,[0,1,0,0,2,-3,0,0]~);
        ? liftall(z)
        %3 = [(-1/2*y - 2)*x + (-1/4*y + 5/4), -3/4*y + 7/4]~
        ? algalgtobasis(A,z)
        %4 = [0, 1, 0, 0, 2, -3, 0, 0]~
        '''
        al = objtogen(al)
        x = objtogen(x)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = algbasistoalg(_al, _x)
        return new_gen(_ret)

    def algcenter(self, al):
        r'''
        If :emphasis:`al` is a table algebra output by :literal:`algtableinit`, returns a
        basis of the center of the algebra :emphasis:`al` over its prime field (:math:`\mathbb{Q}` or
        :math:`\mathbb{F}_p`). If :emphasis:`al` is a central simple algebra output by :literal:`alginit`,
        returns the center of :emphasis:`al`, which is stored in :emphasis:`al`.

        A simple example: the :math:`2 x 2` upper triangular matrices over :math:`\mathbb{Q}`,
        generated by :math:`I_2`, :math:`a = [0,1;0,0]` and :math:`b = [0,0;0,1]`,
        such that :math:`a^2 = 0`, :math:`ab = a`, :math:`ba = 0`, :math:`b^2 = b`: the diagonal matrices
        form the center.

        ::

        ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
        ? A = algtableinit(mt);
        ? algcenter(A) \\ = (I_2)
        %3 =
        [1]
        
        [0]
        
        [0]

        An example in the central simple case:

        ::

        ? nf = nfinit(y^3-y+1);
        ? A = alginit(nf, [-1,-1]);
        ? algcenter(A).pol
        %3 = y^3 - y + 1
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algcenter(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algcentralproj(self, al, z, long maps=0):
        r'''
        Given a table algebra :emphasis:`al` output by :literal:`algtableinit` and a
        :literal:`t_VEC` :math:`z = [z_1,...,z_n]` of orthogonal central idempotents,
        returns a :literal:`t_VEC` :math:`[al_1,...,al_n]` of algebras such that
        :math:`al_i = z_i al`. If :math:`maps = 1`, each :math:`al_i` is a :literal:`t_VEC`
        :math:`[quo,proj,lift]` where :emphasis:`quo` is the quotient algebra, :emphasis:`proj` is a
        :literal:`t_MAT` representing the projection onto this quotient and :emphasis:`lift` is a
        :literal:`t_MAT` representing a lift.

        A simple example: :math:`\mathbb{F}_2 x \mathbb{F}_4`, generated by :math:`1 = (1,1)`, :math:`e = (1,0)`
        and :math:`x` such that :math:`x^2+x+1 = 0`. We have :math:`e^2 = e`, :math:`x^2 = x+1` and :math:`ex = 0`.

        ::

        ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
        ? A = algtableinit(mt,2);
        ? e = [0,1,0]~;
        ? e2 = algsub(A,[1,0,0]~,e);
        ? [a,a2] = algcentralproj(A,[e,e2]);
        ? algdim(a)
        %6 = 1
        ? algdim(a2)
        %7 = 2
        '''
        al = objtogen(al)
        z = objtogen(z)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _z = (<Gen>z).g
        cdef GEN _ret = alg_centralproj(_al, _z, maps)
        return new_gen(_ret)

    def algchar(self, al):
        r'''
        Given an algebra :emphasis:`al` output by :literal:`alginit` or :literal:`algtableinit`,
        returns the characteristic of :emphasis:`al`.

        ::

        ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
        ? A = algtableinit(mt,13);
        ? algchar(A)
        %3 = 13
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algchar(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algcharpoly(self, al, b, v=None, long abs=0):
        r'''
        Given an element :math:`b` in :emphasis:`al`, returns its characteristic polynomial
        as a polynomial in the variable :math:`v`. If :emphasis:`al` is a table algebra output
        by :literal:`algtableinit` or if :math:`abs = 1`, returns the absolute characteristic
        polynomial of :emphasis:`b`, which is an element of :math:`\mathbb{F}_p[v]` or :math:`\mathbb{Q}[v]`; if :emphasis:`al`
        is a central simple algebra output by :literal:`alginit` and :math:`abs = 0`, returns the
        reduced characteristic polynomial of :emphasis:`b`, which is an element of :math:`K[v]`
        where :math:`K` is the center of :emphasis:`al`.

        ::

        ? al = alginit(nfinit(y), [-1,-1]); \\ (-1,-1)_Q
        ? algcharpoly(al, [0,1]~)
        %2 = x^2 + 1
        ? algcharpoly(al, [0,1]~,,1)
        %3 = x^4 + 2*x^2 + 1
        ? nf = nfinit(y^2-5);
        ? al = alginit(nf,[-1,y]);
        ? a = [y,1+x]~*Mod(1,y^2-5)*Mod(1,x^2+1);
        ? P = lift(algcharpoly(al,a))
        %7 = x^2 - 2*y*x + (-2*y + 5)
        ? algcharpoly(al,a,,1)
        %8 = x^8 - 20*x^6 - 80*x^5 + 110*x^4 + 800*x^3 + 1500*x^2 - 400*x + 25
        ? lift(P*subst(P,y,-y)*Mod(1,y^2-5))^2
        %9 = x^8 - 20*x^6 - 80*x^5 + 110*x^4 + 800*x^3 + 1500*x^2 - 400*x + 25

        Also accepts a square matrix with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        b = objtogen(b)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _ret = algcharpoly(_al, _b, _v, abs)
        return new_gen(_ret)

    def algdegree(self, al):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, returns
        the degree of :emphasis:`al`.

        ::

        ? nf = nfinit(y^3-y+1);
        ? A = alginit(nf, [-1,-1]);
        ? algdegree(A)
        %3 = 2
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef long _ret = algdegree(_al)
        clear_stack()
        return _ret

    def algdep(self, z, long k, long flag=0):
        r'''
        :math:`z` being real/complex, or :math:`p`-adic, finds a polynomial (in the variable
        :literal:`'x`) of degree at most
        :math:`k`, with integer coefficients, having :math:`z` as approximate root. Note that the
        polynomial which is obtained is not necessarily the "correct" one. In fact
        it is not even guaranteed to be irreducible. One can check the closeness
        either by a polynomial evaluation (use :literal:`subst`), or by computing the
        roots of the polynomial given by :literal:`algdep` (use :literal:`polroots` or
        :literal:`polrootspadic`).

        Internally, :literal:`lindep`:math:`([1,z,...,z^k], flag)` is used. A non-zero value of
        :math:`flag` may improve on the default behavior if the input number is known to a
        :emphasis:`huge` accuracy, and you suspect the last bits are incorrect: if :math:`flag > 0`
        the computation is done with an accuracy of :math:`flag` decimal digits; to get
        meaningful results, the parameter :math:`flag` should be smaller than the number of
        correct decimal digits in the input.
        But default values are usually sufficient, so try without :math:`flag` first:

        ::

        ? \p200
        ? z = 2^(1/6)+3^(1/5);
        ? algdep(z, 30); \\ right in 280ms
        ? algdep(z, 30, 100); \\ wrong in 169ms
        ? algdep(z, 30, 170); \\ right in 288ms
        ? algdep(z, 30, 200); \\ wrong in 320ms
        ? \p250
        ? z = 2^(1/6)+3^(1/5); \\ recompute to new, higher, accuracy !
        ? algdep(z, 30); \\ right in 329ms
        ? algdep(z, 30, 200); \\ right in 324ms
        ? \p500
        ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 677ms
        ? \p1000
        ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 1.5s

        The changes in :literal:`realprecision` only affect the quality of the
        initial approximation to :math:`2^{1/6} + 3^{1/5}`, :literal:`algdep` itself uses
        exact operations. The size of its operands depend on the accuracy of the
        input of course: more accurate input means slower operations.

        Proceeding by increments of 5 digits of accuracy, :literal:`algdep` with default
        flag produces its first correct result at 195 digits, and from then on a
        steady stream of correct results:

        ::

        \\ assume T contains the correct result, for comparison
        forstep(d=100, 250, 5, localprec(d);\
        print(d, " ", algdep(2^(1/6)+3^(1/5),30) == T))

        The above example is the test case studied in a 2000 paper by Borwein and
        Lisonek: Applications of integer relation algorithms, :emphasis:`Discrete Math.`,
        :strong:`217`, p. 65--82. The version of PARI tested there was 1.39, which
        succeeded reliably from precision 265 on, in about 200 as much time as the
        current version.
        '''
        z = objtogen(z)
        sig_on()
        cdef GEN _z = (<Gen>z).g
        cdef GEN _ret = algdep0(_z, k, flag)
        return new_gen(_ret)

    def algdim(self, al, long abs=0):
        r'''
        If :emphasis:`al` is a table algebra output by :literal:`algtableinit` or if :math:`abs = 1`,
        returns the dimension of :emphasis:`al` over its prime subfield (:math:`\mathbb{Q}` or :math:`\mathbb{F}_p`).
        If :emphasis:`al` is a central simple algebra output by :literal:`alginit` and :math:`abs = 0`,
        returns the dimension of :emphasis:`al` over its center.

        ::

        ? nf = nfinit(y^3-y+1);
        ? A = alginit(nf, [-1,-1]);
        ? algdim(A)
        %3 = 4
        ? algdim(A,1)
        %4 = 12
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef long _ret = algdim(_al, abs)
        clear_stack()
        return _ret

    def algdisc(self, al):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, computes
        the discriminant of the order :math:`O_0` stored in :emphasis:`al`, that is the
        determinant of the trace form :math:`\rm{Tr} : O_0 x O_0 \to \mathbb{Z}`.

        ::

        ? nf = nfinit(y^2-5);
        ? A = alginit(nf, [-3,1-y]);
        ? [PR,h] = alghassef(A)
        %3 = [[[2, [2, 0]~, 1, 2, 1], [3, [3, 0]~, 1, 2, 1]], Vecsmall([0, 1])]
        ? n = algdegree(A);
        ? D = algdim(A,1);
        ? h = vector(#h, i, n - gcd(n,h[i]));
        ? n^D * nf.disc^(n^2) * idealnorm(nf, idealfactorback(nf,PR,h))^n
        %4 = 12960000
        ? algdisc(A)
        %5 = 12960000
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algdisc(_al)
        return new_gen(_ret)

    def algdivl(self, al, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in :emphasis:`al`, computes their left quotient
        :math:`x\backslash y` in the algebra :emphasis:`al`: an element :math:`z` such that :math:`xz = y` (such
        an element is not unique when :math:`x` is a zerodivisor). If :math:`x` is invertible, this
        is the same as :math:`x^{-1}y`. Assumes that :math:`y` is left divisible by :math:`x` (i.e. that
        :math:`z` exists). Also accepts matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = algdivl(_al, _x, _y)
        return new_gen(_ret)

    def algdivr(self, al, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in :emphasis:`al`, returns :math:`xy^{-1}`. Also accepts
        matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = algdivr(_al, _x, _y)
        return new_gen(_ret)

    def alggroup(self, gal, p=None):
        r'''
        Initializes the group algebra :math:`K[G]` over :math:`K = \mathbb{Q}` (:math:`p` omitted) or :math:`\mathbb{F}_p`
        where :math:`G` is the underlying group of the :literal:`galoisinit` structure :emphasis:`gal`.
        The input :emphasis:`gal` is also allowed to be a :literal:`t_VEC` of permutations that is
        closed under products.

        Example:

        ::

        ? K = nfsplitting(x^3-x+1);
        ? gal = galoisinit(K);
        ? al = alggroup(gal);
        ? algissemisimple(al)
        %4 = 1
        ? G = [Vecsmall([1,2,3]), Vecsmall([1,3,2])];
        ? al2 = alggroup(G, 2);
        ? algissemisimple(al2)
        %8 = 0
        '''
        gal = objtogen(gal)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _ret = alggroup(_gal, _p)
        return new_gen(_ret)

    def alggroupcenter(self, gal, p=None, cc=None):
        r'''
        Initializes the center :math:`Z(K[G])` of the group algebra :math:`K[G]` over :math:`K = \mathbb{Q}`
        (:math:`p = 0` or omitted) or :math:`\mathbb{F}_p` where :math:`G` is the underlying group of the
        :literal:`galoisinit` structure :emphasis:`gal`. The input :emphasis:`gal` is also allowed to
        be a :literal:`t_VEC` of permutations that is closed under products.
        Sets :emphasis:`cc` to a :literal:`t_VEC` :math:`[elts,conjclass,rep,flag]`
        where :emphasis:`elts` is a sorted :literal:`t_VEC` containing the list of elements
        of :math:`G`, :emphasis:`conjclass` is a :literal:`t_VECSMALL` of the same length as :emphasis:`elts`
        containing the index of the conjugacy class of the corresponding element (an
        integer between :math:`1` and the number of conjugacy classes), and :emphasis:`rep` is a
        :literal:`t_VECSMALL` of length the number of conjugacy classes giving for each
        conjugacy class the index in :emphasis:`elts` of a representative of this conjugacy
        class. Finally :emphasis:`flag` is :math:`1` if and only if the permutation
        representation of :math:`G` is transitive, in which case the :math:`i`-th element
        of :emphasis:`elts` is characterized by :math:`g[1] = i`; this is always the case
        when :emphasis:`gal` is a :literal:`galoisinit` structure. The basis of :math:`Z(K[G])` as
        output consists of the indicator functions of the conjugacy classes in the
        ordering given by :emphasis:`cc`. Example:

        ::

        ? K = nfsplitting(x^4+x+1);
        ? gal = galoisinit(K); \\ S4
        ? al = alggroupcenter(gal,,&cc);
        ? algiscommutative(al)
        %4 = 1
        ? #cc[3] \\ number of conjugacy classes of S4
        %5 = 5
        ? gal = [Vecsmall([1,2,3]),Vecsmall([1,3,2])]; \\ C2
        ? al = alggroupcenter(gal,,&cc);
        ? cc[3]
        %8 = Vecsmall([1, 2])
        ? cc[4]
        %9 = 0
        '''
        gal = objtogen(gal)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        cdef bint _have_cc = (cc is not None)
        if _have_cc:
            raise NotImplementedError("optional argument cc not available")
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN * _cc = NULL
        cdef GEN _ret = alggroupcenter(_gal, _p, _cc)
        return new_gen(_ret)

    def alghasse(self, al, pl):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit` and a prime
        ideal or an integer between :math:`1` and :math:`r_1+r_2`, returns a :literal:`t_FRAC` :math:`h` : the
        local Hasse invariant of :emphasis:`al` at the place specified by :emphasis:`pl`.

        ::

        ? nf = nfinit(y^2-5);
        ? A = alginit(nf, [-1,y]);
        ? alghasse(A, 1)
        %3 = 1/2
        ? alghasse(A, 2)
        %4 = 0
        ? alghasse(A, idealprimedec(nf,2)[1])
        %5 = 1/2
        ? alghasse(A, idealprimedec(nf,5)[1])
        %6 = 0
        '''
        al = objtogen(al)
        pl = objtogen(pl)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _pl = (<Gen>pl).g
        cdef GEN _ret = alghasse(_al, _pl)
        return new_gen(_ret)

    def alghassef(self, al):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, returns
        a :literal:`t_VEC` :math:`[PR, h_f]` describing the local Hasse invariants at the
        finite places of the center: :literal:`PR` is a :literal:`t_VEC` of primes and :math:`h_f` is a
        :literal:`t_VECSMALL` of integers modulo the degree :math:`d` of :emphasis:`al`. The Hasse
        invariant of :emphasis:`al` at the primes outside :literal:`PR` is :math:`0`, but :literal:`PR` can
        include primes at which the Hasse invariant is :math:`0`.

        ::

        ? nf = nfinit(y^2-5);
        ? A = alginit(nf, [-1,2*y-1]);
        ? [PR,hf] = alghassef(A);
        ? PR
        %4 = [[19, [10, 2]~, 1, 1, [-8, 2; 2, -10]], [2, [2, 0]~, 1, 2, 1]]
        ? hf
        %5 = Vecsmall([1, 0])
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = alghassef(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def alghassei(self, al):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, returns
        a :literal:`t_VECSMALL` :math:`h_i` of :math:`r_1` integers modulo the degree :math:`d` of :emphasis:`al`,
        where :math:`r_1` is the number of real places of the center: the local Hasse
        invariants of :emphasis:`al` at infinite places.

        ::

        ? nf = nfinit(y^2-5);
        ? A = alginit(nf, [-1,y]);
        ? alghassei(A)
        %3 = Vecsmall([1, 0])
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = alghassei(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algindex(self, al, pl=None):
        r'''
        Returns the index of the central simple algebra :math:`A` over :math:`K` (as output by
        alginit), that is the degree :math:`e` of the unique central division algebra :math:`D`
        over :math:`K` such that :math:`A` is isomorphic to some matrix algebra :math:`M_k(D)`. If
        :emphasis:`pl` is set, it should be a prime ideal of :math:`K` or an integer between :math:`1`
        and :math:`r_1+r_2`, and in that case return the local index at the place :emphasis:`pl`
        instead.

        ::

        ? nf = nfinit(y^2-5);
        ? A = alginit(nf, [-1,y]);
        ? algindex(A, 1)
        %3 = 2
        ? algindex(A, 2)
        %4 = 1
        ? algindex(A, idealprimedec(nf,2)[1])
        %5 = 2
        ? algindex(A, idealprimedec(nf,5)[1])
        %6 = 1
        ? algindex(A)
        %7 = 2
        '''
        al = objtogen(al)
        cdef bint _have_pl = (pl is not None)
        if _have_pl:
            pl = objtogen(pl)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _pl = NULL
        if _have_pl:
            _pl = (<Gen>pl).g
        cdef long _ret = algindex(_al, _pl)
        clear_stack()
        return _ret

    def alginit(self, B, C, v=None, long maxord=1):
        r'''
        Initializes the central simple algebra defined by data :math:`B`, :math:`C` and
        variable :math:`v`, as follows.

        - (multiplication table) :math:`B` is the base number field :math:`K` in :literal:`nfinit`
        form, :math:`C` is a "multiplication table" over :math:`K`.
        As a :math:`K`-vector space, the algebra is generated by a basis
        :math:`(e_1 = 1,..., e_n)`; the table is given as a :literal:`t_VEC` of :math:`n` matrices in
        :math:`M_n(K)`, giving the left multiplication by the basis elements :math:`e_i`, in the
        given basis.
        Assumes that :math:`e_1 = 1`, that the multiplication table is integral, and that
        :math:`(\bigoplus_{i = 1}^nK e_i,C)` describes a central simple algebra over :math:`K`.

        ::

        { mi = [0,-1,0, 0;
        1, 0,0, 0;
        0, 0,0,-1;
        0, 0,1, 0];
        mj = [0, 0,-1,0;
        0, 0, 0,1;
        1, 0, 0,0;
        0,-1, 0,0];
        mk = [0, 0, 0, 0;
        0, 0,-1, 0;
        0, 1, 0, 0;
        1, 0, 0,-1];
        A = alginit(nfinit(y), [matid(4), mi,mj,mk], 0); }

        represents (in a complicated way) the quaternion algebra :math:`(-1,-1)_\mathbb{Q}`.
        See below for a simpler solution.

        - (cyclic algebra) :math:`B` is an :literal:`rnf` structure attached to a cyclic
        number field extension :math:`L/K` of degree :math:`d`, :math:`C` is a :literal:`t_VEC`
        :literal:`[sigma,b]` with 2 components: :literal:`sigma` is a :literal:`t_POLMOD` representing
        an automorphism generating :math:`Gal(L/K)`, :math:`b` is an element in :math:`K^*`. This
        represents the cyclic algebra :math:`(L/K,\sigma,b)`. Currently the element :math:`b` has
        to be integral.

        ::

        ? Q = nfinit(y); T = polcyclo(5, 'x); F = rnfinit(Q, T);
        ? A = alginit(F, [Mod(x^2,T), 3]);

        defines the cyclic algebra :math:`(L/\mathbb{Q}, \sigma, 3)`, where
        :math:`L = \mathbb{Q} (\zeta_5)` and :math:`\sigma:\zeta:--->\zeta^2` generates
        :math:`Gal(L/\mathbb{Q})`.

        - (quaternion algebra, special case of the above) :math:`B` is an :literal:`nf`
        structure attached to a number field :math:`K`, :math:`C = [a,b]` is a vector
        containing two elements of :math:`K^*` with :math:`a` not a square in :math:`K`, returns the quaternion algebra :math:`(a,b)_K`.
        The variable :math:`v` (:literal:`'x` by default) must have higher priority than the
        variable of :math:`K`:literal:`.pol` and is used to represent elements in the splitting
        field :math:`L = K[x]/(x^2-a)`.

        ::

        ? Q = nfinit(y); A = alginit(Q, [-1,-1]); \\ (-1,-1)_Q

        - (algebra/:math:`K` defined by local Hasse invariants)
        :math:`B` is an :literal:`nf` structure attached to a number field :math:`K`,
        :math:`C = [d, [PR,h_f], h_i]` is a triple
        containing an integer :math:`d > 1`, a pair :math:`[PR, h_f]` describing the
        Hasse invariants at finite places, and :math:`h_i` the Hasse invariants
        at archimedean (real) places. A local Hasse invariant belongs to :math:`(1/d)\mathbb{Z}/\mathbb{Z}
        \subset \mathbb{Q}/\mathbb{Z}`, and is given either as a :literal:`t_FRAC` (lift to :math:`(1/d)\mathbb{Z}`),
        a :literal:`t_INT` or :literal:`t_INTMOD` modulo :math:`d` (lift to :math:`\mathbb{Z}/d\mathbb{Z}`); a whole vector
        of local invariants can also be given as a :literal:`t_VECSMALL`, whose
        entries are handled as :literal:`t_INT` s. :literal:`PR` is a list of prime ideals
        (:literal:`prid` structures), and :math:`h_f` is a vector of the same length giving the
        local invariants at those maximal ideals. The invariants at infinite real
        places are indexed by the real roots :math:`K`:literal:`.roots`: if the Archimedean
        place :math:`v` is attached to the :math:`j`-th root, the value of
        :math:`h_v` is given by :math:`h_i[j]`, must be :math:`0` or :math:`1/2` (or :math:`d/2` modulo :math:`d`), and
        can be nonzero only if :math:`d` is even.

        By class field theory, provided the local invariants :math:`h_v` sum to :math:`0`, up
        to Brauer equivalence, there is a unique central simple algebra over :math:`K`
        with given local invariants and trivial invariant elsewhere. In particular,
        up to isomorphism, there is a unique such algebra :math:`A` of degree :math:`d`.

        We realize :math:`A` as a cyclic algebra through class field theory. The variable :math:`v`
        (:literal:`'x` by default) must have higher priority than the variable of
        :math:`K`:literal:`.pol` and is used to represent elements in the (cyclic) splitting
        field extension :math:`L/K` for :math:`A`.

        ::

        ? nf = nfinit(y^2+1);
        ? PR = idealprimedec(nf,5); #PR
        %2 = 2
        ? hi = [];
        ? hf = [PR, [1/3,-1/3]];
        ? A = alginit(nf, [3,hf,hi]);
        ? algsplittingfield(A).pol
        %6 = x^3 - 21*x + 7

        - (matrix algebra, toy example) :math:`B` is an :literal:`nf` structure attached
        to a number field :math:`K`, :math:`C = d` is a positive integer. Returns a cyclic
        algebra isomorphic to the matrix algebra :math:`M_d(K)`.

        In all cases, this function computes a maximal order for the algebra by default,
        which may require a lot of time. Setting :math:`maxord = 0` prevents this computation.

        The pari object representing such an algebra :math:`A` is a :literal:`t_VEC` with the
        following data:

        - A splitting field :math:`L` of :math:`A` of the same degree over :math:`K` as :math:`A`, in
        :literal:`rnfinit` format, accessed with :literal:`algsplittingfield`.

        - The Hasse invariants at the real places of :math:`K`, accessed with
        :literal:`alghassei`.

        - The Hasse invariants of :math:`A` at the finite primes of :math:`K` that ramify in
        the natural order of :math:`A`, accessed with :literal:`alghassef`.

        - A basis of an order :math:`O_0` expressed on the basis of the natural
        order, accessed with :literal:`algbasis`.

        - A basis of the natural order expressed on the basis of :math:`O_0`,
        accessed with :literal:`alginvbasis`.

        - The left multiplication table of :math:`O_0` on the previous basis,
        accessed with :literal:`algmultable`.

        - The characteristic of :math:`A` (always :math:`0`), accessed with :literal:`algchar`.

        - The absolute traces of the elements of the basis of :math:`O_0`.

        - If :math:`A` was constructed as a cyclic algebra :math:`(L/K,\sigma,b)` of degree
        :math:`d`, a :literal:`t_VEC` :math:`[\sigma,\sigma^2,...,\sigma^{d-1}]`. The function
        :literal:`algaut` returns :math:`\sigma`.

        - If :math:`A` was constructed as a cyclic algebra :math:`(L/K,\sigma,b)`, the
        element :math:`b`, accessed with :literal:`algb`.

        - If :math:`A` was constructed with its multiplication table :math:`mt` over :math:`K`,
        the :literal:`t_VEC` of :literal:`t_MAT` :math:`mt`, accessed with :literal:`algrelmultable`.

        - If :math:`A` was constructed with its multiplication table :math:`mt` over :math:`K`,
        a :literal:`t_VEC` with three components: a :literal:`t_COL` representing an element of :math:`A`
        generating the splitting field :math:`L` as a maximal subfield of :math:`A`, a :literal:`t_MAT`
        representing an :math:`L`-basis :math:`B` of :math:`A` expressed on the :math:`\mathbb{Z}`-basis of
        :math:`O_0`, and a :literal:`t_MAT` representing the :math:`\mathbb{Z}`-basis of :math:`O_0`
        expressed on :math:`B`. This data is accessed with :literal:`algsplittingdata`.
        '''
        B = objtogen(B)
        C = objtogen(C)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _B = (<Gen>B).g
        cdef GEN _C = (<Gen>C).g
        cdef GEN _ret = alginit(_B, _C, _v, maxord)
        return new_gen(_ret)

    def alginv(self, al, x):
        r'''
        Given an element :math:`x` in :emphasis:`al`, computes its inverse :math:`x^{-1}` in the
        algebra :emphasis:`al`. Assumes that :math:`x` is invertible.

        ::

        ? A = alginit(nfinit(y), [-1,-1]);
        ? alginv(A,[1,1,0,0]~)
        %2 = [1/2, 1/2, 0, 0]~

        Also accepts matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = alginv(_al, _x)
        return new_gen(_ret)

    def alginvbasis(self, al):
        r'''
        Given an central simple algebra :emphasis:`al` output by :literal:`alginit`, returns
        a :math:`\mathbb{Z}`-basis of the natural order in :emphasis:`al` with respect to the
        order :math:`O_0` stored in :emphasis:`al`.

        ::

        A = alginit(nfinit(y), [-1,-1]);
        ? alginvbasis(A)
        %2 =
        [1 0 0 -1]
        
        [0 1 0 -1]
        
        [0 0 1 -1]
        
        [0 0 0 2]
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = alginvbasis(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algisassociative(self, mt, p=None):
        r'''
        Returns 1 if the multiplication table :literal:`mt` is suitable for
        :literal:`algtableinit(mt,p)`, 0 otherwise. More precisely, :literal:`mt` should be
        a :literal:`t_VEC` of :math:`n` matrices in :math:`M_n(K)`, giving the left multiplications
        by the basis elements :math:`e_1,..., e_n` (structure constants).
        We check whether the first basis element :math:`e_1` is :math:`1` and :math:`e_i(e_je_k) =
        (e_ie_j)e_k` for all :math:`i,j,k`.

        ::

        ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
        ? algisassociative(mt)
        %2 = 1

        May be used to check a posteriori an algebra: we also allow :literal:`mt` as
        output by :literal:`algtableinit` (:math:`p` is ignored in this case).
        '''
        mt = objtogen(mt)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _mt = (<Gen>mt).g
        cdef GEN _p = gen_0
        if _have_p:
            _p = (<Gen>p).g
        cdef int _ret = algisassociative(_mt, _p)
        clear_stack()
        return _ret

    def algiscommutative(self, al):
        r'''
        :emphasis:`al` being a table algebra output by :literal:`algtableinit` or a central
        simple algebra output by :literal:`alginit`, tests whether the algebra :emphasis:`al` is
        commutative.

        ::

        ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
        ? A = algtableinit(mt);
        ? algiscommutative(A)
        %3 = 0
        ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
        ? A = algtableinit(mt,2);
        ? algiscommutative(A)
        %6 = 1
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef int _ret = algiscommutative(_al)
        clear_stack()
        return _ret

    def algisdivision(self, al, pl=None):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, tests
        whether :emphasis:`al` is a division algebra. If :emphasis:`pl` is set, it should be a
        prime ideal of :math:`K` or an integer between :math:`1` and :math:`r_1+r_2`, and in that case
        tests whether :emphasis:`al` is locally a division algebra at the place :emphasis:`pl`
        instead.

        ::

        ? nf = nfinit(y^2-5);
        ? A = alginit(nf, [-1,y]);
        ? algisdivision(A, 1)
        %3 = 1
        ? algisdivision(A, 2)
        %4 = 0
        ? algisdivision(A, idealprimedec(nf,2)[1])
        %5 = 1
        ? algisdivision(A, idealprimedec(nf,5)[1])
        %6 = 0
        ? algisdivision(A)
        %7 = 1
        '''
        al = objtogen(al)
        cdef bint _have_pl = (pl is not None)
        if _have_pl:
            pl = objtogen(pl)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _pl = NULL
        if _have_pl:
            _pl = (<Gen>pl).g
        cdef int _ret = algisdivision(_al, _pl)
        clear_stack()
        return _ret

    def algisdivl(self, al, x, y, z=None):
        r'''
        Given two elements :math:`x` and :math:`y` in :emphasis:`al`, tests whether :math:`y` is left
        divisible by :math:`x`, that is whether there exists :math:`z` in :emphasis:`al` such
        that :math:`xz = y`, and sets :math:`z` to this element if it exists.

        ::

        ? A = alginit(nfinit(y), [-1,1]);
        ? algisdivl(A,[x+2,-x-2]~,[x,1]~)
        %2 = 0
        ? algisdivl(A,[x+2,-x-2]~,[-x,x]~,&z)
        %3 = 1
        ? z
        %4 = [Mod(-2/5*x - 1/5, x^2 + 1), 0]~

        Also accepts matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        y = objtogen(y)
        cdef bint _have_z = (z is not None)
        if _have_z:
            raise NotImplementedError("optional argument z not available")
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN * _z = NULL
        cdef int _ret = algisdivl(_al, _x, _y, _z)
        clear_stack()
        return _ret

    def algisinv(self, al, x, ix=None):
        r'''
        Given an element :math:`x` in :emphasis:`al`, tests whether :math:`x` is invertible, and sets
        :math:`ix` to the inverse of :math:`x`.

        ::

        ? A = alginit(nfinit(y), [-1,1]);
        ? algisinv(A,[-1,1]~)
        %2 = 0
        ? algisinv(A,[1,2]~,&ix)
        %3 = 1
        ? ix
        %4 = [Mod(Mod(-1/3, y), x^2 + 1), Mod(Mod(2/3, y), x^2 + 1)]~

        Also accepts matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        cdef bint _have_ix = (ix is not None)
        if _have_ix:
            raise NotImplementedError("optional argument ix not available")
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _ix = NULL
        cdef int _ret = algisinv(_al, _x, _ix)
        clear_stack()
        return _ret

    def algisramified(self, al, pl=None):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, tests
        whether :emphasis:`al` is ramified, i.e. not isomorphic to a matrix algebra over its
        center. If :emphasis:`pl` is set, it should be a prime ideal of :math:`K` or an integer
        between :math:`1` and :math:`r_1+r_2`, and in that case tests whether :emphasis:`al` is locally
        ramified at the place :emphasis:`pl` instead.

        ::

        ? nf = nfinit(y^2-5);
        ? A = alginit(nf, [-1,y]);
        ? algisramified(A, 1)
        %3 = 1
        ? algisramified(A, 2)
        %4 = 0
        ? algisramified(A, idealprimedec(nf,2)[1])
        %5 = 1
        ? algisramified(A, idealprimedec(nf,5)[1])
        %6 = 0
        ? algisramified(A)
        %7 = 1
        '''
        al = objtogen(al)
        cdef bint _have_pl = (pl is not None)
        if _have_pl:
            pl = objtogen(pl)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _pl = NULL
        if _have_pl:
            _pl = (<Gen>pl).g
        cdef int _ret = algisramified(_al, _pl)
        clear_stack()
        return _ret

    def algissemisimple(self, al):
        r'''
        :emphasis:`al` being a table algebra output by :literal:`algtableinit` or a central
        simple algebra output by :literal:`alginit`, tests whether the algebra :emphasis:`al` is
        semisimple.

        ::

        ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
        ? A = algtableinit(mt);
        ? algissemisimple(A)
        %3 = 0
        ? m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; \\ quaternion algebra (-1,-1)
        ? m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
        ? m_k=[0,0,0,-1;0,0,-1,0;0,1,0,0;1,0,0,0];
        ? mt = [matid(4), m_i, m_j, m_k];
        ? A = algtableinit(mt);
        ? algissemisimple(A)
        %9 = 1
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef int _ret = algissemisimple(_al)
        clear_stack()
        return _ret

    def algissimple(self, al, long ss=0):
        r'''
        :emphasis:`al` being a table algebra output by :literal:`algtableinit` or a central
        simple algebra output by :literal:`alginit`, tests whether the algebra :emphasis:`al` is
        simple. If :math:`ss = 1`, assumes that the algebra :emphasis:`al` is semisimple
        without testing it.

        ::

        ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
        ? A = algtableinit(mt); \\ matrices [*,*; 0,*]
        ? algissimple(A)
        %3 = 0
        ? algissimple(A,1) \\ incorrectly assume that A is semisimple
        %4 = 1
        ? m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
        ? m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
        ? m_k=[0,0,0,-1;0,0,b,0;0,1,0,0;1,0,0,0];
        ? mt = [matid(4), m_i, m_j, m_k];
        ? A = algtableinit(mt); \\ quaternion algebra (-1,-1)
        ? algissimple(A)
        %10 = 1
        ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
        ? A = algtableinit(mt,2); \\ direct product F_4 x F_2
        ? algissimple(A)
        %13 = 0
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef int _ret = algissimple(_al, ss)
        clear_stack()
        return _ret

    def algissplit(self, al, pl=None):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, tests
        whether :emphasis:`al` is split, i.e. isomorphic to a matrix algebra over its center.
        If :emphasis:`pl` is set, it should be a prime ideal of :math:`K` or an integer between :math:`1`
        and :math:`r_1+r_2`, and in that case tests whether :emphasis:`al` is locally split at the
        place :emphasis:`pl` instead.

        ::

        ? nf = nfinit(y^2-5);
        ? A = alginit(nf, [-1,y]);
        ? algissplit(A, 1)
        %3 = 0
        ? algissplit(A, 2)
        %4 = 1
        ? algissplit(A, idealprimedec(nf,2)[1])
        %5 = 0
        ? algissplit(A, idealprimedec(nf,5)[1])
        %6 = 1
        ? algissplit(A)
        %7 = 0
        '''
        al = objtogen(al)
        cdef bint _have_pl = (pl is not None)
        if _have_pl:
            pl = objtogen(pl)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _pl = NULL
        if _have_pl:
            _pl = (<Gen>pl).g
        cdef int _ret = algissplit(_al, _pl)
        clear_stack()
        return _ret

    def alglatadd(self, al, lat1, lat2, ptinter=None):
        r'''
        Given an algebra :emphasis:`al` and two lattices :emphasis:`lat1` and :emphasis:`lat2`
        in :emphasis:`al`, computes the sum :math:`lat1 + lat2`. If :emphasis:`ptinter` is
        present, set it to the intersection :math:`lat1 \cap lat2`.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? lat1 = alglathnf(al,[1,1,0,0,0,0,0,0]~);
        ? lat2 = alglathnf(al,[1,0,1,0,0,0,0,0]~);
        ? latsum = alglatadd(al,lat1,lat2,&latinter);
        ? matdet(latsum[1])
        %5 = 4
        ? matdet(latinter[1])
        %6 = 64
        '''
        al = objtogen(al)
        lat1 = objtogen(lat1)
        lat2 = objtogen(lat2)
        cdef bint _have_ptinter = (ptinter is not None)
        if _have_ptinter:
            raise NotImplementedError("optional argument ptinter not available")
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _lat1 = (<Gen>lat1).g
        cdef GEN _lat2 = (<Gen>lat2).g
        cdef GEN * _ptinter = NULL
        cdef GEN _ret = alglatadd(_al, _lat1, _lat2, _ptinter)
        return new_gen(_ret)

    def alglatcontains(self, al, lat, x, ptc=None):
        r'''
        Given an algebra :emphasis:`al`, a lattice :emphasis:`lat` and :emphasis:`x` in :emphasis:`al`,
        tests whether :math:`x\in lat`. If :emphasis:`ptc` is present, sets it to the :literal:`t_COL` of
        coordinates of :math:`x` in the basis of :emphasis:`lat`.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? a1 = [1,-1,0,1,2,0,1,2]~;
        ? lat1 = alglathnf(al,a1);
        ? alglatcontains(al,lat1,a1,&c)
        %4 = 1
        ? c
        %5 = [-1, -2, -1, 1, 2, 0, 1, 1]~
        '''
        al = objtogen(al)
        lat = objtogen(lat)
        x = objtogen(x)
        cdef bint _have_ptc = (ptc is not None)
        if _have_ptc:
            raise NotImplementedError("optional argument ptc not available")
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _lat = (<Gen>lat).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _ptc = NULL
        cdef int _ret = alglatcontains(_al, _lat, _x, _ptc)
        clear_stack()
        return _ret

    def alglatelement(self, al, lat, c):
        r'''
        Given an algebra :emphasis:`al`, a lattice :emphasis:`lat` and a :literal:`t_COL` :emphasis:`c`,
        returns the element of :emphasis:`al` whose coordinates on the \mathbb{Z}-basis of :emphasis:`lat`
        are given by :emphasis:`c`.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? a1 = [1,-1,0,1,2,0,1,2]~;
        ? lat1 = alglathnf(al,a1);
        ? c = [1..8]~;
        ? elt = alglatelement(al,lat1,c);
        ? alglatcontains(al,lat1,elt,&c2)
        %6 = 1
        ? c==c2
        %7 = 1
        '''
        al = objtogen(al)
        lat = objtogen(lat)
        c = objtogen(c)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _lat = (<Gen>lat).g
        cdef GEN _c = (<Gen>c).g
        cdef GEN _ret = alglatelement(_al, _lat, _c)
        return new_gen(_ret)

    def alglathnf(self, al, m, d=None):
        r'''
        Given an algebra :emphasis:`al` and a matrix :emphasis:`m` with columns representing
        elements of :emphasis:`al`, returns the lattice :math:`L` generated by the columns of
        :emphasis:`m`. If provided, :emphasis:`d` must be a rational number such that :math:`L` contains
        :emphasis:`d` times the natural basis of :emphasis:`al`. The argument :emphasis:`m` is also
        allowed to be a :literal:`t_VEC` of :literal:`t_MAT`, in which case :emphasis:`m` is replaced by
        the concatenation of the matrices, or a :literal:`t_COL`, in which case :emphasis:`m` is
        replaced by its left multiplication table as an element of :emphasis:`al`.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? a = [1,1,-1/2,1,1/3,-1,1,1]~;
        ? mt = algtomatrix(al,a,1);
        ? lat = alglathnf(al,mt);
        ? lat[2]
        %5 = 1/6
        '''
        al = objtogen(al)
        m = objtogen(m)
        cdef bint _have_d = (d is not None)
        if _have_d:
            d = objtogen(d)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _m = (<Gen>m).g
        cdef GEN _d = gen_0
        if _have_d:
            _d = (<Gen>d).g
        cdef GEN _ret = alglathnf(_al, _m, _d)
        return new_gen(_ret)

    def alglatindex(self, al, lat1, lat2):
        r'''
        Given an algebra :emphasis:`al` and two lattices :emphasis:`lat1` and :emphasis:`lat2`
        in :emphasis:`al`, computes the generalized index of :emphasis:`lat1` relative
        to :emphasis:`lat2`, i.e. :math:`\|lat2/lat1\cap lat2\|/\|lat1/lat1\cap lat2\|`.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? lat1 = alglathnf(al,[1,1,0,0,0,0,0,0]~);
        ? lat2 = alglathnf(al,[1,0,1,0,0,0,0,0]~);
        ? alglatindex(al,lat1,lat2)
        %4 = 1
        ? lat1==lat2
        %5 = 0
        '''
        al = objtogen(al)
        lat1 = objtogen(lat1)
        lat2 = objtogen(lat2)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _lat1 = (<Gen>lat1).g
        cdef GEN _lat2 = (<Gen>lat2).g
        cdef GEN _ret = alglatindex(_al, _lat1, _lat2)
        return new_gen(_ret)

    def alglatinter(self, al, lat1, lat2, ptsum=None):
        r'''
        Given an algebra :emphasis:`al` and two lattices :emphasis:`lat1` and :emphasis:`lat2`
        in :emphasis:`al`, computes the intersection :math:`lat1\cap lat2`. If :emphasis:`ptsum` is
        present, sets it to the sum :math:`lat1 + lat2`.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? lat1 = alglathnf(al,[1,1,0,0,0,0,0,0]~);
        ? lat2 = alglathnf(al,[1,0,1,0,0,0,0,0]~);
        ? latinter = alglatinter(al,lat1,lat2,&latsum);
        ? matdet(latsum[1])
        %5 = 4
        ? matdet(latinter[1])
        %6 = 64
        '''
        al = objtogen(al)
        lat1 = objtogen(lat1)
        lat2 = objtogen(lat2)
        cdef bint _have_ptsum = (ptsum is not None)
        if _have_ptsum:
            raise NotImplementedError("optional argument ptsum not available")
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _lat1 = (<Gen>lat1).g
        cdef GEN _lat2 = (<Gen>lat2).g
        cdef GEN * _ptsum = NULL
        cdef GEN _ret = alglatinter(_al, _lat1, _lat2, _ptsum)
        return new_gen(_ret)

    def alglatlefttransporter(self, al, lat1, lat2):
        r'''
        Given an algebra :emphasis:`al` and two lattices :emphasis:`lat1` and :emphasis:`lat2`
        in :emphasis:`al`, computes the left transporter from :emphasis:`lat1` to :emphasis:`lat2`, i.e.
        the set of :math:`x\in al` such that :math:`x.lat1 \subset lat2`.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? lat1 = alglathnf(al,[1,-1,0,1,2,0,5,2]~);
        ? lat2 = alglathnf(al,[0,1,-2,-1,0,0,3,1]~);
        ? tr = alglatlefttransporter(al,lat1,lat2);
        ? a = alglatelement(al,tr,[0,0,0,0,0,0,1,0]~);
        ? alglatsubset(al,alglatmul(al,a,lat1),lat2)
        %6 = 1
        ? alglatsubset(al,alglatmul(al,lat1,a),lat2)
        %7 = 0
        '''
        al = objtogen(al)
        lat1 = objtogen(lat1)
        lat2 = objtogen(lat2)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _lat1 = (<Gen>lat1).g
        cdef GEN _lat2 = (<Gen>lat2).g
        cdef GEN _ret = alglatlefttransporter(_al, _lat1, _lat2)
        return new_gen(_ret)

    def alglatmul(self, al, lat1, lat2):
        r'''
        Given an algebra :emphasis:`al` and two lattices :emphasis:`lat1` and :emphasis:`lat2`
        in :emphasis:`al`, computes the lattice generated by the products of elements
        of :emphasis:`lat1` and :emphasis:`lat2`.
        One of :emphasis:`lat1` and :emphasis:`lat2` is also allowed to be an element of :emphasis:`al`;
        in this case, computes the product of the element and the lattice.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? a1 = [1,-1,0,1,2,0,1,2]~;
        ? a2 = [0,1,2,-1,0,0,3,1]~;
        ? lat1 = alglathnf(al,a1);
        ? lat2 = alglathnf(al,a2);
        ? lat3 = alglatmul(al,lat1,lat2);
        ? matdet(lat3[1])
        %7 = 29584
        ? lat3 == alglathnf(al, algmul(al,a1,a2))
        %8 = 0
        ? lat3 == alglatmul(al, lat1, a2)
        %9 = 0
        ? lat3 == alglatmul(al, a1, lat2)
        %10 = 0
        '''
        al = objtogen(al)
        lat1 = objtogen(lat1)
        lat2 = objtogen(lat2)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _lat1 = (<Gen>lat1).g
        cdef GEN _lat2 = (<Gen>lat2).g
        cdef GEN _ret = alglatmul(_al, _lat1, _lat2)
        return new_gen(_ret)

    def alglatrighttransporter(self, al, lat1, lat2):
        r'''
        Given an algebra :emphasis:`al` and two lattices :emphasis:`lat1` and :emphasis:`lat2`
        in :emphasis:`al`, computes the right transporter from :emphasis:`lat1` to :emphasis:`lat2`, i.e.
        the set of :math:`x\in al` such that :math:`lat1.x \subset lat2`.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? lat1 = alglathnf(al,matdiagonal([1,3,7,1,2,8,5,2]));
        ? lat2 = alglathnf(al,matdiagonal([5,3,8,1,9,8,7,1]));
        ? tr = alglatrighttransporter(al,lat1,lat2);
        ? a = alglatelement(al,tr,[0,0,0,0,0,0,0,1]~);
        ? alglatsubset(al,alglatmul(al,lat1,a),lat2)
        %6 = 1
        ? alglatsubset(al,alglatmul(al,a,lat1),lat2)
        %7 = 0
        '''
        al = objtogen(al)
        lat1 = objtogen(lat1)
        lat2 = objtogen(lat2)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _lat1 = (<Gen>lat1).g
        cdef GEN _lat2 = (<Gen>lat2).g
        cdef GEN _ret = alglatrighttransporter(_al, _lat1, _lat2)
        return new_gen(_ret)

    def alglatsubset(self, al, lat1, lat2, ptindex=None):
        r'''
        Given an algebra :emphasis:`al` and two lattices :emphasis:`lat1` and :emphasis:`lat2`
        in :emphasis:`al`, tests whether :math:`lat1\subset lat2`. If it is true and :emphasis:`ptindex`
        is present, sets it to the index of :emphasis:`lat1` in :emphasis:`lat2`.

        ::

        ? al = alginit(nfinit(y^2+7), [-1,-1]);
        ? lat1 = alglathnf(al,[1,1,0,0,0,0,0,0]~);
        ? lat2 = alglathnf(al,[1,0,1,0,0,0,0,0]~);
        ? alglatsubset(al,lat1,lat2)
        %4 = 0
        ? latsum = alglatadd(al,lat1,lat2);
        ? alglatsubset(al,lat1,latsum,&index)
        %6 = 1
        ? index
        %7 = 4
        '''
        al = objtogen(al)
        lat1 = objtogen(lat1)
        lat2 = objtogen(lat2)
        cdef bint _have_ptindex = (ptindex is not None)
        if _have_ptindex:
            raise NotImplementedError("optional argument ptindex not available")
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _lat1 = (<Gen>lat1).g
        cdef GEN _lat2 = (<Gen>lat2).g
        cdef GEN * _ptindex = NULL
        cdef int _ret = alglatsubset(_al, _lat1, _lat2, _ptindex)
        clear_stack()
        return _ret

    def algmakeintegral(self, mt, long maps=0):
        r'''
        :emphasis:`mt` being a multiplication table over :math:`\mathbb{Q}` in the same format as the
        input of :literal:`algtableinit`, computes an integral multiplication table for an
        isomorphic algebra. When :math:`maps = 1`, returns a :literal:`t_VEC`
        :math:`[mt2,S,T]` where :emphasis:`S` and :emphasis:`T` are matrices
        respectively representing the map from the algebra defined by :emphasis:`mt` to the
        one defined by :emphasis:`mt2` and its inverse.

        ::

        ? mt = [matid(2),[0,-1/4;1,0]];
        ? algtableinit(mt);
        *** at top-level: algtableinit(mt)
        *** ^----------------
        *** algtableinit: domain error in algtableinit: denominator(mt) != 1
        ? mt2 = algmakeintegral(mt);
        ? al = algtableinit(mt2);
        ? algisassociative(al)
        %4 = 1
        '''
        mt = objtogen(mt)
        sig_on()
        cdef GEN _mt = (<Gen>mt).g
        cdef GEN _ret = algmakeintegral(_mt, maps)
        return new_gen(_ret)

    def algmul(self, al, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in :emphasis:`al`, computes their product :math:`xy`
        in the algebra :emphasis:`al`.

        ::

        ? A = alginit(nfinit(y), [-1,-1]);
        ? algmul(A,[1,1,0,0]~,[0,0,2,1]~)
        %2 = [2, 3, 5, -4]~

        Also accepts matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = algmul(_al, _x, _y)
        return new_gen(_ret)

    def algmultable(self, al):
        r'''
        Returns a multiplication table of :emphasis:`al` over its
        prime subfield (:math:`\mathbb{Q}` or :math:`\mathbb{F}_p`), as a :literal:`t_VEC` of :literal:`t_MAT`: the left
        multiplication tables of basis elements. If :emphasis:`al` was output by
        :literal:`algtableinit`, returns the multiplication table used to define :emphasis:`al`.
        If :emphasis:`al` was output by :literal:`alginit`, returns the multiplication table of
        the order :math:`O_0` stored in :emphasis:`al`.

        ::

        ? A = alginit(nfinit(y), [-1,-1]);
        ? M = algmultable(A);
        ? #M
        %3 = 4
        ? M[1] \\ multiplication by e_1 = 1
        %4 =
        [1 0 0 0]
        
        [0 1 0 0]
        
        [0 0 1 0]
        
        [0 0 0 1]
        
        ? M[2]
        %5 =
        [0 -1 1 0]
        
        [1 0 1 1]
        
        [0 0 1 1]
        
        [0 0 -2 -1]
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algmultable(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algneg(self, al, x):
        r'''
        Given an element :math:`x` in :emphasis:`al`, computes its opposite :math:`-x` in the
        algebra :emphasis:`al`.

        ::

        ? A = alginit(nfinit(y), [-1,-1]);
        ? algneg(A,[1,1,0,0]~)
        %2 = [-1, -1, 0, 0]~

        Also accepts matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = algneg(_al, _x)
        return new_gen(_ret)

    def algnorm(self, al, x, long abs=0):
        r'''
        Given an element :emphasis:`x` in :emphasis:`al`, computes its norm. If :emphasis:`al` is
        a table algebra output by :literal:`algtableinit` or if :math:`abs = 1`, returns the
        absolute norm of :emphasis:`x`, which is an element of :math:`\mathbb{F}_p` of :math:`\mathbb{Q}`; if :emphasis:`al` is
        a central simple algebra output by :literal:`alginit` and :math:`abs = 0` (default), returns
        the reduced norm of :emphasis:`x`, which is an element of the center of :emphasis:`al`.

        ::

        ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
        ? A = algtableinit(mt,19);
        ? algnorm(A,[0,-2,3]~)
        %3 = 18
        ? nf = nfinit(y^2-5);
        ? B = alginit(nf,[-1,y]);
        ? b = [x,1]~;
        ? n = algnorm(B,b)
        %7 = Mod(-y + 1, y^2 - 5)
        ? algnorm(B,b,1)
        %8 = 16
        ? nfeltnorm(nf,n)^algdegree(B)
        %9 = 16

        Also accepts a square matrix with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = algnorm(_al, _x, abs)
        return new_gen(_ret)

    def algpoleval(self, al, T, b):
        r'''
        Given an element :math:`b` in :emphasis:`al` and a polynomial :math:`T` in :math:`K[X]`,
        computes :math:`T(b)` in :emphasis:`al`. Also accepts as input a :literal:`t_VEC` :math:`[b,mb]`
        where :math:`mb` is the left multiplication table of :math:`b`.

        ::

        ? nf = nfinit(y^2-5);
        ? al = alginit(nf,[y,-1]);
        ? b = [1..8]~;
        ? pol = algcharpoly(al,b,,1);
        ? algpoleval(al,pol,b)==0
        %5 = 1
        ? mb = algtomatrix(al,b,1);
        ? algpoleval(al,pol,[b,mb])==0
        %7 = 1
        '''
        al = objtogen(al)
        T = objtogen(T)
        b = objtogen(b)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _T = (<Gen>T).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _ret = algpoleval(_al, _T, _b)
        return new_gen(_ret)

    def algpow(self, al, x, n):
        r'''
        Given an element :math:`x` in :emphasis:`al` and an integer :math:`n`, computes the
        power :math:`x^n` in the algebra :emphasis:`al`.

        ::

        ? A = alginit(nfinit(y), [-1,-1]);
        ? algpow(A,[1,1,0,0]~,7)
        %2 = [8, -8, 0, 0]~

        Also accepts a square matrix with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        n = objtogen(n)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = algpow(_al, _x, _n)
        return new_gen(_ret)

    def algprimesubalg(self, al):
        r'''
        :emphasis:`al` being the output of :literal:`algtableinit` representing a semisimple
        algebra of positive characteristic, returns a basis of the prime subalgebra
        of :emphasis:`al`. The prime subalgebra of :emphasis:`al` is the subalgebra fixed by the
        Frobenius automorphism of the center of :emphasis:`al`. It is abstractly isomorphic
        to a product of copies of :math:`\mathbb{F}_p`.

        ::

        ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
        ? A = algtableinit(mt,2);
        ? algprimesubalg(A)
        %3 =
        [1 0]
        
        [0 1]
        
        [0 0]
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algprimesubalg(_al)
        return new_gen(_ret)

    def algquotient(self, al, I, long maps=0):
        r'''
        :emphasis:`al` being a table algebra output by :literal:`algtableinit` and :emphasis:`I`
        being a basis of a two-sided ideal of :emphasis:`al` represented by a matrix,
        returns the quotient :math:`al/I`. When :math:`maps = 1`, returns a
        :literal:`t_VEC` :math:`[al/I,proj,lift]` where :emphasis:`proj` and
        :emphasis:`lift` are matrices respectively representing the projection map and a
        section of it.

        ::

        ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
        ? A = algtableinit(mt,2);
        ? AQ = algquotient(A,[0;1;0]);
        ? algdim(AQ)
        %4 = 2
        '''
        al = objtogen(al)
        I = objtogen(I)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _I = (<Gen>I).g
        cdef GEN _ret = alg_quotient(_al, _I, maps)
        return new_gen(_ret)

    def algradical(self, al):
        r'''
        :emphasis:`al` being a table algebra output by :literal:`algtableinit`, returns a
        basis of the Jacobson radical of the algebra :emphasis:`al` over its prime field
        (:math:`\mathbb{Q}` or :math:`\mathbb{F}_p`).

        Here is an example with :math:`A = \mathbb{Q}[x]/(x^2)`, with the basis :math:`(1,x)`:

        ::

        ? mt = [matid(2),[0,0;1,0]];
        ? A = algtableinit(mt);
        ? algradical(A) \\ = (x)
        %3 =
        [0]
        
        [1]

        Another one with :math:`2 x 2` upper triangular matrices over :math:`\mathbb{Q}`, with basis
        :math:`I_2`, :math:`a = [0,1;0,0]` and :math:`b = [0,0;0,1]`, such that :math:`a^2 =
        0`, :math:`ab = a`, :math:`ba = 0`, :math:`b^2 = b`:

        ::

        ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
        ? A = algtableinit(mt);
        ? algradical(A) \\ = (a)
        %6 =
        [0]
        
        [1]
        
        [0]
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algradical(_al)
        return new_gen(_ret)

    def algramifiedplaces(self, al):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, returns a
        :literal:`t_VEC` containing the list of places of the center of :emphasis:`al` that are
        ramified in :emphasis:`al`. Each place is described as an integer between :math:`1`
        and :math:`r_1` or as a prime ideal.

        ::

        ? nf = nfinit(y^2-5);
        ? A = alginit(nf, [-1,y]);
        ? algramifiedplaces(A)
        %3 = [1, [2, [2, 0]~, 1, 2, 1]]
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algramifiedplaces(_al)
        return new_gen(_ret)

    def algrandom(self, al, b):
        r'''
        Given an algebra :emphasis:`al` and an integer :emphasis:`b`, returns a random
        element in :emphasis:`al` with coefficients in :math:`[-b,b]`.
        '''
        al = objtogen(al)
        b = objtogen(b)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _ret = algrandom(_al, _b)
        return new_gen(_ret)

    def algrelmultable(self, al):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit` defined by a multiplication table over its center (a number field), returns this multiplication table.

        ::

        ? nf = nfinit(y^3-5); a = y; b = y^2;
        ? {m_i = [0,a,0,0;
        1,0,0,0;
        0,0,0,a;
        0,0,1,0];}
        ? {m_j = [0, 0,b, 0;
        0, 0,0,-b;
        1, 0,0, 0;
        0,-1,0, 0];}
        ? {m_k = [0, 0,0,-a*b;
        0, 0,b, 0;
        0,-a,0, 0;
        1, 0,0, 0];}
        ? mt = [matid(4), m_i, m_j, m_k];
        ? A = alginit(nf,mt,'x);
        ? M = algrelmultable(A);
        ? M[2] == m_i
        %8 = 1
        ? M[3] == m_j
        %9 = 1
        ? M[4] == m_k
        %10 = 1
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algrelmultable(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algsimpledec(self, al, long maps=0):
        r'''
        :emphasis:`al` being the output of :literal:`algtableinit`, returns a :literal:`t_VEC`
        :math:`[J,[al_1,al_2,...,al_n]]` where :math:`J` is a basis of the
        Jacobson radical of :emphasis:`al` and :math:`al/J` is isomorphic to the direct
        product of the simple algebras :math:`al_i`. When :math:`maps = 1`,
        each :math:`al_i` is replaced with a :literal:`t_VEC`
        :math:`[al_i,proj_i,lift_i]` where :math:`proj_i` and :math:`lift_i`
        are matrices respectively representing the projection map :math:`al \to
        al_i` and a section of it. Modulo :math:`J`, the images of the :math:`lift_i`
        form a direct sum in :math:`al/J`, so that the images of :math:`1\inal_i`
        under :math:`lift_i` are central primitive idempotents of :math:`al/J`. The
        factors are sorted by increasing dimension, then increasing dimension of the
        center. This ensures that the ordering of the isomorphism classes of the
        factors is deterministic over finite fields, but not necessarily over :math:`\mathbb{Q}`.
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algsimpledec(_al, maps)
        return new_gen(_ret)

    def algsplit(self, al, v=None):
        r'''
        If :emphasis:`al` is a table algebra over :math:`\mathbb{F}_p` output by :literal:`algtableinit`
        that represents a simple algebra, computes an isomorphism between :emphasis:`al` and
        a matrix algebra :math:`M_d(\mathbb{F}_{p^n})` where :math:`N = nd^2` is the dimension of :emphasis:`al`.
        Returns a :literal:`t_VEC` :math:`[map,mapi]`, where:

        - :emphasis:`map` is a :literal:`t_VEC` of :math:`N` matrices of size :math:`d x d` with
        :literal:`t_FFELT` coefficients using the variable :emphasis:`v`, representing the image of
        the basis of :emphasis:`al` under the isomorphism.

        - :emphasis:`mapi` is an :math:`N x N` matrix with :literal:`t_INT` coefficients,
        representing the image in :emphasis:`al` by the inverse isomorphism of the
        basis :math:`(b_i)` of :math:`M_d(\mathbb{F}_p[\alpha])` (where :math:`\alpha` has degree :math:`n`
        over :math:`\mathbb{F}_p`) defined as follows:
        let :math:`E_{i,j}` be the matrix having all coefficients :math:`0` except the :math:`(i,j)`-th
        coefficient equal to :math:`1`, and define
        

        .. MATH::

        b_i = E_{((i-1)/nd)+1, ((i-1)/n mod d)+1} \alpha^{(i-1) mod n}.

        Example:

        ::

        ? al0 = alginit(nfinit(y^2+7), [-1,-1]);
        ? al = algtableinit(algmultable(al0), 3); \\ isomorphic to M_2(F_9)
        ? [map,mapi] = algsplit(al, 'a);
        ? x = [1,2,1,0,0,0,0,0]~; fx = map*x
        %4 =
        [2*a 0]
        
        [ 0 2]
        ? y = [0,0,0,0,1,0,0,1]~; fy = map*y
        %5 =
        [1 2*a]
        
        [2 a + 2]
        ? map*algmul(al,x,y) == fx*fy
        %6 = 1
        ? map*mapi[,6]
        %7 =
        [0 0]
        
        [a 0]

        :strong:`Warning.` If :emphasis:`al` is not simple, :literal:`algsplit(al)` can trigger
        an error, but can also run into an infinite loop. Example:

        ::

        ? al = alginit(nfinit(y),[-1,-1]); \\ ramified at 2
        ? al2 = algtableinit(algmultable(al),2); \\ maximal order modulo 2
        ? algsplit(al2); \\ not semisimple, infinite loop
        '''
        al = objtogen(al)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algsplit(_al, _v)
        return new_gen(_ret)

    def algsplittingdata(self, al):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit` defined
        by a multiplication table over its center :math:`K` (a number field), returns data
        stored to compute a splitting of :emphasis:`al` over an extension. This data is a
        :literal:`t_VEC` :literal:`[t,Lbas,Lbasinv]` with :math:`3` components:

        - an element :math:`t` of :emphasis:`al` such that :math:`L = K(t)` is a maximal subfield
        of :emphasis:`al`;

        - a matrix :literal:`Lbas` expressing a :math:`L`-basis of :emphasis:`al` (given an
        :math:`L`-vector space structure by multiplication on the right) on the integral
        basis of :emphasis:`al`;

        - a matrix :literal:`Lbasinv` expressing the integral basis of :emphasis:`al` on
        the previous :math:`L`-basis.

        ::

        ? nf = nfinit(y^3-5); a = y; b = y^2;
        ? {m_i = [0,a,0,0;
        1,0,0,0;
        0,0,0,a;
        0,0,1,0];}
        ? {m_j = [0, 0,b, 0;
        0, 0,0,-b;
        1, 0,0, 0;
        0,-1,0, 0];}
        ? {m_k = [0, 0,0,-a*b;
        0, 0,b, 0;
        0,-a,0, 0;
        1, 0,0, 0];}
        ? mt = [matid(4), m_i, m_j, m_k];
        ? A = alginit(nf,mt,'x);
        ? [t,Lb,Lbi] = algsplittingdata(A);
        ? t
        %8 = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]~;
        ? matsize(Lb)
        %9 = [12, 2]
        ? matsize(Lbi)
        %10 = [2, 12]
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algsplittingdata(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algsplittingfield(self, al):
        r'''
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, returns
        an :literal:`rnf` structure: the splitting field of :emphasis:`al` that is stored in
        :emphasis:`al`, as a relative extension of the center.

        ::

        nf = nfinit(y^3-5);
        a = y; b = y^2;
        {m_i = [0,a,0,0;
        1,0,0,0;
        0,0,0,a;
        0,0,1,0];}
        {m_j = [0, 0,b, 0;
        0, 0,0,-b;
        1, 0,0, 0;
        0,-1,0, 0];}
        {m_k = [0, 0,0,-a*b;
        0, 0,b, 0;
        0,-a,0, 0;
        1, 0,0, 0];}
        mt = [matid(4), m_i, m_j, m_k];
        A = alginit(nf,mt,'x);
        algsplittingfield(A).pol
        %8 = x^2 - y
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _ret = algsplittingfield(_al)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def algsqr(self, al, x):
        r'''
        Given an element :math:`x` in :emphasis:`al`, computes its square :math:`x^2` in the
        algebra :emphasis:`al`.

        ::

        ? A = alginit(nfinit(y), [-1,-1]);
        ? algsqr(A,[1,0,2,0]~)
        %2 = [-3, 0, 4, 0]~

        Also accepts a square matrix with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = algsqr(_al, _x)
        return new_gen(_ret)

    def algsub(self, al, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in :emphasis:`al`, computes their difference
        :math:`x-y` in the algebra :emphasis:`al`.

        ::

        ? A = alginit(nfinit(y), [-1,-1]);
        ? algsub(A,[1,1,0,0]~,[1,0,1,0]~)
        %2 = [0, 1, -1, 0]~

        Also accepts matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = algsub(_al, _x, _y)
        return new_gen(_ret)

    def algsubalg(self, al, B):
        r'''
        :emphasis:`al` being a table algebra output by :literal:`algtableinit` and :emphasis:`B`
        being a basis of a subalgebra of :emphasis:`al` represented by a matrix, computes an
        algebra :emphasis:`al2` isomorphic to :emphasis:`B`.

        Returns :math:`[al2,B2]` where :emphasis:`B2` is a possibly different basis of
        the subalgebra :emphasis:`al2`, with respect to which the multiplication table of
        :emphasis:`al2` is defined.

        ::

        ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
        ? A = algtableinit(mt,2);
        ? B = algsubalg(A,[1,0; 0,0; 0,1]);
        ? algdim(A)
        %4 = 3
        ? algdim(B[1])
        %5 = 2
        ? m = matcompanion(x^4+1);
        ? mt = [m^i | i <- [0..3]];
        ? al = algtableinit(mt);
        ? B = [1,0;0,0;0,1/2;0,0];
        ? al2 = algsubalg(al,B);
        ? algdim(al2[1])
        ? al2[2]
        %13 =
        [1 0]
        
        [0 0]
        
        [0 1]
        
        [0 0]
        '''
        al = objtogen(al)
        B = objtogen(B)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _B = (<Gen>B).g
        cdef GEN _ret = algsubalg(_al, _B)
        return new_gen(_ret)

    def algtableinit(self, mt, p=None):
        r'''
        Initializes the associative algebra over :math:`K = \mathbb{Q}` (:math:`p` omitted) or :math:`\mathbb{F}_p`
        defined by the multiplication table :emphasis:`mt`.
        As a :math:`K`-vector space, the algebra is generated by a basis
        :math:`(e_1 = 1, e_2,..., e_n)`; the table is given as a :literal:`t_VEC` of :math:`n` matrices in
        :math:`M_n(K)`, giving the left multiplication by the basis elements :math:`e_i`, in the
        given basis.
        Assumes that :math:`e_1 = 1`, that :math:`K e_1\oplus...\oplus K e_n]` describes an
        associative algebra over :math:`K`, and in the case :math:`K = \mathbb{Q}` that the multiplication
        table is integral. If the algebra is already known to be central
        and simple, then the case :math:`K = \mathbb{F}_p` is useless, and one should use
        :literal:`alginit` directly.

        The point of this function is to input a finite dimensional :math:`K`-algebra, so
        as to later compute its radical, then to split the quotient algebra as a
        product of simple algebras over :math:`K`.

        The pari object representing such an algebra :math:`A` is a :literal:`t_VEC` with the
        following data:

        - The characteristic of :math:`A`, accessed with :literal:`algchar`.

        - The multiplication table of :math:`A`, accessed with :literal:`algmultable`.

        - The traces of the elements of the basis.

        A simple example: the :math:`2 x 2` upper triangular matrices over :math:`\mathbb{Q}`,
        generated by :math:`I_2`, :math:`a = [0,1;0,0]` and :math:`b = [0,0;0,1]`,
        such that :math:`a^2 = 0`, :math:`ab = a`, :math:`ba = 0`, :math:`b^2 = b`:

        ::

        ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
        ? A = algtableinit(mt);
        ? algradical(A) \\ = (a)
        %6 =
        [0]
        
        [1]
        
        [0]
        ? algcenter(A) \\ = (I_2)
        %7 =
        [1]
        
        [0]
        
        [0]
        '''
        mt = objtogen(mt)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _mt = (<Gen>mt).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _ret = algtableinit(_mt, _p)
        return new_gen(_ret)

    def algtensor(self, al1, al2, long maxord=1):
        r'''
        Given two algebras :emphasis:`al1` and :emphasis:`al2`, computes their tensor
        product. Computes a maximal order by default. Prevent this computation by
        setting :math:`maxord = 0`.

        Currently only implemented for cyclic algebras of coprime degree over the same
        center :math:`K`, and the tensor product is over :math:`K`.
        '''
        al1 = objtogen(al1)
        al2 = objtogen(al2)
        sig_on()
        cdef GEN _al1 = (<Gen>al1).g
        cdef GEN _al2 = (<Gen>al2).g
        cdef GEN _ret = algtensor(_al1, _al2, maxord)
        return new_gen(_ret)

    def algtomatrix(self, al, x, long abs=0):
        r'''
        Given an element :emphasis:`x` in :emphasis:`al`, returns the image of :emphasis:`x` under a
        homomorphism to a matrix algebra. If :emphasis:`al` is a table algebra output by
        :literal:`algtableinit` or if :math:`abs = 1`, returns the left multiplication table on the
        integral basis; if :emphasis:`al` is a central simple algebra and :math:`abs = 0`,
        returns :math:`\phi (x)` where :math:`\phi : A\otimes_K L \to M_d(L)` (where :math:`d` is the
        degree of the algebra and :math:`L` is an extension of :math:`L` with :math:`[L:K] = d`) is an
        isomorphism stored in :emphasis:`al`. Also accepts a square matrix with coefficients
        in :emphasis:`al`.

        ::

        ? A = alginit(nfinit(y), [-1,-1]);
        ? algtomatrix(A,[0,0,0,2]~)
        %2 =
        [Mod(x + 1, x^2 + 1) Mod(Mod(1, y)*x + Mod(-1, y), x^2 + 1)]
        
        [Mod(x + 1, x^2 + 1) Mod(-x + 1, x^2 + 1)]
        ? algtomatrix(A,[0,1,0,0]~,1)
        %2 =
        [0 -1 1 0]
        
        [1 0 1 1]
        
        [0 0 1 1]
        
        [0 0 -2 -1]
        ? algtomatrix(A,[0,x]~,1)
        %3 =
        [-1 0 0 -1]
        
        [-1 0 1 0]
        
        [-1 -1 0 -1]
        
        [ 2 0 0 1]

        Also accepts matrices with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = algtomatrix(_al, _x, abs)
        return new_gen(_ret)

    def algtrace(self, al, x, long abs=0):
        r'''
        Given an element :emphasis:`x` in :emphasis:`al`, computes its trace. If :emphasis:`al` is
        a table algebra output by :literal:`algtableinit` or if :math:`abs = 1`, returns the
        absolute trace of :emphasis:`x`, which is an element of :math:`\mathbb{F}_p` or :math:`\mathbb{Q}`; if :emphasis:`al`
        is the output of :literal:`alginit` and :math:`abs = 0` (default), returns the reduced trace
        of :emphasis:`x`, which is an element of the center of :emphasis:`al`.

        ::

        ? A = alginit(nfinit(y), [-1,-1]);
        ? algtrace(A,[5,0,0,1]~)
        %2 = 11
        ? algtrace(A,[5,0,0,1]~,1)
        %3 = 22
        ? nf = nfinit(y^2-5);
        ? A = alginit(nf,[-1,y]);
        ? a = [1+x+y,2*y]~*Mod(1,y^2-5)*Mod(1,x^2+1);
        ? t = algtrace(A,a)
        %7 = Mod(2*y + 2, y^2 - 5)
        ? algtrace(A,a,1)
        %8 = 8
        ? algdegree(A)*nfelttrace(nf,t)
        %9 = 8

        Also accepts a square matrix with coefficients in :emphasis:`al`.
        '''
        al = objtogen(al)
        x = objtogen(x)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = algtrace(_al, _x, abs)
        return new_gen(_ret)

    def algtype(self, al):
        r'''
        Given an algebra :emphasis:`al` output by :literal:`alginit` or by :literal:`algtableinit`, returns an integer indicating the type of algebra:

        - :math:`0`: not a valid algebra.

        - :math:`1`: table algebra output by :literal:`algtableinit`.

        - :math:`2`: central simple algebra output by :literal:`alginit` and represented by
        a multiplication table over its center.

        - :math:`3`: central simple algebra output by :literal:`alginit` and represented by
        a cyclic algebra.

        ::

        ? algtype([])
        %1 = 0
        ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
        ? A = algtableinit(mt,2);
        ? algtype(A)
        %4 = 1
        ? nf = nfinit(y^3-5);
        ? a = y; b = y^2;
        ? {m_i = [0,a,0,0;
        1,0,0,0;
        0,0,0,a;
        0,0,1,0];}
        ? {m_j = [0, 0,b, 0;
        0, 0,0,-b;
        1, 0,0, 0;
        0,-1,0, 0];}
        ? {m_k = [0, 0,0,-a*b;
        0, 0,b, 0;
        0,-a,0, 0;
        1, 0,0, 0];}
        ? mt = [matid(4), m_i, m_j, m_k];
        ? A = alginit(nf,mt,'x);
        ? algtype(A)
        %12 = 2
        ? A = alginit(nfinit(y), [-1,-1]);
        ? algtype(A)
        %14 = 3
        '''
        al = objtogen(al)
        sig_on()
        cdef GEN _al = (<Gen>al).g
        cdef long _ret = algtype(_al)
        clear_stack()
        return _ret

    def apply(self, f, A):
        r'''
        Apply the :literal:`t_CLOSURE` :literal:`f` to the entries of :literal:`A`. If :literal:`A`
        is a scalar, return :literal:`f(A)`. If :literal:`A` is a polynomial or power series,
        apply :literal:`f` on all coefficients. If :literal:`A` is a vector or list, return
        the elements :math:`f(x)` where :math:`x` runs through :literal:`A`. If :literal:`A` is a matrix,
        return the matrix whose entries are the :math:`f(A[i,j])`.

        ::

        ? apply(x->x^2, [1,2,3,4])
        %1 = [1, 4, 9, 16]
        ? apply(x->x^2, [1,2;3,4])
        %2 =
        [1 4]
        
        [9 16]
        ? apply(x->x^2, 4*x^2 + 3*x+ 2)
        %3 = 16*x^2 + 9*x + 4

        Note that many functions already act componentwise on
        vectors or matrices, but they almost never act on lists; in this
        case, :literal:`apply` is a good solution:

        ::

        ? L = List([Mod(1,3), Mod(2,4)]);
        ? lift(L)
        *** at top-level: lift(L)
        *** ^-------
        *** lift: incorrect type in lift.
        ? apply(lift, L);
        %2 = List([1, 2])

        :strong:`Remark.` For :math:`v` a :literal:`t_VEC`, :literal:`t_COL`, :literal:`t_LIST` or :literal:`t_MAT`,
        the alternative set-notations

        ::

        [g(x) | x <- v, f(x)]
        [x | x <- v, f(x)]
        [g(x) | x <- v]

        are available as shortcuts for

        ::

        apply(g, select(f, Vec(v)))
        select(f, Vec(v))
        apply(g, Vec(v))

        respectively:

        ::

        ? L = List([Mod(1,3), Mod(2,4)]);
        ? [ lift(x) | x<-L ]
        %2 = [1, 2]
        '''
        f = objtogen(f)
        A = objtogen(A)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _A = (<Gen>A).g
        cdef GEN _ret = apply0(_f, _A)
        return new_gen(_ret)

    def arg(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Argument of the complex number :math:`x`, such that :math:`-\pi < \arg (x) <= \pi`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = garg(_x, precision)
        return new_gen(_ret)

    def asin(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of :math:`\sin^{-1}(x) = -i \log (ix + \sqrt{1 - x^2})`.
        In particular, :math:`\Re (asin(x))\in [-\pi/2,\pi/2]` and if :math:`x\in \mathbb{R}` and
        :math:`\|x\| > 1` then :math:`asin(x)` is complex. The branch cut is in two pieces:
        :math:`]- oo ,-1]`, continuous with quadrant II, and :math:`[1,+ oo [` continuous
        with quadrant IV. The function satisfies :math:`i asin(x) =
        asinh(ix)`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gasin(_x, precision)
        return new_gen(_ret)

    def asinh(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of :math:`\sinh^{-1}(x) = \log (x + \sqrt{1+x^2})`. In
        particular :math:`\Im (asinh(x))\in [-\pi/2,\pi/2]`.
        The branch cut is in two pieces: :math:`]-i oo ,-i]`, continuous with quadrant
        III and :math:`[+i,+i oo [`, continuous with quadrant I.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gasinh(_x, precision)
        return new_gen(_ret)

    def asympnum(self, expr, long k=0, alpha=None, long precision=DEFAULT_BITPREC):
        r'''
        Asymptotic expansion of :emphasis:`expr`, corresponding to a sequence :math:`u(n)`,
        assuming it has the shape

        .. MATH::

        u(n) ~ \sum_{i >= 0} a_i n^{-i\alpha}

        with rational coefficients :math:`a_i` with reasonable height; the algorithm
        is heuristic and performs repeated calls to limitnum, with
        :literal:`k` and :literal:`alpha` are as in :literal:`limitnum`

        ::

        ? f(n) = n! / (n^n*exp(-n)*sqrt(n));
        ? asympnum(f)
        %2 = [] \\ failure !
        ? l = limitnum(f)
        %3 = 2.5066282746310005024157652848110452530
        ? asympnum(n->f(n)/l) \\ normalize
        %4 = [1, 1/12, 1/288, -139/51840]

        and we indeed get a few terms of Stirling's expansion. Note
        that it helps to normalize with a limit computed to higher accuracy:

        ::

        ? \p100
        ? L = limitnum(f)
        ? \p38
        ? asympnum(n->f(n)/L) \\ we get more terms!
        %6 = [1, 1/12, 1/288, -139/51840, -571/2488320, 163879/209018880,\
        5246819/75246796800, -534703531/902961561600]

        If :literal:`alpha` is not an integer, loss of accuracy is
        expected, so it should be precomputed to double accuracy, say:

        ::

        ? \p38
        ? asympnum(n->-log(1-1/n^Pi),,Pi)
        %1 = [0, 1, 1/2, 1/3]
        ? asympnum(n->-log(1-1/sqrt(n)),,1/2)
        %2 = [0, 1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, \
        1/13, 1/14, 1/15, 1/16, 1/17, 1/18, 1/19, 1/20, 1/21, 1/22]
        
        ? localprec(100); a = Pi;
        ? asympnum(n->-log(1-1/n^a),,a) \\ better !
        %4 = [0, 1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12]
        '''
        expr = objtogen(expr)
        cdef bint _have_alpha = (alpha is not None)
        if _have_alpha:
            alpha = objtogen(alpha)
        sig_on()
        cdef GEN _expr = (<Gen>expr).g
        cdef GEN _alpha = NULL
        if _have_alpha:
            _alpha = (<Gen>alpha).g
        precision = nbits2prec(precision)
        cdef GEN _ret = asympnum0(_expr, k, _alpha, precision)
        return new_gen(_ret)

    def atan(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of :math:`tan^{-1}(x) = \log ((1+ix)/(1-ix)) /
        2i`. In particular the real part of :math:`atan(x)` belongs to
        :math:`]-\pi/2,\pi/2[`.
        The branch cut is in two pieces:
        :math:`]-i oo ,-i[`, continuous with quadrant IV, and :math:`]i,+i oo [` continuous
        with quadrant II. The function satisfies :math:`atan(x) =
        -iatanh(ix)` for all :math:`x != ± i`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gatan(_x, precision)
        return new_gen(_ret)

    def atanh(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of :math:`tanh^{-1}(x) = \log ((1+x)/(1-x)) / 2`. In
        particular the imaginary part of :math:`atanh(x)` belongs to
        :math:`[-\pi/2,\pi/2]`; if :math:`x\in \mathbb{R}` and :math:`\|x\| > 1` then :math:`atanh(x)` is complex.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gatanh(_x, precision)
        return new_gen(_ret)

    def bernfrac(self, long x):
        r'''
        Bernoulli number :math:`B_x`,
        where :math:`B_0 = 1`, :math:`B_1 = -1/2`, :math:`B_2 = 1/6`,..., expressed as a rational number.
        The argument :math:`x` should be of type integer.
        '''
        sig_on()
        cdef GEN _ret = bernfrac(x)
        return new_gen(_ret)

    def bernpol(self, long n, v=None):
        r'''
        Bernoulli polynomial :math:`B_n` in variable :math:`v`.

        ::

        ? bernpol(1)
        %1 = x - 1/2
        ? bernpol(3)
        %2 = x^3 - 3/2*x^2 + 1/2*x
        '''
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _ret = bernpol(n, _v)
        return new_gen(_ret)

    def bernreal(self, long x, long precision=DEFAULT_BITPREC):
        r'''
        Bernoulli number
        :math:`B_x`, as :literal:`bernfrac`, but :math:`B_x` is returned as a real number
        (with the current precision).
        '''
        sig_on()
        precision = nbits2prec(precision)
        cdef GEN _ret = bernreal(x, precision)
        return new_gen(_ret)

    def bernvec(self, long x):
        r'''
        This routine is obsolete, kept for backward compatibility only.
        '''
        from warnings import warn
        warn('the PARI/GP function bernvec is obsolete (2007-03-30)', DeprecationWarning)
        sig_on()
        cdef GEN _ret = bernvec(x)
        return new_gen(_ret)

    def besselh1(self, nu, x, long precision=DEFAULT_BITPREC):
        r'''
        :math:`H^1`-Bessel function of index :emphasis:`nu` and argument :math:`x`.
        '''
        nu = objtogen(nu)
        x = objtogen(x)
        sig_on()
        cdef GEN _nu = (<Gen>nu).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = hbessel1(_nu, _x, precision)
        return new_gen(_ret)

    def besselh2(self, nu, x, long precision=DEFAULT_BITPREC):
        r'''
        :math:`H^2`-Bessel function of index :emphasis:`nu` and argument :math:`x`.
        '''
        nu = objtogen(nu)
        x = objtogen(x)
        sig_on()
        cdef GEN _nu = (<Gen>nu).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = hbessel2(_nu, _x, precision)
        return new_gen(_ret)

    def besseli(self, nu, x, long precision=DEFAULT_BITPREC):
        r'''
        :math:`I`-Bessel function of index :emphasis:`nu` and
        argument :math:`x`. If :math:`x` converts to a power series, the initial factor
        :math:`(x/2)^\nu/\Gamma (\nu+1)` is omitted (since it cannot be represented in PARI
        when :math:`\nu` is not integral).
        '''
        nu = objtogen(nu)
        x = objtogen(x)
        sig_on()
        cdef GEN _nu = (<Gen>nu).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ibessel(_nu, _x, precision)
        return new_gen(_ret)

    def besselj(self, nu, x, long precision=DEFAULT_BITPREC):
        r'''
        :math:`J`-Bessel function of index :emphasis:`nu` and
        argument :math:`x`. If :math:`x` converts to a power series, the initial factor
        :math:`(x/2)^\nu/\Gamma (\nu+1)` is omitted (since it cannot be represented in PARI
        when :math:`\nu` is not integral).
        '''
        nu = objtogen(nu)
        x = objtogen(x)
        sig_on()
        cdef GEN _nu = (<Gen>nu).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = jbessel(_nu, _x, precision)
        return new_gen(_ret)

    def besseljh(self, n, x, long precision=DEFAULT_BITPREC):
        r'''
        :math:`J`-Bessel function of half integral index.
        More precisely, :math:`besseljh (n,x)` computes :math:`J_{n+1/2}(x)` where :math:`n`
        must be of type integer, and :math:`x` is any element of :math:`\mathbb{C}`. In the
        present version :strong:`2.11.4`, this function is not very accurate when :math:`x` is small.
        '''
        n = objtogen(n)
        x = objtogen(x)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = jbesselh(_n, _x, precision)
        return new_gen(_ret)

    def besselk(self, nu, x, long precision=DEFAULT_BITPREC):
        r'''
        :math:`K`-Bessel function of index :emphasis:`nu` and argument :math:`x`.
        '''
        nu = objtogen(nu)
        x = objtogen(x)
        sig_on()
        cdef GEN _nu = (<Gen>nu).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = kbessel(_nu, _x, precision)
        return new_gen(_ret)

    def besseln(self, nu, x, long precision=DEFAULT_BITPREC):
        r'''
        :math:`N`-Bessel function of index :emphasis:`nu` and argument :math:`x`.
        '''
        nu = objtogen(nu)
        x = objtogen(x)
        sig_on()
        cdef GEN _nu = (<Gen>nu).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = nbessel(_nu, _x, precision)
        return new_gen(_ret)

    def bestappr(self, x, B=None):
        r'''
        Using variants of the extended Euclidean algorithm, returns a rational
        approximation :math:`a/b` to :math:`x`, whose denominator is limited
        by :math:`B`, if present. If :math:`B` is omitted, return the best approximation
        affordable given the input accuracy; if you are looking for true rational
        numbers, presumably approximated to sufficient accuracy, you should first
        try that option. Otherwise, :math:`B` must be a positive real scalar (impose
        :math:`0 < b <= B`).

        - If :math:`x` is a :literal:`t_REAL` or a :literal:`t_FRAC`, this function uses continued
        fractions.

        ::

        ? bestappr(Pi, 100)
        %1 = 22/7
        ? bestappr(0.1428571428571428571428571429)
        %2 = 1/7
        ? bestappr([Pi, sqrt(2) + 'x], 10^3)
        %3 = [355/113, x + 1393/985]

        By definition, :math:`a/b` is the best rational approximation to :math:`x` if
        :math:`\|b x - a\| < \|v x - u\|` for all integers :math:`(u,v)` with :math:`0 < v <= B`.
        (Which implies that :math:`n/d` is a convergent of the continued fraction of :math:`x`.)

        - If :math:`x` is a :literal:`t_INTMOD` modulo :math:`N` or a :literal:`t_PADIC` of precision :math:`N =
        p^k`, this function performs rational modular reconstruction modulo :math:`N`. The
        routine then returns the unique rational number :math:`a/b` in coprime integers
        :math:`\|a\| < N/2B` and :math:`b <= B` which is congruent to :math:`x` modulo :math:`N`. Omitting
        :math:`B` amounts to choosing it of the order of :math:`\sqrt{N/2}`. If rational
        reconstruction is not possible (no suitable :math:`a/b` exists), returns :math:`[]`.

        ::

        ? bestappr(Mod(18526731858, 11^10))
        %1 = 1/7
        ? bestappr(Mod(18526731858, 11^20))
        %2 = []
        ? bestappr(3 + 5 + 3*5^2 + 5^3 + 3*5^4 + 5^5 + 3*5^6 + O(5^7))
        %2 = -1/3

        In most concrete uses, :math:`B` is a prime power and we performed
        Hensel lifting to obtain :math:`x`.

        The function applies recursively to components of complex objects
        (polynomials, vectors,...). If rational reconstruction fails for even a
        single entry, return :math:`[]`.
        '''
        x = objtogen(x)
        cdef bint _have_B = (B is not None)
        if _have_B:
            B = objtogen(B)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _B = NULL
        if _have_B:
            _B = (<Gen>B).g
        cdef GEN _ret = bestappr(_x, _B)
        return new_gen(_ret)

    def bestapprPade(self, x, long B=-1):
        r'''
        Using variants of the extended Euclidean algorithm (Padé
        approximants), returns a rational
        function approximation :math:`a/b` to :math:`x`, whose denominator is limited
        by :math:`B`, if present. If :math:`B` is omitted, return the best approximation
        affordable given the input accuracy; if you are looking for true rational
        functions, presumably approximated to sufficient accuracy, you should first
        try that option. Otherwise, :math:`B` must be a non-negative real
        (impose :math:`0 <= degree(b) <= B`).

        - If :math:`x` is a :literal:`t_POLMOD` modulo :math:`N` this function performs rational
        modular reconstruction modulo :math:`N`. The routine then returns the unique
        rational function :math:`a/b` in coprime polynomials, with :math:`degree(b) <= B`
        and :math:`degree(a)` minimal, which is congruent to :math:`x` modulo :math:`N`.
        Omitting :math:`B` amounts to choosing it equal to the floor of
        :math:`degree(N) / 2`. If rational reconstruction is not possible (no
        suitable :math:`a/b` exists), returns :math:`[]`.

        ::

        ? T = Mod(x^3 + x^2 + x + 3, x^4 - 2);
        ? bestapprPade(T)
        %2 = (2*x - 1)/(x - 1)
        ? U = Mod(1 + x + x^2 + x^3 + x^5, x^9);
        ? bestapprPade(U) \\ internally chooses B = 4
        %3 = []
        ? bestapprPade(U, 5) \\ with B = 5, a solution exists
        %4 = (2*x^4 + x^3 - x - 1)/(-x^5 + x^3 + x^2 - 1)

        - If :math:`x` is a :literal:`t_SER`, we implicitly
        convert the input to a :literal:`t_POLMOD` modulo :math:`N = t^k` where :math:`k` is the
        series absolute precision.

        ::

        ? T = 1 + t + t^2 + t^3 + t^4 + t^5 + t^6 + O(t^7); \\ mod t^7
        ? bestapprPade(T)
        %1 = 1/(-t + 1)

        - If :math:`x` is a :literal:`t_RFRAC`, we implicitly convert the input to a
        :literal:`t_POLMOD` modulo :math:`N = t^k` where :math:`k = 2B + 1`. If :math:`B` was omitted,
        we return :math:`x`:

        ::

        ? T = (4*t^2 + 2*t + 3)/(t+1)^10;
        ? bestapprPade(T,1)
        %2 = [] \\ impossible
        ? bestapprPade(T,2)
        %3 = 27/(337*t^2 + 84*t + 9)
        ? bestapprPade(T,3)
        %4 = (4253*t - 3345)/(-39007*t^3 - 28519*t^2 - 8989*t - 1115)

        The function applies recursively to components of complex objects
        (polynomials, vectors,...). If rational reconstruction fails for even a
        single entry, return :math:`[]`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = bestapprPade(_x, B)
        return new_gen(_ret)

    def bestapprnf(self, V, T, rootT=None, long precision=DEFAULT_BITPREC):
        r'''
        :math:`T` being an integral polynomial and :math:`V` being a scalar, vector, or
        matrix with complex coefficients, return a reasonable approximation of :math:`V`
        with polmods modulo :math:`T`. :math:`T` can also be any number field structure, in which
        case the minimal polynomial attached to the structure (:literal:`:math:`T``.pol) is
        used. The :emphasis:`rootT` argument, if present, must be an element of
        :literal:`polroots(:math:`T`)` (or :literal:`:math:`T``.pol), i.e. a complex root of :math:`T` fixing an embedding of
        :math:`\mathbb{Q}[x]/(T)` into :math:`\mathbb{C}`.

        ::

        ? bestapprnf(sqrt(5), polcyclo(5))
        %1 = Mod(-2*x^3 - 2*x^2 - 1, x^4 + x^3 + x^2 + x + 1)
        ? bestapprnf(sqrt(5), polcyclo(5), exp(4*I*Pi/5))
        %2 = Mod(2*x^3 + 2*x^2 + 1, x^4 + x^3 + x^2 + x + 1)

        When the output has huge rational coefficients, try to
        increase the working :literal:`realbitprecision`: if the answer does not
        stabilize, consider that the reconstruction failed.
        Beware that if :math:`T` is not Galois over :math:`\mathbb{Q}`, some embeddings
        may not allow to reconstruct :math:`V`:

        ::

        ? T = x^3-2; vT = polroots(T); z = 3*2^(1/3)+1;
        ? bestapprnf(z, T, vT[1])
        %2 = Mod(3*x + 1, x^3 - 2)
        ? bestapprnf(z, T, vT[2])
        %3 = 4213714286230872/186454048314072 \\ close to 3*2^(1/3) + 1
        '''
        V = objtogen(V)
        T = objtogen(T)
        cdef bint _have_rootT = (rootT is not None)
        if _have_rootT:
            rootT = objtogen(rootT)
        sig_on()
        cdef GEN _V = (<Gen>V).g
        cdef GEN _T = (<Gen>T).g
        cdef GEN _rootT = NULL
        if _have_rootT:
            _rootT = (<Gen>rootT).g
        precision = nbits2prec(precision)
        cdef GEN _ret = bestapprnf(_V, _T, _rootT, precision)
        return new_gen(_ret)

    def bezout(self, x, y):
        r'''
        Deprecated alias for :literal:`gcdext`
        '''
        from warnings import warn
        warn('the PARI/GP function bezout is obsolete (2013-04-03)', DeprecationWarning)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = gcdext0(_x, _y)
        return new_gen(_ret)

    def bezoutres(self, A, B, v=None):
        r'''
        Deprecated alias for :literal:`polresultantext`
        '''
        from warnings import warn
        warn('the PARI/GP function bezoutres is obsolete (2015-01-13)', DeprecationWarning)
        A = objtogen(A)
        B = objtogen(B)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _B = (<Gen>B).g
        cdef GEN _ret = polresultantext0(_A, _B, _v)
        return new_gen(_ret)

    def bigomega(self, x):
        r'''
        Number of prime divisors of the integer :math:`\|x\|` counted with
        multiplicity:

        ::

        ? factor(392)
        %1 =
        [2 3]
        
        [7 2]
        
        ? bigomega(392)
        %2 = 5; \\ = 3+2
        ? omega(392)
        %3 = 2; \\ without multiplicity
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = bigomega(_x)
        clear_stack()
        return _ret

    def binary(self, x):
        r'''
        Outputs the vector of the binary digits of :math:`\|x\|`. Here :math:`x` can be an
        integer, a real number (in which case the result has two components, one for
        the integer part, one for the fractional part) or a vector/matrix.

        ::

        ? binary(10)
        %1 = [1, 0, 1, 0]
        
        ? binary(3.14)
        %2 = [[1, 1], [0, 0, 1, 0, 0, 0, [...]]
        
        ? binary([1,2])
        %3 = [[1], [1, 0]]

        By convention, :math:`0` has no digits:

        ::

        ? binary(0)
        %4 = []
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = binaire(_x)
        return new_gen(_ret)

    def binomial(self, x, k=None):
        r'''
        binomial coefficient :math:`binom{x}{k}`.
        Here :math:`k` must be an integer, but :math:`x` can be any PARI object.

        ::

        ? binomial(4,2)
        %1 = 6
        ? n = 4; vector(n+1, k, binomial(n,k-1))
        %2 = [1, 4, 6, 4, 1]

        The argument :math:`k` may be omitted if :math:`x = n` is a
        non-negative integer; in this case, return the vector with :math:`n+1`
        components whose :math:`k+1`-th entry is :literal:`binomial`:math:`(n,k)`

        ::

        ? binomial(4)
        %3 = [1, 4, 6, 4, 1]
        '''
        x = objtogen(x)
        cdef bint _have_k = (k is not None)
        if _have_k:
            k = objtogen(k)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _k = NULL
        if _have_k:
            _k = (<Gen>k).g
        cdef GEN _ret = binomial0(_x, _k)
        return new_gen(_ret)

    def bitand(self, x, y):
        r'''
        Bitwise :literal:`and`
        of two integers :math:`x` and :math:`y`, that is the integer

        .. MATH::

        \sum_i (x_i and y_i) 2^i

        Negative numbers behave :math:`2`-adically, i.e. the result is the :math:`2`-adic limit
        of :literal:`bitand`:math:`(x_n,y_n)`, where :math:`x_n` and :math:`y_n` are non-negative integers
        tending to :math:`x` and :math:`y` respectively. (The result is an ordinary integer,
        possibly negative.)

        ::

        ? bitand(5, 3)
        %1 = 1
        ? bitand(-5, 3)
        %2 = 3
        ? bitand(-5, -3)
        %3 = -7
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = gbitand(_x, _y)
        return new_gen(_ret)

    def bitneg(self, x, long n=-1):
        r'''
        bitwise negation of an integer :math:`x`,
        truncated to :math:`n` bits, :math:`n >= 0`, that is the integer

        .. MATH::

        \sum_{i = 0}^{n-1} not (x_i) 2^i.

        The special case :math:`n = -1` means no truncation: an infinite sequence of
        leading :math:`1` is then represented as a negative number.

        See ``bitand`` (in the PARI manual) for the behavior for negative arguments.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gbitneg(_x, n)
        return new_gen(_ret)

    def bitnegimply(self, x, y):
        r'''
        Bitwise negated imply of two integers :math:`x` and
        :math:`y` (or :literal:`not` :math:`(x ==> y)`), that is the integer

        .. MATH::

        \sum
        (x_i and not (y_i)) 2^i

        See ``bitand`` (in the PARI manual) for the behavior for negative arguments.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = gbitnegimply(_x, _y)
        return new_gen(_ret)

    def bitor(self, x, y):
        r'''
        bitwise (inclusive)
        :literal:`or` of two integers :math:`x` and :math:`y`, that is the integer

        .. MATH::

        \sum
        (x_i or y_i) 2^i

        See ``bitand`` (in the PARI manual) for the behavior for negative arguments.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = gbitor(_x, _y)
        return new_gen(_ret)

    def bitprecision(self, x, long n=0):
        r'''
        The function behaves differently according to whether :math:`n` is
        present and positive or not. If :math:`n` is missing, the function returns the
        (floating point) precision in bits of the PARI object :math:`x`. If :math:`x` is an
        exact object, the function returns :literal:`+oo`.

        ::

        ? bitprecision(exp(1e-100))
        %1 = 512 \\ 512 bits
        ? bitprecision( [ exp(1e-100), 0.5 ] )
        %2 = 128 \\ minimal accuracy among components
        ? bitprecision(2 + x)
        %3 = +oo \\ exact object

        If :math:`n` is present and positive, the function creates a new object equal to :math:`x`
        with the new bit-precision roughly :math:`n`. In fact, the smallest multiple of 64
        (resp. 32 on a 32-bit machine) larger than or equal to :math:`n`.

        For :math:`x` a vector or a matrix, the operation is
        done componentwise; for series and polynomials, the operation is done
        coefficientwise. For real :math:`x`, :math:`n` is the number of desired significant
        :emphasis:`bits`. If :math:`n` is smaller than the precision of :math:`x`, :math:`x` is truncated,
        otherwise :math:`x` is extended with zeros. For exact or non-floating point types,
        no change.

        ::

        ? bitprecision(Pi, 10) \\ actually 64 bits ~ 19 decimal digits
        %1 = 3.141592653589793239
        ? bitprecision(1, 10)
        %2 = 1
        ? bitprecision(1 + O(x), 10)
        %3 = 1 + O(x)
        ? bitprecision(2 + O(3^5), 10)
        %4 = 2 + O(3^5)
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = bitprecision0(_x, n)
        return new_gen(_ret)

    def bittest(self, x, long n):
        r'''
        Outputs the :math:`n-th` bit of :math:`x` starting
        from the right (i.e. the coefficient of :math:`2^n` in the binary expansion of :math:`x`).
        The result is 0 or 1.

        ::

        ? bittest(7, 0)
        %1 = 1 \\ the bit 0 is 1
        ? bittest(7, 2)
        %2 = 1 \\ the bit 2 is 1
        ? bittest(7, 3)
        %3 = 0 \\ the bit 3 is 0

        See ``bitand`` (in the PARI manual) for the behavior at negative arguments.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gbittest(_x, n)
        return new_gen(_ret)

    def bitxor(self, x, y):
        r'''
        Bitwise (exclusive) :literal:`or`
        of two integers :math:`x` and :math:`y`, that is the integer

        .. MATH::

        \sum (x_i xor y_i) 2^i

        See ``bitand`` (in the PARI manual) for the behavior for negative arguments.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = gbitxor(_x, _y)
        return new_gen(_ret)

    def bnfcertify(self, bnf, long flag=0):
        r'''
        :math:`bnf` being as output by
        :literal:`bnfinit`, checks whether the result is correct, i.e. whether it is
        possible to remove the assumption of the Generalized Riemann
        Hypothesis. It is correct if and only if the answer is 1. If it is
        incorrect, the program may output some error message, or loop indefinitely.
        You can check its progress by increasing the debug level. The :emphasis:`bnf`
        structure must contain the fundamental units:

        ::

        ? K = bnfinit(x^3+2^2^3+1); bnfcertify(K)
        *** at top-level: K=bnfinit(x^3+2^2^3+1);bnfcertify(K)
        *** ^-------------
        *** bnfcertify: missing units in bnf.
        ? K = bnfinit(x^3+2^2^3+1, 1); \\ include units
        ? bnfcertify(K)
        %3 = 1

        If flag is present, only certify that the class group is a quotient of the
        one computed in bnf (much simpler in general); likewise, the computed units
        may form a subgroup of the full unit group. In this variant, the units are
        no longer needed:

        ::

        ? K = bnfinit(x^3+2^2^3+1); bnfcertify(K, 1)
        %4 = 1
        '''
        bnf = objtogen(bnf)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef long _ret = bnfcertify0(_bnf, flag)
        clear_stack()
        return _ret

    def bnfcompress(self, bnf):
        r'''
        Computes a compressed version of :emphasis:`bnf` (from :literal:`bnfinit`), a
        "small Buchmann's number field" (or :emphasis:`sbnf` for short) which contains
        enough information to recover a full :math:`bnf` vector very rapidly, but
        which is much smaller and hence easy to store and print. Calling
        :literal:`bnfinit` on the result recovers a true :literal:`bnf`, in general different
        from the original. Note that an :emphasis:`snbf` is useless for almost all
        purposes besides storage, and must be converted back to :emphasis:`bnf` form
        before use; for instance, no :literal:`nf*`, :literal:`bnf*` or member function
        accepts them.

        An :emphasis:`sbnf` is a 12 component vector :math:`v`, as follows. Let :literal:`bnf` be
        the result of a full :literal:`bnfinit`, complete with units. Then :math:`v[1]` is
        :literal:`bnf.pol`, :math:`v[2]` is the number of real embeddings :literal:`bnf.sign[1]`,
        :math:`v[3]` is :literal:`bnf.disc`, :math:`v[4]` is :literal:`bnf.zk`, :math:`v[5]` is the list of roots
        :literal:`bnf.roots`, :math:`v[7]` is the matrix :math:`W = bnf[1]`,
        :math:`v[8]` is the matrix :math:`matalpha = bnf[2]`,
        :math:`v[9]` is the prime ideal factor base :literal:`bnf[5]` coded in a compact way,
        and ordered according to the permutation :literal:`bnf[6]`, :math:`v[10]` is the
        2-component vector giving the number of roots of unity and a generator,
        expressed on the integral basis, :math:`v[11]` is the list of fundamental units,
        expressed on the integral basis, :math:`v[12]` is a vector containing the algebraic
        numbers alpha corresponding to the columns of the matrix :literal:`matalpha`,
        expressed on the integral basis.

        All the components are exact (integral or rational), except for the roots in
        :math:`v[5]`.
        '''
        bnf = objtogen(bnf)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _ret = bnfcompress(_bnf)
        return new_gen(_ret)

    def bnfdecodemodule(self, nf, m):
        r'''
        If :math:`m` is a module as output in the
        first component of an extension given by :literal:`bnrdisclist`, outputs the
        true module.

        ::

        ? K = bnfinit(x^2+23); L = bnrdisclist(K, 10); s = L[2]
        %1 = [[[Vecsmall([8]), Vecsmall([1])], [[0, 0, 0]]],
        [[Vecsmall([9]), Vecsmall([1])], [[0, 0, 0]]]]
        ? bnfdecodemodule(K, s[1][1])
        %2 =
        [2 0]
        
        [0 1]
        ? bnfdecodemodule(K,s[2][1])
        %3 =
        [2 1]
        
        [0 1]
        '''
        nf = objtogen(nf)
        m = objtogen(m)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _m = (<Gen>m).g
        cdef GEN _ret = decodemodule(_nf, _m)
        return new_gen(_ret)

    def bnfinit(self, P, long flag=0, tech=None, long precision=DEFAULT_BITPREC):
        r'''
        Initializes a
        :literal:`bnf` structure. Used in programs such as :literal:`bnfisprincipal`,
        :literal:`bnfisunit` or :literal:`bnfnarrow`. By default, the results are conditional
        on the GRH, see ``GRHbnf`` (in the PARI manual). The result is a
        10-component vector :emphasis:`bnf`.

        This implements Buchmann's sub-exponential algorithm for computing the
        class group, the regulator and a system of fundamental units of the
        general algebraic number field :math:`K` defined by the irreducible polynomial :math:`P`
        with integer coefficients.

        If the precision becomes insufficient, :literal:`gp` does not strive to compute
        the units by default (:math:`flag = 0`).

        When :math:`flag = 1`, we insist on finding the fundamental units exactly. Be
        warned that this can take a very long time when the coefficients of the
        fundamental units on the integral basis are very large. If the fundamental
        units are simply too large to be represented in this form, an error message
        is issued. They could be obtained using the so-called compact representation
        of algebraic numbers as a formal product of algebraic integers. The latter is
        implemented internally but not publicly accessible yet.

        :math:`tech` is a technical vector (empty by default, see ``GRHbnf`` (in the PARI manual)).
        Careful use of this parameter may speed up your computations,
        but it is mostly obsolete and you should leave it alone.

        The components of a :emphasis:`bnf` or :emphasis:`sbnf` are technical and never used by
        the casual user. In fact: :emphasis:`never access a component directly, always use
        a proper member function.` However, for the sake of completeness and internal
        documentation, their description is as follows. We use the notations
        explained in the book by H. Cohen, :emphasis:`A Course in Computational Algebraic
        Number Theory`, Graduate Texts in Maths :strong:`138`, Springer-Verlag, 1993,
        Section 6.5, and subsection 6.5.5 in particular.

        :math:`bnf[1]` contains the matrix :math:`W`, i.e. the matrix in Hermite normal
        form giving relations for the class group on prime ideal generators
        :math:`(p_i)_{1 <= i <= r}`.

        :math:`bnf[2]` contains the matrix :math:`B`, i.e. the matrix containing the
        expressions of the prime ideal factorbase in terms of the :math:`p_i`.
        It is an :math:`r x c` matrix.

        :math:`bnf[3]` contains the complex logarithmic embeddings of the system of
        fundamental units which has been found. It is an :math:`(r_1+r_2) x (r_1+r_2-1)`
        matrix.

        :math:`bnf[4]` contains the matrix :math:`M"_C` of Archimedean components of the
        relations of the matrix :math:`(W\|B)`.

        :math:`bnf[5]` contains the prime factor base, i.e. the list of prime
        ideals used in finding the relations.

        :math:`bnf[6]` used to contain a permutation of the prime factor base, but
        has been obsoleted. It contains a dummy :math:`0`.

        :math:`bnf[7]` or :literal:`:emphasis:`bnf`.nf` is equal to the number field data
        :math:`nf` as would be given by :literal:`nfinit`.

        :math:`bnf[8]` is a vector containing the classgroup :literal:`:emphasis:`bnf`.clgp`
        as a finite abelian group, the regulator :literal:`:emphasis:`bnf`.reg`, a :math:`1` (used to
        contain an obsolete "check number"), the number of roots of unity and a
        generator :literal:`:emphasis:`bnf`.tu`, the fundamental units :literal:`:emphasis:`bnf`.fu`.

        :math:`bnf[9]` is a 3-element row vector used in :literal:`bnfisprincipal` only
        and obtained as follows. Let :math:`D = U W V` obtained by applying the
        Smith normal form algorithm to the matrix :math:`W` ( = :math:`bnf[1]`) and
        let :math:`U_r` be the reduction of :math:`U` modulo :math:`D`. The first elements of the
        factorbase are given (in terms of :literal:`bnf.gen`) by the columns of :math:`U_r`,
        with Archimedean component :math:`g_a`; let also :math:`GD_a` be the Archimedean
        components of the generators of the (principal) ideals defined by the
        :literal:`bnf.gen[i]^bnf.cyc[i]`. Then :math:`bnf[9] = [U_r, g_a, GD_a]`.

        :math:`bnf[10]` is by default unused and set equal to 0. This field is used
        to store further information about the field as it becomes available, which
        is rarely needed, hence would be too expensive to compute during the initial
        :literal:`bnfinit` call. For instance, the generators of the principal ideals
        :literal:`bnf.gen[i]^bnf.cyc[i]` (during a call to :literal:`bnrisprincipal`), or
        those corresponding to the relations in :math:`W` and :math:`B` (when the :literal:`bnf`
        internal precision needs to be increased).
        '''
        P = objtogen(P)
        cdef bint _have_tech = (tech is not None)
        if _have_tech:
            tech = objtogen(tech)
        sig_on()
        cdef GEN _P = (<Gen>P).g
        cdef GEN _tech = NULL
        if _have_tech:
            _tech = (<Gen>tech).g
        precision = nbits2prec(precision)
        cdef GEN _ret = bnfinit0(_P, flag, _tech, precision)
        return new_gen(_ret)

    def bnfisintnorm(self, bnf, x):
        r'''
        Computes a complete system of
        solutions (modulo units of positive norm) of the absolute norm equation
        :math:`\mathrm{Norm} (a) = x`,
        where :math:`a` is an integer in :math:`bnf`. If :math:`bnf` has not been certified,
        the correctness of the result depends on the validity of GRH.

        See also :literal:`bnfisnorm`.
        '''
        bnf = objtogen(bnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = bnfisintnorm(_bnf, _x)
        return new_gen(_ret)

    def bnfisnorm(self, bnf, x, long flag=1):
        r'''
        Tries to tell whether the
        rational number :math:`x` is the norm of some element y in :math:`bnf`. Returns a
        vector :math:`[a,b]` where :math:`x = Norm(a)*b`. Looks for a solution which is an :math:`S`-unit,
        with :math:`S` a certain set of prime ideals containing (among others) all primes
        dividing :math:`x`. If :math:`bnf` is known to be Galois, set :math:`flag = 0` (in
        this case, :math:`x` is a norm iff :math:`b = 1`). If :math:`flag` is non zero the program adds to
        :math:`S` the following prime ideals, depending on the sign of :math:`flag`. If :math:`flag > 0`,
        the ideals of norm less than :math:`flag`. And if :math:`flag < 0` the ideals dividing :math:`flag`.

        Assuming GRH, the answer is guaranteed (i.e. :math:`x` is a norm iff :math:`b = 1`),
        if :math:`S` contains all primes less than :math:`12\log (\mathrm{disc} (Bnf))^2`, where
        :math:`Bnf` is the Galois closure of :math:`bnf`.

        See also :literal:`bnfisintnorm`.
        '''
        bnf = objtogen(bnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = bnfisnorm(_bnf, _x, flag)
        return new_gen(_ret)

    def bnfisprincipal(self, bnf, x, long flag=1):
        r'''
        :math:`bnf` being the
        number field data output by :literal:`bnfinit`, and :math:`x` being an ideal, this
        function tests whether the ideal is principal or not. The result is more
        complete than a simple true/false answer and solves general discrete
        logarithm problem. Assume the class group is :math:`\oplus (\mathbb{Z}/d_i\mathbb{Z})g_i`
        (where the generators :math:`g_i` and their orders :math:`d_i` are respectively given by
        :literal:`bnf.gen` and :literal:`bnf.cyc`). The routine returns a row vector :math:`[e,t]`,
        where :math:`e` is a vector of exponents :math:`0 <= e_i < d_i`, and :math:`t` is a number
        field element such that

        .. MATH::

        x = (t) \prod_i g_i^{e_i}.

        For :emphasis:`given` :math:`g_i` (i.e. for a given :literal:`bnf`), the :math:`e_i` are unique,
        and :math:`t` is unique modulo units.

        In particular, :math:`x` is principal if and only if :math:`e` is the zero vector. Note
        that the empty vector, which is returned when the class number is :math:`1`, is
        considered to be a zero vector (of dimension :math:`0`).

        ::

        ? K = bnfinit(y^2+23);
        ? K.cyc
        %2 = [3]
        ? K.gen
        %3 = [[2, 0; 0, 1]] \\ a prime ideal above 2
        ? P = idealprimedec(K,3)[1]; \\ a prime ideal above 3
        ? v = bnfisprincipal(K, P)
        %5 = [[2]~, [3/4, 1/4]~]
        ? idealmul(K, v[2], idealfactorback(K, K.gen, v[1]))
        %6 =
        [3 0]
        
        [0 1]
        ? % == idealhnf(K, P)
        %7 = 1

        The binary digits of :emphasis:`flag` mean:

        - :math:`1`: If set, outputs :math:`[e,t]` as explained above, otherwise returns
        only :math:`e`, which is much easier to compute. The following idiom only tests
        whether an ideal is principal:

        ::

        is_principal(bnf, x) = !bnfisprincipal(bnf,x,0);

        - :math:`2`: It may not be possible to recover :math:`t`, given the initial accuracy
        to which the :literal:`bnf` structure was computed. In that case, a warning is
        printed and :math:`t` is set equal to the empty vector :literal:`[]~`. If this bit is
        set, increase the precision and recompute needed quantities until :math:`t` can be
        computed. Warning: setting this may induce :emphasis:`lengthy` computations.
        '''
        bnf = objtogen(bnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = bnfisprincipal0(_bnf, _x, flag)
        return new_gen(_ret)

    def bnfissunit(self, bnf, sfu, x):
        r'''
        :math:`bnf` being output by
        :literal:`bnfinit`, :emphasis:`sfu` by :literal:`bnfsunit`, gives the column vector of
        exponents of :math:`x` on the fundamental :math:`S`-units and the roots of unity, in the
        following order: the fundamental units :emphasis:`bnf.fu`, the root of
        unity :emphasis:`bnf.tu`, and the :math:`S`-units :emphasis:`sfu[1]`.
        If :math:`x` is not an :math:`S`-unit, outputs an empty vector.

        ::

        ? bnf = bnfinit(x^4 - x^3 + 4*x^2 + 3*x + 9, 1);
        ? bnf.sign
        %2 = [0, 2]
        ? S = idealprimedec(bnf,5); #S
        %3 = 2
        ? sfu = bnfsunit(bnf,S);
        ? sfu[1]
        %5 = [-5/6*x^3 + 4/3*x^2 - 4/3*x - 3/2, 5]
        ? u = [10,-40,24,11]~;
        ? bnfissunit(bnf,sfu,u)
        %7 = [1, Mod(2, 6), 2, 0]~
        ? bnfissunit(bnf,sfu,3)
        %8 = []~
        '''
        bnf = objtogen(bnf)
        sfu = objtogen(sfu)
        x = objtogen(x)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _sfu = (<Gen>sfu).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = bnfissunit(_bnf, _sfu, _x)
        return new_gen(_ret)

    def bnfisunit(self, bnf, x):
        r'''
        :emphasis:`bnf` being the number field data
        output by :literal:`bnfinit` and :math:`x` being an algebraic number (type integer,
        rational or polmod), this outputs the decomposition of :math:`x` on the fundamental
        units and the roots of unity if :math:`x` is a unit, the empty vector otherwise.
        More precisely, if :math:`u_1`,...,:math:`u_r` are the fundamental units, and :math:`\zeta`
        is the generator of the group of roots of unity (:literal:`bnf.tu`), the output is
        a vector :math:`[x_1,...,x_r,x_{r+1}]` such that :math:`x = u_1^{x_1}...
        u_r^{x_r}.\zeta^{x_{r+1}}`. The :math:`x_i` are integers for :math:`i <= r` and is an
        integer modulo the order of :math:`\zeta` for :math:`i = r+1`.

        Note that :emphasis:`bnf` need not contain the fundamental unit explicitly:

        ::

        ? setrand(1); bnf = bnfinit(x^2-x-100000);
        ? bnf.fu
        *** at top-level: bnf.fu
        *** ^--
        *** _.fu: missing units in .fu.
        ? u = [119836165644250789990462835950022871665178127611316131167, \
        379554884019013781006303254896369154068336082609238336]~;
        ? bnfisunit(bnf, u)
        %3 = [-1, Mod(0, 2)]~

        The given :math:`u` is the inverse of the fundamental unit
        implicitly stored in :emphasis:`bnf`. In this case, the fundamental unit was not
        computed and stored in algebraic form since the default accuracy was too
        low. (Re-run the command at \\g1 or higher to see such diagnostics.)
        '''
        bnf = objtogen(bnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = bnfisunit(_bnf, _x)
        return new_gen(_ret)

    def bnflog(self, bnf, l):
        r'''
        Let :emphasis:`bnf` be a :emphasis:`bnf` structure attached to the number field :math:`F` and let :math:`l` be
        a prime number (hereafter denoted :math:`\ell` for typographical reasons). Return
        the logarithmic :math:`\ell`-class group :math:`~{Cl}_F`
        of :math:`F`. This is an abelian group, conjecturally finite (known to be finite
        if :math:`F/\mathbb{Q}` is abelian). The function returns if and only if
        the group is indeed finite (otherwise it would run into an infinite loop).
        Let :math:`S = { p_1,..., p_k}` be the set of :math:`\ell`-adic places
        (maximal ideals containing :math:`\ell`).
        The function returns :math:`[D, G(\ell), G']`, where

        - :math:`D` is the vector of elementary divisors for :math:`~{Cl}_F`.

        - :math:`G(\ell)` is the vector of elementary divisors for
        the (conjecturally finite) abelian group
        

        .. MATH::

        ~{\mathrm{Cl}}(\ell) =
        \{ a = \sum_{i <= k} a_i p_i : \deg_F a = 0},

        where the :math:`p_i` are the :math:`\ell`-adic places of :math:`F`; this is a
        subgroup of :math:`~{\mathrm{Cl}}`.

        - :math:`G'` is the vector of elementary divisors for the :math:`\ell`-Sylow :math:`Cl'`
        of the :math:`S`-class group of :math:`F`; the group :math:`~{\mathrm{Cl}}` maps to :math:`Cl'`
        with a simple co-kernel.
        '''
        bnf = objtogen(bnf)
        l = objtogen(l)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _l = (<Gen>l).g
        cdef GEN _ret = bnflog(_bnf, _l)
        return new_gen(_ret)

    def bnflogdegree(self, nf, A, l):
        r'''
        Let :emphasis:`nf` be a :emphasis:`nf` structure attached to a number field :math:`F`,
        and let :math:`l` be a prime number (hereafter
        denoted :math:`\ell`). The
        :math:`\ell`-adified group of id\\`{e}les of :math:`F` quotiented by
        the group of logarithmic units is identified to the :math:`\ell`-group
        of logarithmic divisors :math:`\oplus \mathbb{Z}_\ell [p]`, generated by the
        maximal ideals of :math:`F`.

        The :emphasis:`degree` map :math:`\deg_F` is additive with values in :math:`\mathbb{Z}_\ell`,
        defined by :math:`\deg_F p = ~{f}_{p} \deg_\ell p`,
        where the integer :math:`~{f}_{p}` is as in :literal:`bnflogef` and :math:`\deg_\ell p`
        is :math:`\log_\ell p` for :math:`p != \ell`, :math:`\log_\ell (1 + \ell)` for
        :math:`p = \ell != 2` and :math:`\log_\ell (1 + 2^2)` for :math:`p = \ell = 2`.

        Let :math:`A = \prod p^{n_{p}}` be an ideal and let :math:`~{A} =
        \sum n_p [p]` be the attached logarithmic divisor. Return the
        exponential of the :math:`\ell`-adic logarithmic degree :math:`\deg_F A`, which is a
        natural number.
        '''
        nf = objtogen(nf)
        A = objtogen(A)
        l = objtogen(l)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _A = (<Gen>A).g
        cdef GEN _l = (<Gen>l).g
        cdef GEN _ret = bnflogdegree(_nf, _A, _l)
        return new_gen(_ret)

    def bnflogef(self, nf, pr):
        r'''
        Let :emphasis:`nf` be a :emphasis:`nf` structure attached to a number field :math:`F`
        and let :emphasis:`pr` be a :emphasis:`prid` structure attached to a
        maximal ideal :math:`p / p`. Return
        :math:`[~{e}(F_p / \mathbb{Q}_p), ~{f}(F_p / \mathbb{Q}_p)]`
        the logarithmic ramification and residue degrees. Let :math:`\mathbb{Q}_p^c/\mathbb{Q}_p` be the
        cyclotomic :math:`\mathbb{Z}_p`-extension, then
        :math:`~{e} = [F_p : F_p \cap \mathbb{Q}_p^c]` and
        :math:`~{f} = [F_p \cap \mathbb{Q}_p^c : \mathbb{Q}_p]`. Note that
        :math:`~{e}~{f} = e(p/p) f(p/p)`, where :math:`e(p/p)` and :math:`f(p/p)` denote the
        usual ramification and residue degrees.

        ::

        ? F = nfinit(y^6 - 3*y^5 + 5*y^3 - 3*y + 1);
        ? bnflogef(F, idealprimedec(F,2)[1])
        %2 = [6, 1]
        ? bnflogef(F, idealprimedec(F,5)[1])
        %3 = [1, 2]
        '''
        nf = objtogen(nf)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = bnflogef(_nf, _pr)
        return new_gen(_ret)

    def bnfnarrow(self, bnf):
        r'''
        :emphasis:`bnf` being as output by
        :literal:`bnfinit`, computes the narrow class group of :emphasis:`bnf`. The output is
        a 3-component row vector :math:`v` analogous to the corresponding class group
        component :literal:`:emphasis:`bnf`.clgp`: the first component
        is the narrow class number :literal:`:math:`v`.no`, the second component is a vector
        containing the SNF cyclic components :literal:`:math:`v`.cyc` of
        the narrow class group, and the third is a vector giving the generators of
        the corresponding :literal:`:math:`v`.gen` cyclic groups. Note that this function is a
        special case of :literal:`bnrinit`; the :emphasis:`bnf` need not contain fundamental
        units.
        '''
        bnf = objtogen(bnf)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _ret = bnfnarrow(_bnf)
        return new_gen(_ret)

    def bnfsignunit(self, bnf):
        r'''
        :math:`bnf` being as output by
        :literal:`bnfinit`, this computes an :math:`r_1 x (r_1+r_2-1)` matrix having :math:`±1`
        components, giving the signs of the real embeddings of the fundamental units.
        The following functions compute generators for the totally positive units:

        ::

        /* exponents of totally positive units generators on bnf.tufu */
        tpuexpo(bnf)=
        { my(K, S = bnfsignunit(bnf), [m,n] = matsize(S));
        \\ m = bnf.r1, n = r1+r2-1
        S = matrix(m,n, i,j, if (S[i,j] < 0, 1,0));
        S = concat(vectorv(m,i,1), S); \\ add sign(-1)
        K = matker(S * Mod(1,2));
        if (K, mathnfmodid(lift(K), 2), 2*matid(n+1))
        }
        
        /* totally positive fundamental units */
        tpu(bnf)=
        { my(ex = tpuexpo(bnf)[,2..-1]); \\ remove ex[,1], corresponds to 1 or -1
        vector(#ex, i, nffactorback(bnf, bnf.tufu, ex[,i]));
        }
        '''
        bnf = objtogen(bnf)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _ret = signunits(_bnf)
        return new_gen(_ret)

    def bnfsunit(self, bnf, S, long precision=DEFAULT_BITPREC):
        r'''
        Computes the fundamental :math:`S`-units of the
        number field :math:`bnf` (output by :literal:`bnfinit`), where :math:`S` is a list of
        prime ideals (output by :literal:`idealprimedec`). The output is a vector :math:`v` with
        6 components.

        :math:`v[1]` gives a minimal system of (integral) generators of the :math:`S`-unit group
        modulo the unit group.

        :math:`v[2]` contains technical data needed by :literal:`bnfissunit`.

        :math:`v[3]` is an empty vector (used to give the logarithmic embeddings of the
        generators in :math:`v[1]` in version 2.0.16).

        :math:`v[4]` is the :math:`S`-regulator (this is the product of the regulator, the
        determinant of :math:`v[2]` and the natural logarithms of the norms of the ideals
        in :math:`S`).

        :math:`v[5]` gives the :math:`S`-class group structure, in the usual format
        (a row vector whose three components give in order the :math:`S`-class number,
        the cyclic components and the generators).

        :math:`v[6]` is a copy of :math:`S`.
        '''
        bnf = objtogen(bnf)
        S = objtogen(S)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _S = (<Gen>S).g
        precision = nbits2prec(precision)
        cdef GEN _ret = bnfsunit(_bnf, _S, precision)
        return new_gen(_ret)

    def bnrL1(self, bnr, H=None, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Let :emphasis:`bnr` be the number field data output by :literal:`bnrinit` and
        :emphasis:`H` be a square matrix defining a congruence subgroup of the
        ray class group corresponding to :emphasis:`bnr` (the trivial congruence subgroup
        if omitted). This function returns, for each character :math:`\chi` of the ray
        class group which is trivial on :math:`H`, the value at :math:`s = 1` (or :math:`s = 0`) of the
        abelian :math:`L`-function attached to :math:`\chi`. For the value at :math:`s = 0`, the
        function returns in fact for each :math:`\chi` a vector :math:`[r_\chi, c_\chi]` where

        .. MATH::

        L(s, \chi) = c.s^r + O(s^{r + 1})

        near :math:`0`.

        The argument :emphasis:`flag` is optional, its binary digits
        mean 1: compute at :math:`s = 0` if unset or :math:`s = 1` if set, 2: compute the
        primitive :math:`L`-function attached to :math:`\chi` if unset or the :math:`L`-function
        with Euler factors at prime ideals dividing the modulus of :emphasis:`bnr` removed
        if set (that is :math:`L_S(s, \chi)`, where :math:`S` is the
        set of infinite places of the number field together with the finite prime
        ideals dividing the modulus of :emphasis:`bnr`), 3: return also the character if
        set.

        ::

        K = bnfinit(x^2-229);
        bnr = bnrinit(K,1);
        bnrL1(bnr)

        returns the order and the first non-zero term of :math:`L(s, \chi)` at :math:`s = 0`
        where :math:`\chi` runs through the characters of the class group of
        :math:`K = \mathbb{Q} (\sqrt{229})`. Then

        ::

        bnr2 = bnrinit(K,2);
        bnrL1(bnr2,,2)

        returns the order and the first non-zero terms of :math:`L_S(s, \chi)` at :math:`s = 0`
        where :math:`\chi` runs through the characters of the class group of :math:`K` and :math:`S` is
        the set of infinite places of :math:`K` together with the finite prime :math:`2`. Note
        that the ray class group modulo :math:`2` is in fact the class group, so
        :literal:`bnrL1(bnr2,0)` returns the same answer as :literal:`bnrL1(bnr,0)`.

        This function will fail with the message

        ::

        *** bnrL1: overflow in zeta_get_N0 [need too many primes].

        if the approximate functional equation requires us to sum
        too many terms (if the discriminant of :math:`K` is too large).
        '''
        bnr = objtogen(bnr)
        cdef bint _have_H = (H is not None)
        if _have_H:
            H = objtogen(H)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _H = NULL
        if _have_H:
            _H = (<Gen>H).g
        precision = nbits2prec(precision)
        cdef GEN _ret = bnrL1(_bnr, _H, flag, precision)
        return new_gen(_ret)

    def bnrchar(self, bnr, g, v=None):
        r'''
        Returns all characters :math:`\chi` on :literal:`bnr.clgp` such that
        :math:`\chi (g_i) = e(v_i)`, where :math:`e(x) = \exp (2i\pi x)`. If :math:`v` is omitted,
        returns all characters that are trivial on the :math:`g_i`. Else the vectors :math:`g`
        and :math:`v` must have the same length, the :math:`g_i` must be ideals in any form, and
        each :math:`v_i` is a rational number whose denominator must divide the order of
        :math:`g_i` in the ray class group. For convenience, the vector of the :math:`g_i`
        can be replaced by a matrix whose columns give their discrete logarithm,
        as given by :literal:`bnrisprincipal`; this allows to specify abstractly a
        subgroup of the ray class group.

        ::

        ? bnr = bnrinit(bnfinit(x), [160,[1]], 1); /* (Z/160Z)^* */
        ? bnr.cyc
        %2 = [8, 4, 2]
        ? g = bnr.gen;
        ? bnrchar(bnr, g, [1/2,0,0])
        %4 = [[4, 0, 0]] \\ a unique character
        ? bnrchar(bnr, [g[1],g[3]]) \\ all characters trivial on g[1] and g[3]
        %5 = [[0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 0, 0]]
        ? bnrchar(bnr, [1,0,0;0,1,0;0,0,2])
        %6 = [[0, 0, 1], [0, 0, 0]] \\ characters trivial on given subgroup
        '''
        bnr = objtogen(bnr)
        g = objtogen(g)
        cdef bint _have_v = (v is not None)
        if _have_v:
            v = objtogen(v)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _g = (<Gen>g).g
        cdef GEN _v = NULL
        if _have_v:
            _v = (<Gen>v).g
        cdef GEN _ret = bnrchar(_bnr, _g, _v)
        return new_gen(_ret)

    def bnrclassno(self, A, B=None, C=None):
        r'''
        Let :math:`A`, :math:`B`, :math:`C` define a class field :math:`L` over a ground field :math:`K`
        (of type :literal:`[:emphasis:`bnr`]`,
        :literal:`[:emphasis:`bnr`, :emphasis:`subgroup`]`,
        or :literal:`[:emphasis:`bnf`, :emphasis:`modulus`]`,
        or :literal:`[:emphasis:`bnf`, :emphasis:`modulus`,:emphasis:`subgroup`]`,
        ``CFT`` (in the PARI manual)); this function returns the relative degree :math:`[L:K]`.

        In particular if :math:`A` is a :emphasis:`bnf` (with units), and :math:`B` a modulus,
        this function returns the corresponding ray class number modulo :math:`B`.
        One can input the attached :emphasis:`bid` (with generators if the subgroup
        :math:`C` is non trivial) for :math:`B` instead of the module itself, saving some time.

        This function is faster than :literal:`bnrinit` and should be used if only the
        ray class number is desired. See :literal:`bnrclassnolist` if you need ray class
        numbers for all moduli less than some bound.
        '''
        A = objtogen(A)
        cdef bint _have_B = (B is not None)
        if _have_B:
            B = objtogen(B)
        cdef bint _have_C = (C is not None)
        if _have_C:
            C = objtogen(C)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _B = NULL
        if _have_B:
            _B = (<Gen>B).g
        cdef GEN _C = NULL
        if _have_C:
            _C = (<Gen>C).g
        cdef GEN _ret = bnrclassno0(_A, _B, _C)
        return new_gen(_ret)

    def bnrclassnolist(self, bnf, list):
        r'''
        :math:`bnf` being as
        output by :literal:`bnfinit`, and :emphasis:`list` being a list of moduli (with units) as
        output by :literal:`ideallist` or :literal:`ideallistarch`, outputs the list of the
        class numbers of the corresponding ray class groups. To compute a single
        class number, :literal:`bnrclassno` is more efficient.

        ::

        ? bnf = bnfinit(x^2 - 2);
        ? L = ideallist(bnf, 100, 2);
        ? H = bnrclassnolist(bnf, L);
        ? H[98]
        %4 = [1, 3, 1]
        ? l = L[1][98]; ids = vector(#l, i, l[i].mod[1])
        %5 = [[98, 88; 0, 1], [14, 0; 0, 7], [98, 10; 0, 1]]

        The weird :literal:`l[i].mod[1]`, is the first component of :literal:`l[i].mod`, i.e.
        the finite part of the conductor. (This is cosmetic: since by construction
        the Archimedean part is trivial, I do not want to see it). This tells us that
        the ray class groups modulo the ideals of norm 98 (printed as :literal:`\%5`) have
        respectively order :math:`1`, :math:`3` and :math:`1`. Indeed, we may check directly:

        ::

        ? bnrclassno(bnf, ids[2])
        %6 = 3
        '''
        bnf = objtogen(bnf)
        list = objtogen(list)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _list = (<Gen>list).g
        cdef GEN _ret = bnrclassnolist(_bnf, _list)
        return new_gen(_ret)

    def bnrconductor(self, A, B=None, C=None, long flag=0):
        r'''
        Conductor :math:`f` of the subfield of a ray class field as defined by :math:`[A,B,C]`
        (of type :literal:`[:emphasis:`bnr`]`,
        :literal:`[:emphasis:`bnr`, :emphasis:`subgroup`]`,
        :literal:`[:emphasis:`bnf`, :emphasis:`modulus`]` or
        :literal:`[:emphasis:`bnf`, :emphasis:`modulus`, :emphasis:`subgroup`]`,
        ``CFT`` (in the PARI manual))

        If :math:`flag = 0`, returns :math:`f`.

        If :math:`flag = 1`, returns :math:`[f, Cl_f, H]`, where :math:`Cl_f` is the ray class group
        modulo :math:`f`, as a finite abelian group; finally :math:`H` is the subgroup of :math:`Cl_f`
        defining the extension.

        If :math:`flag = 2`, returns :math:`[f, bnr (f), H]`, as above except :math:`Cl_f` is
        replaced by a :literal:`bnr` structure, as output by :math:`bnrinit (,f)`, without
        generators unless the input contained a :emphasis:`bnr` with generators.

        In place of a subgroup :math:`H`, this function also accepts a character
        :literal:`chi` :math:`= (a_j)`, expressed as usual in terms of the generators
        :literal:`bnr.gen`: :math:`\chi (g_j) = \exp (2i\pi a_j / d_j)`, where :math:`g_j` has
        order :math:`d_j = bnr.cyc[j]`. In which case, the function returns
        respectively

        If :math:`flag = 0`, the conductor :math:`f` of :math:`Ker \chi`.

        If :math:`flag = 1`, :math:`[f, Cl_f, \chi_f]`, where :math:`\chi_f` is :math:`\chi` expressed
        on the minimal ray class group, whose modulus is the conductor.

        If :math:`flag = 2`, :math:`[f, bnr (f), \chi_f]`.
        '''
        A = objtogen(A)
        cdef bint _have_B = (B is not None)
        if _have_B:
            B = objtogen(B)
        cdef bint _have_C = (C is not None)
        if _have_C:
            C = objtogen(C)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _B = NULL
        if _have_B:
            _B = (<Gen>B).g
        cdef GEN _C = NULL
        if _have_C:
            _C = (<Gen>C).g
        cdef GEN _ret = bnrconductor0(_A, _B, _C, flag)
        return new_gen(_ret)

    def bnrconductorofchar(self, bnr, chi):
        r'''
        This function is obsolete, use :emphasis:`bnrconductor`.
        '''
        from warnings import warn
        warn('the PARI/GP function bnrconductorofchar is obsolete (2015-11-11)', DeprecationWarning)
        bnr = objtogen(bnr)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = bnrconductorofchar(_bnr, _chi)
        return new_gen(_ret)

    def bnrdisc(self, A, B=None, C=None, long flag=0):
        r'''
        :math:`A`, :math:`B`, :math:`C` defining a class field :math:`L` over a ground field :math:`K`
        (of type :literal:`[:emphasis:`bnr`]`,
        :literal:`[:emphasis:`bnr`, :emphasis:`subgroup`]`,
        :literal:`[:emphasis:`bnr`, :emphasis:`character`]`,
        :literal:`[:emphasis:`bnf`, :emphasis:`modulus`]` or
        :literal:`[:emphasis:`bnf`, :emphasis:`modulus`, :emphasis:`subgroup`]`,
        ``CFT`` (in the PARI manual)), outputs data :math:`[N,r_1,D]` giving the discriminant and
        signature of :math:`L`, depending on the binary digits of :emphasis:`flag`:

        - 1: if this bit is unset, output absolute data related to :math:`L/\mathbb{Q}`:
        :math:`N` is the absolute degree :math:`[L:\mathbb{Q}]`, :math:`r_1` the number of real places of :math:`L`,
        and :math:`D` the discriminant of :math:`L/\mathbb{Q}`. Otherwise, output relative data for :math:`L/K`:
        :math:`N` is the relative degree :math:`[L:K]`, :math:`r_1` is the number of real places of :math:`K`
        unramified in :math:`L` (so that the number of real places of :math:`L` is equal to :math:`r_1`
        times :math:`N`), and :math:`D` is the relative discriminant ideal of :math:`L/K`.

        - 2: if this bit is set and if the modulus is not the conductor of :math:`L`,
        only return 0.
        '''
        A = objtogen(A)
        cdef bint _have_B = (B is not None)
        if _have_B:
            B = objtogen(B)
        cdef bint _have_C = (C is not None)
        if _have_C:
            C = objtogen(C)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _B = NULL
        if _have_B:
            _B = (<Gen>B).g
        cdef GEN _C = NULL
        if _have_C:
            _C = (<Gen>C).g
        cdef GEN _ret = bnrdisc0(_A, _B, _C, flag)
        return new_gen(_ret)

    def bnrdisclist(self, bnf, bound, arch=None):
        r'''
        :math:`bnf` being as output by :literal:`bnfinit` (with units), computes a
        list of discriminants of Abelian extensions of the number field by increasing
        modulus norm up to bound :emphasis:`bound`. The ramified Archimedean places are
        given by :emphasis:`arch`; all possible values are taken if :emphasis:`arch` is omitted.

        The alternative syntax :math:`bnrdisclist (bnf,list)` is
        supported, where :emphasis:`list` is as output by :literal:`ideallist` or
        :literal:`ideallistarch` (with units), in which case :emphasis:`arch` is disregarded.

        The output :math:`v` is a vector, where :math:`v[k]` is itself a vector :math:`w`, whose length
        is the number of ideals of norm :math:`k`.

        - We consider first the case where :emphasis:`arch` was specified. Each
        component of :math:`w` corresponds to an ideal :math:`m` of norm :math:`k`, and
        gives invariants attached to the ray class field :math:`L` of :math:`bnf` of
        conductor :math:`[m, arch]`. Namely, each contains a vector :math:`[m,d,r,D]` with
        the following meaning: :math:`m` is the prime ideal factorization of the modulus,
        :math:`d = [L:\mathbb{Q}]` is the absolute degree of :math:`L`, :math:`r` is the number of real places
        of :math:`L`, and :math:`D` is the factorization of its absolute discriminant. We set :math:`d
        = r = D = 0` if :math:`m` is not the finite part of a conductor.

        - If :emphasis:`arch` was omitted, all :math:`t = 2^{r_1}` possible values are taken
        and a component of :math:`w` has the form
        :math:`[m, [[d_1,r_1,D_1],..., [d_t,r_t,D_t]]]`,
        where :math:`m` is the finite part of the conductor as above, and
        :math:`[d_i,r_i,D_i]` are the invariants of the ray class field of conductor
        :math:`[m,v_i]`, where :math:`v_i` is the :math:`i`-th Archimedean component, ordered by
        inverse lexicographic order; so :math:`v_1 = [0,...,0]`, :math:`v_2 = [1,0...,0]`,
        etc. Again, we set :math:`d_i = r_i = D_i = 0` if :math:`[m,v_i]` is not a conductor.

        Finally, each prime ideal :math:`pr = [p,\alpha,e,f,\beta]` in the prime
        factorization :math:`m` is coded as the integer :math:`p.n^2+(f-1).n+(j-1)`,
        where :math:`n` is the degree of the base field and :math:`j` is such that

        :literal:`pr = idealprimedec(:emphasis:`nf`,p)[j]`.

        :math:`m` can be decoded using :literal:`bnfdecodemodule`.

        Note that to compute such data for a single field, either :literal:`bnrclassno`
        or :literal:`bnrdisc` are (much) more efficient.
        '''
        bnf = objtogen(bnf)
        bound = objtogen(bound)
        cdef bint _have_arch = (arch is not None)
        if _have_arch:
            arch = objtogen(arch)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _bound = (<Gen>bound).g
        cdef GEN _arch = NULL
        if _have_arch:
            _arch = (<Gen>arch).g
        cdef GEN _ret = bnrdisclist0(_bnf, _bound, _arch)
        return new_gen(_ret)

    def bnrgaloisapply(self, bnr, mat, H):
        r'''
        Apply the automorphism given by its matrix :emphasis:`mat` to the congruence
        subgroup :math:`H` given as a HNF matrix.
        The matrix :emphasis:`mat` can be computed with :literal:`bnrgaloismatrix`.
        '''
        bnr = objtogen(bnr)
        mat = objtogen(mat)
        H = objtogen(H)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _mat = (<Gen>mat).g
        cdef GEN _H = (<Gen>H).g
        cdef GEN _ret = bnrgaloisapply(_bnr, _mat, _H)
        return new_gen(_ret)

    def bnrgaloismatrix(self, bnr, aut):
        r'''
        Return the matrix of the action of the automorphism :emphasis:`aut` of the base
        field :literal:`bnf.nf` on the generators of the ray class field :literal:`bnr.gen`.
        :emphasis:`aut` can be given as a polynomial, an algebraic number, or a vector of
        automorphisms or a Galois group as output by :literal:`galoisinit`, in which case a
        vector of matrices is returned (in the later case, only for the generators
        :literal:`aut.gen`).

        See :literal:`bnrisgalois` for an example.
        '''
        bnr = objtogen(bnr)
        aut = objtogen(aut)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _aut = (<Gen>aut).g
        cdef GEN _ret = bnrgaloismatrix(_bnr, _aut)
        return new_gen(_ret)

    def bnrinit(self, bnf, f, long flag=0):
        r'''
        :math:`bnf` is as
        output by :literal:`bnfinit` (including fundamental units), :math:`f` is a modulus,
        initializes data linked to the ray class group structure corresponding to
        this module, a so-called :literal:`bnr` structure. One can input the attached
        :emphasis:`bid` with generators for :math:`f` instead of the module itself, saving some
        time. (As in :literal:`idealstar`, the finite part of the conductor may be given
        by a factorization into prime ideals, as produced by :literal:`idealfactor`.)

        The following member functions are available
        on the result: :literal:`.bnf` is the underlying :emphasis:`bnf`,
        :literal:`.mod` the modulus, :literal:`.bid` the :literal:`bid` structure attached to the
        modulus; finally, :literal:`.clgp`, :literal:`.no`, :literal:`.cyc`, :literal:`.gen` refer to the
        ray class group (as a finite abelian group), its cardinality, its elementary
        divisors, its generators (only computed if :math:`flag = 1`).

        The last group of functions are different from the members of the underlying
        :emphasis:`bnf`, which refer to the class group; use :literal:`:emphasis:`bnr`.bnf.:emphasis:`xxx``
        to access these, e.g. :literal:`:emphasis:`bnr`.bnf.cyc` to get the cyclic decomposition
        of the class group.

        They are also different from the members of the underlying :emphasis:`bid`, which
        refer to :math:`(\mathbb{Z}_K/f)^*`; use :literal:`:emphasis:`bnr`.bid.:emphasis:`xxx`` to access these,
        e.g. :literal:`:emphasis:`bnr`.bid.no` to get :math:`\phi (f)`.

        If :math:`flag = 0` (default), the generators of the ray class group are not computed,
        which saves time. Hence :literal:`:emphasis:`bnr`.gen` would produce an error.

        If :math:`flag = 1`, as the default, except that generators are computed.
        '''
        bnf = objtogen(bnf)
        f = objtogen(f)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _f = (<Gen>f).g
        cdef GEN _ret = bnrinit0(_bnf, _f, flag)
        return new_gen(_ret)

    def bnrisconductor(self, A, B=None, C=None):
        r'''
        Fast variant of :literal:`bnrconductor`:math:`(A,B,C)`; :math:`A`, :math:`B`, :math:`C` represent
        an extension of the base field, given by class field theory
        (see ``CFT`` (in the PARI manual)). Outputs 1 if this modulus is the conductor, and 0
        otherwise. This is slightly faster than :literal:`bnrconductor` when the
        character or subgroup is not primitive.
        '''
        A = objtogen(A)
        cdef bint _have_B = (B is not None)
        if _have_B:
            B = objtogen(B)
        cdef bint _have_C = (C is not None)
        if _have_C:
            C = objtogen(C)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _B = NULL
        if _have_B:
            _B = (<Gen>B).g
        cdef GEN _C = NULL
        if _have_C:
            _C = (<Gen>C).g
        cdef long _ret = bnrisconductor0(_A, _B, _C)
        clear_stack()
        return _ret

    def bnrisgalois(self, bnr, gal, H):
        r'''
        Check whether the class field attached to the subgroup :math:`H` is Galois
        over the subfield of :literal:`bnr.nf` fixed by the group :emphasis:`gal`, which can be
        given as output by :literal:`galoisinit`, or as a matrix or a vector of matrices as
        output by :literal:`bnrgaloismatrix`, the second option being preferable, since it
        saves the recomputation of the matrices. Note: The function assumes that the
        ray class field attached to bnr is Galois, which is not checked.

        In the following example, we lists the congruence subgroups of subextension of
        degree at most :math:`3` of the ray class field of conductor :math:`9` which are Galois
        over the rationals.

        ::

        K=bnfinit(a^4-3*a^2+253009);
        G=galoisinit(K);
        B=bnrinit(K,9,1);
        L1=[H|H<-subgrouplist(B,3), bnrisgalois(B,G,H)]
        ##
        M=bnrgaloismatrix(B,G)
        L2=[H|H<-subgrouplist(B,3), bnrisgalois(B,M,H)]
        ##

        The second computation is much faster since :literal:`bnrgaloismatrix(B,G)` is
        computed only once.
        '''
        bnr = objtogen(bnr)
        gal = objtogen(gal)
        H = objtogen(H)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _H = (<Gen>H).g
        cdef long _ret = bnrisgalois(_bnr, _gal, _H)
        clear_stack()
        return _ret

    def bnrisprincipal(self, bnr, x, long flag=1):
        r'''
        Let :emphasis:`bnr` be the ray class group data output by
        :literal:`bnrinit`:math:`(,,1)` and let :math:`x` be an ideal in any form, coprime
        to the modulus :math:`f = bnr.mod`. Solves the discrete logarithm problem
        in the ray class group, with respect to the generators :literal:`bnr.gen`,
        in a way similar to :literal:`bnfisprincipal`. If :math:`x` is not coprime to the
        modulus of :emphasis:`bnr` the result is undefined.

        If :math:`flag = 1`, returns a 2-component vector :math:`v` where :math:`v[1]` is the
        vector of components of :math:`x` on the ray class group generators, :math:`v[2]` is
        an element :math:`\alpha` congruent to :math:`1 mod^* f` such that
        :math:`x = \alpha \prod_i g_i^{x_i}`.

        If :math:`flag = 0`, outputs only :math:`v_1`. In that case, :emphasis:`bnr` need not contain the
        ray class group generators, i.e. it may be created with
        :literal:`bnrinit`:math:`(,,0)`; in that case, although :literal:`bnr.gen` is undefined, we
        can still define canonical generators attached to the :literal:`bnr` and compute
        with respect to them.

        ::

        ? K = bnfinit(x^2 - 30); bnr = bnrinit(K, [4, [1,1]]);
        ? bnr.clgp \\ ray class group is isomorphic to Z/4 x Z/2 x Z/2
        %2 = [16, [4, 2, 2]]
        ? P = idealprimedec(K, 3)[1]; \\ a prime ideal above 3
        ? bnrisprincipal(bnr,P)
        %4 = [[1, 0, 0]~, 1]
        ? bnrisprincipal(bnr,P, 0) \\ omit the principal part
        %4 = [1, 0, 0]~
        '''
        bnr = objtogen(bnr)
        x = objtogen(x)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = bnrisprincipal(_bnr, _x, flag)
        return new_gen(_ret)

    def bnrrootnumber(self, bnr, chi, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        If :math:`\chi = chi` is a
        character over :emphasis:`bnr`, not necessarily primitive, let
        :math:`L(s,\chi) = \sum_{id} \chi (id) N(id)^{-s}` be the attached
        Artin L-function. Returns the so-called Artin root number, i.e. the
        complex number :math:`W(\chi)` of modulus 1 such that

        .. MATH::

        \Lambda (1-s,\chi) = W(\chi) \Lambda (s,\overline{\chi})

        where :math:`\Lambda (s,\chi) = A(\chi)^{s/2}\gamma_\chi (s) L(s,\chi)` is
        the enlarged L-function attached to :math:`L`.

        You can set :math:`flag = 1` if the character is known to be primitive. Example:

        ::

        bnf = bnfinit(x^2 - x - 57);
        bnr = bnrinit(bnf, [7,[1,1]]);
        bnrrootnumber(bnr, [2,1])

        returns the root number of the character :math:`\chi` of
        :math:`\mathrm{Cl}_{7 oo _1 oo _2}(\mathbb{Q} (\sqrt{229}))` defined by :math:`\chi (g_1^ag_2^b)
        = \zeta_1^{2a}\zeta_2^b`. Here :math:`g_1, g_2` are the generators of the
        ray-class group given by :literal:`bnr.gen` and :math:`\zeta_1 = e^{2i\pi/N_1},
        \zeta_2 = e^{2i\pi/N_2}` where :math:`N_1, N_2` are the orders of :math:`g_1` and
        :math:`g_2` respectively (:math:`N_1 = 6` and :math:`N_2 = 3` as :literal:`bnr.cyc` readily tells us).
        '''
        bnr = objtogen(bnr)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _chi = (<Gen>chi).g
        precision = nbits2prec(precision)
        cdef GEN _ret = bnrrootnumber(_bnr, _chi, flag, precision)
        return new_gen(_ret)

    def bnrstark(self, bnr, subgroup=None, long precision=DEFAULT_BITPREC):
        r'''
        :emphasis:`bnr` being as output by :literal:`bnrinit`, finds a relative equation
        for the class field corresponding to the modulus in :emphasis:`bnr` and the given
        congruence subgroup (as usual, omit :math:`subgroup` if you want the whole ray
        class group).

        The main variable of :emphasis:`bnr` must not be :math:`x`, and the ground field and the
        class field must be totally real. When the base field is :math:`\mathbb{Q}`, the vastly
        simpler :literal:`galoissubcyclo` is used instead. Here is an example:

        ::

        bnf = bnfinit(y^2 - 3);
        bnr = bnrinit(bnf, 5);
        bnrstark(bnr)

        returns the ray class field of :math:`\mathbb{Q} (\sqrt{3})` modulo :math:`5`. Usually, one wants
        to apply to the result one of

        ::

        rnfpolredabs(bnf, pol, 16) \\ compute a reduced relative polynomial
        rnfpolredabs(bnf, pol, 16 + 2) \\ compute a reduced absolute polynomial

        The routine uses Stark units and needs to find a suitable auxiliary
        conductor, which may not exist when the class field is not cyclic over the
        base. In this case :literal:`bnrstark` is allowed to return a vector of
        polynomials defining :emphasis:`independent` relative extensions, whose compositum
        is the requested class field. It was decided that it was more useful
        to keep the extra information thus made available, hence the user has to take
        the compositum herself.

        Even if it exists, the auxiliary conductor may be so large that later
        computations become unfeasible. (And of course, Stark's conjecture may simply
        be wrong.) In case of difficulties, try :literal:`rnfkummer`:

        ::

        ? bnr = bnrinit(bnfinit(y^8-12*y^6+36*y^4-36*y^2+9,1), 2);
        ? bnrstark(bnr)
        *** at top-level: bnrstark(bnr)
        *** ^-------------
        *** bnrstark: need 3919350809720744 coefficients in initzeta.
        *** Computation impossible.
        ? lift( rnfkummer(bnr) )
        time = 24 ms.
        %2 = x^2 + (1/3*y^6 - 11/3*y^4 + 8*y^2 - 5)
        '''
        bnr = objtogen(bnr)
        cdef bint _have_subgroup = (subgroup is not None)
        if _have_subgroup:
            subgroup = objtogen(subgroup)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _subgroup = NULL
        if _have_subgroup:
            _subgroup = (<Gen>subgroup).g
        precision = nbits2prec(precision)
        cdef GEN _ret = bnrstark(_bnr, _subgroup, precision)
        return new_gen(_ret)

    def call(self, f, A):
        r'''
        :math:`A = [a_1,..., a_n]` being a vector and :math:`f` being a function, returns the
        evaluation of :math:`f(a_1,...,a_n)`.
        :math:`f` can also be the name of a built-in GP function.
        If :math:`\# A = 1`, :literal:`call` (:math:`f,A`) = :literal:`apply` (:math:`f,A`)[1].
        If :math:`f` is variadic, the variadic arguments must grouped in a vector in
        the last component of :math:`A`.

        This function is useful

        - when writing a variadic function, to call another one:

        ::

        fprintf(file,format,args[..]) = write(file,call(Strprintf,[format,args]))

        - when dealing with function arguments with unspecified arity

        The function below implements a global memoization interface:

        ::

        memo=Map();
        memoize(f,A[..])=
        {
        my(res);
        if(!mapisdefined(memo, [f,A], &res),
        res = call(f,A);
        mapput(memo,[f,A],res));
        res;
        }

        for example:

        ::

        ? memoize(factor,2^128+1)
        %3 = [59649589127497217,1;5704689200685129054721,1]
        ? ##
        *** last result computed in 76 ms.
        ? memoize(factor,2^128+1)
        %4 = [59649589127497217,1;5704689200685129054721,1]
        ? ##
        *** last result computed in 0 ms.
        ? memoize(ffinit,3,3)
        %5 = Mod(1,3)*x^3+Mod(1,3)*x^2+Mod(1,3)*x+Mod(2,3)
        ? fibo(n)=if(n==0,0,n==1,1,memoize(fibo,n-2)+memoize(fibo,n-1));
        ? fibo(100)
        %7 = 354224848179261915075

        - to call operators through their internal names without using
        :literal:`alias`

        ::

        matnbelts(M) = call("_*_",matsize(M))
        '''
        f = objtogen(f)
        A = objtogen(A)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _A = (<Gen>A).g
        cdef GEN _ret = call0(_f, _A)
        return new_gen(_ret)

    def ceil(self, x):
        r'''
        Ceiling of :math:`x`. When :math:`x` is in :math:`\mathbb{R}`, the result is the
        smallest integer greater than or equal to :math:`x`. Applied to a rational
        function, :math:`ceil (x)` returns the Euclidean quotient of the numerator by
        the denominator.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gceil(_x)
        return new_gen(_ret)

    def centerlift(self, x, v=None):
        r'''
        Same as :literal:`lift`, except that :literal:`t_INTMOD` and :literal:`t_PADIC` components
        are lifted using centered residues:

        - for a :literal:`t_INTMOD` :math:`x\in \mathbb{Z}/n\mathbb{Z}`, the lift :math:`y` is such that
        :math:`-n/2 < y <= n/2`.

        - a :literal:`t_PADIC` :math:`x` is lifted in the same way as above (modulo
        :math:`p^padicprec(x)`) if its valuation :math:`v` is non-negative; if not, returns
        the fraction :math:`p^v` :literal:`centerlift`:math:`(x p^{-v})`; in particular, rational
        reconstruction is not attempted. Use :literal:`bestappr` for this.

        For backward compatibility, :literal:`centerlift(x,'v)` is allowed as an alias
        for :literal:`lift(x,'v)`.
        '''
        x = objtogen(x)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = centerlift0(_x, _v)
        return new_gen(_ret)

    def characteristic(self, x):
        r'''
        Returns the characteristic of the base ring over which :math:`x` is defined (as
        defined by :literal:`t_INTMOD` and :literal:`t_FFELT` components). The function raises an
        exception if incompatible primes arise from :literal:`t_FFELT` and :literal:`t_PADIC`
        components.

        ::

        ? characteristic(Mod(1,24)*x + Mod(1,18)*y)
        %1 = 6
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = characteristic(_x)
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def charconj(self, cyc, chi):
        r'''
        Let :emphasis:`cyc` represent a finite abelian group by its elementary
        divisors, i.e. :math:`(d_j)` represents :math:`\sum_{j <= k} \mathbb{Z}/d_j\mathbb{Z}` with :math:`d_k
        | ... \| d_1`; any object which has a :literal:`.cyc` method is also
        allowed, e.g. the output of :literal:`znstar` or :literal:`bnrinit`. A character
        on this group is given by a row vector :math:`\chi = [a_1,...,a_n]` such that
        :math:`\chi (\prod g_j^{n_j}) = \exp (2\pi i\sum a_j n_j / d_j)`, where :math:`g_j` denotes
        the generator (of order :math:`d_j`) of the :math:`j`-th cyclic component.

        This function returns the conjugate character.

        ::

        ? cyc = [15,5]; chi = [1,1];
        ? charconj(cyc, chi)
        %2 = [14, 4]
        ? bnf = bnfinit(x^2+23);
        ? bnf.cyc
        %4 = [3]
        ? charconj(bnf, [1])
        %5 = [2]

        For Dirichlet characters (when :literal:`cyc` is
        :literal:`znstar(q,1)`), characters in Conrey representation are available,
        see ``dirichletchar`` (in the PARI manual) or :literal:`??character`:

        ::

        ? G = znstar(8, 1); \\ (Z/8Z)^*
        ? charorder(G, 3) \\ Conrey label
        %2 = 2
        ? chi = znconreylog(G, 3);
        ? charorder(G, chi) \\ Conrey logarithm
        %4 = 2
        '''
        cyc = objtogen(cyc)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _cyc = (<Gen>cyc).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = charconj0(_cyc, _chi)
        return new_gen(_ret)

    def chardiv(self, cyc, a, b):
        r'''
        Let :emphasis:`cyc` represent a finite abelian group by its elementary
        divisors, i.e. :math:`(d_j)` represents :math:`\sum_{j <= k} \mathbb{Z}/d_j\mathbb{Z}` with :math:`d_k
        | ... \| d_1`; any object which has a :literal:`.cyc` method is also
        allowed, e.g. the output of :literal:`znstar` or :literal:`bnrinit`. A character
        on this group is given by a row vector :math:`a = [a_1,...,a_n]` such that
        :math:`\chi (\prod g_j^{n_j}) = \exp (2\pi i\sum a_j n_j / d_j)`, where :math:`g_j` denotes
        the generator (of order :math:`d_j`) of the :math:`j`-th cyclic component.

        Given two characters :math:`a` and :math:`b`, return the character
        :math:`a / b = a \overline{b}`.

        ::

        ? cyc = [15,5]; a = [1,1]; b = [2,4];
        ? chardiv(cyc, a,b)
        %2 = [14, 2]
        ? bnf = bnfinit(x^2+23);
        ? bnf.cyc
        %4 = [3]
        ? chardiv(bnf, [1], [2])
        %5 = [2]

        For Dirichlet characters on :math:`(\mathbb{Z}/N\mathbb{Z})^*`, additional
        representations are available (Conrey labels, Conrey logarithm),
        see ``dirichletchar`` (in the PARI manual) or :literal:`??character`.
        If the two characters are in the same format, the
        result is given in the same format, otherwise a Conrey logarithm is used.

        ::

        ? G = znstar(100, 1);
        ? G.cyc
        %2 = [20, 2]
        ? a = [10, 1]; \\ usual representation for characters
        ? b = 7; \\ Conrey label;
        ? c = znconreylog(G, 11); \\ Conrey log
        ? chardiv(G, b,b)
        %6 = 1 \\ Conrey label
        ? chardiv(G, a,b)
        %7 = [0, 5]~ \\ Conrey log
        ? chardiv(G, a,c)
        %7 = [0, 14]~ \\ Conrey log
        '''
        cyc = objtogen(cyc)
        a = objtogen(a)
        b = objtogen(b)
        sig_on()
        cdef GEN _cyc = (<Gen>cyc).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _ret = chardiv0(_cyc, _a, _b)
        return new_gen(_ret)

    def chareval(self, G, chi, x, z=None):
        r'''
        Let :math:`G` be an abelian group structure affording a discrete logarithm
        method, e.g :math:`G = znstar (N, 1)` for :math:`(\mathbb{Z}/N\mathbb{Z})^*` or a :literal:`bnr`
        structure, let :math:`x` be an element of :math:`G` and let :emphasis:`chi` be a character of
        :math:`G` (see the note below for details). This function returns the value of
        :emphasis:`chi` at :math:`x`.

        :strong:`Note on characters.`
        Let :math:`K` be some field. If :math:`G` is an abelian group,
        let :math:`\chi: G \to K^*` be a character of finite order and let :math:`o` be a
        multiple of the character order such that :math:`\chi (n) = \zeta^{c(n)}` for some
        fixed :math:`\zeta\in K^*` of multiplicative order :math:`o` and a unique morphism :math:`c: G
        \to (\mathbb{Z}/o\mathbb{Z},+)`. Our usual convention is to write

        .. MATH::

        G = (\mathbb{Z}/o_1\mathbb{Z}) g_1 \oplus...\oplus (\mathbb{Z}/o_d\mathbb{Z}) g_d

        for some generators :math:`(g_i)` of respective order :math:`d_i`, where the group has
        exponent :math:`o := lcm_i o_i`. Since :math:`\zeta^o = 1`, the vector :math:`(c_i)` in
        :math:`\prod (\mathbb{Z}/o_i\mathbb{Z})` defines a character :math:`\chi` on :math:`G` via :math:`\chi (g_i) =
        \zeta^{c_i (o/o_i)}` for all :math:`i`. Classical Dirichlet characters have values
        in :math:`K = \mathbb{C}` and we can take :math:`\zeta = \exp (2i\pi/o)`.

        :strong:`Note on Dirichlet characters.`
        In the special case where :emphasis:`bid` is attached to :math:`G = (\mathbb{Z}/q\mathbb{Z})^*`
        (as per :literal:`G = znstar(q,1)`), the Dirichlet
        character :emphasis:`chi` can be written in one of the usual 3 formats: a :literal:`t_VEC`
        in terms of :literal:`bid.gen` as above, a :literal:`t_COL` in terms of the Conrey
        generators, or a :literal:`t_INT` (Conrey label);
        see ``dirichletchar`` (in the PARI manual) or :literal:`??character`.

        The character value is encoded as follows, depending on the optional
        argument :math:`z`:

        - If :math:`z` is omitted: return the rational number :math:`c(x)/o` for :math:`x` coprime
        to :math:`q`, where we normalize :math:`0 <= c(x) < o`. If :math:`x` can not be mapped to the
        group (e.g. :math:`x` is not coprime to the conductor of a Dirichlet or Hecke
        character) we return the sentinel value :math:`-1`.

        - If :math:`z` is an integer :math:`o`, then we assume that :math:`o` is a multiple of the
        character order and we return the integer :math:`c(x)` when :math:`x` belongs
        to the group, and the sentinel value :math:`-1` otherwise.

        - :math:`z` can be of the form :math:`[zeta, o]`, where :emphasis:`zeta`
        is an :math:`o`-th root of :math:`1` and :math:`o` is a multiple of the character order.
        We return :math:`\zeta^{c(x)}` if :math:`x` belongs to the group, and the sentinel
        value :math:`0` otherwise. (Note that this coincides with the usual extension
        of Dirichlet characters to :math:`\mathbb{Z}`, or of Hecke characters to general ideals.)

        - Finally, :math:`z` can be of the form :math:`[vzeta, o]`, where
        :emphasis:`vzeta` is a vector of powers :math:`\zeta^0,..., \zeta^{o-1}`
        of some :math:`o`-th root of :math:`1` and :math:`o` is a multiple of the character order.
        As above, we return :math:`\zeta^{c(x)}` after a table lookup. Or the sentinel
        value :math:`0`.
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        x = objtogen(x)
        cdef bint _have_z = (z is not None)
        if _have_z:
            z = objtogen(z)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _z = NULL
        if _have_z:
            _z = (<Gen>z).g
        cdef GEN _ret = chareval(_G, _chi, _x, _z)
        return new_gen(_ret)

    def chargalois(self, cyc, ORD=None):
        r'''
        Let :emphasis:`cyc` represent a finite abelian group by its elementary divisors
        (any object which has a :literal:`.cyc` method is also allowed, i.e. the output of
        :literal:`znstar` or :literal:`bnrinit`). Return a list of representatives for the
        Galois orbits of complex characters of :math:`G`.
        If :literal:`ORD` is present, select characters depending on their orders:

        - if :literal:`ORD` is a :literal:`t_INT`, restrict to orders less than this
        bound;

        - if :literal:`ORD` is a :literal:`t_VEC` or :literal:`t_VECSMALL`, restrict to orders in
        the list.

        ::

        ? G = znstar(96);
        ? #chargalois(G) \\ 16 orbits of characters mod 96
        %2 = 16
        ? #chargalois(G,4) \\ order less than 4
        %3 = 12
        ? chargalois(G,[1,4]) \\ order 1 or 4; 5 orbits
        %4 = [[0, 0, 0], [2, 0, 0], [2, 1, 0], [2, 0, 1], [2, 1, 1]]

        Given a character :math:`\chi`, of order :math:`n` (:literal:`charorder(G,chi)`), the
        elements in its orbit are the :math:`\phi (n)` characters :math:`\chi^i`, :math:`(i,n) = 1`.
        '''
        cyc = objtogen(cyc)
        cdef bint _have_ORD = (ORD is not None)
        if _have_ORD:
            ORD = objtogen(ORD)
        sig_on()
        cdef GEN _cyc = (<Gen>cyc).g
        cdef GEN _ORD = NULL
        if _have_ORD:
            _ORD = (<Gen>ORD).g
        cdef GEN _ret = chargalois(_cyc, _ORD)
        return new_gen(_ret)

    def charker(self, cyc, chi):
        r'''
        Let :emphasis:`cyc` represent a finite abelian group by its elementary
        divisors, i.e. :math:`(d_j)` represents :math:`\sum_{j <= k} \mathbb{Z}/d_j\mathbb{Z}` with :math:`d_k
        | ... \| d_1`; any object which has a :literal:`.cyc` method is also
        allowed, e.g. the output of :literal:`znstar` or :literal:`bnrinit`. A character
        on this group is given by a row vector :math:`\chi = [a_1,...,a_n]` such that
        :math:`\chi (\prod g_j^{n_j}) = \exp (2\pi i\sum a_j n_j / d_j)`, where :math:`g_j` denotes
        the generator (of order :math:`d_j`) of the :math:`j`-th cyclic component.

        This function returns the kernel of :math:`\chi`, as a matrix :math:`K` in HNF which is a
        left-divisor of :literal:`matdiagonal(d)`. Its columns express in terms of
        the :math:`g_j` the generators of the subgroup. The determinant of :math:`K` is the
        kernel index.

        ::

        ? cyc = [15,5]; chi = [1,1];
        ? charker(cyc, chi)
        %2 =
        [15 12]
        
        [ 0 1]
        
        ? bnf = bnfinit(x^2+23);
        ? bnf.cyc
        %4 = [3]
        ? charker(bnf, [1])
        %5 =
        [3]

        Note that for Dirichlet characters (when :literal:`cyc` is
        :literal:`znstar(q, 1)`), characters in Conrey representation are available,
        see ``dirichletchar`` (in the PARI manual) or :literal:`??character`.

        ::

        ? G = znstar(8, 1); \\ (Z/8Z)^*
        ? charker(G, 1) \\ Conrey label for trivial character
        %2 =
        [1 0]
        
        [0 1]
        '''
        cyc = objtogen(cyc)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _cyc = (<Gen>cyc).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = charker0(_cyc, _chi)
        return new_gen(_ret)

    def charmul(self, cyc, a, b):
        r'''
        Let :emphasis:`cyc` represent a finite abelian group by its elementary
        divisors, i.e. :math:`(d_j)` represents :math:`\sum_{j <= k} \mathbb{Z}/d_j\mathbb{Z}` with :math:`d_k
        | ... \| d_1`; any object which has a :literal:`.cyc` method is also
        allowed, e.g. the output of :literal:`znstar` or :literal:`bnrinit`. A character
        on this group is given by a row vector :math:`a = [a_1,...,a_n]` such that
        :math:`\chi (\prod g_j^{n_j}) = \exp (2\pi i\sum a_j n_j / d_j)`, where :math:`g_j` denotes
        the generator (of order :math:`d_j`) of the :math:`j`-th cyclic component.

        Given two characters :math:`a` and :math:`b`, return the product character :math:`ab`.

        ::

        ? cyc = [15,5]; a = [1,1]; b = [2,4];
        ? charmul(cyc, a,b)
        %2 = [3, 0]
        ? bnf = bnfinit(x^2+23);
        ? bnf.cyc
        %4 = [3]
        ? charmul(bnf, [1], [2])
        %5 = [0]

        For Dirichlet characters on :math:`(\mathbb{Z}/N\mathbb{Z})^*`, additional
        representations are available (Conrey labels, Conrey logarithm), see
        ``dirichletchar`` (in the PARI manual) or :literal:`??character`. If the two characters are in
        the same format, their
        product is given in the same format, otherwise a Conrey logarithm is used.

        ::

        ? G = znstar(100, 1);
        ? G.cyc
        %2 = [20, 2]
        ? a = [10, 1]; \\ usual representation for characters
        ? b = 7; \\ Conrey label;
        ? c = znconreylog(G, 11); \\ Conrey log
        ? charmul(G, b,b)
        %6 = 49 \\ Conrey label
        ? charmul(G, a,b)
        %7 = [0, 15]~ \\ Conrey log
        ? charmul(G, a,c)
        %7 = [0, 6]~ \\ Conrey log
        '''
        cyc = objtogen(cyc)
        a = objtogen(a)
        b = objtogen(b)
        sig_on()
        cdef GEN _cyc = (<Gen>cyc).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _ret = charmul0(_cyc, _a, _b)
        return new_gen(_ret)

    def charorder(self, cyc, chi):
        r'''
        Let :emphasis:`cyc` represent a finite abelian group by its elementary
        divisors, i.e. :math:`(d_j)` represents :math:`\sum_{j <= k} \mathbb{Z}/d_j\mathbb{Z}` with :math:`d_k
        | ... \| d_1`; any object which has a :literal:`.cyc` method is also
        allowed, e.g. the output of :literal:`znstar` or :literal:`bnrinit`. A character
        on this group is given by a row vector :math:`\chi = [a_1,...,a_n]` such that
        :math:`\chi (\prod g_j^{n_j}) = \exp (2\pi i\sum a_j n_j / d_j)`, where :math:`g_j` denotes
        the generator (of order :math:`d_j`) of the :math:`j`-th cyclic component.

        This function returns the order of the character :literal:`chi`.

        ::

        ? cyc = [15,5]; chi = [1,1];
        ? charorder(cyc, chi)
        %2 = 15
        ? bnf = bnfinit(x^2+23);
        ? bnf.cyc
        %4 = [3]
        ? charorder(bnf, [1])
        %5 = 3

        For Dirichlet characters (when :literal:`cyc` is
        :literal:`znstar(q, 1)`), characters in Conrey representation are available,
        see ``dirichletchar`` (in the PARI manual) or :literal:`??character`:

        ::

        ? G = znstar(100, 1); \\ (Z/100Z)^*
        ? charorder(G, 7) \\ Conrey label
        %2 = 4
        '''
        cyc = objtogen(cyc)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _cyc = (<Gen>cyc).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = charorder0(_cyc, _chi)
        return new_gen(_ret)

    def charpoly(self, A, v=None, long flag=5):
        r'''
        characteristic polynomial
        of :math:`A` with respect to the variable :math:`v`, i.e. determinant of :math:`v*I-A` if :math:`A`
        is a square matrix.

        ::

        ? charpoly([1,2;3,4]);
        %1 = x^2 - 5*x - 2
        ? charpoly([1,2;3,4],, 't)
        %2 = t^2 - 5*t - 2

        If :math:`A` is not a square matrix, the function returns the characteristic
        polynomial of the map "multiplication by :math:`A`" if :math:`A` is a scalar:

        ::

        ? charpoly(Mod(x+2, x^3-2))
        %1 = x^3 - 6*x^2 + 12*x - 10
        ? charpoly(I)
        %2 = x^2 + 1
        ? charpoly(quadgen(5))
        %3 = x^2 - x - 1
        ? charpoly(ffgen(ffinit(2,4)))
        %4 = Mod(1, 2)*x^4 + Mod(1, 2)*x^3 + Mod(1, 2)*x^2 + Mod(1, 2)*x + Mod(1, 2)

        The value of :math:`flag` is only significant for matrices, and we advise to stick
        to the default value. Let :math:`n` be the dimension of :math:`A`.

        If :math:`flag = 0`, same method (Le Verrier's) as for computing the adjoint matrix,
        i.e. using the traces of the powers of :math:`A`. Assumes that :math:`n!` is
        invertible; uses :math:`O(n^4)` scalar operations.

        If :math:`flag = 1`, uses Lagrange interpolation which is usually the slowest method.
        Assumes that :math:`n!` is invertible; uses :math:`O(n^4)` scalar operations.

        If :math:`flag = 2`, uses the Hessenberg form. Assumes that the base ring is a field.
        Uses :math:`O(n^3)` scalar operations, but suffers from coefficient explosion
        unless the base field is finite or :math:`\mathbb{R}`.

        If :math:`flag = 3`, uses Berkowitz's division free algorithm, valid over any
        ring (commutative, with unit). Uses :math:`O(n^4)` scalar operations.

        If :math:`flag = 4`, :math:`x` must be integral. Uses a modular algorithm: Hessenberg form
        for various small primes, then Chinese remainders.

        If :math:`flag = 5` (default), uses the "best" method given :math:`x`.
        This means we use Berkowitz unless the base ring is :math:`\mathbb{Z}` (use :math:`flag = 4`)
        or a field where coefficient explosion does not occur,
        e.g. a finite field or the reals (use :math:`flag = 2`).
        '''
        A = objtogen(A)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _ret = charpoly0(_A, _v, flag)
        return new_gen(_ret)

    def charpow(self, cyc, a, n):
        r'''
        Let :emphasis:`cyc` represent a finite abelian group by its elementary
        divisors, i.e. :math:`(d_j)` represents :math:`\sum_{j <= k} \mathbb{Z}/d_j\mathbb{Z}` with :math:`d_k
        | ... \| d_1`; any object which has a :literal:`.cyc` method is also
        allowed, e.g. the output of :literal:`znstar` or :literal:`bnrinit`. A character
        on this group is given by a row vector :math:`a = [a_1,...,a_n]` such that
        :math:`\chi (\prod g_j^{n_j}) = \exp (2\pi i\sum a_j n_j / d_j)`, where :math:`g_j` denotes
        the generator (of order :math:`d_j`) of the :math:`j`-th cyclic component.

        Given :math:`n\in \mathbb{Z}` and a character :math:`a`, return the character :math:`a^n`.

        ::

        ? cyc = [15,5]; a = [1,1];
        ? charpow(cyc, a, 3)
        %2 = [3, 3]
        ? charpow(cyc, a, 5)
        %2 = [5, 0]
        ? bnf = bnfinit(x^2+23);
        ? bnf.cyc
        %4 = [3]
        ? charpow(bnf, [1], 3)
        %5 = [0]

        For Dirichlet characters on :math:`(\mathbb{Z}/N\mathbb{Z})^*`, additional
        representations are available (Conrey labels, Conrey logarithm), see
        ``dirichletchar`` (in the PARI manual) or :literal:`??character` and the output uses the
        same format as the input.

        ::

        ? G = znstar(100, 1);
        ? G.cyc
        %2 = [20, 2]
        ? a = [10, 1]; \\ standard representation for characters
        ? b = 7; \\ Conrey label;
        ? c = znconreylog(G, 11); \\ Conrey log
        ? charpow(G, a,3)
        %6 = [10, 1] \\ standard representation
        ? charpow(G, b,3)
        %7 = 43 \\ Conrey label
        ? charpow(G, c,3)
        %8 = [1, 8]~ \\ Conrey log
        '''
        cyc = objtogen(cyc)
        a = objtogen(a)
        n = objtogen(n)
        sig_on()
        cdef GEN _cyc = (<Gen>cyc).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = charpow0(_cyc, _a, _n)
        return new_gen(_ret)

    def chinese(self, x, y=None):
        r'''
        If :math:`x` and :math:`y` are both intmods or both polmods, creates (with the same
        type) a :math:`z` in the same residue class as :math:`x` and in the same residue class as
        :math:`y`, if it is possible.

        ::

        ? chinese(Mod(1,2), Mod(2,3))
        %1 = Mod(5, 6)
        ? chinese(Mod(x,x^2-1), Mod(x+1,x^2+1))
        %2 = Mod(-1/2*x^2 + x + 1/2, x^4 - 1)

        This function also allows vector and matrix arguments, in which case the
        operation is recursively applied to each component of the vector or matrix.

        ::

        ? chinese([Mod(1,2),Mod(1,3)], [Mod(1,5),Mod(2,7)])
        %3 = [Mod(1, 10), Mod(16, 21)]

        For polynomial arguments in the same variable, the function is applied to each
        coefficient; if the polynomials have different degrees, the high degree terms
        are copied verbatim in the result, as if the missing high degree terms in the
        polynomial of lowest degree had been :literal:`Mod(0,1)`. Since the latter
        behavior is usually :emphasis:`not` the desired one, we propose to convert the
        polynomials to vectors of the same length first:

        ::

        ? P = x+1; Q = x^2+2*x+1;
        ? chinese(P*Mod(1,2), Q*Mod(1,3))
        %4 = Mod(1, 3)*x^2 + Mod(5, 6)*x + Mod(3, 6)
        ? chinese(Vec(P,3)*Mod(1,2), Vec(Q,3)*Mod(1,3))
        %5 = [Mod(1, 6), Mod(5, 6), Mod(4, 6)]
        ? Pol(%)
        %6 = Mod(1, 6)*x^2 + Mod(5, 6)*x + Mod(4, 6)

        If :math:`y` is omitted, and :math:`x` is a vector, :literal:`chinese` is applied recursively
        to the components of :math:`x`, yielding a residue belonging to the same class as all
        components of :math:`x`.

        Finally :math:`chinese (x,x) = x` regardless of the type of :math:`x`; this allows
        vector arguments to contain other data, so long as they are identical in both
        vectors.
        '''
        x = objtogen(x)
        cdef bint _have_y = (y is not None)
        if _have_y:
            y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = NULL
        if _have_y:
            _y = (<Gen>y).g
        cdef GEN _ret = chinese(_x, _y)
        return new_gen(_ret)

    def cmp(self, x, y):
        r'''
        Gives the result of a comparison between arbitrary objects :math:`x` and :math:`y`
        (as :math:`-1`, :math:`0` or :math:`1`). The underlying order relation is transitive,
        the function returns :math:`0` if and only if :math:`x  ===  y`. It has no
        mathematical meaning but satisfies the following properties when comparing
        entries of the same type:

        - two :literal:`t_INT` s compare as usual (i.e. :literal:`cmp`:math:`(x,y) < 0` if and only
        if :math:`x < y`);

        - two :literal:`t_VECSMALL` s of the same length compare lexicographically;

        - two :literal:`t_STR` s compare lexicographically.

        In case all components are equal up to the smallest length of the operands,
        the more complex is considered to be larger. More precisely, the longest is
        the largest; when lengths are equal, we have matrix :math:`>` vector :math:`>` scalar.
        For example:

        ::

        ? cmp(1, 2)
        %1 = -1
        ? cmp(2, 1)
        %2 = 1
        ? cmp(1, 1.0) \\ note that 1 == 1.0, but (1===1.0) is false.
        %3 = -1
        ? cmp(x + Pi, [])
        %4 = -1

        This function is mostly useful to handle sorted lists or
        vectors of arbitrary objects. For instance, if :math:`v` is a vector, the
        construction :literal:`vecsort(v, cmp)` is equivalent to :literal:`Set(v)`.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef int _ret = cmp_universal(_x, _y)
        clear_stack()
        return _ret

    def component(self, x, long n):
        r'''
        Extracts the :math:`n-th`-component of :math:`x`. This is to be understood
        as follows: every PARI type has one or two initial code words. The
        components are counted, starting at 1, after these code words. In particular
        if :math:`x` is a vector, this is indeed the :math:`n-th`-component of :math:`x`, if
        :math:`x` is a matrix, the :math:`n-th` column, if :math:`x` is a polynomial, the
        :math:`n-th` coefficient (i.e. of degree :math:`n-1`), and for power series,
        the :math:`n-th` significant coefficient.

        For polynomials and power series, one should rather use :literal:`polcoeff`, and
        for vectors and matrices, the :literal:`[]` operator. Namely, if :math:`x` is a
        vector, then :literal:`x[n]` represents the :math:`n-th` component of :math:`x`. If
        :math:`x` is a matrix, :literal:`x[m,n]` represents the coefficient of row :literal:`m` and
        column :literal:`n` of the matrix, :literal:`x[m,]` represents the :math:`m-th`
        :emphasis:`row` of :math:`x`, and :literal:`x[,n]` represents the :math:`n-th`
        :emphasis:`column` of :math:`x`.

        Using of this function requires detailed knowledge of the structure of the
        different PARI types, and thus it should almost never be used directly.
        Some useful exceptions:

        ::

        ? x = 3 + O(3^5);
        ? component(x, 2)
        %2 = 81 \\ p^(p-adic accuracy)
        ? component(x, 1)
        %3 = 3 \\ p
        ? q = Qfb(1,2,3);
        ? component(q, 1)
        %5 = 1
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = compo(_x, n)
        return new_gen(_ret)

    def concat(self, x, y=None):
        r'''
        Concatenation of :math:`x` and :math:`y`. If :math:`x` or :math:`y` is
        not a vector or matrix, it is considered as a one-dimensional vector. All
        types are allowed for :math:`x` and :math:`y`, but the sizes must be compatible. Note
        that matrices are concatenated horizontally, i.e. the number of rows stays
        the same. Using transpositions, one can concatenate them vertically,
        but it is often simpler to use :literal:`matconcat`.

        ::

        ? x = matid(2); y = 2*matid(2);
        ? concat(x,y)
        %2 =
        [1 0 2 0]
        
        [0 1 0 2]
        ? concat(x~,y~)~
        %3 =
        [1 0]
        
        [0 1]
        
        [2 0]
        
        [0 2]
        ? matconcat([x;y])
        %4 =
        [1 0]
        
        [0 1]
        
        [2 0]
        
        [0 2]

        To concatenate vectors sideways (i.e. to obtain a two-row or two-column
        matrix), use :literal:`Mat` instead, or :literal:`matconcat`:

        ::

        ? x = [1,2];
        ? y = [3,4];
        ? concat(x,y)
        %3 = [1, 2, 3, 4]
        
        ? Mat([x,y]~)
        %4 =
        [1 2]
        
        [3 4]
        ? matconcat([x;y])
        %5 =
        [1 2]
        
        [3 4]

        Concatenating a row vector to a matrix having the same number of columns will
        add the row to the matrix (top row if the vector is :math:`x`, i.e. comes first, and
        bottom row otherwise).

        The empty matrix :literal:`[;]` is considered to have a number of rows compatible
        with any operation, in particular concatenation. (Note that this is
        :emphasis:`not` the case for empty vectors :literal:`[ ]` or :literal:`[ ]~`.)

        If :math:`y` is omitted, :math:`x` has to be a row vector or a list, in which case its
        elements are concatenated, from left to right, using the above rules.

        ::

        ? concat([1,2], [3,4])
        %1 = [1, 2, 3, 4]
        ? a = [[1,2]~, [3,4]~]; concat(a)
        %2 =
        [1 3]
        
        [2 4]
        
        ? concat([1,2; 3,4], [5,6]~)
        %3 =
        [1 2 5]
        
        [3 4 6]
        ? concat([%, [7,8]~, [1,2,3,4]])
        %5 =
        [1 2 5 7]
        
        [3 4 6 8]
        
        [1 2 3 4]
        '''
        x = objtogen(x)
        cdef bint _have_y = (y is not None)
        if _have_y:
            y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = NULL
        if _have_y:
            _y = (<Gen>y).g
        cdef GEN _ret = gconcat(_x, _y)
        return new_gen(_ret)

    def conj(self, x):
        r'''
        Conjugate of :math:`x`. The meaning of this
        is clear, except that for real quadratic numbers, it means conjugation in the
        real quadratic field. This function has no effect on integers, reals,
        intmods, fractions or :math:`p`-adics. The only forbidden type is polmod
        (see :literal:`conjvec` for this).
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gconj(_x)
        return new_gen(_ret)

    def conjvec(self, z, long precision=DEFAULT_BITPREC):
        r'''
        Conjugate vector representation of :math:`z`. If :math:`z` is a
        polmod, equal to :literal:`Mod`:math:`(a,T)`, this gives a vector of length
        :math:`degree(T)` containing:

        - the complex embeddings of :math:`z` if :math:`T` has rational coefficients,
        i.e. the :math:`a(r[i])` where :math:`r = polroots (T)`;

        - the conjugates of :math:`z` if :math:`T` has some intmod coefficients;

        if :math:`z` is a finite field element, the result is the vector of
        conjugates :math:`[z,z^p,z^{p^2},...,z^{p^{n-1}}]` where :math:`n = degree(T)`.

        If :math:`z` is an integer or a rational number, the result is :math:`z`. If
        :math:`z` is a (row or column) vector, the result is a matrix whose columns are
        the conjugate vectors of the individual elements of :math:`z`.
        '''
        z = objtogen(z)
        sig_on()
        cdef GEN _z = (<Gen>z).g
        precision = nbits2prec(precision)
        cdef GEN _ret = conjvec(_z, precision)
        return new_gen(_ret)

    def content(self, x, D=None):
        r'''
        Computes the gcd of all the coefficients of :math:`x`,
        when this gcd makes sense. This is the natural definition
        if :math:`x` is a polynomial (and by extension a power series) or a
        vector/matrix. This is in general a weaker notion than the :emphasis:`ideal`
        generated by the coefficients:

        ::

        ? content(2*x+y)
        %1 = 1 \\ = gcd(2,y) over Q[y]

        If :math:`x` is a scalar, this simply returns the absolute value of :math:`x` if :math:`x` is
        rational (:literal:`t_INT` or :literal:`t_FRAC`), and either :math:`1` (inexact input) or :math:`x`
        (exact input) otherwise; the result should be identical to :literal:`gcd(x, 0)`.

        The content of a rational function is the ratio of the contents of the
        numerator and the denominator. In recursive structures, if a
        matrix or vector :emphasis:`coefficient` :math:`x` appears, the gcd is taken
        not with :math:`x`, but with its content:

        ::

        ? content([ [2], 4*matid(3) ])
        %1 = 2

        The content of a :literal:`t_VECSMALL` is computed assuming the
        entries are signed integers.

        The optional argument :math:`D` allows to control over which ring we compute
        and get a more predictable behaviour:

        - :math:`1`: we only consider the underlying :math:`\mathbb{Q}`-structure and the
        denominator is a (positive) rational number

        - a simple variable, say :literal:`'x`: all entries are considered as
        rational functions in :math:`K(x)` for some field :math:`K` and the content is an
        element of :math:`K`.

        ::

        ? f = x + 1/y + 1/2;
        ? content(f) \\ as a t_POL in x
        %2 = 1/(2*y)
        ? content(f, 1) \\ Q-content
        %3 = 1/2
        ? content(f, y) \\ as a rational function in y
        %4 = 1/2
        ? g = x^2*y + y^2*x;
        ? content(g, x)
        %6 = y
        ? content(g, y)
        %7 = x
        '''
        x = objtogen(x)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = content0(_x, _D)
        return new_gen(_ret)

    def contfrac(self, x, b=None, long nmax=0):
        r'''
        Returns the row vector whose components are the partial quotients of the
        continued fraction expansion of :math:`x`. In other words, a result
        :math:`[a_0,...,a_n]` means that :math:`x ~ a_0+1/(a_1+...+1/a_n)`. The
        output is normalized so that :math:`a_n != 1` (unless we also have :math:`n = 0`).

        The number of partial quotients :math:`n+1` is limited by :literal:`nmax`. If
        :literal:`nmax` is omitted, the expansion stops at the last significant partial
        quotient.

        ::

        ? \p19
        realprecision = 19 significant digits
        ? contfrac(Pi)
        %1 = [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2]
        ? contfrac(Pi,, 3) \\ n = 2
        %2 = [3, 7, 15]

        :math:`x` can also be a rational function or a power series.

        If a vector :math:`b` is supplied, the numerators are equal to the coefficients
        of :math:`b`, instead of all equal to :math:`1` as above; more precisely, :math:`x ~
        (1/b_0)(a_0+b_1/(a_1+...+b_n/a_n))`; for a numerical continued fraction
        (:math:`x` real), the :math:`a_i` are integers, as large as possible; if :math:`x` is a
        rational function, they are polynomials with :math:`\deg a_i = \deg b_i + 1`.
        The length of the result is then equal to the length of :math:`b`, unless the next
        partial quotient cannot be reliably computed, in which case the expansion
        stops. This happens when a partial remainder is equal to zero (or too small
        compared to the available significant digits for :math:`x` a :literal:`t_REAL`).

        A direct implementation of the numerical continued fraction
        :literal:`contfrac(x,b)` described above would be

        ::

        \\ "greedy" generalized continued fraction
        cf(x, b) =
        { my( a= vector(#b), t );
        
        x *= b[1];
        for (i = 1, #b,
        a[i] = floor(x);
        t = x - a[i]; if (!t || i == #b, break);
        x = b[i+1] / t;
        ); a;
        }

        There is some degree of freedom when choosing the :math:`a_i`; the
        program above can easily be modified to derive variants of the standard
        algorithm. In the same vein, although no builtin
        function implements the related Engel expansion (a special kind of
        Egyptian fraction decomposition: :math:`x = 1/a_1 + 1/(a_1a_2) +...` ),
        it can be obtained as follows:

        ::

        \\ n terms of the Engel expansion of x
        engel(x, n = 10) =
        { my( u = x, a = vector(n) );
        for (k = 1, n,
        a[k] = ceil(1/u);
        u = u*a[k] - 1;
        if (!u, break);
        ); a
        }

        :strong:`Obsolete hack.` (don't use this): if :math:`b` is an integer, :emphasis:`nmax`
        is ignored and the command is understood as :literal:`contfrac(:math:`x,, b`)`.
        '''
        x = objtogen(x)
        cdef bint _have_b = (b is not None)
        if _have_b:
            b = objtogen(b)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _b = NULL
        if _have_b:
            _b = (<Gen>b).g
        cdef GEN _ret = contfrac0(_x, _b, nmax)
        return new_gen(_ret)

    def contfraceval(self, CF, t, long lim=-1):
        r'''
        Given a continued fraction :literal:`CF` output by :literal:`contfracinit`, evaluate
        the first :literal:`lim` terms of the continued fraction at :literal:`t` (all
        terms if :literal:`lim` is negative or omitted; if positive, :literal:`lim` must be
        less than or equal to the length of :literal:`CF`.
        '''
        CF = objtogen(CF)
        t = objtogen(t)
        sig_on()
        cdef GEN _CF = (<Gen>CF).g
        cdef GEN _t = (<Gen>t).g
        cdef GEN _ret = contfraceval(_CF, _t, lim)
        return new_gen(_ret)

    def contfracinit(self, M, long lim=-1):
        r'''
        Given :math:`M` representing the power series :math:`S = \sum_{n >= 0} M[n+1]z^n`,
        transform it into a continued fraction; restrict to :math:`n <= lim`
        if latter is non-negative. :math:`M` can be a vector, a power
        series, a polynomial, or a rational function.
        The result is a 2-component vector :math:`[A,B]` such that
        :math:`S = M[1] / (1+A[1]z+B[1]z^2/(1+A[2]z+B[2]z^2/(1+...1/(1+A[lim/2]z))))`.
        Does not work if any coefficient of :math:`M` vanishes, nor for series for
        which certain partial denominators vanish.
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = contfracinit(_M, lim)
        return new_gen(_ret)

    def contfracpnqn(self, x, long n=-1):
        r'''
        When :math:`x` is a vector or a one-row matrix, :math:`x`
        is considered as the list of partial quotients :math:`[a_0,a_1,...,a_n]` of a
        rational number, and the result is the 2 by 2 matrix
        :math:`[p_n,p_{n-1};q_n,q_{n-1}]` in the standard notation of continued fractions,
        so :math:`p_n/q_n = a_0+1/(a_1+...+1/a_n)`. If :math:`x` is a matrix with two rows
        :math:`[b_0,b_1,...,b_n]` and :math:`[a_0,a_1,...,a_n]`, this is then considered as a
        generalized continued fraction and we have similarly
        :math:`p_n/q_n = (1/b_0)(a_0+b_1/(a_1+...+b_n/a_n))`. Note that in this case one
        usually has :math:`b_0 = 1`.

        If :math:`n >= 0` is present, returns all convergents from :math:`p_0/q_0` up to
        :math:`p_n/q_n`. (All convergents if :math:`x` is too small to compute the :math:`n+1`
        requested convergents.)

        ::

        ? a = contfrac(Pi,10)
        %1 = [3, 7, 15, 1, 292, 1, 1, 1, 3]
        ? allpnqn(x) = contfracpnqn(x,#x) \\ all convergents
        ? allpnqn(a)
        %3 =
        [3 22 333 355 103993 104348 208341 312689 1146408]
        
        [1 7 106 113 33102 33215 66317 99532 364913]
        ? contfracpnqn(a) \\ last two convergents
        %4 =
        [1146408 312689]
        
        [ 364913 99532]
        
        ? contfracpnqn(a,3) \\ first three convergents
        %5 =
        [3 22 333 355]
        
        [1 7 106 113]
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = contfracpnqn(_x, n)
        return new_gen(_ret)

    def core(self, n, long flag=0):
        r'''
        If :math:`n` is an integer written as
        :math:`n = df^2` with :math:`d` squarefree, returns :math:`d`. If :math:`flag` is non-zero,
        returns the two-element row vector :math:`[d,f]`. By convention, we write :math:`0 = 0
        x 1^2`, so :literal:`core(0, 1)` returns :math:`[0,1]`.
        '''
        n = objtogen(n)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = core0(_n, flag)
        return new_gen(_ret)

    def coredisc(self, n, long flag=0):
        r'''
        A :emphasis:`fundamental discriminant` is an integer of the form :math:`t = 1
        mod 4` or :math:`4t = 8,12 mod 16`, with :math:`t` squarefree (i.e. :math:`1` or the
        discriminant of a quadratic number field). Given a non-zero integer
        :math:`n`, this routine returns the (unique) fundamental discriminant :math:`d`
        such that :math:`n = df^2`, :math:`f` a positive rational number. If :math:`flag` is non-zero,
        returns the two-element row vector :math:`[d,f]`. If :math:`n` is congruent to
        0 or 1 modulo 4, :math:`f` is an integer, and a half-integer otherwise.

        By convention, :literal:`coredisc(0, 1))` returns :math:`[0,1]`.

        Note that :literal:`quaddisc`:math:`(n)` returns the same value as :literal:`coredisc`:math:`(n)`,
        and also works with rational inputs :math:`n\in\mathbb{Q}^*`.
        '''
        n = objtogen(n)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = coredisc0(_n, flag)
        return new_gen(_ret)

    def cos(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Cosine of :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gcos(_x, precision)
        return new_gen(_ret)

    def cosh(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Hyperbolic cosine of :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gcosh(_x, precision)
        return new_gen(_ret)

    def cotan(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Cotangent of :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gcotan(_x, precision)
        return new_gen(_ret)

    def cotanh(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Hyperbolic cotangent of :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gcotanh(_x, precision)
        return new_gen(_ret)

    def default(self, key=None, val=None):
        r'''
        Returns the default corresponding to keyword :emphasis:`key`. If :emphasis:`val` is
        present, sets the default to :emphasis:`val` first (which is subject to string
        expansion first). Typing :literal:`default()` (or :literal:`\\d`) yields the complete
        default list as well as their current values. See ``defaults`` (in the PARI manual) for an
        introduction to GP defaults, ``gp_defaults`` (in the PARI manual) for a
        list of available defaults, and ``meta`` (in the PARI manual) for some shortcut
        alternatives. Note that the shortcuts are meant for interactive use and
        usually display more information than :literal:`default`.
        '''
        cdef char* _key
        if key is None:
            _key = NULL
        else:
            key = to_bytes(key)
            _key = <bytes>key
        cdef char* _val
        if val is None:
            _val = NULL
        else:
            val = to_bytes(val)
            _val = <bytes>val
        sig_on()
        cdef GEN _ret = default0(_key, _val)
        return new_gen(_ret)

    def denominator(self, f, D=None):
        r'''
        Denominator of :math:`f`. The meaning of this is clear when :math:`f` is a rational number
        or function. If :math:`f` is an integer or a polynomial, it is treated as a rational
        number or function, respectively, and the result is equal to :math:`1`. For
        polynomials, you probably want to use

        ::

        denominator( content(f) )

        instead. As for modular objects, :literal:`t_INTMOD` and :literal:`t_PADIC`
        have denominator :math:`1`, and the denominator of a :literal:`t_POLMOD` is the
        denominator of its lift.

        If :math:`f` is a recursive structure, for instance a vector or matrix, the lcm
        of the denominators of its components (a common denominator) is computed.
        This also applies for :literal:`t_COMPLEX` s and :literal:`t_QUAD` s.

        :strong:`Warning.` Multivariate objects are created according to variable
        priorities, with possibly surprising side effects (:math:`x/y` is a polynomial, but
        :math:`y/x` is a rational function). See ``priority`` (in the PARI manual).

        The optional argument :math:`D` allows to control over which ring we compute the
        denominator and get a more predictable behaviour:

        - :math:`1`: we only consider the underlying :math:`\mathbb{Q}`-structure and the
        denominator is a (positive) rational integer

        - a simple variable, say :literal:`'x`: all entries as rational functions
        in :math:`K(x)` and the denominator is a polynomial in :math:`x`.

        ::

        ? f = x + 1/y + 1/2;
        ? denominator(f) \\ a t_POL in x
        %2 = 1
        ? denominator(f, 1) \\ Q-denominator
        %3 = 2
        ? denominator(f, x) \\ as a t_POL in x, seen above
        %4 = 1
        ? denominator(f, y) \\ as a rational function in y
        %5 = 2*y
        '''
        f = objtogen(f)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = denominator(_f, _D)
        return new_gen(_ret)

    def deriv(self, x, v=None):
        r'''
        Derivative of :math:`x` with respect to the main
        variable if :math:`v` is omitted, and with respect to :math:`v` otherwise. The derivative
        of a scalar type is zero, and the derivative of a vector or matrix is done
        componentwise. One can use :math:`x'` as a shortcut if the derivative is with
        respect to the main variable of :math:`x`.

        By definition, the main variable of a :literal:`t_POLMOD` is the main variable among
        the coefficients from its two polynomial components (representative and
        modulus); in other words, assuming a polmod represents an element of
        :math:`R[X]/(T(X))`, the variable :math:`X` is a mute variable and the derivative is
        taken with respect to the main variable used in the base ring :math:`R`.
        '''
        x = objtogen(x)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = deriv(_x, _v)
        return new_gen(_ret)

    def diffop(self, x, v, d, long n=1):
        r'''
        Let :math:`v` be a vector of variables, and :math:`d` a vector of the same length,
        return the image of :math:`x` by the :math:`n`-power (:math:`1` if n is not given) of the differential
        operator :math:`D` that assumes the value :literal:`d[i]` on the variable :literal:`v[i]`.
        The value of :math:`D` on a scalar type is zero, and :math:`D` applies componentwise to a vector
        or matrix. When applied to a :literal:`t_POLMOD`, if no value is provided for the variable
        of the modulus, such value is derived using the implicit function theorem.

        Some examples:
        This function can be used to differentiate formal expressions:
        If :math:`E = \exp (X^2)` then we have :math:`E' = 2*X*E`. We can derivate :math:`X*exp(X^2)` as follow:

        ::

        ? diffop(E*X,[X,E],[1,2*X*E])
        %1 = (2*X^2 + 1)*E

        Let :literal:`Sin` and :literal:`Cos` be two function such that :math:`Sin^2+Cos^2 = 1`
        and :math:`Cos' = -Sin`. We can differentiate :math:`Sin/Cos` as follow,
        PARI inferring the value of :math:`Sin'` from the equation:

        ::

        ? diffop(Mod('Sin/'Cos,'Sin^2+'Cos^2-1),['Cos],[-'Sin])
        %1 = Mod(1/Cos^2, Sin^2 + (Cos^2 - 1))
        

        Compute the Bell polynomials (both complete and partial) via the Faa di Bruno formula:

        ::

        Bell(k,n=-1)=
        {
        my(var(i)=eval(Str("X",i)));
        my(x,v,dv);
        v=vector(k,i,if(i==1,'E,var(i-1)));
        dv=vector(k,i,if(i==1,'X*var(1)*'E,var(i)));
        x=diffop('E,v,dv,k)/'E;
        if(n<0,subst(x,'X,1),polcoeff(x,n,'X))
        }
        '''
        x = objtogen(x)
        v = objtogen(v)
        d = objtogen(d)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _v = (<Gen>v).g
        cdef GEN _d = (<Gen>d).g
        cdef GEN _ret = diffop0(_x, _v, _d, n)
        return new_gen(_ret)

    def digits(self, x, b=None):
        r'''
        Outputs the vector of the digits of :math:`\|x\|` in base :math:`b`, where :math:`x` and :math:`b` are
        integers (:math:`b = 10` by default). See :literal:`fromdigits` for the reverse
        operation.

        ::

        ? digits(1230)
        %1 = [1, 2, 3, 0]
        
        ? digits(10, 2) \\ base 2
        %2 = [1, 0, 1, 0]

        By convention, :math:`0` has no digits:

        ::

        ? digits(0)
        %3 = []
        '''
        x = objtogen(x)
        cdef bint _have_b = (b is not None)
        if _have_b:
            b = objtogen(b)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _b = NULL
        if _have_b:
            _b = (<Gen>b).g
        cdef GEN _ret = digits(_x, _b)
        return new_gen(_ret)

    def dilog(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of the dilogarithm of :math:`x`,
        i.e. analytic continuation of the power series :math:`\log_2(x) = \sum_{n >= 1}x^n/n^2`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = dilog(_x, precision)
        return new_gen(_ret)

    def dirdiv(self, x, y):
        r'''
        :math:`x` and :math:`y` being vectors of perhaps different
        lengths but with :math:`y[1] != 0` considered as Dirichlet series, computes
        the quotient of :math:`x` by :math:`y`, again as a vector.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = dirdiv(_x, _y)
        return new_gen(_ret)

    def dirmul(self, x, y):
        r'''
        :math:`x` and :math:`y` being vectors of perhaps different lengths representing
        the Dirichlet series :math:`\sum_n x_n n^{-s}` and :math:`\sum_n y_n n^{-s}`,
        computes the product of :math:`x` by :math:`y`, again as a vector.

        ::

        ? dirmul(vector(10,n,1), vector(10,n,moebius(n)))
        %1 = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

        The product
        length is the minimum of :math:`\# x* v(y)` and :math:`\# y* v(x)`,
        where :math:`v(x)` is the index of the first non-zero coefficient.

        ::

        ? dirmul([0,1], [0,1]);
        %2 = [0, 0, 0, 1]
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = dirmul(_x, _y)
        return new_gen(_ret)

    def dirzetak(self, nf, b):
        r'''
        Gives as a vector the first :math:`b`
        coefficients of the Dedekind zeta function of the number field :math:`nf`
        considered as a Dirichlet series.
        '''
        nf = objtogen(nf)
        b = objtogen(b)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _ret = dirzetak(_nf, _b)
        return new_gen(_ret)

    def divisors(self, x, long flag=0):
        r'''
        Creates a row vector whose components are the
        divisors of :math:`x`. The factorization of :math:`x` (as output by :literal:`factor`) can
        be used instead. If :math:`flag = 1`, return pairs :math:`[d, factor (d)]`.

        By definition, these divisors are the products of the irreducible
        factors of :math:`n`, as produced by :literal:`factor(n)`, raised to appropriate
        powers (no negative exponent may occur in the factorization). If :math:`n` is
        an integer, they are the positive divisors, in increasing order.

        ::

        ? divisors(12)
        %1 = [1, 2, 3, 4, 6, 12]
        ? divisors(12, 1) \\ include their factorization
        %2 = [[1, matrix(0,2)], [2, Mat([2, 1])], [3, Mat([3, 1])],
        [4, Mat([2, 2])], [6, [2, 1; 3, 1]], [12, [2, 2; 3, 1]]]
        
        ? divisors(x^4 + 2*x^3 + x^2) \\ also works for polynomials
        %3 = [1, x, x^2, x + 1, x^2 + x, x^3 + x^2, x^2 + 2*x + 1,
        x^3 + 2*x^2 + x, x^4 + 2*x^3 + x^2]
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = divisors0(_x, flag)
        return new_gen(_ret)

    def divisorslenstra(self, N, r, s):
        r'''
        Given three integers :math:`N > s > r >= 0` such that :math:`(r,s) = 1`
        and :math:`s^3 > N`, find all divisors :math:`d` of :math:`N` such that :math:`d = r (mod s)`.
        There are at most :math:`11` such divisors (Lenstra).

        ::

        ? N = 245784; r = 19; s = 65 ;
        ? divisorslenstra(N, r, s)
        %2 = [19, 84, 539, 1254, 3724, 245784]
        ? [ d | d <- divisors(N), d % s == r]
        %3 = [19, 84, 539, 1254, 3724, 245784]

        When the preconditions are not met, the result is undefined:

        ::

        ? N = 4484075232; r = 7; s = 1303; s^3 > N
        %4 = 0
        ? divisorslenstra(N, r, s)
        ? [ d | d <- divisors(N), d % s == r ]
        %6 = [7, 2613, 9128, 19552, 264516, 3407352, 344928864]

        (Divisors were missing but :math:`s^3 < N`.)
        '''
        N = objtogen(N)
        r = objtogen(r)
        s = objtogen(s)
        sig_on()
        cdef GEN _N = (<Gen>N).g
        cdef GEN _r = (<Gen>r).g
        cdef GEN _s = (<Gen>s).g
        cdef GEN _ret = divisorslenstra(_N, _r, _s)
        return new_gen(_ret)

    def divrem(self, x, y, v=None):
        r'''
        Creates a column vector with two components, the first being the Euclidean
        quotient (:literal:`:math:`x` \\:math:`y``), the second the Euclidean remainder
        (:literal:`:math:`x` - (:math:`x`\\:math:`y`)*:math:`y``), of the division of :math:`x` by :math:`y`. This avoids the
        need to do two divisions if one needs both the quotient and the remainder.
        If :math:`v` is present, and :math:`x`, :math:`y` are multivariate
        polynomials, divide with respect to the variable :math:`v`.

        Beware that :literal:`divrem(:math:`x`,:math:`y`)[2]` is in general not the same as
        :literal:`:math:`x` \% :math:`y``; no GP operator corresponds to it:

        ::

        ? divrem(1/2, 3)[2]
        %1 = 1/2
        ? (1/2) % 3
        %2 = 2
        ? divrem(Mod(2,9), 3)[2]
        *** at top-level: divrem(Mod(2,9),3)[2
        *** ^--------------------
        *** forbidden division t_INTMOD \ t_INT.
        ? Mod(2,9) % 6
        %3 = Mod(2,3)
        '''
        x = objtogen(x)
        y = objtogen(y)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = divrem(_x, _y, _v)
        return new_gen(_ret)

    def eint1(self, x, n=None, long precision=DEFAULT_BITPREC):
        r'''
        Exponential integral :math:`\int_x^ oo (e^{-t})/(t)dt =
        incgam (0, x)`, where the latter expression extends the function
        definition from real :math:`x > 0` to all complex :math:`x != 0`.

        If :math:`n` is present, we must have :math:`x > 0`; the function returns the
        :math:`n`-dimensional vector :math:`[eint1 (x),...,eint1 (nx)]`. Contrary to
        other transcendental functions, and to the default case (:math:`n` omitted), the
        values are correct up to a bounded :emphasis:`absolute`, rather than relative,
        error :math:`10^{-n}`, where :math:`n` is :literal:`precision`:math:`(x)` if :math:`x` is a :literal:`t_REAL`
        and defaults to :literal:`realprecision` otherwise. (In the most important
        application, to the computation of :math:`L`-functions via approximate functional
        equations, those values appear as weights in long sums and small individual
        relative errors are less useful than controlling the absolute error.) This is
        faster than repeatedly calling :literal:`eint1(:math:`i` * x)`, but less precise.
        '''
        x = objtogen(x)
        cdef bint _have_n = (n is not None)
        if _have_n:
            n = objtogen(n)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _n = NULL
        if _have_n:
            _n = (<Gen>n).g
        precision = nbits2prec(precision)
        cdef GEN _ret = veceint1(_x, _n, precision)
        return new_gen(_ret)

    def ellL1(self, E, long r=0, long precision=DEFAULT_BITPREC):
        r'''
        Returns the value at :math:`s = 1` of the derivative of order :math:`r` of the
        :math:`L`-function of the elliptic curve :math:`E`.

        ::

        ? E = ellinit("11a1"); \\ order of vanishing is 0
        ? ellL1(E)
        %2 = 0.2538418608559106843377589233
        ? E = ellinit("389a1"); \\ order of vanishing is 2
        ? ellL1(E)
        %4 = -5.384067311837218089235032414 E-29
        ? ellL1(E, 1)
        %5 = 0
        ? ellL1(E, 2)
        %6 = 1.518633000576853540460385214

        The main use of this function, after computing at :emphasis:`low` accuracy the
        order of vanishing using :literal:`ellanalyticrank`, is to compute the
        leading term at :emphasis:`high` accuracy to check (or use) the Birch and
        Swinnerton-Dyer conjecture:

        ::

        ? \p18
        realprecision = 18 significant digits
        ? E = ellinit("5077a1"); ellanalyticrank(E)
        time = 8 ms.
        %1 = [3, 10.3910994007158041]
        ? \p200
        realprecision = 202 significant digits (200 digits displayed)
        ? ellL1(E, 3)
        time = 104 ms.
        %3 = 10.3910994007158041387518505103609170697263563756570092797[...]
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellL1_bitprec(_E, r, precision)
        return new_gen(_ret)

    def elladd(self, E, z1, z2):
        r'''
        Sum of the points :math:`z1` and :math:`z2` on the
        elliptic curve corresponding to :math:`E`.
        '''
        E = objtogen(E)
        z1 = objtogen(z1)
        z2 = objtogen(z2)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _z1 = (<Gen>z1).g
        cdef GEN _z2 = (<Gen>z2).g
        cdef GEN _ret = elladd(_E, _z1, _z2)
        return new_gen(_ret)

    def ellak(self, E, n):
        r'''
        Computes the coefficient :math:`a_n` of the :math:`L`-function of the elliptic curve
        :math:`E/\mathbb{Q}`, i.e. coefficients of a newform of weight 2 by the modularity theorem
        (Taniyama-Shimura-Weil conjecture). :math:`E` must be an :literal:`ell` structure
        over :math:`\mathbb{Q}` as output by :literal:`ellinit`. :math:`E` must be given by an integral model,
        not necessarily minimal, although a minimal model will make the function
        faster.

        ::

        ? E = ellinit([1,-1,0,4,3]);
        ? ellak(E, 10)
        %2 = -3
        ? e = ellchangecurve(E, [1/5,0,0,0]); \\ made not minimal at 5
        ? ellak(e, 10) \\ wasteful but works
        %3 = -3
        ? E = ellminimalmodel(e); \\ now minimal
        ? ellak(E, 5)
        %5 = -3

        If the model is not minimal at a number of bad primes, then
        the function will be slower on those :math:`n` divisible by the bad primes.
        The speed should be comparable for other :math:`n`:

        ::

        ? for(i=1,10^6, ellak(E,5))
        time = 699 ms.
        ? for(i=1,10^6, ellak(e,5)) \\ 5 is bad, markedly slower
        time = 1,079 ms.
        
        ? for(i=1,10^5,ellak(E,5*i))
        time = 1,477 ms.
        ? for(i=1,10^5,ellak(e,5*i)) \\ still slower but not so much on average
        time = 1,569 ms.
        '''
        E = objtogen(E)
        n = objtogen(n)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = akell(_E, _n)
        return new_gen(_ret)

    def ellan(self, E, long n):
        r'''
        Computes the vector of the first :math:`n` Fourier coefficients :math:`a_k`
        corresponding to the elliptic curve :math:`E` defined over a number field.
        If :math:`E` is defined over :math:`\mathbb{Q}`, the curve may be given by an
        arbitrary model, not necessarily minimal,
        although a minimal model will make the function faster. Over a more general
        number field, the model must be locally minimal at all primes above :math:`2`
        and :math:`3`.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellan(_E, n)
        return new_gen(_ret)

    def ellanalyticrank(self, E, eps=None, long precision=DEFAULT_BITPREC):
        r'''
        Returns the order of vanishing at :math:`s = 1` of the :math:`L`-function of the
        elliptic curve :math:`E` and the value of the first non-zero derivative. To
        determine this order, it is assumed that any value less than :literal:`eps` is
        zero. If :literal:`eps` is omitted, :math:`2^{-b/2}` is used, where :math:`b`
        is the current bit precision.

        ::

        ? E = ellinit("11a1"); \\ rank 0
        ? ellanalyticrank(E)
        %2 = [0, 0.2538418608559106843377589233]
        ? E = ellinit("37a1"); \\ rank 1
        ? ellanalyticrank(E)
        %4 = [1, 0.3059997738340523018204836835]
        ? E = ellinit("389a1"); \\ rank 2
        ? ellanalyticrank(E)
        %6 = [2, 1.518633000576853540460385214]
        ? E = ellinit("5077a1"); \\ rank 3
        ? ellanalyticrank(E)
        %8 = [3, 10.39109940071580413875185035]
        '''
        E = objtogen(E)
        cdef bint _have_eps = (eps is not None)
        if _have_eps:
            eps = objtogen(eps)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _eps = NULL
        if _have_eps:
            _eps = (<Gen>eps).g
        cdef GEN _ret = ellanalyticrank_bitprec(_E, _eps, precision)
        return new_gen(_ret)

    def ellap(self, E, p=None):
        r'''
        Let :literal:`E` be an :literal:`ell` structure as output by :literal:`ellinit`, attached
        to an elliptic curve :math:`E/K`. If the field :math:`K = \mathbb{F}_q` is finite, return the
        trace of Frobenius :math:`t`, defined by the equation :math:`\#E(\mathbb{F}_q) = q+1 - t`.

        For other fields of definition and :math:`p` defining a finite residue field
        :math:`\mathbb{F}_q`, return the trace of Frobenius for the reduction of :math:`E`: the argument
        :math:`p` is best left omitted if :math:`K = \mathbb{Q}_\ell` (else we must have :math:`p = \ell`) and
        must be a prime number (:math:`K = \mathbb{Q}`) or prime ideal (:math:`K` a general number field)
        with residue field :math:`\mathbb{F}_q` otherwise. The equation need not be minimal
        or even integral at :math:`p`; of course, a minimal model will be more efficient.

        For a number field :math:`K`, the trace of Frobenius is the :math:`a_p`
        coefficient in the Euler product defining the curve :math:`L`-series, whence
        the function name:

        .. MATH::

        L(E/K,s) = \prod_{bad p} (1-a_p (Np)^{-s})^{-1}
        \prod_{good p} (1-a_p (Np)^{-s} + (Np)^{1-2s})^{-1}.

        When the characteristic of the finite field is large, the availability of
        the :literal:`seadata` package will speed up the computation.

        ::

        ? E = ellinit([0,1]); \\ y^2 = x^3 + 0.x + 1, defined over Q
        ? ellap(E, 7) \\ 7 necessary here
        %2 = -4 \\ #E(F_7) = 7+1-(-4) = 12
        ? ellcard(E, 7)
        %3 = 12 \\ OK
        
        ? E = ellinit([0,1], 11); \\ defined over F_11
        ? ellap(E) \\ no need to repeat 11
        %4 = 0
        ? ellap(E, 11) \\ ... but it also works
        %5 = 0
        ? ellgroup(E, 13) \\ ouch, inconsistent input!
        *** at top-level: ellap(E,13)
        *** ^-----------
        *** ellap: inconsistent moduli in Rg_to_Fp:
        11
        13
        ? a = ffgen(ffinit(11,3), 'a); \\ defines F_q := F_{11^3}
        ? E = ellinit([a+1,a]); \\ y^2 = x^3 + (a+1)x + a, defined over F_q
        ? ellap(E)
        %8 = -3

        If the curve is defined over a more general number field than :math:`\mathbb{Q}`,
        the maximal ideal :math:`p` must be explicitly given in :literal:`idealprimedec`
        format. There is no assumption of local minimality at :math:`p`.

        ::

        ? K = nfinit(a^2+1); E = ellinit([1+a,0,1,0,0], K);
        ? fa = idealfactor(K, E.disc)
        %2 =
        [ [5, [-2, 1]~, 1, 1, [2, -1; 1, 2]] 1]
        
        [[13, [5, 1]~, 1, 1, [-5, -1; 1, -5]] 2]
        ? ellap(E, fa[1,1])
        %3 = -1 \\ non-split multiplicative reduction
        ? ellap(E, fa[2,1])
        %4 = 1 \\ split multiplicative reduction
        ? P17 = idealprimedec(K,17)[1];
        ? ellap(E, P17)
        %6 = 6 \\ good reduction
        ? E2 = ellchangecurve(E, [17,0,0,0]);
        ? ellap(E2, P17)
        %8 = 6 \\ same, starting from a non-miminal model
        
        ? P3 = idealprimedec(K,3)[1];
        ? ellap(E, P3) \\ OK: E is minimal at P3
        %10 = -2
        ? E3 = ellchangecurve(E, [3,0,0,0]);
        ? ellap(E3, P3) \\ not integral at P3
        *** at top-level: ellap(E3,P3)
        *** ^------------
        *** ellap: impossible inverse in Rg_to_ff: Mod(0, 3).

        :strong:`Algorithms used.` If :math:`E/\mathbb{F}_q` has CM by a principal imaginary
        quadratic order we use a fast explicit formula (involving essentially
        Kronecker symbols and Cornacchia's algorithm), in :math:`O(\log q)^2` bit
        operations.
        Otherwise, we use Shanks-Mestre's baby-step/giant-step method, which runs in
        time :math:`~{O}(q^{1/4})` using :math:`~{O}(q^{1/4})` storage, hence becomes
        unreasonable when :math:`q` has about 30 digits. Above this range, the :literal:`SEA`
        algorithm becomes available, heuristically in :math:`~{O}(\log q)^4`, and
        primes of the order of 200 digits become feasible. In small
        characteristic we use Mestre's (p = 2), Kohel's (p = 3,5,7,13), Satoh-Harley
        (all in :math:`~{O}(p^{2} n^2)`) or Kedlaya's (in :math:`~{O}(p n^3)`)
        algorithms.
        '''
        E = objtogen(E)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _ret = ellap(_E, _p)
        return new_gen(_ret)

    def ellbil(self, E, z1, z2, long precision=DEFAULT_BITPREC):
        r'''
        Deprecated alias for :literal:`ellheight(E,P,Q)`.
        '''
        from warnings import warn
        warn('the PARI/GP function ellbil is obsolete (2014-05-21)', DeprecationWarning)
        E = objtogen(E)
        z1 = objtogen(z1)
        z2 = objtogen(z2)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _z1 = (<Gen>z1).g
        cdef GEN _z2 = (<Gen>z2).g
        precision = nbits2prec(precision)
        cdef GEN _ret = bilhell(_E, _z1, _z2, precision)
        return new_gen(_ret)

    def ellbsd(self, E, long precision=DEFAULT_BITPREC):
        r'''
        The object :math:`E` being an elliptic curve over a number field, returns a real
        number :math:`c` such that the BSD conjecture predicts that
        :math:`L_{E}^{(r)}(1)/r != c R S` where :math:`r` is the rank, :math:`R` the regulator and
        :math:`S` the cardinal of the Tate-Shafarevich group.

        ::

        ? e = ellinit([0,-1,1,-10,-20]); \\ rank 0
        ? ellbsd(e)
        %2 = 0.25384186085591068433775892335090946105
        ? lfun(e,1)
        %3 = 0.25384186085591068433775892335090946104
        ? e = ellinit([0,0,1,-1,0]); \\ rank 1
        ? P = ellheegner(e);
        ? ellbsd(e)*ellheight(e,P)
        %6 = 0.30599977383405230182048368332167647445
        ? lfun(e,1,1)
        %7 = 0.30599977383405230182048368332167647445
        ? e = ellinit([1+a,0,1,0,0],nfinit(a^2+1)); \\ rank 0
        ? ellbsd(e)
        %9 = 0.42521832235345764503001271536611593310
        ? lfun(e,1)
        %10 = 0.42521832235345764503001271536611593309
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ellbsd(_E, precision)
        return new_gen(_ret)

    def ellcard(self, E, p=None):
        r'''
        Let :literal:`E` be an :literal:`ell` structure as output by :literal:`ellinit`, attached
        to an elliptic curve :math:`E/K`. If :math:`K = \mathbb{F}_q` is finite, return the order of the
        group :math:`E(\mathbb{F}_q)`.

        ::

        ? E = ellinit([-3,1], 5); ellcard(E)
        %1 = 7
        ? t = ffgen(3^5,'t); E = ellinit([t,t^2+1]); ellcard(E)
        %2 = 217

        For other fields of definition and :math:`p` defining a finite residue field
        :math:`\mathbb{F}_q`, return the order of the reduction of :math:`E`: the argument :math:`p` is best
        left omitted if :math:`K = \mathbb{Q}_\ell` (else we must have :math:`p = \ell`) and must be a
        prime number (:math:`K = \mathbb{Q}`) or prime ideal (:math:`K` a general number field) with
        residue field :math:`\mathbb{F}_q` otherwise. The equation need not be minimal
        or even integral at :math:`p`; of course, a minimal model will be more efficient.
        The function considers the group of non-singular points of the reduction
        of a minimal model of the curve at :math:`p`, so also makes sense when the curve
        has bad reduction.

        ::

        ? E = ellinit([-3,1]);
        ? factor(E.disc)
        %2 =
        [2 4]
        
        [3 4]
        ? ellcard(E, 5) \\ as above !
        %3 = 7
        ? ellcard(E, 2) \\ additive reduction
        %4 = 2

        When the characteristic of the finite field is large, the availability of
        the :literal:`seadata` package will speed the computation. See also :literal:`ellap`
        for the list of implemented algorithms.
        '''
        E = objtogen(E)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _ret = ellcard(_E, _p)
        return new_gen(_ret)

    def ellchangecurve(self, E, v):
        r'''
        Changes the data for the elliptic curve :math:`E`
        by changing the coordinates using the vector :literal:`v = [u,r,s,t]`, i.e. if :math:`x'`
        and :math:`y'` are the new coordinates, then :math:`x = u^2x'+r`, :math:`y = u^3y'+su^2x'+t`.
        :math:`E` must be an :literal:`ell` structure as output by :literal:`ellinit`. The special
        case :math:`v = 1` is also used instead of :math:`[1,0,0,0]` to denote the
        trivial coordinate change.
        '''
        E = objtogen(E)
        v = objtogen(v)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _v = (<Gen>v).g
        cdef GEN _ret = ellchangecurve(_E, _v)
        return new_gen(_ret)

    def ellchangepoint(self, x, v):
        r'''
        Changes the coordinates of the point or
        vector of points :math:`x` using the vector :literal:`v = [u,r,s,t]`, i.e. if :math:`x'` and
        :math:`y'` are the new coordinates, then :math:`x = u^2x'+r`, :math:`y = u^3y'+su^2x'+t` (see also
        :literal:`ellchangecurve`).

        ::

        ? E0 = ellinit([1,1]); P0 = [0,1]; v = [1,2,3,4];
        ? E = ellchangecurve(E0, v);
        ? P = ellchangepoint(P0,v)
        %3 = [-2, 3]
        ? ellisoncurve(E, P)
        %4 = 1
        ? ellchangepointinv(P,v)
        %5 = [0, 1]
        '''
        x = objtogen(x)
        v = objtogen(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _v = (<Gen>v).g
        cdef GEN _ret = ellchangepoint(_x, _v)
        return new_gen(_ret)

    def ellchangepointinv(self, x, v):
        r'''
        Changes the coordinates of the point or vector of points :math:`x` using
        the inverse of the isomorphism attached to :literal:`v = [u,r,s,t]`,
        i.e. if :math:`x'` and :math:`y'` are the old coordinates, then :math:`x = u^2x'+r`,
        :math:`y = u^3y'+su^2x'+t` (inverse of :literal:`ellchangepoint`).

        ::

        ? E0 = ellinit([1,1]); P0 = [0,1]; v = [1,2,3,4];
        ? E = ellchangecurve(E0, v);
        ? P = ellchangepoint(P0,v)
        %3 = [-2, 3]
        ? ellisoncurve(E, P)
        %4 = 1
        ? ellchangepointinv(P,v)
        %5 = [0, 1] \\ we get back P0
        '''
        x = objtogen(x)
        v = objtogen(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _v = (<Gen>v).g
        cdef GEN _ret = ellchangepointinv(_x, _v)
        return new_gen(_ret)

    def ellconvertname(self, name):
        r'''
        Converts an elliptic curve name, as found in the :literal:`elldata` database,
        from a string to a triplet :math:`[conductor, isogeny class,
        index]`. It will also convert a triplet back to a curve name.
        Examples:

        ::

        ? ellconvertname("123b1")
        %1 = [123, 1, 1]
        ? ellconvertname(%)
        %2 = "123b1"
        '''
        name = objtogen(name)
        sig_on()
        cdef GEN _name = (<Gen>name).g
        cdef GEN _ret = ellconvertname(_name)
        return new_gen(_ret)

    def elldivpol(self, E, long n, v=None):
        r'''
        :math:`n`-division polynomial :math:`f_n` for the curve :math:`E` in the
        variable :math:`v`. In standard notation, for any affine point :math:`P = (X,Y)` on the
        curve, we have

        .. MATH::

        [n]P = (\phi_n(P)\psi_n(P) : \omega_n(P) : \psi_n(P)^3)

        for some polynomials :math:`\phi_n,\omega_n,\psi_n` in
        :math:`\mathbb{Z}[a_1,a_2,a_3,a_4,a_6][X,Y]`. We have :math:`f_n(X) = \psi_n(X)` for :math:`n` odd, and
        :math:`f_n(X) = \psi_n(X,Y) (2Y + a_1X+a_3)` for :math:`n` even. We have

        .. MATH::

        f_1 = 1, f_2 = 4X^3 + b_2X^2 + 2b_4 X + b_6, f_3 = 3 X^4 + b_2 X^3 + 3b_4 X^2 + 3 b_6 X + b8,

        .. MATH::

        f_4 = f_2(2X^6 + b_2 X^5 + 5b_4 X^4 + 10 b_6 X^3 + 10 b_8 X^2 +
        (b_2b_8-b_4b_6)X + (b_8b_4 - b_6^2)),...

        For :math:`n >= 2`, the roots of :math:`f_n` are the :math:`X`-coordinates of points in :math:`E[n]`.
        '''
        E = objtogen(E)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = elldivpol(_E, n, _v)
        return new_gen(_ret)

    def elleisnum(self, w, long k, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        :math:`k` being an even positive integer, computes the numerical value of the
        Eisenstein series of weight :math:`k` at the lattice :math:`w`, as given by
        :literal:`ellperiods`, namely

        .. MATH::

        (2i \pi/\omega_2)^k
        (1 + 2/\zeta (1-k) \sum_{n >= 1} n^{k-1}q^n / (1-q^n)),

        where :math:`q = \exp (2i\pi \tau)` and :math:`\tau := \omega_1/\omega_2` belongs to the
        complex upper half-plane. It is also possible to directly input :math:`w =
        [\omega_1,\omega_2]`, or an elliptic curve :math:`E` as given by :literal:`ellinit`.

        ::

        ? w = ellperiods([1,I]);
        ? elleisnum(w, 4)
        %2 = 2268.8726415508062275167367584190557607
        ? elleisnum(w, 6)
        %3 = -3.977978632282564763 E-33
        ? E = ellinit([1, 0]);
        ? elleisnum(E, 4, 1)
        %5 = -47.999999999999999999999999999999999998

        When :emphasis:`flag` is non-zero and :math:`k = 4` or 6, returns the elliptic invariants :math:`g_2`
        or :math:`g_3`, such that

        .. MATH::

        y^2 = 4x^3 - g_2 x - g_3

        is a Weierstrass equation for :math:`E`.
        '''
        w = objtogen(w)
        sig_on()
        cdef GEN _w = (<Gen>w).g
        precision = nbits2prec(precision)
        cdef GEN _ret = elleisnum(_w, k, flag, precision)
        return new_gen(_ret)

    def elleta(self, w, long precision=DEFAULT_BITPREC):
        r'''
        Returns the quasi-periods :math:`[\eta_1,\eta_2]`
        attached to the lattice basis :math:`w = [\omega_1, \omega_2]`.
        Alternatively, :emphasis:`w` can be an elliptic curve :math:`E` as output by
        :literal:`ellinit`, in which case, the quasi periods attached to the period
        lattice basis :literal:`:math:`E`.omega` (namely, :literal:`:math:`E`.eta`) are returned.

        ::

        ? elleta([1, I])
        %1 = [3.141592653589793238462643383, 9.424777960769379715387930149*I]
        '''
        w = objtogen(w)
        sig_on()
        cdef GEN _w = (<Gen>w).g
        precision = nbits2prec(precision)
        cdef GEN _ret = elleta(_w, precision)
        return new_gen(_ret)

    def ellformaldifferential(self, E, long serprec=-1, n=None):
        r'''
        Let :math:`\omega := dx / (2y+a_1x+a_3)` be the invariant differential form
        attached to the model :math:`E` of some elliptic curve (:literal:`ellinit` form),
        and :math:`\eta := x(t)\omega`. Return :math:`n` terms (:literal:`seriesprecision` by default)
        of :math:`f(t),g(t)` two power series in the formal parameter :math:`t = -x/y` such that
        :math:`\omega = f(t) dt`, :math:`\eta = g(t) dt`:

        .. MATH::

        f(t) = 1+a_1 t + (a_1^2 + a_2) t^2 +...,
        g(t) = t^{-2} +...

        ::

        ? E = ellinit([-1,1/4]); [f,g] = ellformaldifferential(E,7,'t);
        ? f
        %2 = 1 - 2*t^4 + 3/4*t^6 + O(t^7)
        ? g
        %3 = t^-2 - t^2 + 1/2*t^4 + O(t^5)
        '''
        E = objtogen(E)
        cdef long _n = -1
        if n is not None:
            _n = get_var(n)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = ellformaldifferential(_E, serprec, _n)
        return new_gen(_ret)

    def ellformalexp(self, E, long serprec=-1, n=None):
        r'''
        The elliptic formal exponential :literal:`Exp` attached to :math:`E` is the
        isomorphism from the formal additive law to the formal group of :math:`E`. It is
        normalized so as to be the inverse of the elliptic logarithm (see
        :literal:`ellformallog`): :math:`Exp o L = \mathrm{Id}`. Return :math:`n` terms of this
        power series:

        ::

        ? E=ellinit([-1,1/4]); Exp = ellformalexp(E,10,'z)
        %1 = z + 2/5*z^5 - 3/28*z^7 + 2/15*z^9 + O(z^11)
        ? L = ellformallog(E,10,'t);
        ? subst(Exp,z,L)
        %3 = t + O(t^11)
        '''
        E = objtogen(E)
        cdef long _n = -1
        if n is not None:
            _n = get_var(n)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = ellformalexp(_E, serprec, _n)
        return new_gen(_ret)

    def ellformallog(self, E, long serprec=-1, n=None):
        r'''
        The formal elliptic logarithm is a series :math:`L` in :math:`t K[[t]]`
        such that :math:`d L = \omega = dx / (2y + a_1x + a_3)`, the canonical invariant
        differential attached to the model :math:`E`. It gives an isomorphism
        from the formal group of :math:`E` to the additive formal group.

        ::

        ? E = ellinit([-1,1/4]); L = ellformallog(E, 9, 't)
        %1 = t - 2/5*t^5 + 3/28*t^7 + 2/3*t^9 + O(t^10)
        ? [f,g] = ellformaldifferential(E,8,'t);
        ? L' - f
        %3 = O(t^8)
        '''
        E = objtogen(E)
        cdef long _n = -1
        if n is not None:
            _n = get_var(n)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = ellformallog(_E, serprec, _n)
        return new_gen(_ret)

    def ellformalpoint(self, E, long serprec=-1, n=None):
        r'''
        If :math:`E` is an elliptic curve, return the coordinates :math:`x(t), y(t)` in the
        formal group of the elliptic curve :math:`E` in the formal parameter :math:`t = -x/y`
        at :math:`oo`:

        .. MATH::

        x = t^{-2} -a_1 t^{-1} - a_2 - a_3 t +...

        .. MATH::

        y = - t^{-3} -a_1 t^{-2} - a_2t^{-1} -a_3 +...

        Return :math:`n` terms (:literal:`seriesprecision` by default) of these two power
        series, whose coefficients are in :math:`\mathbb{Z}[a_1,a_2,a_3,a_4,a_6]`.

        ::

        ? E = ellinit([0,0,1,-1,0]); [x,y] = ellformalpoint(E,8,'t);
        ? x
        %2 = t^-2 - t + t^2 - t^4 + 2*t^5 + O(t^6)
        ? y
        %3 = -t^-3 + 1 - t + t^3 - 2*t^4 + O(t^5)
        ? E = ellinit([0,1/2]); ellformalpoint(E,7)
        %4 = [x^-2 - 1/2*x^4 + O(x^5), -x^-3 + 1/2*x^3 + O(x^4)]
        '''
        E = objtogen(E)
        cdef long _n = -1
        if n is not None:
            _n = get_var(n)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = ellformalpoint(_E, serprec, _n)
        return new_gen(_ret)

    def ellformalw(self, E, long serprec=-1, n=None):
        r'''
        Return the formal power series :math:`w` attached to the elliptic curve :math:`E`,
        in the variable :math:`t`:

        .. MATH::

        w(t) = t^3 + a_1 t^4 + (a_2 + a_1^2) t^5 +...+ O(t^{n+3}),

        which is the formal expansion of :math:`-1/y` in the formal parameter :math:`t := -x/y`
        at :math:`oo` (take :math:`n = seriesprecision` if :math:`n` is omitted). The
        coefficients of :math:`w` belong to :math:`\mathbb{Z}[a_1,a_2,a_3,a_4,a_6]`.

        ::

        ? E=ellinit([3,2,-4,-2,5]); ellformalw(E, 5, 't)
        %1 = t^3 + 3*t^4 + 11*t^5 + 35*t^6 + 101*t^7 + O(t^8)
        '''
        E = objtogen(E)
        cdef long _n = -1
        if n is not None:
            _n = get_var(n)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = ellformalw(_E, serprec, _n)
        return new_gen(_ret)

    def ellfromeqn(self, P):
        r'''
        Given a genus :math:`1` plane curve, defined by the affine equation :math:`f(x,y) = 0`,
        return the coefficients :math:`[a_1,a_2,a_3,a_4,a_6]` of a Weierstrass equation
        for its Jacobian. This allows to recover a Weierstrass model for an elliptic
        curve given by a general plane cubic or by a binary quartic or biquadratic
        model. The function implements the :math:`f :---> f^*` formulae of Artin, Tate
        and Villegas (Advances in Math. 198 (2005), pp. 366--382).

        In the example below, the function is used to convert between twisted Edwards
        coordinates and Weierstrass coordinates.

        ::

        ? e = ellfromeqn(a*x^2+y^2 - (1+d*x^2*y^2))
        %1 = [0, -a - d, 0, -4*d*a, 4*d*a^2 + 4*d^2*a]
        ? E = ellinit(ellfromeqn(y^2-x^2 - 1 +(121665/121666*x^2*y^2)),2^255-19);
        ? isprime(ellcard(E) / 8)
        %3 = 1

        The elliptic curve attached to the sum of two cubes is given by

        ::

        ? ellfromeqn(x^3+y^3 - a)
        %1 = [0, 0, -9*a, 0, -27*a^2]

        :strong:`Congruent number problem:.`
        Let :math:`n` be an integer, if :math:`a^2+b^2 = c^2` and :math:`a b = 2 n`,
        then by substituting :math:`b` by :math:`2 n/a` in the first equation,
        we get :math:`((a^2+(2 n/a)^2)-c^2) a^2 = 0`.
        We set :math:`x = a`, :math:`y = a c`.

        ::

        ? En = ellfromeqn((x^2 + (2*n/x)^2 - (y/x)^2)*x^2)
        %1 = [0, 0, 0, -16*n^2, 0]

        For example :math:`23` is congruent since the curve has a point of infinite order,
        namely:

        ::

        ? ellheegner( ellinit(subst(En, n, 23)) )
        %2 = [168100/289, 68053440/4913]
        '''
        P = objtogen(P)
        sig_on()
        cdef GEN _P = (<Gen>P).g
        cdef GEN _ret = ellfromeqn(_P)
        return new_gen(_ret)

    def ellfromj(self, j):
        r'''
        Returns the coefficients :math:`[a_1,a_2,a_3,a_4,a_6]` of a fixed elliptic curve
        with :math:`j`-invariant :math:`j`.
        '''
        j = objtogen(j)
        sig_on()
        cdef GEN _j = (<Gen>j).g
        cdef GEN _ret = ellfromj(_j)
        return new_gen(_ret)

    def ellgenerators(self, E):
        r'''
        If :math:`E` is an elliptic curve over the rationals, return a :math:`\mathbb{Z}`-basis of the
        free part of the Mordell-Weil group attached to :math:`E`. This relies on
        the :literal:`elldata` database being installed and referencing the curve, and so
        is only available for curves over :math:`\mathbb{Z}` of small conductors.
        If :math:`E` is an elliptic curve over a finite field :math:`\mathbb{F}_q` as output by
        :literal:`ellinit`, return a minimal set of generators for the group :math:`E(\mathbb{F}_q)`.

        :strong:`Caution.` when the group is not cyclic, of shape :math:`\mathbb{Z}/d_1\mathbb{Z} x
        \mathbb{Z}/d_2\mathbb{Z}` with :math:`d_2 \| d_1`, the points :math:`[P,Q]` returned by ellgenerators
        need not have order :math:`d_1` and :math:`d_2`: it is true that
        :math:`P` has order :math:`d_1`, but we only know that :math:`Q` is a generator of
        :math:`E(\mathbb{F}_q)/ <P>` and that the Weil pairing :math:`w(P,Q)` has order :math:`d_2`,
        see :literal:`??ellgroup`.
        If you need generators :math:`[P,R]` with :math:`R` of order :math:`d_2`, find
        :math:`x` such that :math:`R = Q-[x]P` has order :math:`d_2` by solving
        the discrete logarithm problem :math:`[d_2]Q = [x]([d_2]P)` in a cyclic group of
        order :math:`d_1/d_2`. This will be very expensive if :math:`d_1/d_2` has a large
        prime factor.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellgenerators(_E)
        return new_gen(_ret)

    def ellglobalred(self, E):
        r'''
        Let :math:`E` be an :literal:`ell` structure as output by :literal:`ellinit` attached
        to an elliptic curve defined over a number field. This function calculates
        the arithmetic conductor and the global Tamagawa number :math:`c`.
        The result :math:`[N,v,c,F,L]` is slightly different if :math:`E` is defined
        over :math:`\mathbb{Q}` (domain :math:`D = 1` in :literal:`ellinit`) or over a number field
        (domain :math:`D` is a number field structure, including :literal:`nfinit(x)`
        representing :math:`\mathbb{Q}` !):

        - :math:`N` is the arithmetic conductor of the curve,

        - :math:`v` is an obsolete field, left in place for backward compatibility.
        If :math:`E` is defined over :math:`\mathbb{Q}`, :math:`v` gives the coordinate change for :math:`E` to the
        standard minimal integral model (:literal:`ellminimalmodel` provides it in a
        cheaper way); if :math:`E` is defined over another number field, :math:`v` gives a
        coordinate change to an integral model (:literal:`ellintegralmodel` provides it
        in a cheaper way).

        - :math:`c` is the product of the local Tamagawa numbers :math:`c_p`, a quantity
        which enters in the Birch and Swinnerton-Dyer conjecture,

        - :math:`F` is the factorization of :math:`N`,

        - :math:`L` is a vector, whose :math:`i`-th entry contains the local data
        at the :math:`i`-th prime ideal divisor of :math:`N`, i.e.
        :literal:`L[i] = elllocalred(E,F[i,1])`. If :math:`E` is defined over :math:`\mathbb{Q}`, the local
        coordinate change has been deleted and replaced by a 0; if :math:`E` is defined
        over another number field the local coordinate change to a local minimal
        model is given relative to the integral model afforded by :math:`v` (so either
        start from an integral model so that :math:`v` be trivial, or apply :math:`v` first).
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellglobalred(_E)
        return new_gen(_ret)

    def ellgroup(self, E, p=None, long flag=0):
        r'''
        Let :literal:`E` be an :literal:`ell` structure as output by :literal:`ellinit`, attached
        to an elliptic curve :math:`E/K`. We first describle the function when the field
        :math:`K = \mathbb{F}_q` is finite, it computes the structure of the finite abelian group
        :math:`E(\mathbb{F}_q)`:

        - if :math:`flag = 0`, return the structure :math:`[]` (trivial group) or :math:`[d_1]`
        (non-trivial cyclic group) or :math:`[d_1,d_2]` (non-cyclic group) of
        :math:`E(\mathbb{F}_q) ~ \mathbb{Z}/d_1\mathbb{Z} x \mathbb{Z}/d_2\mathbb{Z}`, with :math:`d_2 \| d_1`.

        - if :math:`flag = 1`, return a triple :math:`[h,cyc,gen]`, where
        :math:`h` is the curve cardinality, :emphasis:`cyc` gives the group structure as a
        product of cyclic groups (as per :math:`flag = 0`). More precisely, if :math:`d_2 > 1`,
        the output is :math:`[d_1d_2, [d_1,d_2], [P,Q]]` where :math:`P` is
        of order :math:`d_1` and :math:`[P,Q]` generates the curve.
        :strong:`Caution.` It is not guaranteed that :math:`Q` has order :math:`d_2`, which in
        the worst case requires an expensive discrete log computation. Only that
        :literal:`ellweilpairing`:math:`(E, P, Q, d_1)` has order :math:`d_2`.

        For other fields of definition and :math:`p` defining a finite residue field
        :math:`\mathbb{F}_q`, return the structure of the reduction of :math:`E`: the argument
        :math:`p` is best left omitted if :math:`K = \mathbb{Q}_\ell` (else we must have :math:`p = \ell`) and
        must be a prime number (:math:`K = \mathbb{Q}`) or prime ideal (:math:`K` a general number field)
        with residue field :math:`\mathbb{F}_q` otherwise. The curve is allowed to have bad
        reduction at :math:`p` and in this case we consider the (cyclic) group of
        non-singular points for the reduction of a minimal model at :math:`p`.

        If :math:`flag = 0`, the equation not be minimal or even integral at :math:`p`; of course,
        a minimal model will be more efficient.

        If :math:`flag = 1`, the requested generators depend on the model, which must then
        be minimal at :math:`p`, otherwise an exception is thrown. Use
        :literal:`ellintegralmodel` and/or :literal:`ellocalred` first to reduce to this case.

        ::

        ? E = ellinit([0,1]); \\ y^2 = x^3 + 0.x + 1, defined over Q
        ? ellgroup(E, 7)
        %2 = [6, 2] \\ Z/6 x Z/2, non-cyclic
        ? E = ellinit([0,1] * Mod(1,11)); \\ defined over F_11
        ? ellgroup(E) \\ no need to repeat 11
        %4 = [12]
        ? ellgroup(E, 11) \\ ... but it also works
        %5 = [12]
        ? ellgroup(E, 13) \\ ouch, inconsistent input!
        *** at top-level: ellgroup(E,13)
        *** ^--------------
        *** ellgroup: inconsistent moduli in Rg_to_Fp:
        11
        13
        ? ellgroup(E, 7, 1)
        %6 = [12, [6, 2], [[Mod(2, 7), Mod(4, 7)], [Mod(4, 7), Mod(4, 7)]]]

        Let us now consider curves of bad reduction, in this case we return the
        structure of the (cyclic) group of non-singular points, satisfying
        :math:`\#E_{ns}(\mathbb{F}_p) = p - a_p`:

        ::

        ? E = ellinit([0,5]);
        ? ellgroup(E, 5, 1)
        %2 = [5, [5], [[Mod(4, 5), Mod(2, 5)]]]
        ? ellap(E, 5)
        %3 = 0 \\ additive reduction at 5
        ? E = ellinit([0,-1,0,35,0]);
        ? ellgroup(E, 5, 1)
        %5 = [4, [4], [[Mod(2, 5), Mod(2, 5)]]]
        ? ellap(E, 5)
        %6 = 1 \\ split multiplicative reduction at 5
        ? ellgroup(E, 7, 1)
        %7 = [8, [8], [[Mod(3, 7), Mod(5, 7)]]]
        ? ellap(E, 7)
        %8 = -1 \\ non-split multiplicative reduction at 7
        '''
        E = objtogen(E)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _ret = ellgroup0(_E, _p, flag)
        return new_gen(_ret)

    def ellheegner(self, E):
        r'''
        Let :math:`E` be an elliptic curve over the rationals, assumed to be of
        (analytic) rank :math:`1`. This returns a non-torsion rational point on the curve,
        whose canonical height is equal to the product of the elliptic regulator by the
        analytic Sha.

        This uses the Heegner point method, described in Cohen GTM 239; the complexity
        is proportional to the product of the square root of the conductor and the
        height of the point (thus, it is preferable to apply it to strong Weil curves).

        ::

        ? E = ellinit([-157^2,0]);
        ? u = ellheegner(E); print(u[1], "\n", u[2])
        69648970982596494254458225/166136231668185267540804
        538962435089604615078004307258785218335/67716816556077455999228495435742408
        ? ellheegner(ellinit([0,1])) \\ E has rank 0 !
        *** at top-level: ellheegner(E=ellinit
        *** ^--------------------
        *** ellheegner: The curve has even analytic rank.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellheegner(_E)
        return new_gen(_ret)

    def ellheight(self, E, P, Q=None, long precision=DEFAULT_BITPREC):
        r'''
        Global Néron-Tate height :math:`h(P)` of the point :math:`P` on the elliptic curve
        :math:`E`, defined over :math:`\mathbb{Q}` or a number field, using the same normalization as
        Cremona's :emphasis:`Algorithms for modular elliptic curves`. :math:`E` must be an
        :literal:`ell` as output by :literal:`ellinit`; it needs not be given by a minimal
        model although the computation will be faster if it is. The height of a
        torsion point is exactly 0, else a positive real number.

        If the argument :math:`Q` is present, computes the value of the bilinear
        form :math:`(h(P+Q)-h(P-Q)) / 4`.
        '''
        E = objtogen(E)
        P = objtogen(P)
        cdef bint _have_Q = (Q is not None)
        if _have_Q:
            Q = objtogen(Q)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _Q = NULL
        if _have_Q:
            _Q = (<Gen>Q).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ellheight0(_E, _P, _Q, precision)
        return new_gen(_ret)

    def ellheightmatrix(self, E, x, long precision=DEFAULT_BITPREC):
        r'''
        :math:`x` being a vector of points, this
        function outputs the Gram matrix of :math:`x` with respect to the Néron-Tate
        height, in other words, the :math:`(i,j)` component of the matrix is equal to
        :literal:`ellbil(:math:`E`,x[:math:`i`],x[:math:`j`])`. The rank of this matrix, at least in some
        approximate sense, gives the rank of the set of points, and if :math:`x` is a
        basis of the Mordell-Weil group of :math:`E`, its determinant is equal to
        the regulator of :math:`E`. Note our height normalization follows Cremona's
        :emphasis:`Algorithms for modular elliptic curves`: this matrix should be divided
        by 2 to be in accordance with, e.g., Silverman's normalizations.
        '''
        E = objtogen(E)
        x = objtogen(x)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ellheightmatrix(_E, _x, precision)
        return new_gen(_ret)

    def ellidentify(self, E):
        r'''
        Look up the elliptic curve :math:`E`, defined by an arbitrary model over :math:`\mathbb{Q}`,
        in the :literal:`elldata` database.
        Return :literal:`[[N, M, G], C]` where :math:`N` is the curve name in Cremona's
        elliptic curve database, :math:`M` is the minimal model, :math:`G` is a :math:`\mathbb{Z}`-basis of
        the free part of the Mordell-Weil group :math:`E(\mathbb{Q})` and :math:`C` is the
        change of coordinates change, suitable for :literal:`ellchangecurve`.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellidentify(_E)
        return new_gen(_ret)

    def ellinit(self, x, D=None, long precision=DEFAULT_BITPREC):
        r'''
        Initialize an :literal:`ell` structure, attached to the elliptic curve :math:`E`.
        :math:`E` is either

        - a :math:`5`-component vector :math:`[a_1,a_2,a_3,a_4,a_6]` defining the elliptic
        curve with Weierstrass equation
        

        .. MATH::

        Y^2 + a_1 XY + a_3 Y = X^3 + a_2 X^2 + a_4 X + a_6,

        - a :math:`2`-component vector :math:`[a_4,a_6]` defining the elliptic
        curve with short Weierstrass equation
        

        .. MATH::

        Y^2 = X^3 + a_4 X + a_6,

        - a character string in Cremona's notation, e.g. :literal:`"11a1"`, in which
        case the curve is retrieved from the :literal:`elldata` database if available.

        The optional argument :math:`D` describes the domain over which the curve is
        defined:

        - the :literal:`t_INT` :math:`1` (default): the field of rational numbers :math:`\mathbb{Q}`.

        - a :literal:`t_INT` :math:`p`, where :math:`p` is a prime number: the prime finite field
        :math:`\mathbb{F}_p`.

        - an :literal:`t_INTMOD` :literal:`Mod(a, p)`, where :math:`p` is a prime number: the
        prime finite field :math:`\mathbb{F}_p`.

        - a :literal:`t_FFELT`, as returned by :literal:`ffgen`: the corresponding finite
        field :math:`\mathbb{F}_q`.

        - a :literal:`t_PADIC`, :math:`O(p^n)`: the field :math:`\mathbb{Q}_p`, where :math:`p`-adic quantities
        will be computed to a relative accuracy of :math:`n` digits. We advise to input a
        model defined over :math:`\mathbb{Q}` for such curves. In any case, if you input an
        approximate model with :literal:`t_PADIC` coefficients, it will be replaced by a lift
        to :math:`\mathbb{Q}` (an exact model "close" to the one that was input) and all quantities
        will then be computed in terms of this lifted model, at the given accuracy.

        - a :literal:`t_REAL` :math:`x`: the field :math:`\mathbb{C}` of complex numbers, where floating
        point quantities are by default computed to a relative accuracy of
        :literal:`precision`:math:`(x)`. If no such argument is given, the value of
        :literal:`realprecision` at the time :literal:`ellinit` is called will be used.

        - a number field :math:`K`, given by a :literal:`nf` or :literal:`bnf` structure; a
        :literal:`bnf` is required for :literal:`ellminimalmodel`.

        - a prime ideal :math:`p`, given by a :literal:`prid` structure; valid if
        :math:`x` is a curve defined over a number field :math:`K` and the equation is integral
        and minimal at :math:`p`.

        This argument :math:`D` is indicative: the curve coefficients are checked for
        compatibility, possibly changing :math:`D`; for instance if :math:`D = 1` and
        an :literal:`t_INTMOD` is found. If inconsistencies are detected, an error is
        raised:

        ::

        ? ellinit([1 + O(5), 1], O(7));
        *** at top-level: ellinit([1+O(5),1],O
        *** ^--------------------
        *** ellinit: inconsistent moduli in ellinit: 7 != 5

        If the curve coefficients are too general to fit any of the
        above domain categories, only basic operations, such as point addition, will
        be supported later.

        If the curve (seen over the domain :math:`D`) is singular, fail and return an
        empty vector :math:`[]`.

        ::

        ? E = ellinit([0,0,0,0,1]); \\ y^2 = x^3 + 1, over Q
        ? E = ellinit([0,1]); \\ the same curve, short form
        ? E = ellinit("36a1"); \\ sill the same curve, Cremona's notations
        ? E = ellinit([0,1], 2) \\ over F2: singular curve
        %4 = []
        ? E = ellinit(['a4,'a6] * Mod(1,5)); \\ over F_5[a4,a6], basic support !

        The result of :literal:`ellinit` is an :emphasis:`ell` structure. It contains at least
        the following information in its components:

        .. MATH::

        a_1,a_2,a_3,a_4,a_6,b_2,b_4,b_6,b_8,c_4,c_6,\Delta,j.

        All are accessible via member functions. In particular, the discriminant is
        :literal:`:math:`E`.disc`, and the :math:`j`-invariant is :literal:`:math:`E`.j`.

        ::

        ? E = ellinit([a4, a6]);
        ? E.disc
        %2 = -64*a4^3 - 432*a6^2
        ? E.j
        %3 = -6912*a4^3/(-4*a4^3 - 27*a6^2)

        Further components contain domain-specific data, which are in general dynamic:
        only computed when needed, and then cached in the structure.

        ::

        ? E = ellinit([2,3], 10^60+7); \\ E over F_p, p large
        ? ellap(E)
        time = 4,440 ms.
        %2 = -1376268269510579884904540406082
        ? ellcard(E); \\ now instantaneous !
        time = 0 ms.
        ? ellgenerators(E);
        time = 5,965 ms.
        ? ellgenerators(E); \\ second time instantaneous
        time = 0 ms.

        See the description of member functions related to elliptic curves at the
        beginning of this section.
        '''
        x = objtogen(x)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ellinit(_x, _D, precision)
        return new_gen(_ret)

    def ellintegralmodel(self, E, v=None):
        r'''
        Let :math:`E` be an :literal:`ell` structure over a number field :math:`K` or :math:`\mathbb{Q}_p`.
        This function returns an integral model. If :math:`v` is present, sets
        :math:`v = [u,0,0,0]` to the corresponding change of variable: the return value is
        identical to that of :literal:`ellchangecurve(E, v)`.

        ::

        ? e = ellinit([1/17,1/42]);
        ? e = ellintegralmodel(e,&v);
        ? e[1..5]
        %3 = [0, 0, 0, 15287762448, 3154568630095008]
        ? v
        %4 = [1/714, 0, 0, 0]
        '''
        E = objtogen(E)
        cdef bint _have_v = (v is not None)
        if _have_v:
            raise NotImplementedError("optional argument v not available")
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN * _v = NULL
        cdef GEN _ret = ellintegralmodel(_E, _v)
        return new_gen(_ret)

    def ellisdivisible(self, E, P, n, Q=None):
        r'''
        Given :math:`E/K` a number field and :math:`P` in :math:`E(K)`
        return :math:`1` if :math:`P = [n]R` for some :math:`R` in :math:`E(K)` and set :math:`Q` to one such :math:`R`;
        and return :math:`0` otherwise. The integer :math:`n >= 0` may be given as
        :literal:`ellxn(E,n)`, if many points need to be tested.

        ::

        ? K = nfinit(polcyclo(11,t));
        ? E = ellinit([0,-1,1,0,0], K);
        ? P = [0,0];
        ? ellorder(E,P)
        %4 = 5
        ? ellisdivisible(E,P,5, &Q)
        %5 = 1
        ? lift(Q)
        %6 = [-t^7-t^6-t^5-t^4+1, -t^9-2*t^8-2*t^7-3*t^6-3*t^5-2*t^4-2*t^3-t^2-1]
        ? ellorder(E, Q)
        %7 = 25

        The algebraic complexity of the underlying algorithm is in
        :math:`O(n^4)`, so it is advisable to first factor :math:`n`, then use a chain of checks
        attached to the prime divisors of :math:`n`: the function will do it itself unless
        :math:`n` is given in :literal:`ellxn` form.
        '''
        E = objtogen(E)
        P = objtogen(P)
        n = objtogen(n)
        cdef bint _have_Q = (Q is not None)
        if _have_Q:
            raise NotImplementedError("optional argument Q not available")
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _n = (<Gen>n).g
        cdef GEN * _Q = NULL
        cdef long _ret = ellisdivisible(_E, _P, _n, _Q)
        clear_stack()
        return _ret

    def ellisogeny(self, E, G, long only_image=0, x=None, y=None):
        r'''
        Given an elliptic curve :math:`E`, a finite subgroup :math:`G` of :math:`E` is given either
        as a generating point :math:`P` (for a cyclic :math:`G`) or as a polynomial whose roots
        vanish on the :math:`x`-coordinates of the non-zero elements of :math:`G` (general case
        and more efficient if available). This function returns the
        :math:`[a_1,a_2,a_3,a_4,a_6]` invariants of the quotient elliptic curve :math:`E/G` and
        (if :emphasis:`only_image` is zero (the default)) a vector of rational
        functions :math:`[f, g, h]` such that the isogeny :math:`E \to E/G` is given by :math:`(x,y)
        :---> (f(x)/h(x)^2, g(x,y)/h(x)^3)`.

        ::

        ? E = ellinit([0,1]);
        ? elltors(E)
        %2 = [6, [6], [[2, 3]]]
        ? ellisogeny(E, [2,3], 1) \\ Weierstrass model for E/<P>
        %3 = [0, 0, 0, -135, -594]
        ? ellisogeny(E,[-1,0])
        %4 = [[0,0,0,-15,22], [x^3+2*x^2+4*x+3, y*x^3+3*y*x^2-2*y, x+1]]
        '''
        E = objtogen(E)
        G = objtogen(G)
        cdef long _x = -1
        if x is not None:
            _x = get_var(x)
        cdef long _y = -1
        if y is not None:
            _y = get_var(y)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _G = (<Gen>G).g
        cdef GEN _ret = ellisogeny(_E, _G, only_image, _x, _y)
        return new_gen(_ret)

    def ellisogenyapply(self, f, g):
        r'''
        Given an isogeny of elliptic curves :math:`f:E'\to E` (being the result of a call
        to :literal:`ellisogeny`), apply :math:`f` to :math:`g`:

        - if :math:`g` is a point :math:`P` in the domain of :math:`f`, return the image :math:`f(P)`;

        - if :math:`g:E"\to E'` is a compatible isogeny, return the composite
        isogeny :math:`f o g: E"\to E`.

        ::

        ? one = ffgen(101, 't)^0;
        ? E = ellinit([6, 53, 85, 32, 34] * one);
        ? P = [84, 71] * one;
        ? ellorder(E, P)
        %4 = 5
        ? [F, f] = ellisogeny(E, P); \\ f: E->F = E/<P>
        ? ellisogenyapply(f, P)
        %6 = [0]
        ? F = ellinit(F);
        ? Q = [89, 44] * one;
        ? ellorder(F, Q)
        %9 = 2
        ? [G, g] = ellisogeny(F, Q); \\ g: F->G = F/<Q>
        ? gof = ellisogenyapply(g, f); \\ gof: E -> G
        '''
        f = objtogen(f)
        g = objtogen(g)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _g = (<Gen>g).g
        cdef GEN _ret = ellisogenyapply(_f, _g)
        return new_gen(_ret)

    def ellisomat(self, E, long p=0, long fl=0):
        r'''
        Given an elliptic curve :math:`E` defined over a number field, compute
        representatives of the isomorphism classes of elliptic curves :math:`\mathbb{Q}`-isogenous
        to :math:`E`. The function returns a vector :math:`[L,M]` where :math:`L` is a list of triples
        :math:`[E_i, f_i, g_i]`, where :math:`E_i` is an elliptic curve in :math:`[a_4,a_6]` form,
        :math:`f_i: E \to E_i` is a rational isogeny, :math:`g_i: E_i \to E` is the dual isogeny
        of :math:`f_i`, and :math:`M` is the matrix such that :math:`M_{i,j}` is the degree of the
        isogeny between :math:`E_i` and :math:`E_j`. Furthermore the first curve :math:`E_1` is
        isomorphic to :math:`E` by :math:`f_1`. If the flag :math:`fl = 1`, the :math:`f_i` and :math:`g_i` are
        not computed, which saves time, and :math:`L` is the list of the curves :math:`E_i`.
        If :math:`p` is set, it must be a prime number; in this which case only isogenies of
        degree a power of :math:`p` are considered.
        Over a number field, the possible isogeny degrees are determined by
        Billerey algorithm. As a consequence, CM curves over a number field are not
        fully supported.

        ::

        ? E = ellinit("14a1");
        ? [L,M] = ellisomat(E);
        ? LE = apply(x->x[1], L) \\ list of curves
        %3 = [[215/48,-5291/864],[-675/16,6831/32],[-8185/48,-742643/864],
        [-1705/48,-57707/864],[-13635/16,306207/32],[-131065/48,-47449331/864]]
        ? L[2][2] \\ isogeny f_2
        %4 = [x^3+3/4*x^2+19/2*x-311/12,
        1/2*x^4+(y+1)*x^3+(y-4)*x^2+(-9*y+23)*x+(55*y+55/2),x+1/3]
        ? L[2][3] \\ dual isogeny g_2
        %5 = [1/9*x^3-1/4*x^2-141/16*x+5613/64,
        -1/18*x^4+(1/27*y-1/3)*x^3+(-1/12*y+87/16)*x^2+(49/16*y-48)*x
        +(-3601/64*y+16947/512),x-3/4]
        ? apply(E->ellidentify(ellinit(E))[1][1], LE)
        %6 = ["14a1","14a4","14a3","14a2","14a6","14a5"]
        ? M
        %7 =
        [1 3 3 2 6 6]
        
        [3 1 9 6 2 18]
        
        [3 9 1 6 18 2]
        
        [2 6 6 1 3 3]
        
        [6 2 18 3 1 9]
        
        [6 18 2 3 9 1]
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellisomat(_E, p, fl)
        return new_gen(_ret)

    def ellisoncurve(self, E, z):
        r'''
        Gives 1 (i.e. true) if the point :math:`z` is on the elliptic curve :math:`E`, 0
        otherwise. If :math:`E` or :math:`z` have imprecise coefficients, an attempt is made to
        take this into account, i.e. an imprecise equality is checked, not a precise
        one. It is allowed for :math:`z` to be a vector of points in which case a vector
        (of the same type) is returned.
        '''
        E = objtogen(E)
        z = objtogen(z)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _z = (<Gen>z).g
        cdef GEN _ret = ellisoncurve(_E, _z)
        return new_gen(_ret)

    def ellisotree(self, E):
        r'''
        Given an elliptic curve :math:`E` defined over :math:`\mathbb{Q}` or a set of
        :math:`\mathbb{Q}`-isogenous curves as given by :literal:`ellisomat`, return a pair :math:`[L,M]` where

        - :math:`L` lists the minimal models of the isomorphism classes of elliptic
        curves :math:`\mathbb{Q}`-isogenous to :math:`E` (or in the set of isogenous curves),

        - :math:`M` is the adjacency matrix of the prime degree isogenies tree:
        there is an edge from :math:`E_i` to :math:`E_j` if there is an isogeny :math:`E_i \to E_j` of
        prime degree such that the Néron differential forms are preserved.

        ::

        ? E = ellinit("14a1");
        ? [L,M] = ellisotree(E);
        ? M
        %3 =
        [0 0 3 2 0 0]
        
        [3 0 0 0 2 0]
        
        [0 0 0 0 0 2]
        
        [0 0 0 0 0 3]
        
        [0 0 0 3 0 0]
        
        [0 0 0 0 0 0]
        ? [L2,M2] = ellisotree(ellisomat(E,2,1));
        %4 =
        [0 2]
        
        [0 0]
        ? [L3,M3] = ellisotree(ellisomat(E,3,1));
        ? M3
        %6 =
        [0 0 3]
        
        [3 0 0]
        
        [0 0 0]

        Compare with the result of :literal:`ellisomat`.

        ::

        ? [L,M]=ellisomat(E,,1);
        ? M
        %7 =
        [1 3 3 2 6 6]
        
        [3 1 9 6 2 18]
        
        [3 9 1 6 18 2]
        
        [2 6 6 1 3 3]
        
        [6 2 18 3 1 9]
        
        [6 18 2 3 9 1]
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellisotree(_E)
        return new_gen(_ret)

    def ellissupersingular(self, E, p=None):
        r'''
        Return 1 if the elliptic curve :math:`E` defined over a number field, :math:`\mathbb{Q}_p`
        or a finite field is supersingular at :math:`p`, and :math:`0` otherwise.
        If the curve is defined over a number field, :math:`p` must be explicitly given,
        and must be a prime number, resp. a maximal ideal, if the curve is defined
        over :math:`\mathbb{Q}`, resp. a general number field: we return :math:`1` if and only if :math:`E`
        has supersingular good reduction at :math:`p`.

        Alternatively, :math:`E` can be given by its :math:`j`-invariant in a finite field. In
        this case :math:`p` must be omitted.

        ::

        ? setrand(1); \\ make the choice of g deterministic
        ? g = ffprimroot(ffgen(7^5))
        %1 = 4*x^4 + 5*x^3 + 6*x^2 + 5*x + 6
        ? [g^n | n <- [1 .. 7^5 - 1], ellissupersingular(g^n)]
        %2 = [6]
        
        ? K = nfinit(y^3-2); P = idealprimedec(K, 2)[1];
        ? E = ellinit([y,1], K);
        ? ellissupersingular(E, P)
        %5 = 1
        ? Q = idealprimedec(K,5)[1];
        ? ellissupersingular(E, Q)
        %6 = 0
        '''
        E = objtogen(E)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef int _ret = ellissupersingular(_E, _p)
        clear_stack()
        return _ret

    def ellj(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Elliptic :math:`j`-invariant. :math:`x` must be a complex number
        with positive imaginary part, or convertible into a power series or a
        :math:`p`-adic number with positive valuation.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = jell(_x, precision)
        return new_gen(_ret)

    def elllocalred(self, E, p=None):
        r'''
        Calculates the Kodaira type of the local fiber of the elliptic curve
        :math:`E` at :math:`p`. :math:`E` must be an :literal:`ell` structure as output by
        :literal:`ellinit`, over :math:`\mathbb{Q}_\ell` (:math:`p` better left omitted, else equal to :math:`\ell`)
        over :math:`\mathbb{Q}` (:math:`p` a rational prime) or a number field :math:`K` (:math:`p`
        a maximal ideal given by a :literal:`prid` structure).
        The result is a 4-component vector :math:`[f,kod,v,c]`. Here :math:`f` is the exponent of
        :math:`p` in the arithmetic conductor of :math:`E`, and :math:`kod` is the Kodaira type which
        is coded as follows:

        1 means good reduction (type I:math:`_0`), 2, 3 and 4 mean types II, III and IV
        respectively, :math:`4+\nu` with :math:`\nu > 0` means type I:math:`_\nu`;
        finally the opposite values :math:`-1`, :math:`-2`, etc. refer to the starred types
        I:math:`_0^*`, II:math:`^*`, etc. The third component :math:`v` is itself a vector :math:`[u,r,s,t]`
        giving the coordinate changes done during the local reduction;
        :math:`u = 1` if and only if the given equation was already minimal at :math:`p`.
        Finally, the last component :math:`c` is the local Tamagawa number :math:`c_p`.
        '''
        E = objtogen(E)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _ret = elllocalred(_E, _p)
        return new_gen(_ret)

    def elllog(self, E, P, G, o=None):
        r'''
        Given two points :math:`P` and :math:`G` on the elliptic curve :math:`E/\mathbb{F}_q`, returns the
        discrete logarithm of :math:`P` in base :math:`G`, i.e. the smallest non-negative
        integer :math:`n` such that :math:`P = [n]G`.
        See :literal:`znlog` for the limitations of the underlying discrete log algorithms.
        If present, :math:`o` represents the order of :math:`G`, see ``DLfun`` (in the PARI manual);
        the preferred format for this parameter is :literal:`[N, factor(N)]`, where :math:`N`
        is the order of :math:`G`.

        If no :math:`o` is given, assume that :math:`G` generates the curve.
        The function also assumes that :math:`P` is a multiple of :math:`G`.

        ::

        ? a = ffgen(ffinit(2,8),'a);
        ? E = ellinit([a,1,0,0,1]); \\ over F_{2^8}
        ? x = a^3; y = ellordinate(E,x)[1];
        ? P = [x,y]; G = ellmul(E, P, 113);
        ? ord = [242, factor(242)]; \\ P generates a group of order 242. Initialize.
        ? ellorder(E, G, ord)
        %4 = 242
        ? e = elllog(E, P, G, ord)
        %5 = 15
        ? ellmul(E,G,e) == P
        %6 = 1
        '''
        E = objtogen(E)
        P = objtogen(P)
        G = objtogen(G)
        cdef bint _have_o = (o is not None)
        if _have_o:
            o = objtogen(o)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _G = (<Gen>G).g
        cdef GEN _o = NULL
        if _have_o:
            _o = (<Gen>o).g
        cdef GEN _ret = elllog(_E, _P, _G, _o)
        return new_gen(_ret)

    def elllseries(self, E, s, A=None, long precision=DEFAULT_BITPREC):
        r'''
        This function is deprecated, use :literal:`lfun(E,s)` instead.

        :math:`E` being an elliptic curve, given by an arbitrary model over :math:`\mathbb{Q}` as output
        by :literal:`ellinit`, this function computes the value of the :math:`L`-series of :math:`E` at
        the (complex) point :math:`s`. This function uses an :math:`O(N^{1/2})` algorithm, where
        :math:`N` is the conductor.

        The optional parameter :math:`A` fixes a cutoff point for the integral and is best
        left omitted; the result must be independent of :math:`A`, up to
        :literal:`realprecision`, so this allows to check the function's accuracy.
        '''
        from warnings import warn
        warn('the PARI/GP function elllseries is obsolete (2016-08-08)', DeprecationWarning)
        E = objtogen(E)
        s = objtogen(s)
        cdef bint _have_A = (A is not None)
        if _have_A:
            A = objtogen(A)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _s = (<Gen>s).g
        cdef GEN _A = NULL
        if _have_A:
            _A = (<Gen>A).g
        precision = nbits2prec(precision)
        cdef GEN _ret = elllseries(_E, _s, _A, precision)
        return new_gen(_ret)

    def ellminimaldisc(self, E):
        r'''
        :math:`E` being an elliptic curve defined over a number field output by
        :literal:`ellinit`, return the minimal discriminant ideal of E.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellminimaldisc(_E)
        return new_gen(_ret)

    def ellminimalmodel(self, E, v=None):
        r'''
        Let :math:`E` be an :literal:`ell` structure over a number field :math:`K`. This function
        determines whether :math:`E` admits a global minimal integral model. If so, it
        returns it and sets :math:`v = [u,r,s,t]` to the corresponding change of variable:
        the return value is identical to that of :literal:`ellchangecurve(E, v)`.

        Else return the (non-principal) Weierstrass class of :math:`E`, i.e. the class of
        :math:`\prod p^{(v_{p}{\Delta} - \delta_{p}) / 12}` where
        :math:`\Delta = E.disc` is the model's discriminant and
        :math:`p ^ \delta_{p}` is the local minimal discriminant.
        This function requires either that :math:`E` be defined
        over the rational field :math:`\mathbb{Q}` (with domain :math:`D = 1` in :literal:`ellinit`),
        in which case a global minimal model always exists, or over a number
        field given by a :emphasis:`bnf` structure. The Weierstrass class is given in
        :literal:`bnfisprincipal` format, i.e. in terms of the :literal:`K.gen` generators.

        The resulting model has integral coefficients and is everywhere minimal, the
        coefficients :math:`a_1` and :math:`a_3` are reduced modulo :math:`2` (in terms of the fixed
        integral basis :literal:`K.zk`) and :math:`a_2` is reduced modulo :math:`3`. Over :math:`\mathbb{Q}`, we
        further require that :math:`a_1` and :math:`a_3` be :math:`0` or :math:`1`, that :math:`a_2` be :math:`0` or :math:`±
        1` and that :math:`u > 0` in the change of variable: both the model and the change
        of variable :math:`v` are then unique.

        ::

        ? e = ellinit([6,6,12,55,233]); \\ over Q
        ? E = ellminimalmodel(e, &v);
        ? E[1..5]
        %3 = [0, 0, 0, 1, 1]
        ? v
        %4 = [2, -5, -3, 9]

        ::

        ? K = bnfinit(a^2-65); \\ over a non-principal number field
        ? K.cyc
        %2 = [2]
        ? u = Mod(8+a, K.pol);
        ? E = ellinit([1,40*u+1,0,25*u^2,0], K);
        ? ellminimalmodel(E) \\ no global minimal model exists over Z_K
        %6 = [1]~
        '''
        E = objtogen(E)
        cdef bint _have_v = (v is not None)
        if _have_v:
            raise NotImplementedError("optional argument v not available")
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN * _v = NULL
        cdef GEN _ret = ellminimalmodel(_E, _v)
        return new_gen(_ret)

    def ellminimaltwist(self, E, long flag=0):
        r'''
        Let :math:`E` be an elliptic curve defined over :math:`\mathbb{Q}`, return
        a discriminant :math:`D` such that the twist of :math:`E` by :math:`D` is minimal among all
        possible quadratic twists, i.e. if :math:`flag = 0`, its minimal model has minimal
        discriminant, or if :math:`flag = 1`, it has minimal conductor.

        In the example below, we find a curve with :math:`j`-invariant :math:`3` and minimal
        conductor.

        ::

        ? E = ellminimalmodel(ellinit(ellfromj(3)));
        ? ellglobalred(E)[1]
        %2 = 357075
        ? D = ellminimaltwist(E,1)
        %3 = -15
        ? E2 = ellminimalmodel(ellinit(elltwist(E,D)));
        ? ellglobalred(E2)[1]
        %5 = 14283

        In the example below, :math:`flag = 0` and :math:`flag = 1` give different results.

        ::

        ? E = ellinit([1,0]);
        ? D0 = ellminimaltwist(E,0)
        %7 = 1
        ? D1 = ellminimaltwist(E,1)
        %8 = 8
        ? E0 = ellminimalmodel(ellinit(elltwist(E,D0)));
        ? [E0.disc, ellglobalred(E0)[1]]
        %10 = [-64, 64]
        ? E1 = ellminimalmodel(ellinit(elltwist(E,D1)));
        ? [E1.disc, ellglobalred(E1)[1]]
        %12 = [-4096, 32]
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellminimaltwist0(_E, flag)
        return new_gen(_ret)

    def ellmoddegree(self, e):
        r'''
        :math:`e` being an elliptic curve defined over :math:`\mathbb{Q}` output by :literal:`ellinit`,
        compute the modular degree of :math:`e` divided by the square of
        the Manin constant :math:`c`. It is conjectured that :math:`c = 1` for the strong Weil
        curve in the isogeny class (optimal quotient of :math:`J_0(N)`) and this can be
        proven using :literal:`ellweilcurve` when the conductor :math:`N` is moderate.

        ::

        ? E = ellinit("11a1"); \\ from Cremona table: strong Weil curve and c = 1
        ? [v,smith] = ellweilcurve(E); smith \\ proof of the above
        %2 = [[1, 1], [5, 1], [1, 1/5]]
        ? ellmoddegree(E)
        %3 = 1
        ? [ellidentify(e)[1][1] | e<-v]
        %4 = ["11a1", "11a2", "11a3"]
        ? ellmoddegree(ellinit("11a2"))
        %5 = 5
        ? ellmoddegree(ellinit("11a3"))
        %6 = 1/5

        The modular degree of :literal:`11a1` is :math:`1` (because
        :literal:`ellweilcurve` or Cremona's table prove that the Manin constant
        is :math:`1` for this curve); the output of :literal:`ellweilcurve` also proves
        that the Manin constants of :literal:`11a2` and :literal:`11a3` are 1 and 5
        respectively, so the actual modular degree of both :literal:`11a2` and :literal:`11a3`
        is 5.
        '''
        e = objtogen(e)
        sig_on()
        cdef GEN _e = (<Gen>e).g
        cdef GEN _ret = ellmoddegree(_e)
        return new_gen(_ret)

    def ellmodulareqn(self, long N, x=None, y=None):
        r'''
        Given a prime :math:`N < 500`, return a vector :math:`[P,t]` where :math:`P(x,y)`
        is a modular equation of level :math:`N`, i.e. a bivariate polynomial with integer
        coefficients; :math:`t` indicates the type of this equation: either
        :emphasis:`canonical` (:math:`t = 0`) or :emphasis:`Atkin` (:math:`t = 1`). This function requires
        the :literal:`seadata` package and its only use is to give access to the package
        contents. See :literal:`polmodular` for a more general and more flexible function.

        Let :math:`j` be the :math:`j`-invariant function. The polynomial :math:`P` satisfies
        the functional equation,

        .. MATH::

        P(f,j) = P(f \| W_N, j \| W_N) = 0

        for some modular function :math:`f = f_N` (hand-picked for each fixed :math:`N` to
        minimize its size, see below), where :math:`W_N(\tau) = -1 / (N \tau)` is the
        Atkin-Lehner involution. These two equations allow to compute the values of
        the classical modular polynomial :math:`\Phi_N`, such that :math:`\Phi_N(j(\tau),
        j(N\tau)) = 0`, while being much smaller than the latter. More precisely, we
        have :math:`j(W_N(\tau)) = j(N \tau)`; the function :math:`f` is invariant under
        :math:`\Gamma_0(N)` and also satisfies

        - for Atkin type: :math:`f \| W_N = f`;

        - for canonical type: let :math:`s = 12/\mathrm{gcd} (12,N-1)`, then
        :math:`f \| W_N = N^s / f`. In this case, :math:`f` has a simple definition:
        :math:`f(\tau) = N^s (\eta (N \tau) / \eta (\tau) )^{2 s}`,
        where :math:`\eta` is Dedekind's eta function.

        The following GP function returns values of the classical modular polynomial
        by eliminating :math:`f_N(\tau)` in the above functional equation,
        for :math:`N <= 31` or :math:`N\in{41,47,59,71}`.

        ::

        classicaleqn(N, X='X, Y='Y)=
        {
        my([P,t] = ellmodulareqn(N), Q, d);
        if (poldegree(P,'y) > 2, error("level unavailable in classicaleqn"));
        if (t == 0, \\ Canonical
        my(s = 12/gcd(12,N-1));
        Q = 'x^(N+1) * substvec(P,['x,'y],[N^s/'x,Y]);
        d = N^(s*(2*N+1)) * (-1)^(N+1);
        , \\ Atkin
        Q = subst(P,'y,Y);
        d = (X-Y)^(N+1));
        polresultant(subst(P,'y,X), Q) / d;
        }
        '''
        cdef long _x = -1
        if x is not None:
            _x = get_var(x)
        cdef long _y = -1
        if y is not None:
            _y = get_var(y)
        sig_on()
        cdef GEN _ret = ellmodulareqn(N, _x, _y)
        return new_gen(_ret)

    def ellmul(self, E, z, n):
        r'''
        Computes :math:`[n]z`, where :math:`z` is a point on the elliptic curve :math:`E`. The
        exponent :math:`n` is in :math:`\mathbb{Z}`, or may be a complex quadratic integer if the curve :math:`E`
        has complex multiplication by :math:`n` (if not, an error message is issued).

        ::

        ? Ei = ellinit([1,0]); z = [0,0];
        ? ellmul(Ei, z, 10)
        %2 = [0] \\ unsurprising: z has order 2
        ? ellmul(Ei, z, I)
        %3 = [0, 0] \\ Ei has complex multiplication by Z[i]
        ? ellmul(Ei, z, quadgen(-4))
        %4 = [0, 0] \\ an alternative syntax for the same query
        ? Ej = ellinit([0,1]); z = [-1,0];
        ? ellmul(Ej, z, I)
        *** at top-level: ellmul(Ej,z,I)
        *** ^--------------
        *** ellmul: not a complex multiplication in ellmul.
        ? ellmul(Ej, z, 1+quadgen(-3))
        %6 = [1 - w, 0]

        The simple-minded algorithm for the CM case assumes that we are in
        characteristic :math:`0`, and that the quadratic order to which :math:`n` belongs has
        small discriminant.
        '''
        E = objtogen(E)
        z = objtogen(z)
        n = objtogen(n)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _z = (<Gen>z).g
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = ellmul(_E, _z, _n)
        return new_gen(_ret)

    def ellneg(self, E, z):
        r'''
        Opposite of the point :math:`z` on elliptic curve :math:`E`.
        '''
        E = objtogen(E)
        z = objtogen(z)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _z = (<Gen>z).g
        cdef GEN _ret = ellneg(_E, _z)
        return new_gen(_ret)

    def ellnonsingularmultiple(self, E, P):
        r'''
        Given an elliptic curve :math:`E/\mathbb{Q}` (more precisely, a model defined over :math:`\mathbb{Q}`
        of a curve) and a rational point :math:`P \in E(\mathbb{Q})`, returns the pair :math:`[R,n]`,
        where :math:`n` is the least positive integer such that :math:`R := [n]P` has good
        reduction at every prime. More precisely, its image in a minimal model is
        everywhere non-singular.

        ::

        ? e = ellinit("57a1"); P = [2,-2];
        ? ellnonsingularmultiple(e, P)
        %2 = [[1, -1], 2]
        ? e = ellinit("396b2"); P = [35, -198];
        ? [R,n] = ellnonsingularmultiple(e, P);
        ? n
        %5 = 12
        '''
        E = objtogen(E)
        P = objtogen(P)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _ret = ellnonsingularmultiple(_E, _P)
        return new_gen(_ret)

    def ellorder(self, E, z, o=None):
        r'''
        Gives the order of the point :math:`z` on the elliptic
        curve :math:`E`, defined over a finite field or a number field.
        Return (the impossible value) zero if the point has infinite order.

        ::

        ? E = ellinit([-157^2,0]); \\ the "157-is-congruent" curve
        ? P = [2,2]; ellorder(E, P)
        %2 = 2
        ? P = ellheegner(E); ellorder(E, P) \\ infinite order
        %3 = 0
        ? K = nfinit(polcyclo(11,t)); E=ellinit("11a3", K); T = elltors(E);
        ? ellorder(E, T.gen[1])
        %5 = 25
        ? E = ellinit(ellfromj(ffgen(5^10)));
        ? ellcard(E)
        %7 = 9762580
        ? P = random(E); ellorder(E, P)
        %8 = 4881290
        ? p = 2^160+7; E = ellinit([1,2], p);
        ? N = ellcard(E)
        %9 = 1461501637330902918203686560289225285992592471152
        ? o = [N, factor(N)];
        ? for(i=1,100, ellorder(E,random(E)))
        time = 260 ms.

        The parameter :math:`o`, is now mostly useless, and kept for backward
        compatibility. If present, it represents a non-zero multiple of the order
        of :math:`z`, see ``DLfun`` (in the PARI manual); the preferred format for this parameter is
        :literal:`[ord, factor(ord)]`, where :literal:`ord` is the cardinality of the curve.
        It is no longer needed since PARI is now able to compute it over large
        finite fields (was restricted to small prime fields at the time this feature
        was introduced), :emphasis:`and` caches the result in :math:`E` so that it is computed
        and factored only once. Modifying the last example, we see that including
        this extra parameter provides no improvement:

        ::

        ? o = [N, factor(N)];
        ? for(i=1,100, ellorder(E,random(E),o))
        time = 260 ms.
        '''
        E = objtogen(E)
        z = objtogen(z)
        cdef bint _have_o = (o is not None)
        if _have_o:
            o = objtogen(o)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _z = (<Gen>z).g
        cdef GEN _o = NULL
        if _have_o:
            _o = (<Gen>o).g
        cdef GEN _ret = ellorder(_E, _z, _o)
        return new_gen(_ret)

    def ellordinate(self, E, x, long precision=DEFAULT_BITPREC):
        r'''
        Gives a 0, 1 or 2-component vector containing
        the :math:`y`-coordinates of the points of the curve :math:`E` having :math:`x` as
        :math:`x`-coordinate.
        '''
        E = objtogen(E)
        x = objtogen(x)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ellordinate(_E, _x, precision)
        return new_gen(_ret)

    def ellpadicL(self, E, p, long n, s=None, long r=0, D=None):
        r'''
        Returns the value (or :math:`r`-th derivative) on a character :math:`\chi^s` of
        :math:`\mathbb{Z}_p^*` of the :math:`p`-adic :math:`L`-function of the elliptic curve :math:`E/\mathbb{Q}`, twisted by
        :math:`D`, given modulo :math:`p^n`.

        :strong:`Characters.` The set of continuous characters of
        :math:`Gal(\mathbb{Q} (\mu_{p^{ oo }})/ \mathbb{Q})` is identified to :math:`\mathbb{Z}_p^*` via the
        cyclotomic character :math:`\chi` with values in :math:`\overline{\mathbb{Q}_p}^*`. Denote by
        :math:`\tau:\mathbb{Z}_p^*\to\mathbb{Z}_p^*` the Teichmüller character, with values
        in the :math:`(p-1)`-th roots of :math:`1` for :math:`p != 2`, and :math:`{-1,1}` for :math:`p = 2`;
        finally, let
        :math:`<\chi>= \chi \tau^{-1}`, with values in :math:`1 + 2p\mathbb{Z}_p`.
        In GP, the continuous character of
        :math:`Gal(\mathbb{Q} (\mu_{p^{ oo }})/ \mathbb{Q})` given by :math:`<\chi>^{s_1}
        \tau^{s_2}` is represented by the pair of integers :math:`s = (s_1,s_2)`, with :math:`s_1
        \in \mathbb{Z}_p` and :math:`s_2 mod p-1` for :math:`p > 2`, (resp. mod :math:`2` for :math:`p = 2`); :math:`s`
        may be also an integer, representing :math:`(s,s)` or :math:`\chi^s`.

        :strong:`The :math:`p`-adic :math:`L` function.`
        The :math:`p`-adic :math:`L` function :math:`L_p` is defined on the set of continuous
        characters of :math:`Gal(\mathbb{Q} (\mu_{p^{ oo }})/ \mathbb{Q})`, as :math:`\int_{\mathbb{Z}_p^*}
        \chi^s d \mu` for a certain :math:`p`-adic distribution :math:`\mu` on :math:`\mathbb{Z}_p^*`. The
        derivative is given by

        .. MATH::

        L_p^{(r)}(E, \chi^s) = \int_{\mathbb{Z}_p^*} \log_p^r(a) \chi^s(a) d\mu (a).

        More precisely:

        - When :math:`E` has good supersingular reduction, :math:`L_p` takes its
        values in :math:`D := H^1_{dR}(E/\mathbb{Q})\otimes_\mathbb{Q} \mathbb{Q}_p` and satisfies
        

        .. MATH::

        (1-p^{-1} F)^{-2} L_p(E, \chi^0) = (L(E,1) / \Omega).\omega

        where :math:`F` is the Frobenius, :math:`L(E,1)` is the value of the complex :math:`L`
        function at :math:`1`, :math:`\omega` is the Néron differential
        and :math:`\Omega` the attached period on :math:`E(\mathbb{R})`. Here, :math:`\chi^0` represents
        the trivial character.

        The function returns the components of :math:`L_p^{(r)}(E,\chi^s)` in
        the basis :math:`(\omega, F \omega)`.

        - When :math:`E` has ordinary good reduction, this method only defines
        the projection of :math:`L_p(E,\chi^s)` on the :math:`\alpha`-eigenspace,
        where :math:`\alpha` is the unit eigenvalue for :math:`F`. This is what the function
        returns. We have
        

        .. MATH::

        (1- \alpha^{-1})^{-2} L_{p,\alpha}(E,\chi^0) = L(E,1) / \Omega.

        Two supersingular examples:

        ::

        ? cxL(e) = bestappr( ellL1(e) / e.omega[1] );
        
        ? e = ellinit("17a1"); p=3; \\ supersingular, a3 = 0
        ? L = ellpadicL(e,p,4);
        ? F = [0,-p;1,ellap(e,p)]; \\ Frobenius matrix in the basis (omega,F(omega))
        ? (1-p^(-1)*F)^-2 * L / cxL(e)
        %5 = [1 + O(3^5), O(3^5)]~ \\ [1,0]~
        
        ? e = ellinit("116a1"); p=3; \\ supersingular, a3 != 0~
        ? L = ellpadicL(e,p,4);
        ? F = [0,-p; 1,ellap(e,p)];
        ? (1-p^(-1)*F)^-2*L~ / cxL(e)
        %9 = [1 + O(3^4), O(3^5)]~

        Good ordinary reduction:

        ::

        ? e = ellinit("17a1"); p=5; ap = ellap(e,p)
        %1 = -2 \\ ordinary
        ? L = ellpadicL(e,p,4)
        %2 = 4 + 3*5 + 4*5^2 + 2*5^3 + O(5^4)
        ? al = padicappr(x^2 - ap*x + p, ap + O(p^7))[1];
        ? (1-al^(-1))^(-2) * L / cxL(e)
        %4 = 1 + O(5^4)

        Twist and Teichmüller:

        ::

        ? e = ellinit("17a1"); p=5; \\ ordinary
        \\ 2nd derivative at tau^1, twist by -7
        ? ellpadicL(e, p, 4, [0,1], 2, -7)
        %2 = 2*5^2 + 5^3 + O(5^4)

        We give an example of non split multiplicative reduction (see
        :literal:`ellpadicbsd` for more examples).

        ::

        ? e=ellinit("15a1"); p=3; n=5;
        ? L = ellpadicL(e,p,n)
        %2 = 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)
        ? (1 - ellap(e,p))^(-1) * L / cxL(e)
        %3 = 1 + O(3^5)

        This function is a special case of :literal:`mspadicL` and it also appears
        as the first term of :literal:`mspadicseries`:

        ::

        ? e = ellinit("17a1"); p=5;
        ? L = ellpadicL(e,p,4)
        %2 = 4 + 3*5 + 4*5^2 + 2*5^3 + O(5^4)
        ? [M,phi] = msfromell(e, 1);
        ? Mp = mspadicinit(M, p, 4);
        ? mu = mspadicmoments(Mp, phi);
        ? mspadicL(mu)
        %6 = 4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + O(5^6)
        ? mspadicseries(mu)
        %7 = (4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + O(5^6))
        + (3 + 3*5 + 5^2 + 5^3 + O(5^4))*x
        + (2 + 3*5 + 5^2 + O(5^3))*x^2
        + (3 + 4*5 + 4*5^2 + O(5^3))*x^3
        + (3 + 2*5 + O(5^2))*x^4 + O(x^5)

        These are more cumbersome than :literal:`ellpadicL` but allow to
        compute at different characters, or successive derivatives, or to
        twist by a quadratic character essentially for the cost of a single call to
        :literal:`ellpadicL` due to precomputations.
        '''
        E = objtogen(E)
        p = objtogen(p)
        cdef bint _have_s = (s is not None)
        if _have_s:
            s = objtogen(s)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _s = NULL
        if _have_s:
            _s = (<Gen>s).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = ellpadicL(_E, _p, n, _s, r, _D)
        return new_gen(_ret)

    def ellpadicbsd(self, E, p, long n, D=None):
        r'''
        Given an elliptic curve :math:`E` over :math:`\mathbb{Q}`, its quadratic twist :math:`E_D`
        and a prime number :math:`p`, this function is a :math:`p`-adic analog of the complex
        functions :literal:`ellanalyticrank` and :literal:`ellbsd`. It calls :literal:`ellpadicL`
        with initial accuracy :math:`p^n` and may increase it internally;
        it returns a vector :math:`[r, L_p]` where

        - :math:`L_p` is a :math:`p`-adic number (resp. a pair of :math:`p`-adic numbers if
        :math:`E` has good supersingular reduction) defined modulo :math:`p^N`, conjecturally
        equal to :math:`R_p S`, where :math:`R_p` is the :math:`p`-adic regulator as given by
        :literal:`ellpadicregulator` (in the basis :math:`(\omega, F \omega)`) and :math:`S` is the
        cardinal of the Tate-Shafarevich group for the quadratic twist :math:`E_D`.

        - :math:`r` is an upper bound for the analytic rank of the :math:`p`-adic
        :math:`L`-function attached to :math:`E_D`: we know for sure that the :math:`i`-th
        derivative of :math:`L_p(E_D,.)` at :math:`\chi^0` is :math:`O(p^N)` for all :math:`i < r`
        and that its :math:`r`-th derivative is non-zero; it is expected that the true
        analytic rank is equal to the rank of the Mordell-Weil group :math:`E_D(\mathbb{Q})`,
        plus :math:`1` if the reduction of :math:`E_D` at :math:`p` is split multiplicative;
        if :math:`r = 0`, then both the analytic rank and the Mordell-Weil rank are
        unconditionnally :math:`0`.

        Recall that the :math:`p`-adic BSD conjecture (Mazur, Tate, Teitelbaum, Bernardi,
        Perrin-Riou) predicts an explicit link between :math:`R_p S` and

        .. MATH::

        (1-p^{-1} F)^{-2}.L_p^{(r)}(E_D, \chi^0) / r!

        where :math:`r` is the analytic rank of the :math:`p`-adic :math:`L`-function attached to
        :math:`E_D` and :math:`F` is the Frobenius on :math:`H^1_{dR}`; see :literal:`ellpadicL`
        for definitions.

        ::

        ? E = ellinit("11a1"); p = 7; n = 5; \\ good ordinary
        ? ellpadicbsd(E, 7, 5) \\ rank 0,
        %2 = [0, 1 + O(7^5)]
        
        ? E = ellinit("91a1"); p = 7; n = 5; \\ non split multiplicative
        ? [r,Lp] = ellpadicbsd(E, p, n)
        %5 = [1, 2*7 + 6*7^2 + 3*7^3 + 7^4 + O(7^5)]
        ? R = ellpadicregulator(E, p, n, E.gen)
        %6 = 2*7 + 6*7^2 + 3*7^3 + 7^4 + 5*7^5 + O(7^6)
        ? sha = Lp/R
        %7 = 1 + O(7^4)
        
        ? E = ellinit("91b1"); p = 7; n = 5; \\ split multiplicative
        ? [r,Lp] = ellpadicbsd(E, p, n)
        %9 = [2, 2*7 + 7^2 + 5*7^3 + O(7^4)]
        ? ellpadicregulator(E, p, n, E.gen)
        %10 = 2*7 + 7^2 + 5*7^3 + 6*7^4 + 2*7^5 + O(7^6)
        ? [rC, LC] = ellanalyticrank(E);
        ? [r, rC]
        %12 = [2, 1] \\ r = rC+1 because of split multiplicative reduction
        
        ? E = ellinit("53a1"); p = 5; n = 5; \\ supersingular
        ? [r, Lp] = ellpadicbsd(E, p, n);
        ? r
        %15 = 1
        ? Lp
        %16 = [3*5 + 2*5^2 + 2*5^5 + O(5^6), \
        5 + 3*5^2 + 4*5^3 + 2*5^4 + 5^5 + O(5^6)]
        ? R = ellpadicregulator(E, p, n, E.gen)
        %17 = [3*5 + 2*5^2 + 2*5^5 + O(5^6), 5 + 3*5^2 + 4*5^3 + 2*5^4 + O(5^5)]
        \\ expect Lp = R*#Sha, hence (conjecturally) #Sha = 1
        
        ? E = ellinit("84a1"); p = 11; n = 6; D = -443;
        ? [r,Lp] = ellpadicbsd(E, 11, 6, D) \\ Mordell-Weil rank 0, no regulator
        %19 = [0, 3 + 2*11 + O(11^6)]
        ? lift(Lp) \\ expected cardinal for Sha is 5^2
        %20 = 25
        ? ellpadicbsd(E, 3, 12, D) \\ at 3
        %21 = [1, 1 + 2*3 + 2*3^2 + O(3^8)]
        ? ellpadicbsd(E, 7, 8, D) \\ and at 7
        %22 = [0, 4 + 3*7 + O(7^8)]
        '''
        E = objtogen(E)
        p = objtogen(p)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = ellpadicbsd(_E, _p, n, _D)
        return new_gen(_ret)

    def ellpadicfrobenius(self, E, long p, long n):
        r'''
        If :math:`p > 2` is a prime and :math:`E` is an elliptic curve on :math:`\mathbb{Q}` with good
        reduction at :math:`p`, return the matrix of the Frobenius endomorphism :math:`\varphi` on
        the crystalline module :math:`D_p(E) = \mathbb{Q}_p \otimes H^1_{dR}(E/\mathbb{Q})` with respect to
        the basis of the given model :math:`(\omega, \eta = x \omega)`, where
        :math:`\omega = dx/(2 y+a_1 x+a_3)` is the invariant differential.
        The characteristic polynomial of :math:`\varphi` is :math:`x^2 - a_p x + p`.
        The matrix is computed to absolute :math:`p`-adic precision :math:`p^n`.

        ::

        ? E = ellinit([1,-1,1,0,0]);
        ? F = ellpadicfrobenius(E,5,3);
        ? lift(F)
        %3 =
        [120 29]
        
        [ 55 5]
        ? charpoly(F)
        %4 = x^2 + O(5^3)*x + (5 + O(5^3))
        ? ellap(E, 5)
        %5 = 0
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellpadicfrobenius(_E, p, n)
        return new_gen(_ret)

    def ellpadicheight(self, E, p, long n, P, Q=None):
        r'''
        Cyclotomic :math:`p`-adic height of the rational point :math:`P` on the elliptic curve
        :math:`E` (defined over :math:`\mathbb{Q}`), given to :math:`n` :math:`p`-adic digits.
        If the argument :math:`Q` is present, computes the value of the bilinear
        form :math:`(h(P+Q)-h(P-Q)) / 4`.

        Let :math:`D := H^1_{dR}(E) \otimes_\mathbb{Q} \mathbb{Q}_p` be the :math:`\mathbb{Q}_p` vector space
        spanned by :math:`\omega`
        (invariant differential :math:`dx/(2y+a_1x+a3)` related to the given model) and
        :math:`\eta = x \omega`. Then the cyclotomic :math:`p`-adic height :math:`h_E` associates to
        :math:`P\in E(\mathbb{Q})` an element :math:`f \omega + g \eta` in :math:`D`.
        This routine returns the vector :math:`[f, g]` to :math:`n` :math:`p`-adic digits.
        If :math:`P\in E(\mathbb{Q})` is in the kernel of reduction mod :math:`p` and if its reduction
        at all finite places is non singular, then :math:`g = -(\log_E P)^2`, where
        :math:`\log_E` is the logarithm for the formal group of :math:`E` at :math:`p`.

        If furthermore the model is of the form :math:`Y^2 = X^3 + a X + b` and :math:`P = (x,y)`,
        then

        .. MATH::

        f = \log_p(denominator (x)) - 2 \log_p(\sigma (P))

        where :math:`\sigma (P)` is given by :literal:`ellsigma`:math:`(E,P)`.

        Recall (:emphasis:`Advanced topics in the arithmetic of elliptic
        curves`, Theorem 3.2) that the local height function over the complex numbers
        is of the form

        .. MATH::

        \lambda (z) = -\log (\|E.disc\|) / 6 + \Re (z \eta (z)) - 2 \log (
        \sigma (z)).

        (N.B. our normalization for local and global heights is twice that of
        Silverman's).

        ::

        ? E = ellinit([1,-1,1,0,0]); P = [0,0];
        ? ellpadicheight(E,5,3, P)
        %2 = [3*5 + 5^2 + 2*5^3 + O(5^4), 5^2 + 4*5^4 + O(5^5)]
        ? E = ellinit("11a1"); P = [5,5]; \\ torsion point
        ? ellpadicheight(E,19,6, P)
        %4 = [0, 0]
        ? E = ellinit([0,0,1,-4,2]); P = [-2,1];
        ? ellpadicheight(E,3,3, P)
        %6 = [2*3^2 + 2*3^3 + 3^4 + O(3^5), 2*3^2 + 3^4 + O(3^5)]
        ? ellpadicheight(E,3,5, P, elladd(E,P,P))
        %7 = [3^2 + 2*3^3 + O(3^7), 3^2 + 3^3 + 2*3^4 + 3^5 + O(3^7)]

        - When :math:`E` has good ordinary reduction at :math:`p` or non split multiplicative
        reduction, the "canonical" :math:`p`-adic height is given by

        ::

        s2 = ellpadics2(E,p,n);
        ellpadicheight(E, p, n, P) * [1,-s2]~

        Since :math:`s_2` does not depend on :math:`P`, it is preferable to
        compute it only once:

        ::

        ? E = ellinit("5077a1"); p = 5; n = 7; \\ rank 3
        ? s2 = ellpadics2(E,p,n);
        ? M = ellpadicheightmatrix(E,p, n, E.gen) * [1,-s2]~;
        ? matdet(M) \\ p-adic regulator on the points in E.gen
        %4 = 5 + 5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + O(5^7)

        - When :math:`E` has split multiplicative reduction at :math:`p` (Tate curve),
        the "canonical" :math:`p`-adic height is given by

        ::

        Ep = ellinit(E[1..5], O(p^(n))); \\ E seen as a Tate curve over Qp
        [u2,u,q] = Ep.tate;
        ellpadicheight(E, p, n, P) * [1,-s2 + 1/log(q)/u2]]~

        where :math:`s_2` is as above. For example,

        ::

        ? E = ellinit("91b1"); P =[-1, 3]; p = 7; n = 5;
        ? Ep = ellinit(E[1..5], O(p^(n)));
        ? s2 = ellpadics2(E,p,n);
        ? [u2,u,q] = Ep.tate;
        ? H = ellpadicheight(E,p, n, P) * [1,-s2 + 1/log(q)/u2]~
        %5 = 2*7 + 7^2 + 5*7^3 + 6*7^4 + 2*7^5 + O(7^6)

        These normalizations are chosen so that :math:`p`-adic BSD conjectures
        are easy to state, see :literal:`ellpadicbsd`.
        '''
        E = objtogen(E)
        p = objtogen(p)
        P = objtogen(P)
        cdef bint _have_Q = (Q is not None)
        if _have_Q:
            Q = objtogen(Q)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _Q = NULL
        if _have_Q:
            _Q = (<Gen>Q).g
        cdef GEN _ret = ellpadicheight0(_E, _p, n, _P, _Q)
        return new_gen(_ret)

    def ellpadicheightmatrix(self, E, p, long n, Q):
        r'''
        :math:`Q` being a vector of points, this function returns the "Gram matrix"
        :math:`[F,G]` of the cyclotomic :math:`p`-adic height :math:`h_E` with respect to
        the basis :math:`(\omega, \eta)` of :math:`D = H^1_{dR}(E) \otimes_\mathbb{Q} \mathbb{Q}_p`
        given to :math:`n` :math:`p`-adic digits. In other words, if
        :literal:`ellpadicheight`:math:`(E,p,n, Q[i],Q[j]) = [f,g]`, corresponding to
        :math:`f \omega + g \eta` in :math:`D`, then :math:`F[i,j] = f` and :math:`G[i,j] = g`.

        ::

        ? E = ellinit([0,0,1,-7,6]); Q = [[-2,3],[-1,3]]; p = 5; n = 5;
        ? [F,G] = ellpadicheightmatrix(E,p,n,Q);
        ? lift(F) \\ p-adic entries, integral approximation for readability
        %3 =
        [2364 3100]
        
        [3100 3119]
        
        ? G
        %4 =
        [25225 46975]
        
        [46975 61850]
        
        ? [F,G] * [1,-ellpadics2(E,p,n)]~
        %5 =
        [4 + 2*5 + 4*5^2 + 3*5^3 + O(5^5) 4*5^2 + 4*5^3 + 5^4 + O(5^5)]
        
        [ 4*5^2 + 4*5^3 + 5^4 + O(5^5) 4 + 3*5 + 4*5^2 + 4*5^3 + 5^4 + O(5^5)]
        '''
        E = objtogen(E)
        p = objtogen(p)
        Q = objtogen(Q)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _ret = ellpadicheightmatrix(_E, _p, n, _Q)
        return new_gen(_ret)

    def ellpadiclog(self, E, p, long n, P):
        r'''
        Given :math:`E` defined over :math:`K = \mathbb{Q}` or :math:`\mathbb{Q}_p` and :math:`P = [x,y]` on :math:`E(K)` in the
        kernel of reduction mod :math:`p`, let :math:`t(P) = -x/y` be the formal group
        parameter; this function returns :math:`L(t)`, where :math:`L` denotes the formal
        logarithm (mapping the formal group of :math:`E` to the additive formal group)
        attached to the canonical invariant differential:
        :math:`dL = dx/(2y + a_1x + a_3)`.

        ::

        ? E = ellinit([0,0,1,-4,2]); P = [-2,1];
        ? ellpadiclog(E,2,10,P)
        %2 = 2 + 2^3 + 2^8 + 2^9 + 2^10 + O(2^11)
        ? E = ellinit([17,42]);
        ? p=3; Ep = ellinit(E,p); \\ E mod p
        ? P=[114,1218]; ellorder(Ep,P) \\ the order of P on (E mod p) is 2
        %5 = 2
        ? Q = ellmul(E,P,2) \\ we need a point of the form 2*P
        %6 = [200257/7056, 90637343/592704]
        ? ellpadiclog(E,3,10,Q)
        %7 = 3 + 2*3^2 + 3^3 + 3^4 + 3^5 + 3^6 + 2*3^8 + 3^9 + 2*3^10 + O(3^11)
        '''
        E = objtogen(E)
        p = objtogen(p)
        P = objtogen(P)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _ret = ellpadiclog(_E, _p, n, _P)
        return new_gen(_ret)

    def ellpadicregulator(self, E, p, long n, S):
        r'''
        Let :math:`E/\mathbb{Q}` be an elliptic curve. Return the determinant of the Gram
        matrix of the vector of points :math:`S = (S_1,..., S_r)` with respect to the
        "canonical" cyclotomic :math:`p`-adic height on :math:`E`, given to :math:`n` (:math:`p`-adic)
        digits.

        When :math:`E` has ordinary reduction at :math:`p`, this is the expected Gram
        deteterminant in :math:`\mathbb{Q}_p`.

        In the case of supersingular reduction of :math:`E` at :math:`p`, the definition
        requires care: the regulator :math:`R` is an element of
        :math:`D := H^1_{dR}(E) \otimes_\mathbb{Q} \mathbb{Q}_p`, which is a two-dimensional
        :math:`\mathbb{Q}_p`-vector space spanned by :math:`\omega` and :math:`\eta = x \omega`
        (which are defined over :math:`\mathbb{Q}`) or equivalently but now over :math:`\mathbb{Q}_p`
        by :math:`\omega` and :math:`F\omega` where :math:`F` is the Frobenius endomorphism on :math:`D`
        as defined in :literal:`ellpadicfrobenius`. On :math:`D` we
        define the cyclotomic height :math:`h_E = f \omega + g \eta`
        (see :literal:`ellpadicheight`) and a canonical alternating bilinear form
        :math:`[.,.]_D` such that :math:`[\omega, \eta]_D = 1`.

        For any :math:`\nu \in D`, we can define a height :math:`h_\nu := [ h_E, \nu ]_D`
        from :math:`E(\mathbb{Q})` to :math:`\mathbb{Q}_p` and :math:`<.,.>_\nu` the attached
        bilinear form. In particular, if :math:`h_E = f \omega + g\eta`, then
        :math:`h_\eta = [ h_E, \eta ]_D` = f and :math:`h_\omega = [ h_E, \omega ]_D = - g`
        hence :math:`h_E = h_\eta \omega - h_\omega \eta`.
        Then, :math:`R` is the unique element of :math:`D` such that

        .. MATH::

        [\omega,\nu]_D^{r-1} [R, \nu]_D = \det (< S_i, S_j >_{\nu})

        for all :math:`\nu \in D` not in :math:`\mathbb{Q}_p \omega`. The :literal:`ellpadicregulator`
        function returns :math:`R` in the basis :math:`(\omega, F\omega)`, which was chosen
        so that :math:`p`-adic BSD conjectures are easy to state, see :literal:`ellpadicbsd`.

        Note that by definition

        .. MATH::

        [R, \eta]_D = \det (< S_i, S_j >_{\eta})

        and

        .. MATH::

        [R, \omega+\eta]_D = \det (< S_i, S_j >_{\omega+\eta}).
        '''
        E = objtogen(E)
        p = objtogen(p)
        S = objtogen(S)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _S = (<Gen>S).g
        cdef GEN _ret = ellpadicregulator(_E, _p, n, _S)
        return new_gen(_ret)

    def ellpadics2(self, E, p, long n):
        r'''
        If :math:`p > 2` is a prime and :math:`E/\mathbb{Q}` is an elliptic curve with ordinary good
        reduction at :math:`p`, returns the slope of the unit eigenvector
        of :literal:`ellpadicfrobenius(E,p,n)`, i.e., the action of Frobenius :math:`\varphi` on
        the crystalline module :math:`D_p(E) = \mathbb{Q}_p \otimes H^1_{dR}(E/\mathbb{Q})` in the basis of
        the given model :math:`(\omega, \eta = x \omega)`, where :math:`\omega` is the invariant
        differential :math:`dx/(2 y+a_1 x+a_3)`. In other words, :math:`\eta + s_2\omega`
        is an eigenvector for the unit eigenvalue of :math:`\varphi`.

        ::

        ? e=ellinit([17,42]);
        ? ellpadics2(e,13,4)
        %2 = 10 + 2*13 + 6*13^3 + O(13^4)

        This slope is the unique :math:`c \in 3^{-1}\mathbb{Z}_p` such that the odd solution
        :math:`\sigma (t) = t + O(t^2)` of

        .. MATH::

        - d((1)/(\sigma) (d \sigma)/(\omega))
        = (x(t) + c) \omega

        is in :math:`t\mathbb{Z}_p[[t]]`.

        It is equal to :math:`b_2/12 - E_2/12` where :math:`E_2` is the value of the Katz
        :math:`p`-adic Eisenstein series of weight 2 on :math:`(E,\omega)`. This is
        used to construct a canonical :math:`p`-adic height when :math:`E` has good ordinary
        reduction at :math:`p` as follows

        ::

        s2 = ellpadics2(E,p,n);
        h(E,p,n, P, s2) = ellpadicheight(E, [p,[1,-s2]],n, P);

        Since :math:`s_2` does not depend on the point :math:`P`, we compute it
        only once.
        '''
        E = objtogen(E)
        p = objtogen(p)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = ellpadics2(_E, _p, n)
        return new_gen(_ret)

    def ellperiods(self, w, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Let :math:`w` describe a complex period lattice (:math:`w = [w_1,w_2]`
        or an :literal:`ellinit` structure). Returns normalized periods :math:`[W_1,W_2]` generating
        the same lattice such that :math:`\tau := W_1/W_2` has positive imaginary part
        and lies in the standard fundamental domain for :math:`SL_2(\mathbb{Z})`.

        If :math:`flag = 1`, the function returns :math:`[[W_1,W_2], [\eta_1,\eta_2]]`, where
        :math:`\eta_1` and :math:`\eta_2` are the quasi-periods attached to
        :math:`[W_1,W_2]`, satisfying :math:`\eta_2 W_1 - \eta_1 W_2 = 2 i \pi`.

        The output of this function is meant to be used as the first argument
        given to ellwp, ellzeta, ellsigma or elleisnum. Quasi-periods are
        needed by ellzeta and ellsigma only.

        ::

        ? L = ellperiods([1,I],1);
        ? [w1,w2] = L[1]; [e1,e2] = L[2];
        ? e2*w1 - e1*w2
        %3 = 6.2831853071795864769252867665590057684*I
        ? ellzeta(L, 1/2 + 2*I)
        %4 = 1.5707963... - 6.283185307...*I
        ? ellzeta([1,I], 1/2 + 2*I) \\ same but less efficient
        %4 = 1.5707963... - 6.283185307...*I
        '''
        w = objtogen(w)
        sig_on()
        cdef GEN _w = (<Gen>w).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ellperiods(_w, flag, precision)
        return new_gen(_ret)

    def ellpointtoz(self, E, P, long precision=DEFAULT_BITPREC):
        r'''
        If :math:`E/\mathbb{C} ~ \mathbb{C}/\Lambda` is a complex elliptic curve (:math:`\Lambda =
        E.omega`), computes a complex number :math:`z`, well-defined modulo the
        lattice :math:`\Lambda`, corresponding to the point :math:`P`; i.e. such that
        :math:`P = [\wp_\Lambda (z),\wp'_\Lambda (z)]` satisfies the equation

        .. MATH::

        y^2 = 4x^3 - g_2 x - g_3,

        where :math:`g_2`, :math:`g_3` are the elliptic invariants.

        If :math:`E` is defined over :math:`\mathbb{R}` and :math:`P\in E(\mathbb{R})`, we have more precisely, :math:`0 \leq
        \Re (t) < w1` and :math:`0 <= \Im (t) < \Im (w2)`, where :math:`(w1,w2)` are the real and
        complex periods of :math:`E`.

        ::

        ? E = ellinit([0,1]); P = [2,3];
        ? z = ellpointtoz(E, P)
        %2 = 3.5054552633136356529375476976257353387
        ? ellwp(E, z)
        %3 = 2.0000000000000000000000000000000000000
        ? ellztopoint(E, z) - P
        %4 = [2.548947057811923643 E-57, 7.646841173435770930 E-57]
        ? ellpointtoz(E, [0]) \\ the point at infinity
        %5 = 0

        If :math:`E` is defined over a general number field, the function returns the
        values corresponding to the various complex embeddings of the curve
        and of the point, in the same order as :literal:`E.nf.roots`:

        ::

        ? E=ellinit([-22032-15552*x,0], nfinit(x^2-2));
        ? P=[-72*x-108,0];
        ? ellisoncurve(E,P)
        %3 = 1
        ? ellpointtoz(E,P)
        %4 = [-0.52751724240790530394437835702346995884*I,
        -0.090507650025885335533571758708283389896*I]
        ? E.nf.roots
        %5 = [-1.4142135623730950488016887242096980786, \\ x-> -sqrt(2)
        1.4142135623730950488016887242096980786] \\ x-> sqrt(2)

        If :math:`E/\mathbb{Q}_p` has multiplicative reduction, then :math:`E/\bar{\mathbb{Q}_p}` is analytically
        isomorphic to :math:`\bar{\mathbb{Q}}_p^*/q^\mathbb{Z}` (Tate curve) for some :math:`p`-adic integer :math:`q`.
        The behavior is then as follows:

        - If the reduction is split (:math:`E.tate[2]` is a :literal:`t_PADIC`), we have
        an isomorphism :math:`\phi: E(\mathbb{Q}_p) ~ \mathbb{Q}_p^*/q^\mathbb{Z}` and the function returns
        :math:`\phi (P)\in \mathbb{Q}_p`.

        - If the reduction is :emphasis:`not` split (:math:`E.tate[2]` is a
        :literal:`t_POLMOD`), we only have an isomorphism :math:`\phi: E(K) ~ K^*/q^\mathbb{Z}` over
        the unramified quadratic extension :math:`K/\mathbb{Q}_p`. In this case, the output
        :math:`\phi (P)\in K` is a :literal:`t_POLMOD`.

        ::

        ? E = ellinit([0,-1,1,0,0], O(11^5)); P = [0,0];
        ? [u2,u,q] = E.tate; type(u) \\ split multiplicative reduction
        %2 = "t_PADIC"
        ? ellmul(E, P, 5) \\ P has order 5
        %3 = [0]
        ? z = ellpointtoz(E, [0,0])
        %4 = 3 + 11^2 + 2*11^3 + 3*11^4 + 6*11^5 + 10*11^6 + 8*11^7 + O(11^8)
        ? z^5
        %5 = 1 + O(11^9)
        ? E = ellinit(ellfromj(1/4), O(2^6)); x=1/2; y=ellordinate(E,x)[1];
        ? z = ellpointtoz(E,[x,y]); \\ t_POLMOD of t_POL with t_PADIC coeffs
        ? liftint(z) \\ lift all p-adics
        %8 = Mod(8*u + 7, u^2 + 437)
        '''
        E = objtogen(E)
        P = objtogen(P)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _P = (<Gen>P).g
        precision = nbits2prec(precision)
        cdef GEN _ret = zell(_E, _P, precision)
        return new_gen(_ret)

    def ellpow(self, E, z, n):
        r'''
        Deprecated alias for :literal:`ellmul`.
        '''
        from warnings import warn
        warn('the PARI/GP function ellpow is obsolete (2012-06-06)', DeprecationWarning)
        E = objtogen(E)
        z = objtogen(z)
        n = objtogen(n)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _z = (<Gen>z).g
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = ellmul(_E, _z, _n)
        return new_gen(_ret)

    def ellratpoints(self, E, h, long flag=0):
        r'''
        :math:`E` being an integral model of elliptic curve , return a vector
        containing the affine rational points on the curve of naive height less than
        :math:`h`. If :math:`flag = 1`, stop as soon as a point is found; return either an empty
        vector or a vector containing a single point.
        See :literal:`hyperellratpoints` for how :math:`h` can be specified.

        ::

        ? E=ellinit([-25,1]);
        ? ellratpoints(E,10)
        %2 = [[-5,1],[-5,-1],[-3,7],[-3,-7],[-1,5],[-1,-5],
        [0,1],[0,-1],[5,1],[5,-1],[7,13],[7,-13]]
        ? ellratpoints(E,10,1)
        %3 = [[-5,1]]
        '''
        E = objtogen(E)
        h = objtogen(h)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _h = (<Gen>h).g
        cdef GEN _ret = ellratpoints(_E, _h, flag)
        return new_gen(_ret)

    def ellrootno(self, E, p=None):
        r'''
        :math:`E` being an :literal:`ell` structure over :math:`\mathbb{Q}` as output by :literal:`ellinit`,
        this function computes the local root number of its :math:`L`-series at the place
        :math:`p` (at the infinite place if :math:`p = 0`). If :math:`p` is omitted, return the global
        root number and in this case the curve can also be defined over a number field.

        Note that the global root number is the sign of the functional
        equation and conjecturally is the parity of the rank of the
        Mordell-Weil group. The equation for :math:`E` needs not be minimal at :math:`p`,
        but if the model is already minimal the function will run faster.
        '''
        E = objtogen(E)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef long _ret = ellrootno(_E, _p)
        clear_stack()
        return _ret

    def ellsea(self, E, long tors=0):
        r'''
        Let :math:`E` be an :emphasis:`ell` structure as output by :literal:`ellinit`, defined over
        a finite field :math:`\mathbb{F}_q`. This low-level function computes the order of the
        group :math:`E(\mathbb{F}_q)` using the SEA algorithm; compared to the high-level
        function :literal:`ellcard`, which includes SEA among its choice of algorithms,
        the :literal:`tors` argument allows to speed up a search for curves having almost
        prime order and whose quadratic twist may also have almost prime order.
        When :literal:`tors` is set to a non-zero value, the function returns :math:`0` as soon
        as it detects that the order has a small prime factor not dividing :literal:`tors`;
        SEA considers modular polynomials of increasing prime degree :math:`\ell` and we
        return :math:`0` as soon as we hit an :math:`\ell` (coprime to :literal:`tors`) dividing
        :math:`\#E(\mathbb{F}_q)`:

        ::

        ? ellsea(ellinit([1,1], 2^56+3477), 1)
        %1 = 72057594135613381
        ? forprime(p=2^128,oo, q = ellcard(ellinit([1,1],p)); if(isprime(q),break))
        time = 6,571 ms.
        ? forprime(p=2^128,oo, q = ellsea(ellinit([1,1],p),1);if(isprime(q),break))
        time = 522 ms.

        In particular, set :literal:`tors` to :math:`1` if you want a curve with prime order,
        to :math:`2` if you want to allow a cofactor which is a power of two (e.g. for
        Edwards's curves), etc. The early exit on bad curves yields a massive
        speedup compared to running the cardinal algorithm to completion.

        When :literal:`tors` is negative, similar checks are performed for the quadratic
        twist of the curve.

        The following function returns a curve of prime order over :math:`\mathbb{F}_p`.

        ::

        cryptocurve(p) =
        {
        while(1,
        my(E, N, j = Mod(random(p), p));
        E = ellinit(ellfromj(j));
        N = ellsea(E, 1); if (!N, continue);
        if (isprime(N), return(E));
        \\ try the quadratic twist for free
        if (isprime(2*p+2 - N), return(ellinit(elltwist(E))));
        );
        }
        ? p = randomprime([2^255, 2^256]);
        ? E = cryptocurve(p); \\ insist on prime order
        %2 = 47,447ms

        The same example without early abort (using :literal:`ellcard(E)`
        instead of :literal:`ellsea(E, 1)`) runs for about 5 minutes before finding a
        suitable curve.

        The availability of the :literal:`seadata` package will speed up the computation,
        and is strongly recommended. The generic function :literal:`ellcard` should be
        preferred when you only want to compute the cardinal of a given curve without
        caring about it having almost prime order:

        - If the characteristic is too small (:math:`p <= 7`) or the field
        cardinality is tiny (:math:`q <= 523`) the generic algorithm
        :literal:`ellcard` is used instead and the :literal:`tors` argument is ignored.
        (The reason for this is that SEA is not implemented for :math:`p <= 7` and
        that if :math:`q <= 523` it is likely to run into an infinite loop.)

        - If the field cardinality is smaller than about :math:`2^{50}`, the
        generic algorithm will be faster.

        - Contrary to :literal:`ellcard`, :literal:`ellsea` does not store the computed
        cardinality in :math:`E`.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellsea(_E, tors)
        return new_gen(_ret)

    def ellsearch(self, N):
        r'''
        This function finds all curves in the :literal:`elldata` database satisfying
        the constraint defined by the argument :math:`N`:

        - if :math:`N` is a character string, it selects a given curve, e.g.
        :literal:`"11a1"`, or curves in the given isogeny class, e.g. :literal:`"11a"`, or
        curves with given conductor, e.g. :literal:`"11"`;

        - if :math:`N` is a vector of integers, it encodes the same constraints
        as the character string above, according to the :literal:`ellconvertname`
        correspondance, e.g. :literal:`[11,0,1]` for :literal:`"11a1"`, :literal:`[11,0]` for
        :literal:`"11a"` and :literal:`[11]` for :literal:`"11"`;

        - if :math:`N` is an integer, curves with conductor :math:`N` are selected.

        If :math:`N` codes a full curve name, for instance :literal:`"11a1"` or :literal:`[11,0,1]`,
        the output format is :math:`[N, [a_1,a_2,a_3,a_4,a_6], G]` where
        :math:`[a_1,a_2,a_3,a_4,a_6]` are the coefficients of the Weierstrass equation of
        the curve and :math:`G` is a :math:`\mathbb{Z}`-basis of the free part of the
        Mordell-Weil group attached to the curve.

        ::

        ? ellsearch("11a3")
        %1 = ["11a3", [0, -1, 1, 0, 0], []]
        ? ellsearch([11,0,3])
        %2 = ["11a3", [0, -1, 1, 0, 0], []]

        If :math:`N` is not a full curve name, then the output is a vector of all matching
        curves in the above format:

        ::

        ? ellsearch("11a")
        %1 = [["11a1", [0, -1, 1, -10, -20], []],
        ["11a2", [0, -1, 1, -7820, -263580], []],
        ["11a3", [0, -1, 1, 0, 0], []]]
        ? ellsearch("11b")
        %2 = []
        '''
        N = objtogen(N)
        sig_on()
        cdef GEN _N = (<Gen>N).g
        cdef GEN _ret = ellsearch(_N)
        return new_gen(_ret)

    def ellsigma(self, L, z=None, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Computes the value at :math:`z` of the Weierstrass :math:`\sigma` function attached to
        the lattice :math:`L` as given by :literal:`ellperiods`:math:`(,1)`: including quasi-periods
        is useful, otherwise there are recomputed from scratch for each new :math:`z`.

        .. MATH::

        \sigma (z, L) = z \prod_{\omega\in L^*} (1 -
        (z)/(\omega))e^{(z)/(\omega) + (z^2)/(2\omega^2)}.

        It is also possible to directly input :math:`L = [\omega_1,\omega_2]`,
        or an elliptic curve :math:`E` as given by :literal:`ellinit` (:math:`L = E.omega`).

        ::

        ? w = ellperiods([1,I], 1);
        ? ellsigma(w, 1/2)
        %2 = 0.47494937998792065033250463632798296855
        ? E = ellinit([1,0]);
        ? ellsigma(E) \\ at 'x, implicitly at default seriesprecision
        %4 = x + 1/60*x^5 - 1/10080*x^9 - 23/259459200*x^13 + O(x^17)

        If :math:`flag = 1`, computes an arbitrary determination of :math:`\log (\sigma (z))`.
        '''
        L = objtogen(L)
        cdef bint _have_z = (z is not None)
        if _have_z:
            z = objtogen(z)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _z = NULL
        if _have_z:
            _z = (<Gen>z).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ellsigma(_L, _z, flag, precision)
        return new_gen(_ret)

    def ellsub(self, E, z1, z2):
        r'''
        Difference of the points :math:`z1` and :math:`z2` on the
        elliptic curve corresponding to :math:`E`.
        '''
        E = objtogen(E)
        z1 = objtogen(z1)
        z2 = objtogen(z2)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _z1 = (<Gen>z1).g
        cdef GEN _z2 = (<Gen>z2).g
        cdef GEN _ret = ellsub(_E, _z1, _z2)
        return new_gen(_ret)

    def elltamagawa(self, E):
        r'''
        The object :math:`E` being an elliptic curve over a number field, returns the global
        Tamagawa number of the curve (including the factor at infinite places).

        ::

        ? e = ellinit([1, -1, 1, -3002, 63929]); \\ curve "90c6" from elldata
        ? elltamagawa(e)
        %2 = 288
        ? [elllocalred(e,p)[4] | p<-[2,3,5]]
        %3 = [6, 4, 6]
        ? vecprod(%) \\ since e.disc > 0 the factor at infinity is 2
        %4 = 144
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = elltamagawa(_E)
        return new_gen(_ret)

    def elltaniyama(self, E, long serprec=-1):
        r'''
        Computes the modular parametrization of the elliptic curve :math:`E/\mathbb{Q}`,
        where :math:`E` is an :literal:`ell` structure as output by :literal:`ellinit`. This returns
        a two-component vector :math:`[u,v]` of power series, given to :math:`d` significant
        terms (:literal:`seriesprecision` by default), characterized by the following two
        properties. First the point :math:`(u,v)` satisfies the equation of the elliptic
        curve. Second, let :math:`N` be the conductor of :math:`E` and :math:`\Phi: X_0(N)\to E`
        be a modular parametrization; the pullback by :math:`\Phi` of the
        Néron differential :math:`du/(2v+a_1u+a_3)` is equal to :math:`2i\pi
        f(z)dz`, a holomorphic differential form. The variable used in the power
        series for :math:`u` and :math:`v` is :math:`x`, which is implicitly understood to be equal to
        :math:`\exp (2i\pi z)`.

        The algorithm assumes that :math:`E` is a :emphasis:`strong` Weil curve
        and that the Manin constant is equal to 1: in fact, :math:`f(x) = \sum_{n > 0}
        ellan (E, n) x^n`.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = elltaniyama(_E, serprec)
        return new_gen(_ret)

    def elltatepairing(self, E, P, Q, m):
        r'''
        Computes the Tate pairing of the two points :math:`P` and :math:`Q` on the elliptic
        curve :math:`E`. The point :math:`P` must be of :math:`m`-torsion.
        '''
        E = objtogen(E)
        P = objtogen(P)
        Q = objtogen(Q)
        m = objtogen(m)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _m = (<Gen>m).g
        cdef GEN _ret = elltatepairing(_E, _P, _Q, _m)
        return new_gen(_ret)

    def elltors(self, E):
        r'''
        If :math:`E` is an elliptic curve defined over a number field or a finite field,
        outputs the torsion subgroup of :math:`E` as a 3-component vector :literal:`[t,v1,v2]`,
        where :literal:`t` is the order of the torsion group, :literal:`v1` gives the structure
        of the torsion group as a product of cyclic groups (sorted by decreasing
        order), and :literal:`v2` gives generators for these cyclic groups. :math:`E` must be an
        :literal:`ell` structure as output by :literal:`ellinit`.

        ::

        ? E = ellinit([-1,0]);
        ? elltors(E)
        %1 = [4, [2, 2], [[0, 0], [1, 0]]]

        Here, the torsion subgroup is isomorphic to :math:`\mathbb{Z}/2\mathbb{Z} x \mathbb{Z}/2\mathbb{Z}`, with
        generators :math:`[0,0]` and :math:`[1,0]`.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = elltors(_E)
        return new_gen(_ret)

    def elltwist(self, E, P=None):
        r'''
        Returns the coefficients :math:`[a_1,a_2,a_3,a_4,a_6]` of the twist of the
        elliptic curve :math:`E` by the quadratic extension of the coefficient ring
        defined by :math:`P` (when :math:`P` is a polynomial) or :literal:`quadpoly(P)` when :math:`P` is an
        integer. If :math:`E` is defined over a finite field, then :math:`P` can be omitted,
        in which case a random model of the unique non-trivial twist is returned.
        If :math:`E` is defined over a number field, the model should be replaced by a
        minimal model (if one exists).

        Example: Twist by discriminant :math:`-3`:

        ::

        ? elltwist(ellinit([0,a2,0,a4,a6]),-3)
        %1 = [0,-3*a2,0,9*a4,-27*a6]

        Twist by the Artin-Shreier extension given by :math:`x^2+x+T` in
        characteristic :math:`2`:

        ::

        ? lift(elltwist(ellinit([a1,a2,a3,a4,a6]*Mod(1,2)),x^2+x+T))
        %1 = [a1,a2+a1^2*T,a3,a4,a6+a3^2*T]

        Twist of an elliptic curve defined over a finite field:

        ::

        ? E=ellinit([1,7]*Mod(1,19));lift(elltwist(E))
        %1 = [0,0,0,11,12]
        '''
        E = objtogen(E)
        cdef bint _have_P = (P is not None)
        if _have_P:
            P = objtogen(P)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _P = NULL
        if _have_P:
            _P = (<Gen>P).g
        cdef GEN _ret = elltwist(_E, _P)
        return new_gen(_ret)

    def ellweilcurve(self, E, ms=None):
        r'''
        If :math:`E'` is an elliptic curve over :math:`\mathbb{Q}`, let :math:`L_{E'}` be the
        sub-:math:`\mathbb{Z}`-module of :math:`\text{Hom}_{\Gamma_0(N)}(\Delta,\mathbb{Q})` attached to :math:`E'`
        (It is given by :math:`x[3]` if :math:`[M,x] = msfromell (E')`.)

        On the other hand, if :math:`N` is the conductor of :math:`E` and :math:`f` is the modular form
        for :math:`\Gamma_0(N)` attached to :math:`E`, let :math:`L_f` be the lattice of the
        :math:`f`-component of :math:`\text{Hom}_{\Gamma_0(N)}(\Delta,\mathbb{Q})` given by the elements
        :math:`\phi` such that :math:`\phi ({0,\gamma^{-1} 0}) \in \mathbb{Z}` for all
        :math:`\gamma \in \Gamma_0(N)` (see :literal:`mslattice`).

        Let :math:`E'` run through the isomorphism classes of elliptic curves
        isogenous to :math:`E` as given by :literal:`ellisomat` (and in the same order).
        This function returns a pair :literal:`[vE,vS]` where :literal:`vE` contains minimal
        models for the :math:`E'` and :literal:`vS` contains the list of Smith invariants for
        the lattices :math:`L_{E'}` in :math:`L_f`. The function also accepts the output of
        :literal:`ellisomat`, i.e. the isogeny class. If the optional argument :literal:`ms`
        is present, it contains the output of :literal:`msfromell(vE, 0)`, i.e. the new
        modular symbol space :math:`M` of level :math:`N` and a vector of triples :math:`[x^+,x^-, L]`
        attached to each curve :math:`E'`.

        In particular, the strong Weil curve amongst the curves isogenous to :math:`E`
        is the one whose Smith invariants are :math:`[c,c]`, where :math:`c` is the Manin
        constant, conjecturally equal to :math:`1`.

        ::

        ? E = ellinit("11a3");
        ? [vE, vS] = ellweilcurve(E);
        ? [n] = [ i | i<-[1..#vS], vS[i]==[1,1] ] \\ lattice with invariant [1,1]
        %3 = [2]
        ? ellidentify(vE[n]) \\ ... corresponds to strong Weil curve
        %4 = [["11a1", [0, -1, 1, -10, -20], []], [1, 0, 0, 0]]
        
        ? [vE, vS] = ellweilcurve(E, &ms); \\ vE,vS are as above
        ? [M, vx] = ms; msdim(M) \\ ... but ms contains more information
        %6 = 3
        ? #vx
        %7 = 3
        ? vx[1]
        %8 = [[1/25, -1/10, -1/10]~, [0, 1/2, -1/2]~, [1/25,0; -3/5,1; 2/5,-1]]
        ? forell(E, 11,11, print(msfromell(ellinit(E[1]), 1)[2]))
        [1/5, -1/2, -1/2]~
        [1, -5/2, -5/2]~
        [1/25, -1/10, -1/10]~

        The last example prints the modular symbols :math:`x^+` in :math:`M^+`
        attached to the curves :literal:`11a1`, :literal:`11a2` and :literal:`11a3`.
        '''
        E = objtogen(E)
        cdef bint _have_ms = (ms is not None)
        if _have_ms:
            raise NotImplementedError("optional argument ms not available")
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN * _ms = NULL
        cdef GEN _ret = ellweilcurve(_E, _ms)
        return new_gen(_ret)

    def ellweilpairing(self, E, P, Q, m):
        r'''
        Computes the Weil pairing of the two points of :math:`m`-torsion :math:`P` and :math:`Q`
        on the elliptic curve :math:`E`.
        '''
        E = objtogen(E)
        P = objtogen(P)
        Q = objtogen(Q)
        m = objtogen(m)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _m = (<Gen>m).g
        cdef GEN _ret = ellweilpairing(_E, _P, _Q, _m)
        return new_gen(_ret)

    def ellwp(self, w, z=None, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Computes the value at :math:`z` of the Weierstrass :math:`\wp` function attached to
        the lattice :math:`w` as given by :literal:`ellperiods`. It is also possible to
        directly input :math:`w = [\omega_1,\omega_2]`, or an elliptic curve :math:`E` as given
        by :literal:`ellinit` (:math:`w = E.omega`).

        ::

        ? w = ellperiods([1,I]);
        ? ellwp(w, 1/2)
        %2 = 6.8751858180203728274900957798105571978
        ? E = ellinit([1,1]);
        ? ellwp(E, 1/2)
        %4 = 3.9413112427016474646048282462709151389

        One can also compute the series expansion around :math:`z = 0`:

        ::

        ? E = ellinit([1,0]);
        ? ellwp(E) \\ 'x implicitly at default seriesprecision
        %5 = x^-2 - 1/5*x^2 + 1/75*x^6 - 2/4875*x^10 + O(x^14)
        ? ellwp(E, x + O(x^12)) \\ explicit precision
        %6 = x^-2 - 1/5*x^2 + 1/75*x^6 + O(x^9)

        Optional :emphasis:`flag` means 0 (default): compute only :math:`\wp (z)`, 1: compute
        :math:`[\wp (z),\wp'(z)]`.

        For instance, the Dickson elliptic functions :emphasis:`sm` and :emphasis:`sn` can be
        implemented as follows

        ::

        smcm(z) =
        { my(a, b, E = ellinit([0,-1/(4*27)])); \\ ell. invariants (g2,g3)=(0,1/27)
        [a,b] = ellwp(E, z, 1);
        [6*a / (1-3*b), (3*b+1)/(3*b-1)];
        }
        ? [s,c] = smcm(0.5);
        ? s
        %2 = 0.4898258757782682170733218609
        ? c
        %3 = 0.9591820206453842491187464098
        ? s^3+c^3
        %4 = 1.000000000000000000000000000
        ? smcm('x + O('x^11))
        %5 = [x - 1/6*x^4 + 2/63*x^7 - 13/2268*x^10 + O(x^11),
        1 - 1/3*x^3 + 1/18*x^6 - 23/2268*x^9 + O(x^10)]
        '''
        w = objtogen(w)
        cdef bint _have_z = (z is not None)
        if _have_z:
            z = objtogen(z)
        sig_on()
        cdef GEN _w = (<Gen>w).g
        cdef GEN _z = NULL
        if _have_z:
            _z = (<Gen>z).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ellwp0(_w, _z, flag, precision)
        return new_gen(_ret)

    def ellxn(self, E, long n, v=None):
        r'''
        In standard notation, for any affine point :math:`P = (v,w)` on the
        curve :math:`E`, we have

        .. MATH::

        [n]P = (\phi_n(P)\psi_n(P) : \omega_n(P) : \psi_n(P)^3)

        for some polynomials :math:`\phi_n,\omega_n,\psi_n` in
        :math:`\mathbb{Z}[a_1,a_2,a_3,a_4,a_6][v,w]`. This function returns
        :math:`[\phi_n(P),\psi_n(P)^2]`, which give the numerator and denominator of
        the abscissa of :math:`[n]P` and depend only on :math:`v`.

        ::

        ? E = ellinit([17,42]);
        ? T = ellxn(E, 2, 'X)
        %2 = [X^4 - 34*X^2 - 336*X + 289, 4*X^3 + 68*X + 168]
        ? P = [114,1218]; ellmul(E,P,2)
        %3 = [200257/7056, 90637343/592704]
        ? [x,y] = subst(T,'X,P[1]) \\ substitute P[1] in ellxn(E,2)
        %4 = [168416137, 5934096] \\ numerator and denominator of 2*P
        ? x/y \\ check we find ellmul(e,P,2)[1]
        %5 = 200257/7056
        '''
        E = objtogen(E)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = ellxn(_E, n, _v)
        return new_gen(_ret)

    def ellzeta(self, w, z=None, long precision=DEFAULT_BITPREC):
        r'''
        Computes the value at :math:`z` of the Weierstrass :math:`\zeta` function attached to
        the lattice :math:`w` as given by :literal:`ellperiods`:math:`(,1)`: including quasi-periods
        is useful, otherwise there are recomputed from scratch for each new :math:`z`.

        .. MATH::

        \zeta (z, L) = (1)/(z) + z^2\sum_{\omega\in L^*}
        (1)/(\omega^2(z-\omega)).

        It is also possible to directly input :math:`w = [\omega_1,\omega_2]`,
        or an elliptic curve :math:`E` as given by :literal:`ellinit` (:math:`w = E.omega`).
        The quasi-periods of :math:`\zeta`, such that

        .. MATH::

        \zeta (z + a\omega_1 + b\omega_2) = \zeta (z) + a\eta_1 + b\eta_2

        for integers :math:`a` and :math:`b` are obtained as :math:`\eta_i = 2\zeta (\omega_i/2)`.
        Or using directly :literal:`elleta`.

        ::

        ? w = ellperiods([1,I],1);
        ? ellzeta(w, 1/2)
        %2 = 1.5707963267948966192313216916397514421
        ? E = ellinit([1,0]);
        ? ellzeta(E, E.omega[1]/2)
        %4 = 0.84721308479397908660649912348219163647

        One can also compute the series expansion around :math:`z = 0`
        (the quasi-periods are useless in this case):

        ::

        ? E = ellinit([0,1]);
        ? ellzeta(E) \\ at 'x, implicitly at default seriesprecision
        %4 = x^-1 + 1/35*x^5 - 1/7007*x^11 + O(x^15)
        ? ellzeta(E, x + O(x^20)) \\ explicit precision
        %5 = x^-1 + 1/35*x^5 - 1/7007*x^11 + 1/1440257*x^17 + O(x^18)
        '''
        w = objtogen(w)
        cdef bint _have_z = (z is not None)
        if _have_z:
            z = objtogen(z)
        sig_on()
        cdef GEN _w = (<Gen>w).g
        cdef GEN _z = NULL
        if _have_z:
            _z = (<Gen>z).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ellzeta(_w, _z, precision)
        return new_gen(_ret)

    def ellztopoint(self, E, z, long precision=DEFAULT_BITPREC):
        r'''
        :math:`E` being an :emphasis:`ell` as output by
        :literal:`ellinit`, computes the coordinates :math:`[x,y]` on the curve :math:`E`
        corresponding to the complex or :math:`p`-adic parameter :math:`z`. Hence this is the
        inverse function of :literal:`ellpointtoz`.

        - If :math:`E` is defined over a :math:`p`-adic field and has multiplicative
        reduction, then :math:`z` is understood as an element on the
        Tate curve :math:`\bar{Q}_p^* / q^\mathbb{Z}`.

        ::

        ? E = ellinit([0,-1,1,0,0], O(11^5));
        ? [u2,u,q] = E.tate; type(u)
        %2 = "t_PADIC" \\ split multiplicative reduction
        ? z = ellpointtoz(E, [0,0])
        %3 = 3 + 11^2 + 2*11^3 + 3*11^4 + 6*11^5 + 10*11^6 + 8*11^7 + O(11^8)
        ? ellztopoint(E,z)
        %4 = [O(11^9), O(11^9)]
        
        ? E = ellinit(ellfromj(1/4), O(2^6)); x=1/2; y=ellordinate(E,x)[1];
        ? z = ellpointtoz(E,[x,y]); \\ non-split: t_POLMOD with t_PADIC coefficients
        ? P = ellztopoint(E, z);
        ? P[1] \\ y coordinate is analogous, more complicated
        %8 = Mod(O(2^4)*x + (2^-1 + O(2^5)), x^2 + (1 + 2^2 + 2^4 + 2^5 + O(2^7)))

        - If :math:`E` is defined over the complex numbers (for instance over :math:`\mathbb{Q}`),
        :math:`z` is understood as a complex number in :math:`\mathbb{C}/\Lambda_E`. If the
        short Weierstrass equation is :math:`y^2 = 4x^3 - g_2x - g_3`, then :math:`[x,y]`
        represents the Weierstrass :math:`\wp`-function
        and its derivative. For a general Weierstrass equation we have
        

        .. MATH::

        x = \wp (z) - b_2/12, y = \wp'(z)/2 - (a_1 x + a_3)/2.

        If :math:`z` is in the lattice defining :math:`E` over :math:`\mathbb{C}`, the result is the point at
        infinity :math:`[0]`.

        ::

        ? E = ellinit([0,1]); P = [2,3];
        ? z = ellpointtoz(E, P)
        %2 = 3.5054552633136356529375476976257353387
        ? ellwp(E, z)
        %3 = 2.0000000000000000000000000000000000000
        ? ellztopoint(E, z) - P
        %4 = [2.548947057811923643 E-57, 7.646841173435770930 E-57]
        ? ellztopoint(E, 0)
        %5 = [0] \\ point at infinity
        '''
        E = objtogen(E)
        z = objtogen(z)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _z = (<Gen>z).g
        precision = nbits2prec(precision)
        cdef GEN _ret = pointell(_E, _z, precision)
        return new_gen(_ret)

    def erfc(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Complementary error function, analytic continuation of
        :math:`(2/\sqrt\pi)\int_x^ oo e^{-t^2}dt = incgam (1/2,x^2)/\sqrt\pi`,
        where the latter expression extends the function definition from real :math:`x` to
        all complex :math:`x != 0`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gerfc(_x, precision)
        return new_gen(_ret)

    def errname(self, E):
        r'''
        Returns the type of the error message :literal:`E` as a string.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = errname(_E)
        return new_gen(_ret)

    def eta(self, z, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Variants of Dedekind's :math:`\eta` function.
        If :math:`flag = 0`, return :math:`\prod_{n = 1}^ oo (1-q^n)`, where :math:`q` depends on :math:`x`
        in the following way:

        - :math:`q = e^{2i\pi x}` if :math:`x` is a :emphasis:`complex number` (which must then
        have positive imaginary part); notice that the factor :math:`q^{1/24}` is
        missing!

        - :math:`q = x` if :math:`x` is a :literal:`t_PADIC`, or can be converted to a
        :emphasis:`power series` (which must then have positive valuation).

        If :math:`flag` is non-zero, :math:`x` is converted to a complex number and we return the
        true :math:`\eta` function, :math:`q^{1/24}\prod_{n = 1}^ oo (1-q^n)`,
        where :math:`q = e^{2i\pi x}`.
        '''
        z = objtogen(z)
        sig_on()
        cdef GEN _z = (<Gen>z).g
        precision = nbits2prec(precision)
        cdef GEN _ret = eta0(_z, flag, precision)
        return new_gen(_ret)

    def eulerphi(self, x):
        r'''
        Euler's :math:`\phi` (totient) function of the
        integer :math:`\|x\|`, in other words :math:`\|(\mathbb{Z}/x\mathbb{Z})^*\|`.

        ::

        ? eulerphi(40)
        %1 = 16

        According to this definition we let :math:`\phi (0) := 2`, since :math:`\mathbb{Z}^ *= {-1,1}`;
        this is consistent with :literal:`znstar(0)`: we have
        :literal:`znstar:math:`(n)`.no = eulerphi(n)` for all :math:`n\in\mathbb{Z}`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = eulerphi(_x)
        return new_gen(_ret)

    def exp(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Exponential of :math:`x`.
        :math:`p`-adic arguments with positive valuation are accepted.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gexp(_x, precision)
        return new_gen(_ret)

    def expm1(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Return :math:`\exp (x)-1`, computed in a way that is also accurate
        when the real part of :math:`x` is near :math:`0`.
        A naive direct computation would suffer from catastrophic cancellation;
        PARI's direct computation of :math:`\exp (x)` alleviates this well known problem at
        the expense of computing :math:`\exp (x)` to a higher accuracy when :math:`x` is small.
        Using :literal:`expm1` is recommended instead:

        ::

        ? default(realprecision, 10000); x = 1e-100;
        ? a = expm1(x);
        time = 4 ms.
        ? b = exp(x)-1;
        time = 4 ms.
        ? default(realprecision, 10040); x = 1e-100;
        ? c = expm1(x); \\ reference point
        ? abs(a-c)/c \\ relative error in expm1(x)
        %7 = 1.4027986153764843997 E-10019
        ? abs(b-c)/c \\ relative error in exp(x)-1
        %8 = 1.7907031188259675794 E-9919

        As the example above shows, when :math:`x` is near :math:`0`,
        :literal:`expm1` is more accurate than :literal:`exp(x)-1`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gexpm1(_x, precision)
        return new_gen(_ret)

    def exponent(self, x):
        r'''
        When :math:`x` is a :literal:`t_REAL`, the result is the binary exponent :math:`e` of :math:`x`.
        For a non-zero :math:`x`, this is the unique integer :math:`e` such that
        :math:`2^e <= \|x\| < 2^{e+1}`. For a real :math:`0`, this returns the PARI exponent :math:`e`
        attached to :math:`x` (which may represent any floating-point number less than
        :math:`2^e` in absolute value).

        ::

        ? exponent(Pi)
        %1 = 1
        ? exponent(4.0)
        %2 = 2
        ? exponent(0.0)
        %3 = -128
        ? default(realbitprecision)
        %4 = 128

        This definition extends naturally to non-zero integers,
        and the exponent of an exact :math:`0` is :math:`-oo` by convention.

        For convenience, we :emphasis:`define` the exponent of a :literal:`t_FRAC` :math:`a/b` as
        the difference of :literal:`exponent`:math:`(a)` and :literal:`exponent`:math:`(b)`; note that,
        if :math:`e'` denotes the exponent of :literal:`:math:`a/b` * 1.0`, then the exponent :math:`e`
        we return is either :math:`e'` or :math:`e'+1`, thus :math:`2^{e+1}` is an upper bound for
        :math:`\|a/b\|`.

        ::

        ? [ exponent(9), exponent(10), exponent(9/10), exponent(9/10*1.) ]
        %5 = [3, 3, 0, -1]

        For a PARI object of type :literal:`t_COMPLEX`, :literal:`t_POL`, :literal:`t_SER`, :literal:`t_VEC`,
        :literal:`t_COL`, :literal:`t_MAT` this returns the largest exponent found among the
        components of :math:`x`. Hence :math:`2^{e+1}` is a quick upper bound for the sup norm
        of real matrices or polynomials; and :math:`2^{e+(3/2)}` for complex ones.

        ::

        ? exponent(3*x^2 + 15*x - 100)
        %5 = 6
        ? exponent(0)
        %6 = -oo
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gpexponent(_x)
        return new_gen(_ret)

    def extern(self, str):
        r'''
        The string :emphasis:`str` is the name of an external command (i.e. one you
        would type from your UNIX shell prompt). This command is immediately run and
        its output fed into :literal:`gp`, just as if read from a file.
        '''
        str = to_bytes(str)
        cdef char* _str = <bytes>str
        sig_on()
        cdef GEN _ret = gpextern(_str)
        return new_gen(_ret)

    def externstr(self, str):
        r'''
        The string :emphasis:`str` is the name of an external command (i.e. one you
        would type from your UNIX shell prompt). This command is immediately run and
        its output is returned as a vector of GP strings, one component per output
        line.
        '''
        str = to_bytes(str)
        cdef char* _str = <bytes>str
        sig_on()
        cdef GEN _ret = externstr(_str)
        return new_gen(_ret)

    def factor(self, x, D=None):
        r'''
        Factor :math:`x` over domain :math:`D`; if :math:`D` is omitted, it is determined from :math:`x`.
        For instance, if :math:`x` is an integer, it is factored in :math:`\mathbb{Z}`, if it is a
        polynomial with rational coefficients, it is factored in :math:`\mathbb{Q}[x]`, etc., see
        below for details. The result is a two-column matrix: the first contains the
        irreducibles dividing :math:`x` (rational or Gaussian primes, irreducible
        polynomials), and the second the exponents. By convention, :math:`0` is factored
        as :math:`0^1`.

        :strong:`:math:`x \in \mathbb{Q}`.`
        See :literal:`factorint` for the algorithms used. The factorization includes the
        unit :math:`-1` when :math:`x < 0` and all other factors are positive; a denominator is
        factored with negative exponents. The factors are sorted in increasing order.

        ::

        ? factor(-7/106)
        %1 =
        [-1 1]
        
        [ 2 -1]
        
        [ 7 1]
        
        [53 -1]

        By convention, :math:`1` is factored as :literal:`matrix(0,2)`
        (the empty factorization, printed as :literal:`[;]`).

        Large rational "primes" :math:`> 2^{64}` in the factorization are in fact
        :emphasis:`pseudoprimes` (see :literal:`ispseudoprime`), a priori not rigorously proven
        primes. Use :literal:`isprime` to prove primality of these factors, as in

        ::

        ? fa = factor(2^2^7 + 1)
        %1 =
        [59649589127497217 1]
        
        [5704689200685129054721 1]
        
        ? isprime( fa[,1] )
        %2 = [1, 1]~ \\ both entries are proven primes

        Another possibility is to globally set the default :literal:`factor_proven`, which
        will perform a rigorous primality proof for each pseudoprime factor but will
        slow down PARI.

        A :literal:`t_INT` argument :math:`D` can be added, meaning that we look only for
        prime factors :math:`p < D`. The limit :math:`D` must be non-negative.
        In this case, all but the last factor are proven primes, but the remaining
        factor may actually be a proven composite! If the remaining factor is less
        than :math:`D^2`, then it is prime.

        ::

        ? factor(2^2^7 +1, 10^5)
        %3 =
        [340282366920938463463374607431768211457 1]

        :strong:`Deprecated feature.` Setting :math:`D = 0` is the same
        as setting it to :math:`primelimit + 1`.

        This routine uses trial division and perfect power tests, and should not be
        used for huge values of :math:`D` (at most :math:`10^9`, say):
        :literal:`factorint(, 1 + 8)` will in general be faster. The latter does not
        guarantee that all small prime factors are found, but it also finds larger
        factors and in a more efficient way.

        ::

        ? F = (2^2^7 + 1) * 1009 * (10^5+3); factor(F, 10^5) \\ fast, incomplete
        time = 0 ms.
        %4 =
        [1009 1]
        
        [34029257539194609161727850866999116450334371 1]
        
        ? factor(F, 10^9) \\ slow
        time = 3,260 ms.
        %6 =
        [1009 1]
        
        [100003 1]
        
        [340282366920938463463374607431768211457 1]
        
        ? factorint(F, 1+8) \\ much faster and all small primes were found
        time = 8 ms.
        %7 =
        [1009 1]
        
        [100003 1]
        
        [340282366920938463463374607431768211457 1]
        
        ? factor(F) \\ complete factorization
        time = 60 ms.
        %8 =
        [1009 1]
        
        [100003 1]
        
        [59649589127497217 1]
        
        [5704689200685129054721 1]

        Setting :math:`D = I` will factor in the Gaussian integers
        :math:`\mathbb{Z}[i]`:

        :strong:`:math:`x \in \mathbb{Q} (i)`.` The factorization is performed with Gaussian
        primes in :math:`\mathbb{Z}[i]` and includes Gaussian units in :math:`{±1, ± i}`;
        factors are sorted by increasing norm. Except for a possible leading unit,
        the Gaussian factors are normalized: rational factors are positive and
        irrational factors have positive imaginary part (a canonical represneta.

        Unless :literal:`factor_proven` is set, large factors are actually pseudoprimes,
        not proven primes; a rational factor is prime if less than :math:`2^{64}` and an
        irrational one if its norm is less than :math:`2^{64}`.

        ::

        ? factor(5*I)
        %1 =
        [ 2 + I 1]
        
        [1 + 2*I 1]

        One can force the factorization of a rational number
        by setting the domain :math:`D = I`:

        ::

        ? factor(-5, I)
        %2 =
        [ I 1]
        
        [ 2 + I 1]
        
        [1 + 2*I 1]
        ? factorback(%)
        %3 = -5

        :strong:`Univariate polynomials and rational functions.`
        PARI can factor univariate polynomials in :math:`K[t]`. The following base fields
        :math:`K` are currently supported: :math:`\mathbb{Q}`, :math:`\mathbb{R}`, :math:`\mathbb{C}`, :math:`\mathbb{Q}_p`, finite fields and
        number fields. See :literal:`factormod` and :literal:`factorff` for the algorithms used
        over finite fields and :literal:`nffactor` for the algorithms over number fields.
        The irreducible factors are sorted by increasing degree and normalized: they
        are monic except when :math:`K = \mathbb{Q}` where they are primitive in :math:`\mathbb{Z}[t]`.

        The content is :emphasis:`not` included in the factorization, in particular
        :literal:`factorback` will in general recover the original :math:`x` only up to
        multiplication by an element of :math:`K^*`: when :math:`K != \mathbb{Q}`, this scalar is
        :literal:`pollead`:math:`(x)` (since irreducible factors are monic); and when :math:`K = \mathbb{Q}`
        you can either ask for the :math:`\mathbb{Q}`-content explicitly of use factorback:

        ::

        ? P = t^2 + 5*t/2 + 1; F = factor(P)
        %1 =
        [t + 2 1]
        
        [2*t + 1 1]
        
        ? content(P, 1) \\ Q-content
        %2 = 1/2
        
        ? pollead(factorback(F)) / pollead(P)
        %3 = 2

        You can specify :math:`K` using the optional "domain" argument :math:`D` as follows

        - :math:`K = \mathbb{Q}` : :math:`D` a rational number (:literal:`t_INT` or :literal:`t_FRAC`),

        - :math:`K = \mathbb{Z}/p\mathbb{Z}` with :math:`p` prime : :math:`D` a :literal:`t_INTMOD` modulo :math:`p`;
        factoring modulo a non-prime number is not supported.

        - :math:`K = \mathbb{F}_q` : :math:`D` a :literal:`t_FFELT` encoding the finite field; you can also
        use a :literal:`t_POLMOD` of :literal:`t_INTMOD` modulo a prime :math:`p` but this is usualy
        less convenient;

        - :math:`K = \mathbb{Q}[X]/(T)` a number field : :math:`D` a :literal:`t_POLMOD` modulo :math:`T`,

        - :math:`K = \mathbb{Q} (i)` (alternate syntax for special case): :math:`D = I`,

        - :math:`K = \mathbb{Q} (w)` a quadratic number field (alternate syntax for special
        case): :math:`D` a :literal:`t_QUAD`,

        - :math:`K = \mathbb{R}` : :math:`D` a real number (:literal:`t_REAL`); truncate the factorization
        at accuracy :literal:`precision`:math:`(D)`. If :math:`x` is inexact and :literal:`precision`:math:`(x)`
        is less than :literal:`precision`:math:`(D)`, then the precision of :math:`x` is used instead.

        - :math:`K = \mathbb{C}` : :math:`D` a complex number with a :literal:`t_REAL` component, e.g.
        :literal:`I * 1.`; truncate the factorization as for :math:`K = \mathbb{R}`,

        - :math:`K = \mathbb{Q}_p` : :math:`D` a :literal:`t_PADIC`; truncate the factorization at
        :math:`p`-adic accuracy :literal:`padicprec`:math:`(D)`, possibly less if :math:`x` is inexact
        with insufficient :math:`p`-adic accuracy;

        ::

        ? T = x^2+1;
        ? factor(T, 1); \\ over Q
        ? factor(T, Mod(1,3)) \\ over F_3
        ? factor(T, ffgen(ffinit(3,2,'t))^0) \\ over F_{3^2}
        ? factor(T, Mod(Mod(1,3), t^2+t+2)) \\ over F_{3^2}, again
        ? factor(T, O(3^6)) \\ over Q_3, precision 6
        ? factor(T, 1.) \\ over R, current precision
        ? factor(T, I*1.) \\ over C
        ? factor(T, Mod(1, y^3-2)) \\ over Q(2^{1/3})

        In most cases, it is possible and simpler to call a
        specialized variant rather than use the above scheme:

        ::

        ? factormod(T, 3) \\ over F_3
        ? factormod(T, [t^2+t+2, 3]) \\ over F_{3^2}
        ? factormod(T, ffgen(3^2, 't)) \\ over F_{3^2}
        ? factorpadic(T, 3,6) \\ over Q_3, precision 6
        ? nffactor(y^3-2, T) \\ over Q(2^{1/3})
        ? polroots(T) \\ over C
        ? polrootsreal(T) \\ over R (real polynomial)

        It is also possible to let the routine use the smallest field containing all
        coefficients, taking into account quotient structures induced by
        :literal:`t_INTMOD` s and :literal:`t_POLMOD` s (e.g. if a coefficient in :math:`\mathbb{Z}/n\mathbb{Z}` is known,
        all rational numbers encountered are first mapped to :math:`\mathbb{Z}/n\mathbb{Z}`; different
        moduli will produce an error):

        ::

        ? T = x^2+1;
        ? factor(T); \\ over Q
        ? factor(T*Mod(1,3)) \\ over F_3
        ? factor(T*ffgen(ffinit(3,2,'t))^0) \\ over F_{3^2}
        ? factor(T*Mod(Mod(1,3), t^2+t+2)) \\ over F_{3^2}, again
        ? factor(T*(1 + O(3^6)) \\ over Q_3, precision 6
        ? factor(T*1.) \\ over R, current precision
        ? factor(T*(1.+0.*I)) \\ over C
        ? factor(T*Mod(1, y^3-2)) \\ over Q(2^{1/3})

        Multiplying by a suitable field element equal to :math:`1 \in K`
        in this way is error-prone and is not recommanded. Factoring existing
        polynomials with obvious fields of coefficients is fine, the domain
        argument :math:`D` should be used instead ad hoc conversions.

        :strong:`Note on inexact polynomials.`
        Polynomials with inexact coefficients
        (e.g. floating point or :math:`p`-adic numbers)
        are first rounded to an exact representation, then factored to (potentially)
        infinite accuracy and we return a truncated approximation of that
        virtual factorization. To avoid pitfalls, we advise to only factor
        :emphasis:`exact` polynomials:

        ::

        ? factor(x^2-1+O(2^2)) \\ rounded to x^2 + 3, irreducible in Q_2
        %1 =
        [(1 + O(2^2))*x^2 + O(2^2)*x + (1 + 2 + O(2^2)) 1]
        
        ? factor(x^2-1+O(2^3)) \\ rounded to x^2 + 7, reducible !
        %2 =
        [ (1 + O(2^3))*x + (1 + 2 + O(2^3)) 1]
        
        [(1 + O(2^3))*x + (1 + 2^2 + O(2^3)) 1]
        
        ? factor(x^2-1, O(2^2)) \\ no ambiguity now
        %3 =
        [ (1 + O(2^2))*x + (1 + O(2^2)) 1]
        
        [(1 + O(2^2))*x + (1 + 2 + O(2^2)) 1]

        :strong:`Note about inseparable polynomials.` Polynomials with inexact
        coefficients are considered to be squarefree: indeed, there exist a
        squarefree polynomial arbitrarily close to the input, and they cannot be
        distinguished at the input accuracy. This means that irreducible factors are
        repeated according to their apparent multiplicity. On the contrary, using a
        specialized function such as :literal:`factorpadic` with an :emphasis:`exact` rational
        input yields the correct multiplicity when the (now exact) input is not
        separable. Compare:

        ::

        ? factor(z^2 + O(5^2)))
        %1 =
        [(1 + O(5^2))*z + O(5^2) 1]
        
        [(1 + O(5^2))*z + O(5^2) 1]
        ? factor(z^2, O(5^2))
        %2 =
        [1 + O(5^2))*z + O(5^2) 2]

        :strong:`Multivariate polynomials and rational functions.`
        PARI recursively factors :emphasis:`multivariate` polynomials in
        :math:`K[t_1,..., t_d]` for the same fields :math:`K` as above and the argument :math:`D`
        is used in the same way to specify :math:`K`. The irreducible factors are sorted
        by their main variable (least priority first) then by increasing degree.

        ::

        ? factor(x^2 + y^2, Mod(1,5))
        %1 =
        [ x + Mod(2, 5)*y 1]
        
        [Mod(1, 5)*x + Mod(3, 5)*y 1]
        
        ? factor(x^2 + y^2, O(5^2))
        %2 =
        [ (1 + O(5^2))*x + (O(5^2)*y^2 + (2 + 5 + O(5^2))*y + O(5^2)) 1]
        
        [(1 + O(5^2))*x + (O(5^2)*y^2 + (3 + 3*5 + O(5^2))*y + O(5^2)) 1]
        
        ? lift(%)
        %3 =
        [ x + 7*y 1]
        
        [x + 18*y 1]

        Note that the implementation does not really support inexact
        real fields (:math:`\mathbb{R}` or :math:`\mathbb{C}`) and usually misses factors even if the input
        is exact:

        ::

        ? factor(x^2 + y^2, I) \\ over Q(i)
        %4 =
        [x - I*y 1]
        
        [x + I*y 1]
        
        ? factor(x^2 + y^2, I*1.) \\ over C
        %5 =
        [x^2 + y^2 1]
        '''
        x = objtogen(x)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = factor0(_x, _D)
        return new_gen(_ret)

    def factorback(self, f, e=None):
        r'''
        Gives back the factored object corresponding to a factorization. The
        integer :math:`1` corresponds to the empty factorization.

        If :math:`e` is present, :math:`e` and :math:`f` must be vectors of the same length (:math:`e` being
        integral), and the corresponding factorization is the product of the
        :math:`f[i]^{e[i]}`.

        If not, and :math:`f` is vector, it is understood as in the preceding case with :math:`e`
        a vector of 1s: we return the product of the :math:`f[i]`. Finally, :math:`f` can be a
        regular factorization, as produced with any :literal:`factor` command. A few
        examples:

        ::

        ? factor(12)
        %1 =
        [2 2]
        
        [3 1]
        
        ? factorback(%)
        %2 = 12
        ? factorback([2,3], [2,1]) \\ 2^3 * 3^1
        %3 = 12
        ? factorback([5,2,3])
        %4 = 30
        '''
        f = objtogen(f)
        cdef bint _have_e = (e is not None)
        if _have_e:
            e = objtogen(e)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _e = NULL
        if _have_e:
            _e = (<Gen>e).g
        cdef GEN _ret = factorback2(_f, _e)
        return new_gen(_ret)

    def factorcantor(self, x, p):
        r'''
        This function is obsolete, use factormod.
        '''
        from warnings import warn
        warn('the PARI/GP function factorcantor is obsolete (2018-02-28)', DeprecationWarning)
        x = objtogen(x)
        p = objtogen(p)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = factmod(_x, _p)
        return new_gen(_ret)

    def factorff(self, x, p=None, a=None):
        r'''
        Obsolete, kept for backward compatibility: use factormod.
        '''
        from warnings import warn
        warn('the PARI/GP function factorff is obsolete (2018-03-11)', DeprecationWarning)
        x = objtogen(x)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        cdef bint _have_a = (a is not None)
        if _have_a:
            a = objtogen(a)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _a = NULL
        if _have_a:
            _a = (<Gen>a).g
        cdef GEN _ret = factorff(_x, _p, _a)
        return new_gen(_ret)

    def factorial(self, long x, long precision=DEFAULT_BITPREC):
        r'''
        Factorial of :math:`x`. The expression :math:`x!` gives a result which is an integer,
        while :math:`factorial (x)` gives a real number.
        '''
        sig_on()
        precision = nbits2prec(precision)
        cdef GEN _ret = mpfactr(x, precision)
        return new_gen(_ret)

    def factorint(self, x, long flag=0):
        r'''
        Factors the integer :math:`n` into a product of
        pseudoprimes (see :literal:`ispseudoprime`), using a combination of the
        Shanks SQUFOF and Pollard Rho method (with modifications due to
        Brent), Lenstra's ECM (with modifications by Montgomery), and
        MPQS (the latter adapted from the LiDIA code with the kind
        permission of the LiDIA maintainers), as well as a search for pure powers.
        The output is a two-column matrix as for :literal:`factor`: the first column
        contains the "prime" divisors of :math:`n`, the second one contains the
        (positive) exponents.

        By convention :math:`0` is factored as :math:`0^1`, and :math:`1` as the empty factorization;
        also the divisors are by default not proven primes if they are larger than
        :math:`2^{64}`, they only failed the BPSW compositeness test (see
        :literal:`ispseudoprime`). Use :literal:`isprime` on the result if you want to
        guarantee primality or set the :literal:`factor_proven` default to :math:`1`.
        Entries of the private prime tables (see :literal:`addprimes`) are also included
        as is.

        This gives direct access to the integer factoring engine called by most
        arithmetical functions. :emphasis:`flag` is optional; its binary digits mean 1: avoid
        MPQS, 2: skip first stage ECM (we may still fall back to it later), 4: avoid
        Rho and SQUFOF, 8: don't run final ECM (as a result, a huge composite may be
        declared to be prime). Note that a (strong) probabilistic primality test is
        used; thus composites might not be detected, although no example is known.

        You are invited to play with the flag settings and watch the internals at
        work by using :literal:`gp`'s :literal:`debug` default parameter (level 3 shows
        just the outline, 4 turns on time keeping, 5 and above show an increasing
        amount of internal details).
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = factorint(_x, flag)
        return new_gen(_ret)

    def factormod(self, f, D=None, long flag=0):
        r'''
        Factors the polynomial :math:`f` over the finite field defined by the domain
        :math:`D` as follows:

        - :math:`D = p` a prime: factor over :math:`\mathbb{F}_p`;

        - :math:`D = [T,p]` for a prime :math:`p` and :math:`T` an irreducible polynomial over
        :math:`\mathbb{F}_p`: factor over :math:`\mathbb{F}_p[x]/(T)`;

        - :math:`D` a :literal:`t_FFELT`: factor over the attached field;

        - :math:`D` omitted: factor over the field of definition of :math:`f`, which
        must be a finite field.

        The coefficients of :math:`f` must be operation-compatible with the corresponding
        finite field. The result is a two-column matrix, the first column being the
        irreducible polynomials dividing :math:`f`, and the second the exponents.
        By convention, the :math:`0` polynomial factors as :math:`0^1`; a non-zero constant
        polynomial has empty factorization, a :math:`0 x 2` matrix. The irreducible
        factors are ordered by increasing degree and the result is canonical: it will
        not change across multiple calls or sessions.

        ::

        ? factormod(x^2 + 1, 3) \\ over F_3
        %1 =
        [Mod(1, 3)*x^2 + Mod(1, 3) 1]
        ? liftall( factormod(x^2 + 1, [3, t^2+1]) ) \\ over F_9
        %2 =
        [ x + t 1]
        
        [x + 2*t 1]
        ? t = ffgen(t^2+Mod(1,3)); factormod(x^2 + t^0) \\ same using t_FFELT
        %3 =
        [ x + t 1]
        
        [x + 2*t 1]
        ? factormod(x^2+Mod(1,3))
        %4 =
        [Mod(1, 3)*x^2 + Mod(1, 3) 1]
        ? liftall( factormod(x^2 + Mod(Mod(1,3),y^2+1)) )
        %5 =
        [ x + y 1]
        
        [x + 2*y 1]

        If :math:`flag` is non-zero, outputs only the :emphasis:`degrees` of the irreducible
        polynomials (for example to compute an :math:`L`-function). By convention, a
        constant polynomial (including the :math:`0` polynomial) has empty factorization.
        The degrees appear in increasing order but need not correspond to the
        ordering with :math:`flag = 0` when multiplicities are present.

        ::

        ? f = x^3 + 2*x^2 + x + 2;
        ? factormod(f, 5) \\ (x+2)^2 * (x+3)
        %1 =
        [Mod(1, 5)*x + Mod(2, 5) 2]
        
        [Mod(1, 5)*x + Mod(3, 5) 1]
        ? factormod(f, 5, 1) \\ (deg 1) * (deg 1)^2
        %2 =
        [1 1]
        
        [1 2]
        '''
        f = objtogen(f)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = factormod0(_f, _D, flag)
        return new_gen(_ret)

    def factormodDDF(self, f, D=None):
        r'''
        Distinct-degree factorization of the squarefree polynomial :math:`f` over the
        finite field defined by the domain :math:`D` as follows:

        - :math:`D = p` a prime: factor over :math:`\mathbb{F}_p`;

        - :math:`D = [T,p]` for a prime :math:`p` and :math:`T` an irreducible polynomial over
        :math:`\mathbb{F}_p`: factor over :math:`\mathbb{F}_p[x]/(T)`;

        - :math:`D` a :literal:`t_FFELT`: factor over the attached field;

        - :math:`D` omitted: factor over the field of definition of :math:`f`, which
        must be a finite field.

        This is somewhat faster than full factorization. The coefficients of :math:`f`
        must be operation-compatible with the corresponding finite field. The result
        is a two-column matrix:

        - the first column contains monic (squarefree) pairwise coprime polynomials
        dividing :math:`f`, all of whose irreducible factors have degree :math:`d`;

        - the second column contains the degrees of the irreducible factors.

        The factors are ordered by increasing degree and the result is canonical: it
        will not change across multiple calls or sessions.

        ::

        ? f = (x^2 + 1) * (x^2-1);
        ? factormodSQF(f,3) \\ squarefree over F_3
        %2 =
        [Mod(1, 3)*x^4 + Mod(2, 3) 1]
        
        ? factormodDDF(f, 3)
        %3 =
        [Mod(1, 3)*x^2 + Mod(2, 3) 1] \\ two degree 1 factors
        
        [Mod(1, 3)*x^2 + Mod(1, 3) 2] \\ irred of degree 2
        
        ? for(i=1,10^5,factormodDDF(f,3))
        time = 424 ms.
        ? for(i=1,10^5,factormod(f,3)) \\ full factorization is slower
        time = 464 ms.
        
        ? liftall( factormodDDF(x^2 + 1, [3, t^2+1]) ) \\ over F_9
        %6 =
        [x^2 + 1 1] \\ product of two degree 1 factors
        
        ? t = ffgen(t^2+Mod(1,3)); factormodDDF(x^2 + t^0) \\ same using t_FFELT
        %7 =
        [x^2 + 1 1]
        
        ? factormodDDF(x^2-Mod(1,3))
        %8 =
        [Mod(1, 3)*x^2 + Mod(2, 3) 1]
        '''
        f = objtogen(f)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = factormodDDF(_f, _D)
        return new_gen(_ret)

    def factormodSQF(self, f, D=None):
        r'''
        Squarefree factorization of the polynomial :math:`f` over the finite field
        defined by the domain :math:`D` as follows:

        - :math:`D = p` a prime: factor over :math:`\mathbb{F}_p`;

        - :math:`D = [T,p]` for a prime :math:`p` and :math:`T` an irreducible polynomial over
        :math:`\mathbb{F}_p`: factor over :math:`\mathbb{F}_p[x]/(T)`;

        - :math:`D` a :literal:`t_FFELT`: factor over the attached field;

        - :math:`D` omitted: factor over the field of definition of :math:`f`, which
        must be a finite field.

        This is somewhat faster than full factorization. The coefficients of :math:`f`
        must be operation-compatible with the corresponding finite field. The result
        is a two-column matrix:

        - the first column contains monic squarefree pairwise coprime polynomials
        dividing :math:`f`;

        - the second column contains the power to which the polynomial in column
        :math:`1` divides :math:`f`;

        The factors are ordered by increasing degree and the result is canonical: it
        will not change across multiple calls or sessions.

        ::

        ? f = (x^2 + 1)^3 * (x^2-1)^2;
        ? factormodSQF(f, 3) \\ over F_3
        %1 =
        [Mod(1, 3)*x^2 + Mod(2, 3) 2]
        
        [Mod(1, 3)*x^2 + Mod(1, 3) 3]
        
        ? for(i=1,10^5,factormodSQF(f,3))
        time = 192 ms.
        ? for(i=1,10^5,factormod(f,3)) \\ full factorization is slower
        time = 409 ms.
        
        ? liftall( factormodSQF((x^2 + 1)^3, [3, t^2+1]) ) \\ over F_9
        %4 =
        [x^2 + 1 3]
        
        ? t = ffgen(t^2+Mod(1,3)); factormodSQF((x^2 + t^0)^3) \\ same using t_FFELT
        %5 =
        [x^2 + 1 3]
        
        ? factormodSQF(x^8 + x^7 + x^6 + x^2 + x + Mod(1,2))
        %6 =
        [ Mod(1, 2)*x + Mod(1, 2) 2]
        
        [Mod(1, 2)*x^2 + Mod(1, 2)*x + Mod(1, 2) 3]
        '''
        f = objtogen(f)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = factormodSQF(_f, _D)
        return new_gen(_ret)

    def factornf(self, x, t):
        r'''
        This function is obsolete, use :literal:`nffactor`.

        factorization of the univariate polynomial :math:`x`
        over the number field defined by the (univariate) polynomial :math:`t`. :math:`x` may
        have coefficients in :math:`\mathbb{Q}` or in the number field. The algorithm reduces to
        factorization over :math:`\mathbb{Q}` (Trager's trick). The direct approach of
        :literal:`nffactor`, which uses van Hoeij's method in a relative setting, is
        in general faster.

        The main variable of :math:`t` must be of :emphasis:`lower` priority than that of :math:`x`
        (see ``priority`` (in the PARI manual)). However if non-rational number field elements
        occur (as polmods or polynomials) as coefficients of :math:`x`, the variable of
        these polmods :emphasis:`must` be the same as the main variable of :math:`t`. For
        example

        ::

        ? factornf(x^2 + Mod(y, y^2+1), y^2+1);
        ? factornf(x^2 + y, y^2+1); \\ these two are OK
        ? factornf(x^2 + Mod(z,z^2+1), y^2+1)
        *** at top-level: factornf(x^2+Mod(z,z
        *** ^--------------------
        *** factornf: inconsistent data in rnf function.
        ? factornf(x^2 + z, y^2+1)
        *** at top-level: factornf(x^2+z,y^2+1
        *** ^--------------------
        *** factornf: incorrect variable in rnf function.
        '''
        from warnings import warn
        warn('the PARI/GP function factornf is obsolete (2016-08-08)', DeprecationWarning)
        x = objtogen(x)
        t = objtogen(t)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _t = (<Gen>t).g
        cdef GEN _ret = polfnf(_x, _t)
        return new_gen(_ret)

    def factorpadic(self, pol, p, long r):
        r'''
        :math:`p`-adic factorization
        of the polynomial :emphasis:`pol` to precision :math:`r`, the result being a
        two-column matrix as in :literal:`factor`. Note that this is not the same
        as a factorization over :math:`\mathbb{Z}/p^r\mathbb{Z}` (polynomials over that ring do not form a
        unique factorization domain, anyway), but approximations in :math:`\mathbb{Q}/p^r\mathbb{Z}` of
        the true factorization in :math:`\mathbb{Q}_p[X]`.

        ::

        ? factorpadic(x^2 + 9, 3,5)
        %1 =
        [(1 + O(3^5))*x^2 + O(3^5)*x + (3^2 + O(3^5)) 1]
        ? factorpadic(x^2 + 1, 5,3)
        %2 =
        [ (1 + O(5^3))*x + (2 + 5 + 2*5^2 + O(5^3)) 1]
        
        [(1 + O(5^3))*x + (3 + 3*5 + 2*5^2 + O(5^3)) 1]

        The factors are normalized so that their leading coefficient is a power of
        :math:`p`. The method used is a modified version of the round 4 algorithm of
        Zassenhaus.

        If :emphasis:`pol` has inexact :literal:`t_PADIC` coefficients, this is not always
        well-defined; in this case, the polynomial is first made integral by dividing
        out the :math:`p`-adic content, then lifted to :math:`\mathbb{Z}` using :literal:`truncate`
        coefficientwise.
        Hence we actually factor exactly a polynomial which is only :math:`p`-adically
        close to the input. To avoid pitfalls, we advise to only factor polynomials
        with exact rational coefficients.
        '''
        pol = objtogen(pol)
        p = objtogen(p)
        sig_on()
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = factorpadic(_pol, _p, r)
        return new_gen(_ret)

    def ffcompomap(self, f, g):
        r'''
        Let :math:`k`, :math:`l`, :math:`m` be three finite fields and :math:`f` a (partial) map from :math:`l`
        to :math:`m` and :math:`g` a (partial) map from :math:`k` to :math:`l`, return the (partial) map :math:`f
        o g` from :math:`k` to :math:`m`.

        ::

        a = ffgen([3,5],'a); b = ffgen([3,10],'b); c = ffgen([3,20],'c);
        m = ffembed(a, b); n = ffembed(b, c);
        rm = ffinvmap(m); rn = ffinvmap(n);
        nm = ffcompomap(n,m);
        ffmap(n,ffmap(m,a)) == ffmap(nm, a)
        %5 = 1
        ffcompomap(rm, rn) == ffinvmap(nm)
        %6 = 1
        '''
        f = objtogen(f)
        g = objtogen(g)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _g = (<Gen>g).g
        cdef GEN _ret = ffcompomap(_f, _g)
        return new_gen(_ret)

    def ffembed(self, a, b):
        r'''
        Given two finite fields elements :math:`a` and :math:`b`, return a :emphasis:`map`
        embedding the definition field of :math:`a` to the definition field of :math:`b`.
        Assume that the latter contains the former.

        ::

        ? a = ffgen([3,5],'a);
        ? b = ffgen([3,10],'b);
        ? m = ffembed(a, b);
        ? A = ffmap(m, a);
        ? minpoly(A) == minpoly(a)
        %5 = 1
        '''
        a = objtogen(a)
        b = objtogen(b)
        sig_on()
        cdef GEN _a = (<Gen>a).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _ret = ffembed(_a, _b)
        return new_gen(_ret)

    def ffextend(self, a, P, v=None):
        r'''
        Extend the field :math:`K` of definition of :math:`a` by a root of the polynomial
        :math:`P\in K[X]` assumed to be irreducible over :math:`K`. Return :math:`[r, m]` where :math:`r`
        is a root of :math:`P` in the extension field :math:`L` and :math:`m` is a map from :math:`K` to :math:`L`,
        see :literal:`ffmap`.
        If :math:`v` is given, the variable name is used to display the generator of :math:`L`,
        else the name of the variable of :math:`P` is used.
        A generator of :math:`L` can be recovered using :math:`b = ffgen(r)`.
        The image of :math:`P` in :math:`L[X]` can be recovered using :math:`PL = ffmap(m,P)`.

        ::

        ? a = ffgen([3,5],'a);
        ? P = x^2-a; polisirreducible(P)
        %2 = 1
        ? [r,m] = ffextend(a, P, 'b);
        ? r
        %3 = b^9+2*b^8+b^7+2*b^6+b^4+1
        ? subst(ffmap(m, P), x, r)
        %4 = 0
        ? ffgen(r)
        %5 = b
        '''
        a = objtogen(a)
        P = objtogen(P)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _a = (<Gen>a).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _ret = ffextend(_a, _P, _v)
        return new_gen(_ret)

    def fffrobenius(self, m, long n=1):
        r'''
        Return the :math:`n`-th power of the Frobenius map over the field of definition
        of :math:`m`.

        ::

        ? a = ffgen([3,5],'a);
        ? f = fffrobenius(a);
        ? ffmap(f,a) == a^3
        %3 = 1
        ? g = fffrobenius(a, 5);
        ? ffmap(g,a) == a
        %5 = 1
        ? h = fffrobenius(a, 2);
        ? h == ffcompomap(f,f)
        %7 = 1
        '''
        m = objtogen(m)
        sig_on()
        cdef GEN _m = (<Gen>m).g
        cdef GEN _ret = fffrobenius(_m, n)
        return new_gen(_ret)

    def ffgen(self, k, v=None):
        r'''
        Return a generator for the finite field :math:`k` as a :literal:`t_FFELT`.
        The field :math:`k` can be given by

        - its order :math:`q`

        - the pair :math:`[p,f]` where :math:`q = p^f`

        - a monic irreducible polynomial with :literal:`t_INTMOD` coefficients modulo a
        prime.

        - a :literal:`t_FFELT` belonging to :math:`k`.

        If :literal:`v` is given, the variable name is used to display :math:`g`, else the
        variable of the polynomial or the :literal:`t_FFELT` is used, else :math:`x` is used.

        When only the order is specified, the function uses the polynomial generated
        by :literal:`ffinit` and is deterministic: two calls to the function with the
        same parameters will always give the same generator.

        For efficiency, the characteristic is not checked to be prime; similarly
        if a polynomial is given, we do not check whether it is irreducible.

        To obtain a multiplicative generator, call :literal:`ffprimroot` on the result.

        ::

        ? g = ffgen(16, 't);
        ? g.mod \\ recover the underlying polynomial.
        %2 = t^4+t^3+t^2+t+1
        ? g.p \\ recover the characteristic
        %3 = 2
        ? fforder(g) \\ g is not a multiplicative generator
        %4 = 5
        ? a = ffprimroot(g) \\ recover a multiplicative generator
        %5 = t^3+t^2+t
        ? fforder(a)
        %6 = 15
        '''
        k = objtogen(k)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _k = (<Gen>k).g
        cdef GEN _ret = ffgen(_k, _v)
        return new_gen(_ret)

    def ffinit(self, p, long n, v=None):
        r'''
        Computes a monic polynomial of degree :math:`n` which is irreducible over
        :math:`\mathbb{F}_p`, where :math:`p` is assumed to be prime. This function uses a fast variant
        of Adleman and Lenstra's algorithm.

        It is useful in conjunction with :literal:`ffgen`; for instance if
        :literal:`P = ffinit(3,2)`, you can represent elements in :math:`\mathbb{F}_{3^2}` in term of
        :literal:`g = ffgen(P,'t)`. This can be abbreviated as
        :literal:`g = ffgen(3^2, 't)`, where the defining polynomial :math:`P` can be later
        recovered as :literal:`g.mod`.
        '''
        p = objtogen(p)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = ffinit(_p, n, _v)
        return new_gen(_ret)

    def ffinvmap(self, m):
        r'''
        :math:`m` being a map from :math:`K` to :math:`L` two finite fields, return the partial map
        :math:`p` from :math:`L` to :math:`K` such that for all :math:`k\in K`, :math:`p(m(k)) = k`.

        ::

        ? a = ffgen([3,5],'a);
        ? b = ffgen([3,10],'b);
        ? m = ffembed(a, b);
        ? p = ffinvmap(m);
        ? u = random(a);
        ? v = ffmap(m, u);
        ? ffmap(p, v^2+v+2) == u^2+u+2
        %7 = 1
        ? ffmap(p, b)
        %8 = []
        '''
        m = objtogen(m)
        sig_on()
        cdef GEN _m = (<Gen>m).g
        cdef GEN _ret = ffinvmap(_m)
        return new_gen(_ret)

    def fflog(self, x, g, o=None):
        r'''
        Discrete logarithm of the finite field element :math:`x` in base :math:`g`,
        i.e. an :math:`e` in :math:`\mathbb{Z}` such that :math:`g^e = o`. If
        present, :math:`o` represents the multiplicative order of :math:`g`, see
        ``DLfun`` (in the PARI manual); the preferred format for
        this parameter is :literal:`[ord, factor(ord)]`, where :literal:`ord` is the
        order of :math:`g`. It may be set as a side effect of calling :literal:`ffprimroot`.

        If no :math:`o` is given, assume that :math:`g` is a primitive root. The result is
        undefined if :math:`e` does not exist. This function uses

        - a combination of generic discrete log algorithms (see :literal:`znlog`)

        - a cubic sieve index calculus algorithm for large fields of degree at
        least :math:`5`.

        - Coppersmith's algorithm for fields of characteristic at most :math:`5`.

        ::

        ? t = ffgen(ffinit(7,5));
        ? o = fforder(t)
        %2 = 5602 \\ not a primitive root.
        ? fflog(t^10,t)
        %3 = 10
        ? fflog(t^10,t, o)
        %4 = 10
        ? g = ffprimroot(t, &o);
        ? o \\ order is 16806, bundled with its factorization matrix
        %6 = [16806, [2, 1; 3, 1; 2801, 1]]
        ? fforder(g, o)
        %7 = 16806
        ? fflog(g^10000, g, o)
        %8 = 10000
        '''
        x = objtogen(x)
        g = objtogen(g)
        cdef bint _have_o = (o is not None)
        if _have_o:
            o = objtogen(o)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _g = (<Gen>g).g
        cdef GEN _o = NULL
        if _have_o:
            _o = (<Gen>o).g
        cdef GEN _ret = fflog(_x, _g, _o)
        return new_gen(_ret)

    def ffmap(self, m, x):
        r'''
        Given a (partial) map :math:`m` between two finite fields, return the image of
        :math:`x` by :math:`m`. The function is applied recursively to the component of vectors,
        matrices and polynomials. If :math:`m` is a partial map that is not defined at :math:`x`,
        return :math:`[]`.

        ::

        ? a = ffgen([3,5],'a);
        ? b = ffgen([3,10],'b);
        ? m = ffembed(a, b);
        ? P = x^2+a*x+1;
        ? Q = ffmap(m,P);
        ? ffmap(m,poldisc(P)) == poldisc(Q)
        %6 = 1
        '''
        m = objtogen(m)
        x = objtogen(x)
        sig_on()
        cdef GEN _m = (<Gen>m).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = ffmap(_m, _x)
        return new_gen(_ret)

    def ffnbirred(self, q, long n, long fl=0):
        r'''
        Computes the number of monic irreducible polynomials over :math:`\mathbb{F}_q` of degree exactly :math:`n`,
        (:math:`flag = 0` or omitted) or at most :math:`n` (:math:`flag = 1`).
        '''
        q = objtogen(q)
        sig_on()
        cdef GEN _q = (<Gen>q).g
        cdef GEN _ret = ffnbirred0(_q, n, fl)
        return new_gen(_ret)

    def fforder(self, x, o=None):
        r'''
        Multiplicative order of the finite field element :math:`x`. If :math:`o` is
        present, it represents a multiple of the order of the element,
        see ``DLfun`` (in the PARI manual); the preferred format for
        this parameter is :literal:`[N, factor(N)]`, where :literal:`N` is the cardinality
        of the multiplicative group of the underlying finite field.

        ::

        ? t = ffgen(ffinit(nextprime(10^8), 5));
        ? g = ffprimroot(t, &o); \\ o will be useful!
        ? fforder(g^1000000, o)
        time = 0 ms.
        %5 = 5000001750000245000017150000600250008403
        ? fforder(g^1000000)
        time = 16 ms. \\ noticeably slower, same result of course
        %6 = 5000001750000245000017150000600250008403
        '''
        x = objtogen(x)
        cdef bint _have_o = (o is not None)
        if _have_o:
            o = objtogen(o)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _o = NULL
        if _have_o:
            _o = (<Gen>o).g
        cdef GEN _ret = fforder(_x, _o)
        return new_gen(_ret)

    def ffprimroot(self, x, o=None):
        r'''
        Return a primitive root of the multiplicative
        group of the definition field of the finite field element :math:`x` (not necessarily
        the same as the field generated by :math:`x`). If present, :math:`o` is set to
        a vector :literal:`[ord, fa]`, where :literal:`ord` is the order of the group
        and :literal:`fa` its factorization :literal:`factor(ord)`. This last parameter is
        useful in :literal:`fflog` and :literal:`fforder`, see ``DLfun`` (in the PARI manual).

        ::

        ? t = ffgen(ffinit(nextprime(10^7), 5));
        ? g = ffprimroot(t, &o);
        ? o[1]
        %3 = 100000950003610006859006516052476098
        ? o[2]
        %4 =
        [2 1]
        
        [7 2]
        
        [31 1]
        
        [41 1]
        
        [67 1]
        
        [1523 1]
        
        [10498781 1]
        
        [15992881 1]
        
        [46858913131 1]
        
        ? fflog(g^1000000, g, o)
        time = 1,312 ms.
        %5 = 1000000
        '''
        x = objtogen(x)
        cdef bint _have_o = (o is not None)
        if _have_o:
            raise NotImplementedError("optional argument o not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _o = NULL
        cdef GEN _ret = ffprimroot(_x, _o)
        return new_gen(_ret)

    def fibonacci(self, long x):
        r'''
        :math:`x-th` Fibonacci number.
        '''
        sig_on()
        cdef GEN _ret = fibo(x)
        return new_gen(_ret)

    def fileclose(self, long n):
        r'''
        Close the file descriptor :math:`n`, created via :literal:`fileopen` or
        :literal:`fileextern`. Finitely many files can be opened at a given time,
        closing them recycles file descriptors and avoids running out of them:

        ::

        ? n = 0; while(n++, fileopen("/tmp/test", "w"))
        *** at top-level: n=0;while(n++,fileopen("/tmp/test","w"))
        *** ^--------------------------
        *** fileopen: error opening requested file: `/tmp/test'.
        *** Break loop: type 'break' to go back to GP prompt
        break> n
        65533

        This is a limitation of the operating system and does not
        depend on PARI: if you open too many files in :literal:`gp` without closing them,
        the operating system will also prevent unrelated applications from opening
        files. Independently, your operating system (e.g. Windows) may prevent other
        applications from accessing or deleting your file while it is opened by
        :literal:`gp`. Quitting :literal:`gp` implicitly calls this function on all opened
        file descriptors.

        On files opened for writing, this function also forces a write of all
        buffered data to the file system and completes all pending write operations.
        This function is implicitly called for all open file descriptors when
        exiting :literal:`gp` but it is cleaner and safer to call it explicitly, for
        instance in case of a :literal:`gp` crash or general system failure, which could
        cause data loss.

        ::

        ? n = fileopen("./here");
        ? while(l = fileread(n), print(l));
        ? fileclose(n);
        
        ? n = fileopen("./there", "w");
        ? for (i = 1, 100, filewrite(n, i^2+1))
        ? fileclose(n)

        Until a :literal:`fileclose`, there is no guarantee that the file on disk
        contains all the expected data from previous :literal:`filewrite` s. (And even
        then the operating system may delay the actual write to hardware.)

        Closing a file twice raises an exception:

        ::

        ? n = fileopen("/tmp/test");
        ? fileclose(n)
        ? fileclose(n)
        *** at top-level: fileclose(n)
        *** ^------------
        *** fileclose: invalid file descriptor 0
        '''
        sig_on()
        gp_fileclose(n)
        clear_stack()

    def fileextern(self, str):
        r'''
        The string :emphasis:`str` is the name of an external command, i.e. one you
        would type from your UNIX shell prompt. This command is immediately run and
        the function returns a file descriptor attached to the command output as if
        it were read from a file.

        ::

        ? n = fileextern("ls -l");
        ? while(l = filereadstr(n), print(l))
        ? fileclose(n)

        If the :literal:`secure` default is set, this function will raise
        en exception.
        '''
        str = to_bytes(str)
        cdef char* _str = <bytes>str
        sig_on()
        cdef long _ret = gp_fileextern(_str)
        clear_stack()
        return _ret

    def fileflush(self, n=None):
        r'''
        Flushes the file descriptor :math:`n`, created via :literal:`fileopen` or
        :literal:`fileextern`. On files opened for writing, this function forces a write
        of all buffered data to the file system and completes all pending write
        operations. This function is implicitly called by :literal:`fileclose` but you may
        want to call it explicitly at synchronization points, for instance after
        writing a large result to file and before printing diagnostics on screen.
        (In order to be sure that the file contains the expected content on
        inspection.)

        If :math:`n` is omitted, flush all descriptors to output streams.

        ::

        ? n = fileopen("./here", "w");
        ? for (i = 1, 10^5, \
        filewrite(n, i^2+1); \
        if (i % 10000 == 0, fileflush(n)))

        Until a :literal:`fileflush` or :literal:`fileclose`, there is no guarantee
        that the file contains all the expected data from previous :literal:`filewrite` s.
        '''
        cdef bint _have_n = (n is not None)
        if _have_n:
            n = objtogen(n)
        sig_on()
        cdef GEN _n = NULL
        if _have_n:
            _n = (<Gen>n).g
        gp_fileflush0(_n)
        clear_stack()

    def fileopen(self, path, mode=None):
        r'''
        Open the file pointed to by 'path' and return a file descriptor which
        can be used with other file functions.

        The mode can be

        - :literal:`"r"` (default): open for reading; allow :literal:`fileread` and
        :literal:`filereadstr`.

        - :literal:`"w"`: open for writing, discarding existing content; allow
        :literal:`filewrite`, :literal:`filewrite1`.

        - :literal:`"a"`: open for writing, appending to existing content; same
        operations allowed as :literal:`"w"`.

        Eventually, the file should be closed and the descriptor recycled using
        :literal:`fileclose`.

        ::

        ? n = fileopen("./here"); \\ "r" by default
        ? while (l = filereadstr(n), print(l)) \\ print successive lines
        ? fileclose(n) \\ done

        In :emphasis:`read` mode, raise an exception if the file does not
        exist or the user does not have read permission. In :emphasis:`write` mode, raise
        an exception if the file cannot be written to. Trying to read or write to a
        file that was not opend with the right mode raises an exception.

        ::

        ? n = fileopen("./read", "r");
        ? filewrite(n, "test") \\ not open for writing
        *** at top-level: filewrite(n,"test")
        *** ^-------------------
        *** filewrite: invalid file descriptor 0
        '''
        path = to_bytes(path)
        cdef char* _path = <bytes>path
        cdef char* _mode
        if mode is None:
            _mode = "r"
        else:
            mode = to_bytes(mode)
            _mode = <bytes>mode
        sig_on()
        cdef long _ret = gp_fileopen(_path, _mode)
        clear_stack()
        return _ret

    def fileread(self, long n):
        r'''
        Read a logical line from the file attached to the descriptor :math:`n`, opened
        for reading with :literal:`fileopen`. Return 0 at end of file.

        A logical line is a full command as it is prepared by gp's
        preprocessor (skipping blanks and comments or assembling multiline commands
        between braces) before being fed to the interpreter. The function
        :literal:`filereadstr` would read a :emphasis:`raw` line exactly as input, up to the
        next carriage return :literal:`\\n`.

        Compare raw lines

        ::

        ? n = fileopen("examples/bench.gp");
        ? while(l = filereadstr(n), print(l));
        {
        u=v=p=q=1;
        for (k=1, 2000,
        [u,v] = [v,u+v];
        p *= v; q = lcm(q,v);
        if (k%50 == 0,
        print(k, " ", log(p)/log(q))
        )
        )
        }

        and logical lines

        ::

        ? n = fileopen("examples/bench.gp");
        ? while(l = fileread(n), print(l));
        u=v=p=q=1;for(k=1,2000,[u,v]=[v,u+v];p*=v;q=lcm(q,v);[...]
        '''
        sig_on()
        cdef GEN _ret = gp_fileread(n)
        return new_gen(_ret)

    def filereadstr(self, long n):
        r'''
        Read a raw line from the file attached to the descriptor :math:`n`, opened
        for reading with :literal:`fileopen`, discarding the terminating newline.
        In other words the line is read exactly as input, up to the
        next carriage return :literal:`\\n`. By comparison, :literal:`fileread` would
        read a logical line, as assembled by gp's preprocessor (skipping blanks
        and comments for instance).
        '''
        sig_on()
        cdef GEN _ret = gp_filereadstr(n)
        return new_gen(_ret)

    def filewrite(self, long n, s):
        r'''
        Write the string :math:`s` to the file attached to descriptor :math:`n`, ending with
        a newline. The file must have been opened with :literal:`fileopen` in
        :literal:`"w"` or :literal:`"a"` mode. There is no guarantee that :math:`s` is completely
        written to disk until :literal:`fileclose:math:`(n)`` is executed, which is automatic
        when quitting :literal:`gp`.

        If the newline is not desired, use :literal:`filewrite1`.

        :strong:`Variant.` The high-level function :literal:`write` is expensive when many
        consecutive writes are expected because it cannot use buffering. The low-level
        interface :literal:`fileopen` / :literal:`filewrite` / :literal:`fileclose` is more efficient:

        ::

        ? f = "/tmp/bigfile";
        ? for (i = 1, 10^5, write(f, i^2+1))
        time = 240 ms.
        
        ? v = vector(10^5, i, i^2+1);
        time = 10 ms. \\ computing the values is fast
        ? write("/tmp/bigfile2",v)
        time = 12 ms. \\ writing them in one operation is fast
        
        ? n = fileopen("/tmp/bigfile", "w");
        ? for (i = 1, 10^5, filewrite(n, i^2+1))
        time = 24 ms. \\ low-level write is ten times faster
        ? fileclose(n);

        In the final example, the file needs not be in a consistent
        state until the ending :literal:`fileclose` is evaluated, e.g. some lines might be
        half-written or not present at all even though the corresponding
        :literal:`filewrite` was executed already. Both a single high-level :literal:`write`
        and a succession of low-level :literal:`filewrite` s achieve the same efficiency,
        but the latter is often more natural. In fact, concatenating naively
        the entries to be written is quadratic in the number of entries, hence
        much more expensive than the original write operations:

        ::

        ? v = []; for (i = 1, 10^5, v = concat(v,i))
        time = 1min, 41,456 ms.
        '''
        s = to_bytes(s)
        cdef char* _s = <bytes>s
        sig_on()
        gp_filewrite(n, _s)
        clear_stack()

    def filewrite1(self, long n, s):
        r'''
        Write the string :math:`s` to the file attached to descriptor :math:`n`.
        The file must have been opened with :literal:`fileopen` in :literal:`"w"` or :literal:`"a"`
        mode.

        If you want to append a newline at the end of :math:`s`, you can use
        :literal:`Str(s,"\\n")` or :literal:`filewrite`.
        '''
        s = to_bytes(s)
        cdef char* _s = <bytes>s
        sig_on()
        gp_filewrite1(n, _s)
        clear_stack()

    def floor(self, x):
        r'''
        Floor of :math:`x`. When :math:`x` is in :math:`\mathbb{R}`, the result is the
        largest integer smaller than or equal to :math:`x`. Applied to a rational function,
        :math:`floor (x)` returns the Euclidean quotient of the numerator by the
        denominator.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gfloor(_x)
        return new_gen(_ret)

    def fold(self, f, A):
        r'''
        Apply the :literal:`t_CLOSURE` :literal:`f` of arity :math:`2` to the entries of :literal:`A`,
        in order to return :literal:`f(...f(f(A[1],A[2]),A[3])...,A[\#A])`.

        ::

        ? fold((x,y)->x*y, [1,2,3,4])
        %1 = 24
        ? fold((x,y)->[x,y], [1,2,3,4])
        %2 = [[[1, 2], 3], 4]
        ? fold((x,f)->f(x), [2,sqr,sqr,sqr])
        %3 = 256
        ? fold((x,y)->(x+y)/(1-x*y),[1..5])
        %4 = -9/19
        ? bestappr(tan(sum(i=1,5,atan(i))))
        %5 = -9/19
        '''
        f = objtogen(f)
        A = objtogen(A)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _A = (<Gen>A).g
        cdef GEN _ret = fold0(_f, _A)
        return new_gen(_ret)

    def frac(self, x):
        r'''
        Fractional part of :math:`x`. Identical to
        :math:`x-floor(x)`. If :math:`x` is real, the result is in :math:`[0,1[`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gfrac(_x)
        return new_gen(_ret)

    def fromdigits(self, x, b=None):
        r'''
        Gives the integer formed by the elements of :math:`x` seen as the digits of a
        number in base :math:`b` (:math:`b = 10` by default). This is the reverse of :literal:`digits`:

        ::

        ? digits(1234,5)
        %1 = [1,4,4,1,4]
        ? fromdigits([1,4,4,1,4],5)
        %2 = 1234

        By convention, :math:`0` has no digits:

        ::

        ? fromdigits([])
        %3 = 0
        '''
        x = objtogen(x)
        cdef bint _have_b = (b is not None)
        if _have_b:
            b = objtogen(b)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _b = NULL
        if _have_b:
            _b = (<Gen>b).g
        cdef GEN _ret = fromdigits(_x, _b)
        return new_gen(_ret)

    def galoischardet(self, gal, chi, long o=1):
        r'''
        Let :math:`G` be the group attached to the :literal:`galoisinit`
        structure :emphasis:`gal`, and
        let :math:`\chi` be the character of some representation :math:`\rho` of the group :math:`G`,
        where a polynomial variable is to be interpreted as an :math:`o`-th root of 1.
        For instance, if :literal:`[T,o] = galoischartable(gal)` the characters
        :math:`\chi` are input as the columns of :literal:`T`.

        Return the degree-:math:`1` character :math:`\det\rho` as the list of :math:`\det \rho (g)`,
        where :math:`g` runs through representatives of the conjugacy classes
        in :literal:`galoisconjclasses(gal)`, with the same ordering.

        ::

        ? P = x^5 - x^4 - 5*x^3 + 4*x^2 + 3*x - 1;
        ? polgalois(P)
        %2 = [10, 1, 1, "D(5) = 5:2"]
        ? K = nfsplitting(P);
        ? gal = galoisinit(K); \\ dihedral of order 10
        ? [T,o] = galoischartable(gal);
        ? chi = T[,1]; \\ trivial character
        ? galoischardet(gal, chi, o)
        %7 = [1, 1, 1, 1]~
        ? [galoischardet(gal, T[,i], o) | i <- [1..#T]] \\ all characters
        %8 = [[1, 1, 1, 1]~, [1, 1, -1, 1]~, [1, 1, -1, 1]~, [1, 1, -1, 1]~]
        '''
        gal = objtogen(gal)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = galoischardet(_gal, _chi, o)
        return new_gen(_ret)

    def galoischarpoly(self, gal, chi, long o=1):
        r'''
        Let :math:`G` be the group attached to the :literal:`galoisinit`
        structure :emphasis:`gal`, and
        let :math:`\chi` be the character of some representation :math:`\rho` of the group
        :math:`G`, where a polynomial variable is to be interpreted as an :math:`o`-th root of
        1, e.g., if :literal:`[T,o] = galoischartable(gal)` and :math:`\chi` is a column of
        :literal:`T`.
        Return the list of characteristic polynomials :math:`\det (1 - \rho (g)T)`,
        where :math:`g` runs through representatives of the conjugacy classes
        in :literal:`galoisconjclasses(gal)`, with the same ordering.

        ::

        ? T = x^5 - x^4 - 5*x^3 + 4*x^2 + 3*x - 1;
        ? polgalois(T)
        %2 = [10, 1, 1, "D(5) = 5:2"]
        ? K = nfsplitting(T);
        ? gal = galoisinit(K); \\ dihedral of order 10
        ? [T,o] = galoischartable(gal);
        ? o
        %5 = 5
        ? galoischarpoly(gal, T[,1], o) \\ T[,1] is the trivial character
        %6 = [-x + 1, -x + 1, -x + 1, -x + 1]~
        ? galoischarpoly(gal, T[,3], o)
        %7 = [x^2 - 2*x + 1,
        x^2 + (y^3 + y^2 + 1)*x + 1,
        -x^2 + 1,
        x^2 + (-y^3 - y^2)*x + 1]~
        '''
        gal = objtogen(gal)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = galoischarpoly(_gal, _chi, o)
        return new_gen(_ret)

    def galoischartable(self, gal):
        r'''
        Compute the character table of :math:`G`, where :math:`G` is the underlying group of
        the :literal:`galoisinit` structure :emphasis:`gal`. The input :emphasis:`gal` is also allowed
        to be a :literal:`t_VEC` of permutations that is closed under products.
        Let :math:`N` be the number of conjugacy classes of :math:`G`.
        Return a :literal:`t_VEC` :math:`[M,e]` where :math:`e >= 1` is an integer
        and :math:`M` is a square :literal:`t_MAT` of size :math:`N` giving the character table
        of :math:`G`.

        - Each column corresponds to an irreducible character; the characters
        are ordered by increasing dimension and the first column is the trivial
        character (hence contains only :math:`1`'s).

        - Each row corresponds to a conjugacy class; the conjugacy classes are
        ordered as specified by :literal:`galoisconjclasses(gal)`, in particular the
        first row corresponds to the identity and gives the dimension :math:`\chi (1)`
        of the irreducible representation attached to the successive characters
        :math:`\chi`.

        The value :math:`M[i,j]` of the character :math:`j` at the conjugacy class :math:`i`
        is represented by a polynomial in :literal:`y` whose variable should be
        interpreted as an :math:`e`-th root of unity, i.e. as the lift of

        ::

        Mod(y, polcyclo(e,'y))

        (Note that :math:`M` is the transpose of the usual orientation for
        character tables.)

        The integer :math:`e` divides the exponent of the group :math:`G` and is chosen as small
        as posible; for instance :math:`e = 1` when the characters are all defined over
        :math:`\mathbb{Q}`, as is the case for :math:`S_n`. Examples:

        ::

        ? K = nfsplitting(x^4+x+1);
        ? gal = galoisinit(K);
        ? [M,e] = galoischartable(gal);
        ? M~ \\ take the transpose to get the usual orientation
        %4 =
        [1 1 1 1 1]
        
        [1 -1 -1 1 1]
        
        [2 0 0 -1 2]
        
        [3 -1 1 0 -1]
        
        [3 1 -1 0 -1]
        ? e
        %5 = 1
        ? {G = [Vecsmall([1, 2, 3, 4, 5]), Vecsmall([1, 5, 4, 3, 2]),
        Vecsmall([2, 1, 5, 4, 3]), Vecsmall([2, 3, 4, 5, 1]),
        Vecsmall([3, 2, 1, 5, 4]), Vecsmall([3, 4, 5, 1, 2]),
        Vecsmall([4, 3, 2, 1, 5]), Vecsmall([4, 5, 1, 2, 3]),
        Vecsmall([5, 1, 2, 3, 4]), Vecsmall([5, 4, 3, 2, 1])];}
        \\G = D10
        ? [M,e] = galoischartable(G);
        ? M~
        %8 =
        [1 1 1 1]
        
        [1 -1 1 1]
        
        [2 0 -y^3 - y^2 - 1 y^3 + y^2]
        
        [2 0 y^3 + y^2 -y^3 - y^2 - 1]
        ? e
        %9 = 5
        '''
        gal = objtogen(gal)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _ret = galoischartable(_gal)
        return new_gen(_ret)

    def galoisconjclasses(self, gal):
        r'''
        :emphasis:`gal` being output by :literal:`galoisinit`,
        return the list of conjugacy classes of the underlying group.
        The ordering of the classes is consistent with :literal:`galoischartable`
        and the trivial class comes first.

        ::

        ? G = galoisinit(x^6+108);
        ? galoisidentify(G)
        %2 = [6, 1] \\ S_3
        ? S = galoisconjclasses(G)
        %3 = [[Vecsmall([1,2,3,4,5,6])],
        [Vecsmall([3,1,2,6,4,5]),Vecsmall([2,3,1,5,6,4])],
        [Vecsmall([6,5,4,3,2,1]),Vecsmall([5,4,6,2,1,3]),
        Vecsmall([4,6,5,1,3,2])]]
        ? [[permorder(c[1]),#c] | c <- S ]
        %4 = [[1,1], [3,2], [2,3]]

        This command also accepts subgroups returned by :literal:`galoissubgroups`:

        ::

        ? subs = galoissubgroups(G); H = subs[5];
        ? galoisidentify(H)
        %2 = [2, 1] \\ Z/2
        ? S = galoisconjclasses(subgroups_of_G[5]);
        ? [[permorder(c[1]),#c] | c <- S ]
        %4 = [[1,1], [2,1]]
        '''
        gal = objtogen(gal)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _ret = galoisconjclasses(_gal)
        return new_gen(_ret)

    def galoisexport(self, gal, long flag=0):
        r'''
        :emphasis:`gal` being be a Galois group as output by :literal:`galoisinit`,
        export the underlying permutation group as a string suitable
        for (no flags or :math:`flag = 0`) GAP or (:math:`flag = 1`) Magma. The following example
        compute the index of the underlying abstract group in the GAP library:

        ::

        ? G = galoisinit(x^6+108);
        ? s = galoisexport(G)
        %2 = "Group((1, 2, 3)(4, 5, 6), (1, 4)(2, 6)(3, 5))"
        ? extern("echo \"IdGroup("s");\" | gap -q")
        %3 = [6, 1]
        ? galoisidentify(G)
        %4 = [6, 1]

        This command also accepts subgroups returned by :literal:`galoissubgroups`.

        To :emphasis:`import` a GAP permutation into gp (for :literal:`galoissubfields` for
        instance), the following GAP function may be useful:

        ::

        PermToGP := function(p, n)
        return Permuted([1..n],p);
        end;
        
        gap> p:= (1,26)(2,5)(3,17)(4,32)(6,9)(7,11)(8,24)(10,13)(12,15)(14,27)
        (16,22)(18,28)(19,20)(21,29)(23,31)(25,30)
        gap> PermToGP(p,32);
        [ 26, 5, 17, 32, 2, 9, 11, 24, 6, 13, 7, 15, 10, 27, 12, 22, 3, 28, 20, 19,
        29, 16, 31, 8, 30, 1, 14, 18, 21, 25, 23, 4 ]
        '''
        gal = objtogen(gal)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _ret = galoisexport(_gal, flag)
        return new_gen(_ret)

    def galoisfixedfield(self, gal, perm, long flag=0, v=None):
        r'''
        :emphasis:`gal` being be a Galois group as output by :literal:`galoisinit` and
        :emphasis:`perm` an element of :math:`gal.group`, a vector of such elements
        or a subgroup of :emphasis:`gal` as returned by galoissubgroups,
        computes the fixed field of :emphasis:`gal` by the automorphism defined by the
        permutations :emphasis:`perm` of the roots :math:`gal.roots`. :math:`P` is guaranteed to
        be squarefree modulo :math:`gal.p`.

        If no flags or :math:`flag = 0`, output format is the same as for :literal:`nfsubfield`,
        returning :math:`[P,x]` such that :math:`P` is a polynomial defining the fixed field, and
        :math:`x` is a root of :math:`P` expressed as a polmod in :math:`gal.pol`.

        If :math:`flag = 1` return only the polynomial :math:`P`.

        If :math:`flag = 2` return :math:`[P,x,F]` where :math:`P` and :math:`x` are as above and :math:`F` is the
        factorization of :math:`gal.pol` over the field defined by :math:`P`, where
        variable :math:`v` (:math:`y` by default) stands for a root of :math:`P`. The priority of :math:`v`
        must be less than the priority of the variable of :math:`gal.pol` (see
        ``priority`` (in the PARI manual)).
        In this case, :math:`P` is also expressed in the variable :math:`v` for compatibility
        with :math:`F`. Example:

        ::

        ? G = galoisinit(x^4+1);
        ? galoisfixedfield(G,G.group[2],2)
        %2 = [y^2 - 2, Mod(- x^3 + x, x^4 + 1), [x^2 - y*x + 1, x^2 + y*x + 1]]

        computes the factorization :math:`x^4+1 = (x^2-\sqrt{2}x+1)(x^2+\sqrt{2}x+1)`
        '''
        gal = objtogen(gal)
        perm = objtogen(perm)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _perm = (<Gen>perm).g
        cdef GEN _ret = galoisfixedfield(_gal, _perm, flag, _v)
        return new_gen(_ret)

    def galoisgetgroup(self, long a, long b=0):
        r'''
        Query the :literal:`galpol` package for a group of order :math:`a` with index :math:`b`
        in the GAP4 Small Group library, by Hans Ulrich Besche, Bettina Eick and
        Eamonn O'Brien.

        The current version of :literal:`galpol` supports groups of order :math:`a <= 143`.
        If :math:`b` is omitted, return the number of isomorphism classes of
        groups of order :math:`a`.
        '''
        sig_on()
        cdef GEN _ret = galoisgetgroup(a, b)
        return new_gen(_ret)

    def galoisgetname(self, long a, long b):
        r'''
        Query the :literal:`galpol` package for a string describing the group of order
        :math:`a`
        with index :math:`b` in the GAP4 Small Group library, by Hans Ulrich Besche,
        Bettina Eick and Eamonn O'Brien.
        The strings were generated using the GAP4 function :literal:`StructureDescription`.
        It is possible for different groups to have the same name.
        The command below outputs the names of all abstract groups of order 12:

        ::

        ? N = galoisgetgroup(12); \\ # of abstract groups of order 12
        ? for(i=1, N, print(i,". ",galoisgetname(12,i)))
        1. C3 : C4
        2. C12
        3. A4
        4. D12
        5. C6 x C2

        The current version of :literal:`galpol` supports groups of order :math:`a <= 143`.
        '''
        sig_on()
        cdef GEN _ret = galoisgetname(a, b)
        return new_gen(_ret)

    def galoisgetpol(self, long a, long b=0, long s=1):
        r'''
        Query the :literal:`galpol` package for a polynomial with Galois group
        isomorphic to
        GAP4(a,b), totally real if :math:`s = 1` (default) and totally complex if :math:`s = 2`.
        The current version of :literal:`galpol` supports groups of order :math:`a <= 143`.
        The output is a vector [:literal:`pol`, :literal:`den`] where

        - :literal:`pol` is the polynomial of degree :math:`a`

        - :literal:`den` is the denominator of :literal:`nfgaloisconj(pol)`.
        Pass it as an optional argument to :literal:`galoisinit` or :literal:`nfgaloisconj` to
        speed them up:

        ::

        ? [pol,den] = galoisgetpol(64,4,1);
        ? G = galoisinit(pol);
        time = 352ms
        ? galoisinit(pol, den); \\ passing 'den' speeds up the computation
        time = 264ms
        ? % == %`
        %4 = 1 \\ same answer

        If :math:`b` and :math:`s` are omitted, return the number of isomorphism classes of
        groups of order :math:`a`.
        '''
        sig_on()
        cdef GEN _ret = galoisgetpol(a, b, s)
        return new_gen(_ret)

    def galoisidentify(self, gal):
        r'''
        :emphasis:`gal` being be a Galois group as output by :literal:`galoisinit`,
        output the isomorphism class of the underlying abstract group as a
        two-components vector :math:`[o,i]`, where :math:`o` is the group order, and :math:`i` is the
        group index in the GAP4 Small Group library, by Hans Ulrich Besche, Bettina
        Eick and Eamonn O'Brien.

        This command also accepts subgroups returned by :literal:`galoissubgroups`.

        The current implementation is limited to degree less or equal to :math:`127`.
        Some larger "easy" orders are also supported.

        The output is similar to the output of the function :literal:`IdGroup` in GAP4.
        Note that GAP4 :literal:`IdGroup` handles all groups of order less than :math:`2000`
        except :math:`1024`, so you can use :literal:`galoisexport` and GAP4 to identify large
        Galois groups.
        '''
        gal = objtogen(gal)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _ret = galoisidentify(_gal)
        return new_gen(_ret)

    def galoisinit(self, pol, den=None):
        r'''
        Computes the Galois group
        and all necessary information for computing the fixed fields of the
        Galois extension :math:`K/\mathbb{Q}` where :math:`K` is the number field defined by
        :math:`pol` (monic irreducible polynomial in :math:`\mathbb{Z}[X]` or
        a number field as output by :literal:`nfinit`). The extension :math:`K/\mathbb{Q}` must be
        Galois with Galois group "weakly" super-solvable, see below;
        returns 0 otherwise. Hence this permits to quickly check whether a polynomial
        of order strictly less than :math:`36` is Galois or not.

        The algorithm used is an improved version of the paper
        "An efficient algorithm for the computation of Galois automorphisms",
        Bill Allombert, Math. Comp, vol. 73, 245, 2001, pp. 359--375.

        A group :math:`G` is said to be "weakly" super-solvable if there exists a
        normal series

        :math:`{1} = H_0 \triangleleft H_1 \triangleleft...\triangleleft H_{n-1}
        \triangleleft H_n`

        such that each :math:`H_i` is normal in :math:`G` and for :math:`i < n`, each quotient group
        :math:`H_{i+1}/H_i` is cyclic, and either :math:`H_n = G` (then :math:`G` is super-solvable) or
        :math:`G/H_n` is isomorphic to either :math:`A_4` or :math:`S_4`.

        In practice, almost all small groups are WKSS, the exceptions having order
        36(1 exception), 48(2), 56(1), 60(1), 72(5), 75(1), 80(1), 96(10) and :math:`\geq
        108`.

        This function is a prerequisite for most of the :literal:`galois`:math:`xxx` routines.
        For instance:

        ::

        P = x^6 + 108;
        G = galoisinit(P);
        L = galoissubgroups(G);
        vector(#L, i, galoisisabelian(L[i],1))
        vector(#L, i, galoisidentify(L[i]))

        The output is an 8-component vector :emphasis:`gal`.

        :math:`gal[1]` contains the polynomial :emphasis:`pol`
        (:literal:`:emphasis:`gal`.pol`).

        :math:`gal[2]` is a three-components vector :math:`[p,e,q]` where :math:`p` is a
        prime number (:literal:`:emphasis:`gal`.p`) such that :emphasis:`pol` totally split
        modulo :math:`p` , :math:`e` is an integer and :math:`q = p^e` (:literal:`:emphasis:`gal`.mod`) is the
        modulus of the roots in :literal:`:emphasis:`gal`.roots`.

        :math:`gal[3]` is a vector :math:`L` containing the :math:`p`-adic roots of
        :emphasis:`pol` as integers implicitly modulo :literal:`:emphasis:`gal`.mod`.
        (:literal:`:emphasis:`gal`.roots`).

        :math:`gal[4]` is the inverse of the Vandermonde matrix of the
        :math:`p`-adic roots of :emphasis:`pol`, multiplied by :math:`gal[5]`.

        :math:`gal[5]` is a multiple of the least common denominator of the
        automorphisms expressed as polynomial in a root of :emphasis:`pol`.

        :math:`gal[6]` is the Galois group :math:`G` expressed as a vector of
        permutations of :math:`L` (:literal:`:emphasis:`gal`.group`).

        :math:`gal[7]` is a generating subset :math:`S = [s_1,...,s_g]` of :math:`G`
        expressed as a vector of permutations of :math:`L` (:literal:`:emphasis:`gal`.gen`).

        :math:`gal[8]` contains the relative orders :math:`[o_1,...,o_g]` of
        the generators of :math:`S` (:literal:`:emphasis:`gal`.orders`).

        Let :math:`H_n` be as above, we have the following properties:

        :strong:`*` if :math:`G/H_n ~ A_4` then :math:`[o_1,...,o_g]` ends by
        :math:`[2,2,3]`.

        :strong:`*` if :math:`G/H_n ~ S_4` then :math:`[o_1,...,o_g]` ends by
        :math:`[2,2,3,2]`.

        :strong:`*` for :math:`1 <= i <= g` the subgroup of :math:`G` generated by
        :math:`[s_1,...,s_i]` is normal, with the exception of :math:`i = g-2` in the
        :math:`A_4` case and of :math:`i = g-3` in the :math:`S_4` case.

        :strong:`*` the relative order :math:`o_i` of :math:`s_i` is its order in the
        quotient group :math:`G/< s_1,...,s_{i-1}>`, with the same
        exceptions.

        :strong:`*` for any :math:`x\in G` there exists a unique family
        :math:`[e_1,...,e_g]` such that (no exceptions):

        -- for :math:`1 <= i <= g` we have :math:`0 <= e_i < o_i`

        -- :math:`x = g_1^{e_1}g_2^{e_2}...g_n^{e_n}`

        If present :math:`den` must be a suitable value for :math:`gal[5]`.
        '''
        pol = objtogen(pol)
        cdef bint _have_den = (den is not None)
        if _have_den:
            den = objtogen(den)
        sig_on()
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _den = NULL
        if _have_den:
            _den = (<Gen>den).g
        cdef GEN _ret = galoisinit(_pol, _den)
        return new_gen(_ret)

    def galoisisabelian(self, gal, long flag=0):
        r'''
        :emphasis:`gal` being as output by :literal:`galoisinit`, return :math:`0` if
        :emphasis:`gal` is not an abelian group, and the HNF matrix of :emphasis:`gal` over
        :literal:`gal.gen` if :math:`flag = 0`, :math:`1` if :math:`flag = 1`, and the SNF matrix of :emphasis:`gal`
        if :math:`flag = 2`.

        This command also accepts subgroups returned by :literal:`galoissubgroups`.
        '''
        gal = objtogen(gal)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _ret = galoisisabelian(_gal, flag)
        return new_gen(_ret)

    def galoisisnormal(self, gal, subgrp):
        r'''
        :emphasis:`gal` being as output by :literal:`galoisinit`, and :emphasis:`subgrp` a subgroup
        of :emphasis:`gal` as output by :literal:`galoissubgroups`,return :math:`1` if :emphasis:`subgrp` is a
        normal subgroup of :emphasis:`gal`, else return 0.

        This command also accepts subgroups returned by :literal:`galoissubgroups`.
        '''
        gal = objtogen(gal)
        subgrp = objtogen(subgrp)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _subgrp = (<Gen>subgrp).g
        cdef long _ret = galoisisnormal(_gal, _subgrp)
        clear_stack()
        return _ret

    def galoispermtopol(self, gal, perm):
        r'''
        :emphasis:`gal` being a
        Galois group as output by :literal:`galoisinit` and :emphasis:`perm` a element of
        :math:`gal.group`, return the polynomial defining the Galois
        automorphism, as output by :literal:`nfgaloisconj`, attached to the
        permutation :emphasis:`perm` of the roots :math:`gal.roots`. :emphasis:`perm` can
        also be a vector or matrix, in this case, :literal:`galoispermtopol` is
        applied to all components recursively.

        Note that

        ::

        G = galoisinit(pol);
        galoispermtopol(G, G[6])~

        is equivalent to :literal:`nfgaloisconj(pol)`, if degree of :emphasis:`pol` is greater
        or equal to :math:`2`.
        '''
        gal = objtogen(gal)
        perm = objtogen(perm)
        sig_on()
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _perm = (<Gen>perm).g
        cdef GEN _ret = galoispermtopol(_gal, _perm)
        return new_gen(_ret)

    def galoissubcyclo(self, N, H=None, long fl=0, v=None):
        r'''
        Computes the subextension of :math:`\mathbb{Q} (\zeta_n)` fixed by the subgroup
        :math:`H \subset (\mathbb{Z}/n\mathbb{Z})^*`. By the Kronecker-Weber theorem, all abelian number
        fields can be generated in this way (uniquely if :math:`n` is taken to be minimal).

        The pair :math:`(n, H)` is deduced from the parameters :math:`(N, H)` as follows

        - :math:`N` an integer: then :math:`n = N`; :math:`H` is a generator, i.e. an
        integer or an integer modulo :math:`n`; or a vector of generators.

        - :math:`N` the output of :literal:`znstar`:math:`(n)` or :literal:`znstar`:math:`(n,1)`.
        :math:`H` as in the first case above, or a matrix, taken to be a HNF left divisor
        of the SNF for :math:`(\mathbb{Z}/n\mathbb{Z})^*`
        (:literal:`:math:`N`.cyc`), giving the generators of :math:`H` in terms of :literal:`:math:`N`.gen`.

        - :math:`N` the output of :literal:`bnrinit(bnfinit(y), :math:`m`)` where :math:`m` is a
        module. :math:`H` as in the first case, or a matrix taken to be a HNF left
        divisor of the SNF for the ray class group modulo :math:`m`
        (of type :literal:`:math:`N`.cyc`), giving the generators of :math:`H` in terms of
        :literal:`:math:`N`.bid.gen` ( = :literal:`:math:`N``.gen if :math:`N` includes generators).

        In this last case, beware that :math:`H` is understood relatively to :math:`N`; in
        particular, if the infinite place does not divide the module, e.g if :math:`m` is
        an integer, then it is not a subgroup of :math:`(\mathbb{Z}/n\mathbb{Z})^*`, but of its quotient by
        :math:`{± 1}`.

        If :math:`fl = 0`, compute a polynomial (in the variable :emphasis:`v`) defining
        the subfield of :math:`\mathbb{Q} (\zeta_n)` fixed by the subgroup :emphasis:`H` of :math:`(\mathbb{Z}/n\mathbb{Z})^*`.

        If :math:`fl = 1`, compute only the conductor of the abelian extension, as a module.

        If :math:`fl = 2`, output :math:`[pol, N]`, where :math:`pol` is the polynomial as output when
        :math:`fl = 0` and :math:`N` the conductor as output when :math:`fl = 1`.

        The following function can be used to compute all subfields of
        :math:`\mathbb{Q} (\zeta_n)` (of exact degree :literal:`d`, if :literal:`d` is set):

        ::

        subcyclo(n, d = -1)=
        { my(bnr,L,IndexBound);
        IndexBound = if (d < 0, n, [d]);
        bnr = bnrinit(bnfinit(y), [n,[1]]);
        L = subgrouplist(bnr, IndexBound, 1);
        vector(#L,i, galoissubcyclo(bnr,L[i]));
        }

        Setting :literal:`L = subgrouplist(bnr, IndexBound)` would produce subfields of
        exact conductor :math:`n oo`.
        '''
        N = objtogen(N)
        cdef bint _have_H = (H is not None)
        if _have_H:
            H = objtogen(H)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _N = (<Gen>N).g
        cdef GEN _H = NULL
        if _have_H:
            _H = (<Gen>H).g
        cdef GEN _ret = galoissubcyclo(_N, _H, fl, _v)
        return new_gen(_ret)

    def galoissubfields(self, G, long flag=0, v=None):
        r'''
        Outputs all the subfields of the Galois group :emphasis:`G`, as a vector.
        This works by applying :literal:`galoisfixedfield` to all subgroups. The meaning of
        :emphasis:`flag` is the same as for :literal:`galoisfixedfield`.
        '''
        G = objtogen(G)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _ret = galoissubfields(_G, flag, _v)
        return new_gen(_ret)

    def galoissubgroups(self, G):
        r'''
        Outputs all the subgroups of the Galois group :literal:`gal`. A subgroup is a
        vector [:emphasis:`gen`, :emphasis:`orders`], with the same meaning
        as for :math:`gal.gen` and :math:`gal.orders`. Hence :emphasis:`gen` is a vector of
        permutations generating the subgroup, and :emphasis:`orders` is the relatives
        orders of the generators. The cardinality of a subgroup is the product of the
        relative orders. Such subgroup can be used instead of a Galois group in the
        following command: :literal:`galoisisabelian`, :literal:`galoissubgroups`,
        :literal:`galoisexport` and :literal:`galoisidentify`.

        To get the subfield fixed by a subgroup :emphasis:`sub` of :emphasis:`gal`, use

        ::

        galoisfixedfield(gal,sub[1])
        '''
        G = objtogen(G)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _ret = galoissubgroups(_G)
        return new_gen(_ret)

    def gamma(self, s, long precision=DEFAULT_BITPREC):
        r'''
        For :math:`s` a complex number, evaluates Euler's gamma
        function

        .. MATH::

        \Gamma (s) = \int_0^ oo t^{s-1}\exp (-t)dt.

        Error if :math:`s` is a non-positive integer, where :math:`\Gamma` has a pole.

        For :math:`s` a :literal:`t_PADIC`, evaluates the Morita gamma function at :math:`s`, that
        is the unique continuous :math:`p`-adic function on the :math:`p`-adic integers
        extending :math:`\Gamma_p(k) = (-1)^k \prod_{j < k}'j`, where the prime means that :math:`p`
        does not divide :math:`j`.

        ::

        ? gamma(1/4 + O(5^10))
        %1= 1 + 4*5 + 3*5^4 + 5^6 + 5^7 + 4*5^9 + O(5^10)
        ? algdep(%,4)
        %2 = x^4 + 4*x^2 + 5
        '''
        s = objtogen(s)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ggamma(_s, precision)
        return new_gen(_ret)

    def gammah(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Gamma function evaluated at the argument :math:`x+1/2`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = ggammah(_x, precision)
        return new_gen(_ret)

    def gammamellininv(self, G, t, long m=0, long precision=DEFAULT_BITPREC):
        r'''
        Returns the value at :math:`t` of the inverse Mellin transform
        :math:`G` initialized by :literal:`gammamellininvinit`.

        ::

        ? G = gammamellininvinit([0]);
        ? gammamellininv(G, 2) - 2*exp(-Pi*2^2)
        %2 = -4.484155085839414627 E-44

        The alternative shortcut

        ::

        gammamellininv(A,t,m)

        for

        ::

        gammamellininv(gammamellininvinit(A,m), t)

        is available.
        '''
        G = objtogen(G)
        t = objtogen(t)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _t = (<Gen>t).g
        cdef GEN _ret = gammamellininv(_G, _t, m, precision)
        return new_gen(_ret)

    def gammamellininvasymp(self, A, long serprec=-1, long n=0):
        r'''
        Return the first :math:`n` terms of the asymptotic expansion at infinity
        of the :math:`m`-th derivative :math:`K^{(m)}(t)` of the inverse Mellin transform of the
        function

        .. MATH::

        f(s) = \Gamma_\mathbb{R} (s+a_1)...\Gamma_\mathbb{R} (s+a_d) ,

        where :literal:`A` is the vector :math:`[a_1,...,a_d]` and
        :math:`\Gamma_\mathbb{R} (s) = \pi^{-s/2} \Gamma (s/2)` (Euler's :literal:`gamma`).
        The result is a vector
        :math:`[M[1]...M[n]]` with M[1] = 1, such that

        .. MATH::

        K^{(m)}(t) = \sqrt{2^{d+1}/d}t^{a+m(2/d-1)}e^{-d\pi t^{2/d}}
        \sum_{n >= 0} M[n+1] (\pi t^{2/d})^{-n}

        with :math:`a = (1-d+\sum_{1 <= j <= d}a_j)/d`.
        '''
        A = objtogen(A)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = gammamellininvasymp(_A, serprec, n)
        return new_gen(_ret)

    def gammamellininvinit(self, A, long m=0, long precision=DEFAULT_BITPREC):
        r'''
        Initialize data for the computation by :literal:`gammamellininv` of
        the :math:`m`-th derivative of the inverse Mellin transform of the function

        .. MATH::

        f(s) = \Gamma_\mathbb{R} (s+a_1)...\Gamma_\mathbb{R} (s+a_d)

        where :literal:`A` is the vector :math:`[a_1,...,a_d]` and
        :math:`\Gamma_\mathbb{R} (s) = \pi^{-s/2} \Gamma (s/2)` (Euler's :literal:`gamma`). This is the
        special case of Meijer's :math:`G` functions used to compute :math:`L`-values via the
        approximate functional equation.

        :strong:`Caveat.` Contrary to the PARI convention, this function
        guarantees an :emphasis:`absolute` (rather than relative) error bound.

        For instance, the inverse Mellin transform of :math:`\Gamma_\mathbb{R} (s)` is
        :math:`2\exp (-\pi z^2)`:

        ::

        ? G = gammamellininvinit([0]);
        ? gammamellininv(G, 2) - 2*exp(-Pi*2^2)
        %2 = -4.484155085839414627 E-44

        The inverse Mellin transform of :math:`\Gamma_\mathbb{R} (s+1)` is
        :math:`2 z\exp (-\pi z^2)`, and its second derivative is
        :math:`4\pi z \exp (-\pi z^2)(2\pi z^2 - 3)`:

        ::

        ? G = gammamellininvinit([1], 2);
        ? a(z) = 4*Pi*z*exp(-Pi*z^2)*(2*Pi*z^2-3);
        ? b(z) = gammamellininv(G,z);
        ? t(z) = b(z) - a(z);
        ? t(3/2)
        %3 = -1.4693679385278593850 E-39
        '''
        A = objtogen(A)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _ret = gammamellininvinit(_A, m, precision)
        return new_gen(_ret)

    def gcd(self, x, y=None):
        r'''
        Creates the greatest common divisor of :math:`x` and :math:`y`.
        If you also need the :math:`u` and :math:`v` such that :math:`x*u + y*v = \mathrm{gcd} (x,y)`,
        use the :literal:`gcdext` function. :math:`x` and :math:`y` can have rather quite general
        types, for instance both rational numbers. If :math:`y` is omitted and :math:`x` is a
        vector, returns the :math:`gcd` of all components of :math:`x`, i.e. this is
        equivalent to :literal:`content(x)`.

        When :math:`x` and :math:`y` are both given and one of them is a vector/matrix type,
        the GCD is again taken recursively on each component, but in a different way.
        If :math:`y` is a vector, resp. matrix, then the result has the same type as :math:`y`,
        and components equal to :literal:`gcd(x, y[i])`, resp. :literal:`gcd(x, y[,i])`. Else
        if :math:`x` is a vector/matrix the result has the same type as :math:`x` and an
        analogous definition. Note that for these types, :literal:`gcd` is not
        commutative.

        The algorithm used is a naive Euclid except for the following inputs:

        - integers: use modified right-shift binary ("plus-minus"
        variant).

        - univariate polynomials with coefficients in the same number
        field (in particular rational): use modular gcd algorithm.

        - general polynomials: use the subresultant algorithm if
        coefficient explosion is likely (non modular coefficients).

        If :math:`u` and :math:`v` are polynomials in the same variable with :emphasis:`inexact`
        coefficients, their gcd is defined to be scalar, so that

        ::

        ? a = x + 0.0; gcd(a,a)
        %1 = 1
        ? b = y*x + O(y); gcd(b,b)
        %2 = y
        ? c = 4*x + O(2^3); gcd(c,c)
        %3 = 4

        A good quantitative check to decide whether such a
        gcd "should be" non-trivial, is to use :literal:`polresultant`: a value
        close to :math:`0` means that a small deformation of the inputs has non-trivial gcd.
        You may also use :literal:`gcdext`, which does try to compute an approximate gcd
        :math:`d` and provides :math:`u`, :math:`v` to check whether :math:`u x + v y` is close to :math:`d`.
        '''
        x = objtogen(x)
        cdef bint _have_y = (y is not None)
        if _have_y:
            y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = NULL
        if _have_y:
            _y = (<Gen>y).g
        cdef GEN _ret = ggcd0(_x, _y)
        return new_gen(_ret)

    def gcdext(self, x, y):
        r'''
        Returns :math:`[u,v,d]` such that :math:`d` is the gcd of :math:`x,y`,
        :math:`x*u+y*v = \mathrm{gcd} (x,y)`, and :math:`u` and :math:`v` minimal in a natural sense.
        The arguments must be integers or polynomials.

        ::

        ? [u, v, d] = gcdext(32,102)
        %1 = [16, -5, 2]
        ? d
        %2 = 2
        ? gcdext(x^2-x, x^2+x-2)
        %3 = [-1/2, 1/2, x - 1]

        If :math:`x,y` are polynomials in the same variable and :emphasis:`inexact`
        coefficients, then compute :math:`u,v,d` such that :math:`x*u+y*v = d`, where :math:`d`
        approximately divides both and :math:`x` and :math:`y`; in particular, we do not obtain
        :literal:`gcd(x,y)` which is :emphasis:`defined` to be a scalar in this case:

        ::

        ? a = x + 0.0; gcd(a,a)
        %1 = 1
        
        ? gcdext(a,a)
        %2 = [0, 1, x + 0.E-28]
        
        ? gcdext(x-Pi, 6*x^2-zeta(2))
        %3 = [-6*x - 18.8495559, 1, 57.5726923]

        For inexact inputs, the output is thus not well defined
        mathematically, but you obtain explicit polynomials to check whether the
        approximation is close enough for your needs.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = gcdext0(_x, _y)
        return new_gen(_ret)

    def genus2red(self, PQ, p=None):
        r'''
        Let :math:`PQ` be a polynomial :math:`P`, resp. a vector :math:`[P,Q]` of polynomials, with
        rational coefficients.
        Determines the reduction at :math:`p > 2` of the (proper, smooth) genus 2
        curve :math:`C/\mathbb{Q}`, defined by the hyperelliptic equation :math:`y^2 = P(x)`, resp.
        :math:`y^2 + Q(x)*y = P(x)`.
        (The special fiber :math:`X_p` of the minimal regular model :math:`X` of :math:`C` over :math:`\mathbb{Z}`.)

        If :math:`p` is omitted, determines the reduction type for all (odd) prime
        divisors of the discriminant.

        This function was rewritten from an implementation of Liu's
        algorithm by Cohen and Liu (1994), :literal:`genus2reduction-0.3`, see
        :literal:`http://www.math.u-bordeaux.fr/~liu/G2R/`.

        :strong:`CAVEAT.` The function interface may change: for the
        time being, it returns :math:`[N,FaN, T, V]`
        where :math:`N` is either the local conductor at :math:`p` or the
        global conductor, :emphasis:`FaN` is its factorization, :math:`y^2 = T` defines a
        minimal model over :math:`\mathbb{Z}[1/2]` and :math:`V` describes the reduction type at the
        various considered :math:`p`. Unfortunately, the program is not complete for
        :math:`p = 2`, and we may return the odd part of the conductor only: this is the
        case if the factorization includes the (impossible) term :math:`2^{-1}`; if the
        factorization contains another power of :math:`2`, then this is the exact local
        conductor at :math:`2` and :math:`N` is the global conductor.

        ::

        ? default(debuglevel, 1);
        ? genus2red(x^6 + 3*x^3 + 63, 3)
        (potential) stable reduction: [1, []]
        reduction at p: [III{9}] page 184, [3, 3], f = 10
        %1 = [59049, Mat([3, 10]), x^6 + 3*x^3 + 63, [3, [1, []],
        ["[III{9}] page 184", [3, 3]]]]
        ? [N, FaN, T, V] = genus2red(x^3-x^2-1, x^2-x); \\ X_1(13), global reduction
        p = 13
        (potential) stable reduction: [5, [Mod(0, 13), Mod(0, 13)]]
        reduction at p: [I{0}-II-0] page 159, [], f = 2
        ? N
        %3 = 169
        ? FaN
        %4 = Mat([13, 2]) \\ in particular, good reduction at 2 !
        ? T
        %5 = x^6 + 58*x^5 + 1401*x^4 + 18038*x^3 + 130546*x^2 + 503516*x + 808561
        ? V
        %6 = [[13, [5, [Mod(0, 13), Mod(0, 13)]], ["[I{0}-II-0] page 159", []]]]

        We now first describe the format of the vector :math:`V = V_p` in the case where
        :math:`p` was specified (local reduction at :math:`p`): it is a triple :math:`[p, stable,
        red]`. The component :math:`stable = [type, vecj]` contains
        information about the stable reduction after a field extension;
        depending on :emphasis:`type` s, the stable reduction is

        - 1: smooth (i.e. the curve has potentially good reduction). The
        Jacobian :math:`J(C)` has potentially good reduction.

        - 2: an elliptic curve :math:`E` with an ordinary double point; :emphasis:`vecj`
        contains :math:`j` mod :math:`p`, the modular invariant of :math:`E`. The (potential)
        semi-abelian reduction of :math:`J(C)` is the extension of an elliptic curve (with
        modular invariant :math:`j` mod :math:`p`) by a torus.

        - 3: a projective line with two ordinary double points. The Jacobian
        :math:`J(C)` has potentially multiplicative reduction.

        - 4: the union of two projective lines crossing transversally at three
        points. The Jacobian :math:`J(C)` has potentially multiplicative reduction.

        - 5: the union of two elliptic curves :math:`E_1` and :math:`E_2` intersecting
        transversally at one point; :emphasis:`vecj` contains their modular invariants
        :math:`j_1` and :math:`j_2`, which may live in a quadratic extension of :math:`\mathbb{F}_p` and need
        not be distinct. The Jacobian :math:`J(C)` has potentially good reduction,
        isomorphic to the product of the reductions of :math:`E_1` and :math:`E_2`.

        - 6: the union of an elliptic curve :math:`E` and a projective line which has
        an ordinary double point, and these two components intersect transversally
        at one point; :emphasis:`vecj` contains :math:`j` mod :math:`p`, the modular invariant of :math:`E`.
        The (potential) semi-abelian reduction of :math:`J(C)` is the extension of an
        elliptic curve (with modular invariant :math:`j` mod :math:`p`) by a torus.

        - 7: as in type 6, but the two components are both singular. The
        Jacobian :math:`J(C)` has potentially multiplicative reduction.

        The component :math:`red = [NUtype, neron]` contains two data
        concerning the reduction at :math:`p` without any ramified field extension.

        The :emphasis:`NUtype` is a :literal:`t_STR` describing the reduction at :math:`p` of :math:`C`,
        following Namikawa-Ueno, :emphasis:`The complete classification of fibers in
        pencils of curves of genus two`, Manuscripta Math., vol. 9, (1973), pages
        143-186. The reduction symbol is followed by the corresponding page number
        or page range in this article.

        The second datum :emphasis:`neron` is the group of connected components (over an
        algebraic closure of :math:`\mathbb{F}_p`) of the Néron model of :math:`J(C)`, given as a
        finite abelian group (vector of elementary divisors).

        If :math:`p = 2`, the :emphasis:`red` component may be omitted altogether (and
        replaced by :literal:`[]`, in the case where the program could not compute it.
        When :math:`p` was not specified, :math:`V` is the vector of all :math:`V_p`, for all
        considered :math:`p`.

        :strong:`Notes about Namikawa-Ueno types.`

        - A lower index is denoted between braces: for instance,
        :literal:`[I{2}-II-5]` means :literal:`[I_2-II-5]`.

        - If :math:`K` and :math:`K'` are Kodaira symbols for singular fibers of elliptic
        curves, then :literal:`[:math:`K`-:math:`K'`-m]` and :literal:`[:math:`K'`-:math:`K`-m]` are the same.

        We define a total ordering on Kodaira symbol by fixing :math:`I < I* <
        II < II*,...`. If the reduction type is the same, we order by
        the number of components, e.g. :math:`I_2 < I_4`, etc.
        Then we normalize our output so that :math:`K <= K'`.

        - :literal:`[:math:`K`-:math:`K'`-:math:`-1`]` is :literal:`[:math:`K`-:math:`K'`-:math:`\alpha`]` in the notation of
        Namikawa-Ueno.

        - The figure :literal:`[2I_0-m]` in Namikawa-Ueno, page 159, must be denoted
        by :literal:`[2I_0-(m+1)]`.
        '''
        PQ = objtogen(PQ)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _PQ = (<Gen>PQ).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _ret = genus2red(_PQ, _p)
        return new_gen(_ret)

    def getabstime(self):
        r'''
        Returns the CPU time (in milliseconds) elapsed since :literal:`gp` startup.
        This provides a reentrant version of :literal:`gettime`:

        ::

        my (t = getabstime());
        ...
        print("Time: ", getabstime() - t);

        For a version giving wall-clock time, see :literal:`getwalltime`.
        '''
        sig_on()
        cdef long _ret = getabstime()
        clear_stack()
        return _ret

    def getcache(self):
        r'''
        Returns information about various auto-growing caches. For
        each resource, we report its name, its size, the number of cache misses
        (since the last extension), the largest cache miss and the size of the cache
        in bytes.

        The caches are initially empty, then set automatically to a small
        inexpensive default value, then grow on demand up to some maximal value.
        Their size never decreases, they are only freed on exit.

        The current caches are

        - Hurwitz class numbers :math:`H(D)` for :math:`\|D\| <= N`, computed in time
        :math:`O(N^{3/2})` using :math:`O(N)` space.

        - Factorizations of small integers up to :math:`N`, computed in time
        :math:`O(N^{1+\varepsilon})` using :math:`O(N\log N)` space.

        - Divisors of small integers up to :math:`N`, computed in time
        :math:`O(N^{1+\varepsilon})` using :math:`O(N\log N)` space.

        - Primitive dihedral forms of weight :math:`1` and level up to :math:`N`,
        computed in time :math:`O(N^{2+\varepsilon})` and space :math:`O(N^2)`.

        ::

        ? getcache() \\ on startup, all caches are empty
        %1 =
        [ "Factors" 0 0 0 0]
        
        ["Divisors" 0 0 0 0]
        
        [ "H" 0 0 0 0]
        
        ["Dihedral" 0 0 0 0]
        ? mfdim([500,1,0],0); \\ non-trivial computation
        time = 540 ms.
        ? getcache()
        %3 =
        [ "Factors" 50000 0 0 4479272]
        
        ["Divisors" 50000 1 100000 5189808]
        
        [ "H" 50000 0 0 400008]
        
        ["Dihedral" 1000 0 0 2278208]
        '''
        sig_on()
        cdef GEN _ret = getcache()
        return new_gen(_ret)

    def getenv(self, s):
        r'''
        Return the value of the environment variable :literal:`s` if it is defined, otherwise return 0.
        '''
        s = to_bytes(s)
        cdef char* _s = <bytes>s
        sig_on()
        cdef GEN _ret = gp_getenv(_s)
        return new_gen(_ret)

    def getheap(self):
        r'''
        Returns a two-component row vector giving the
        number of objects on the heap and the amount of memory they occupy in long
        words. Useful mainly for debugging purposes.
        '''
        sig_on()
        cdef GEN _ret = getheap()
        return new_gen(_ret)

    def getrand(self):
        r'''
        Returns the current value of the seed used by the
        pseudo-random number generator :literal:`random`. Useful mainly for debugging
        purposes, to reproduce a specific chain of computations. The returned value
        is technical (reproduces an internal state array), and can only be used as an
        argument to :literal:`setrand`.
        '''
        sig_on()
        cdef GEN _ret = getrand()
        return new_gen(_ret)

    def getstack(self):
        r'''
        Returns the current value of :math:`top-avma`, i.e. the number of
        bytes used up to now on the stack. Useful mainly for debugging purposes.
        '''
        sig_on()
        cdef long _ret = getstack()
        clear_stack()
        return _ret

    def gettime(self):
        r'''
        Returns the CPU time (in milliseconds) used since either the last call to
        :literal:`gettime`, or to the beginning of the containing GP instruction (if
        inside :literal:`gp`), whichever came last.

        For a reentrant version, see :literal:`getabstime`.

        For a version giving wall-clock time, see :literal:`getwalltime`.
        '''
        sig_on()
        cdef long _ret = gettime()
        clear_stack()
        return _ret

    def getwalltime(self):
        r'''
        Returns the time (in milliseconds) elapsed since
        00:00:00 UTC Thursday 1, January 1970 (the Unix epoch).

        ::

        my (t = getwalltime());
        ...
        print("Time: ", getwalltime() - t);
        '''
        sig_on()
        cdef GEN _ret = getwalltime()
        return new_gen(_ret)

    def hammingweight(self, x):
        r'''
        If :math:`x` is a :literal:`t_INT`, return the binary Hamming weight of :math:`\|x\|`. Otherwise
        :math:`x` must be of type :literal:`t_POL`, :literal:`t_VEC`, :literal:`t_COL`, :literal:`t_VECSMALL`, or
        :literal:`t_MAT` and the function returns the number of non-zero coefficients of
        :math:`x`.

        ::

        ? hammingweight(15)
        %1 = 4
        ? hammingweight(x^100 + 2*x + 1)
        %2 = 3
        ? hammingweight([Mod(1,2), 2, Mod(0,3)])
        %3 = 2
        ? hammingweight(matid(100))
        %4 = 100
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = hammingweight(_x)
        clear_stack()
        return _ret

    def hilbert(self, x, y, p=None):
        r'''
        Hilbert symbol of :math:`x` and :math:`y` modulo the prime :math:`p`, :math:`p = 0` meaning
        the place at infinity (the result is undefined if :math:`p != 0` is not prime).

        It is possible to omit :math:`p`, in which case we take :math:`p = 0` if both :math:`x`
        and :math:`y` are rational, or one of them is a real number. And take :math:`p = q`
        if one of :math:`x`, :math:`y` is a :literal:`t_INTMOD` modulo :math:`q` or a :math:`q`-adic. (Incompatible
        types will raise an error.)
        '''
        x = objtogen(x)
        y = objtogen(y)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef long _ret = hilbert(_x, _y, _p)
        clear_stack()
        return _ret

    def hyperellcharpoly(self, X):
        r'''
        :math:`X` being a non-singular hyperelliptic curve defined over a finite field,
        return the characteristic polynomial of the Frobenius automorphism.
        :math:`X` can be given either by a squarefree polynomial :math:`P` such that
        :math:`X: y^2 = P(x)` or by a vector :math:`[P,Q]` such that
        :math:`X: y^2 + Q(x) y = P(x)` and :math:`Q^2+4 P` is squarefree.
        '''
        X = objtogen(X)
        sig_on()
        cdef GEN _X = (<Gen>X).g
        cdef GEN _ret = hyperellcharpoly(_X)
        return new_gen(_ret)

    def hyperellpadicfrobenius(self, Q, unsigned long p, long n):
        r'''
        Let :math:`X` be the curve defined by :math:`y^2 = Q(x)`, where :math:`Q` is a polynomial of
        degree :math:`d` over :math:`\mathbb{Q}` and :math:`p >= d` a prime such that :math:`X` has good reduction
        at :math:`p` return the matrix of the Frobenius endomorphism :math:`\varphi` on the
        crystalline module :math:`D_p(X) = \mathbb{Q}_p \otimes H^1_{dR}(X/\mathbb{Q})` with respect to the
        basis of the given model :math:`(\omega, x \omega,...,x^{g-1} \omega)`, where
        :math:`\omega = dx/(2 y)` is the invariant differential, where :math:`g` is the genus of
        :math:`X` (either :math:`d = 2 g+1` or :math:`d = 2 g+2`). The characteristic polynomial of
        :math:`\varphi` is the numerator of the zeta-function of the reduction of the curve
        :math:`X` modulo :math:`p`. The matrix is computed to absolute :math:`p`-adic precision :math:`p^n`.
        '''
        Q = objtogen(Q)
        sig_on()
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _ret = hyperellpadicfrobenius(_Q, p, n)
        return new_gen(_ret)

    def hyperellratpoints(self, X, h, long flag=0):
        r'''
        :math:`X` being a non-singular hyperelliptic curve given by an integral model,
        return a vector containing the affine rational points on the curve of naive height less than :math:`h`.
        If :math:`flag = 1`, stop as soon as a point is found; return either an empty vector or a vector containing a single point.

        :math:`X` is given either by a squarefree polynomial :math:`P` such that :math:`X: y^2 = P(x)`
        or by a vector :math:`[P,Q]` such that :math:`X: y^2+Q(x) y = P(x)` and :math:`Q^2+4 P` is
        squarefree.

        The parameter :math:`h` can be

        - an integer :math:`H`: find the points :math:`[n/d,y]` whose abscissas :math:`x = n/d` have
        naive height ( = :math:`\max (\|n\|, d)`) less than :math:`H`;

        - a vector :math:`[N,D]` with :math:`D <= N`: find the points :math:`[n/d,y]` with
        :math:`\|n\| <= N`, :math:`d <= D`.

        - a vector :math:`[N,[D_1,D_2]]` with :math:`D_1 < D_2 <= N` find the points
        :math:`[n/d,y]` with :math:`\|n\| <= N` and :math:`D_1 <= d <= D_2`.
        '''
        X = objtogen(X)
        h = objtogen(h)
        sig_on()
        cdef GEN _X = (<Gen>X).g
        cdef GEN _h = (<Gen>h).g
        cdef GEN _ret = hyperellratpoints(_X, _h, flag)
        return new_gen(_ret)

    def hyperu(self, a, b, x, long precision=DEFAULT_BITPREC):
        r'''
        :math:`U`-confluent hypergeometric function with
        parameters :math:`a` and :math:`b`. The parameters :math:`a` and :math:`b` can be complex but
        the present implementation requires :math:`x` to be positive.
        '''
        a = objtogen(a)
        b = objtogen(b)
        x = objtogen(x)
        sig_on()
        cdef GEN _a = (<Gen>a).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = hyperu(_a, _b, _x, precision)
        return new_gen(_ret)

    def idealadd(self, nf, x, y):
        r'''
        Sum of the two ideals :math:`x` and :math:`y` in the number field :math:`nf`. The
        result is given in HNF.

        ::

        ? K = nfinit(x^2 + 1);
        ? a = idealadd(K, 2, x + 1) \\ ideal generated by 2 and 1+I
        %2 =
        [2 1]
        
        [0 1]
        ? pr = idealprimedec(K, 5)[1]; \\ a prime ideal above 5
        ? idealadd(K, a, pr) \\ coprime, as expected
        %4 =
        [1 0]
        
        [0 1]

        This function cannot be used to add arbitrary :math:`\mathbb{Z}`-modules, since it assumes
        that its arguments are ideals:

        ::

        ? b = Mat([1,0]~);
        ? idealadd(K, b, b) \\ only square t_MATs represent ideals
        *** idealadd: non-square t_MAT in idealtyp.
        ? c = [2, 0; 2, 0]; idealadd(K, c, c) \\ non-sense
        %6 =
        [2 0]
        
        [0 2]
        ? d = [1, 0; 0, 2]; idealadd(K, d, d) \\ non-sense
        %7 =
        [1 0]
        
        [0 1]
        

        In the last two examples, we get wrong results since the
        matrices :math:`c` and :math:`d` do not correspond to an ideal: the :math:`\mathbb{Z}`-span of their
        columns (as usual interpreted as coordinates with respect to the integer basis
        :literal:`K.zk`) is not an :math:`O_K`-module. To add arbitrary :math:`\mathbb{Z}`-modules generated
        by the columns of matrices :math:`A` and :math:`B`, use :literal:`mathnf(concat(A,B))`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = idealadd(_nf, _x, _y)
        return new_gen(_ret)

    def idealaddtoone(self, nf, x, y=None):
        r'''
        :math:`x` and :math:`y` being two co-prime
        integral ideals (given in any form), this gives a two-component row vector
        :math:`[a,b]` such that :math:`a\in x`, :math:`b\in y` and :math:`a+b = 1`.

        The alternative syntax :math:`idealaddtoone (nf,v)`, is supported, where
        :math:`v` is a :math:`k`-component vector of ideals (given in any form) which sum to
        :math:`\mathbb{Z}_K`. This outputs a :math:`k`-component vector :math:`e` such that :math:`e[i]\in x[i]` for
        :math:`1 <= i <= k` and :math:`\sum_{1 <= i <= k}e[i] = 1`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        cdef bint _have_y = (y is not None)
        if _have_y:
            y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = NULL
        if _have_y:
            _y = (<Gen>y).g
        cdef GEN _ret = idealaddtoone0(_nf, _x, _y)
        return new_gen(_ret)

    def idealappr(self, nf, x, long flag=0):
        r'''
        If :math:`x` is a fractional ideal
        (given in any form), gives an element :math:`\alpha` in :math:`nf` such that for
        all prime ideals :math:`p` such that the valuation of :math:`x` at :math:`p` is
        non-zero, we have :math:`v_{p}(\alpha) = v_{p}(x)`, and
        :math:`v_{p}(\alpha) >= 0` for all other :math:`p`.

        The argument :math:`x` may also be given as a prime ideal factorization, as
        output by :literal:`idealfactor`, but allowing zero exponents.
        This yields an element :math:`\alpha` such that for all prime ideals :math:`p`
        occurring in :math:`x`, :math:`v_{p}(\alpha) = v_{p}(x)`;
        for all other prime ideals, :math:`v_{p}(\alpha) >= 0`.

        flag is deprecated (ignored), kept for backward compatibility.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = idealappr0(_nf, _x, flag)
        return new_gen(_ret)

    def idealchinese(self, nf, x, y=None):
        r'''
        :math:`x` being a prime ideal factorization (i.e. a 2-columns matrix whose first
        column contains prime ideals and the second column contains integral
        exponents), :math:`y` a vector of elements in :math:`nf` indexed by the ideals in
        :math:`x`, computes an element :math:`b` such that

        :math:`v_{p}(b - y_{p}) >= v_{p}(x)` for all prime ideals
        in :math:`x` and :math:`v_{p}(b) >= 0` for all other :math:`p`.

        ::

        ? K = nfinit(t^2-2);
        ? x = idealfactor(K, 2^2*3)
        %2 =
        [[2, [0, 1]~, 2, 1, [0, 2; 1, 0]] 4]
        
        [ [3, [3, 0]~, 1, 2, 1] 1]
        ? y = [t,1];
        ? idealchinese(K, x, y)
        %4 = [4, -3]~

        The argument :math:`x` may also be of the form :math:`[x, s]` where the first component
        is as above and :math:`s` is a vector of signs, with :math:`r_1` components
        :math:`s_i` in :math:`{-1,0,1}`:
        if :math:`\sigma_i` denotes the :math:`i`-th real embedding of the number field,
        the element :math:`b` returned satisfies further
        :math:`sign (\sigma_i(b)) = s_i` for all :math:`i` such that :math:`s_i = ±1`.
        In other words, the sign is fixed to :math:`s_i` at the :math:`i`-th embedding whenever
        :math:`s_i` is non-zero.

        ::

        ? idealchinese(K, [x, [1,1]], y)
        %5 = [16, -3]~
        ? idealchinese(K, [x, [-1,-1]], y)
        %6 = [-20, -3]~
        ? idealchinese(K, [x, [1,-1]], y)
        %7 = [4, -3]~

        If :math:`y` is omitted, return a data structure which can be used in
        place of :math:`x` in later calls and allows to solve many chinese remainder
        problems for a given :math:`x` more efficiently.

        ::

        ? C = idealchinese(K, [x, [1,1]]);
        ? idealchinese(K, C, y) \\ as above
        %9 = [16, -3]~
        ? for(i=1,10^4, idealchinese(K,C,y)) \\ ... but faster !
        time = 80 ms.
        ? for(i=1,10^4, idealchinese(K,[x,[1,1]],y))
        time = 224 ms.

        Finally, this structure is itself allowed in place of :math:`x`, the
        new :math:`s` overriding the one already present in the structure. This allows to
        initialize for different sign conditions more efficiently when the underlying
        ideal factorization remains the same.

        ::

        ? D = idealchinese(K, [C, [1,-1]]); \\ replaces [1,1]
        ? idealchinese(K, D, y)
        %13 = [4, -3]~
        ? for(i=1,10^4,idealchinese(K,[C,[1,-1]]))
        time = 40 ms. \\ faster than starting from scratch
        ? for(i=1,10^4,idealchinese(K,[x,[1,-1]]))
        time = 128 ms.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        cdef bint _have_y = (y is not None)
        if _have_y:
            y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = NULL
        if _have_y:
            _y = (<Gen>y).g
        cdef GEN _ret = idealchinese(_nf, _x, _y)
        return new_gen(_ret)

    def idealcoprime(self, nf, x, y):
        r'''
        Given two integral ideals :math:`x` and :math:`y`
        in the number field :math:`nf`, returns a :math:`\beta` in the field,
        such that :math:`\beta.x` is an integral ideal coprime to :math:`y`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = idealcoprime(_nf, _x, _y)
        return new_gen(_ret)

    def idealdiv(self, nf, x, y, long flag=0):
        r'''
        Quotient :math:`x.y^{-1}` of the two ideals :math:`x` and :math:`y` in the number
        field :math:`nf`. The result is given in HNF.

        If :math:`flag` is non-zero, the quotient :math:`x.y^{-1}` is assumed to be an
        integral ideal. This can be much faster when the norm of the quotient is
        small even though the norms of :math:`x` and :math:`y` are large. More precisely,
        the algorithm cheaply removes all maximal ideals above rational
        primes such that :math:`v_p(Nx) = v_p(Ny)`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = idealdiv0(_nf, _x, _y, flag)
        return new_gen(_ret)

    def idealfactor(self, nf, x, lim=None):
        r'''
        Factors into prime ideal powers the ideal :math:`x` in the number field
        :math:`nf`. The output format is similar to the :literal:`factor` function, and
        the prime ideals are represented in the form output by the
        :literal:`idealprimedec` function. If :emphasis:`lim` is set, return partial
        factorization, including only prime ideals above rational primes
        :math:`< lim`.

        ::

        ? nf = nfinit(x^3-2);
        ? idealfactor(nf, x) \\ a prime ideal above 2
        %2 =
        [[2, [0, 1, 0]~, 3, 1, ...] 1]
        
        ? A = idealhnf(nf, 6*x, 4+2*x+x^2)
        %3 =
        [6 0 4]
        
        [0 6 2]
        
        [0 0 1]
        
        ? idealfactor(nf, A)
        %4 =
        [[2, [0, 1, 0]~, 3, 1, ...] 2]
        
        [[3, [1, 1, 0]~, 3, 1, ...] 2]
        
        ? idealfactor(nf, A, 3) \\ restrict to primes above p < 3
        %5 =
        [[2, [0, 1, 0]~, 3, 1, ...] 2]
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        cdef bint _have_lim = (lim is not None)
        if _have_lim:
            lim = objtogen(lim)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _lim = NULL
        if _have_lim:
            _lim = (<Gen>lim).g
        cdef GEN _ret = gpidealfactor(_nf, _x, _lim)
        return new_gen(_ret)

    def idealfactorback(self, nf, f, e=None, long flag=0):
        r'''
        Gives back the ideal corresponding to a factorization. The integer :math:`1`
        corresponds to the empty factorization.
        If :math:`e` is present, :math:`e` and :math:`f` must be vectors of the same length (:math:`e` being
        integral), and the corresponding factorization is the product of the
        :math:`f[i]^{e[i]}`.

        If not, and :math:`f` is vector, it is understood as in the preceding case with :math:`e`
        a vector of 1s: we return the product of the :math:`f[i]`. Finally, :math:`f` can be a
        regular factorization, as produced by :literal:`idealfactor`.

        ::

        ? nf = nfinit(y^2+1); idealfactor(nf, 4 + 2*y)
        %1 =
        [[2, [1, 1]~, 2, 1, [1, 1]~] 2]
        
        [[5, [2, 1]~, 1, 1, [-2, 1]~] 1]
        
        ? idealfactorback(nf, %)
        %2 =
        [10 4]
        
        [0 2]
        
        ? f = %1[,1]; e = %1[,2]; idealfactorback(nf, f, e)
        %3 =
        [10 4]
        
        [0 2]
        
        ? % == idealhnf(nf, 4 + 2*y)
        %4 = 1

        If :literal:`flag` is non-zero, perform ideal reductions (:literal:`idealred`) along the
        way. This is most useful if the ideals involved are all :emphasis:`extended`
        ideals (for instance with trivial principal part), so that the principal parts
        extracted by :literal:`idealred` are not lost. Here is an example:

        ::

        ? f = vector(#f, i, [f[i], [;]]); \\ transform to extended ideals
        ? idealfactorback(nf, f, e, 1)
        %6 = [[1, 0; 0, 1], [2, 1; [2, 1]~, 1]]
        ? nffactorback(nf, %[2])
        %7 = [4, 2]~

        The extended ideal returned in :literal:`\%6` is the trivial ideal :math:`1`, extended
        with a principal generator given in factored form. We use :literal:`nffactorback`
        to recover it in standard form.
        '''
        nf = objtogen(nf)
        f = objtogen(f)
        cdef bint _have_e = (e is not None)
        if _have_e:
            e = objtogen(e)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _f = (<Gen>f).g
        cdef GEN _e = NULL
        if _have_e:
            _e = (<Gen>e).g
        cdef GEN _ret = idealfactorback(_nf, _f, _e, flag)
        return new_gen(_ret)

    def idealfrobenius(self, nf, gal, pr):
        r'''
        Let :math:`K` be the number field defined by :math:`nf` and assume :math:`K/\mathbb{Q}` be a
        Galois extension with Galois group given :literal:`gal = galoisinit(nf)`,
        and that :emphasis:`pr` is an unramified prime ideal :math:`p` in :literal:`prid`
        format.
        This function returns a permutation of :literal:`gal.group` which defines
        the Frobenius element :math:`\text{Frob}_{p}` attached to :math:`p`.
        If :math:`p` is the unique prime number in :math:`p`, then
        :math:`\text{Frob} (x) = x^p mod p` for all :math:`x\in\mathbb{Z}_K`.

        ::

        ? nf = nfinit(polcyclo(31));
        ? gal = galoisinit(nf);
        ? pr = idealprimedec(nf,101)[1];
        ? g = idealfrobenius(nf,gal,pr);
        ? galoispermtopol(gal,g)
        %5 = x^8

        This is correct since :math:`101 = 8 mod 31`.
        '''
        nf = objtogen(nf)
        gal = objtogen(gal)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = idealfrobenius(_nf, _gal, _pr)
        return new_gen(_ret)

    def idealhnf(self, nf, u, v=None):
        r'''
        Gives the Hermite normal form of the ideal :math:`u\mathbb{Z}_K+v\mathbb{Z}_K`, where :math:`u`
        and :math:`v` are elements of the number field :math:`K` defined by :emphasis:`nf`.

        ::

        ? nf = nfinit(y^3 - 2);
        ? idealhnf(nf, 2, y+1)
        %2 =
        [1 0 0]
        
        [0 1 0]
        
        [0 0 1]
        ? idealhnf(nf, y/2, [0,0,1/3]~)
        %3 =
        [1/3 0 0]
        
        [0 1/6 0]
        
        [0 0 1/6]

        If :math:`b` is omitted, returns the HNF of the ideal defined by :math:`u`: :math:`u` may be an
        algebraic number (defining a principal ideal), a maximal ideal (as given by
        :literal:`idealprimedec` or :literal:`idealfactor`), or a matrix whose columns give
        generators for the ideal. This last format is a little complicated, but
        useful to reduce general modules to the canonical form once in a while:

        - if strictly less than :math:`N = [K:\mathbb{Q}]` generators are given, :math:`u`
        is the :math:`\mathbb{Z}_K`-module they generate,

        - if :math:`N` or more are given, it is :emphasis:`assumed` that they form a
        :math:`\mathbb{Z}`-basis of the ideal, in particular that the matrix has maximal rank :math:`N`.
        This acts as :literal:`mathnf` since the :math:`\mathbb{Z}_K`-module structure is (taken for
        granted hence) not taken into account in this case.

        ::

        ? idealhnf(nf, idealprimedec(nf,2)[1])
        %4 =
        [2 0 0]
        
        [0 1 0]
        
        [0 0 1]
        ? idealhnf(nf, [1,2;2,3;3,4])
        %5 =
        [1 0 0]
        
        [0 1 0]
        
        [0 0 1]

        Finally, when :math:`K` is quadratic with discriminant :math:`D_K`, we
        allow :math:`u =` :literal:`Qfb(a,b,c)`, provided :math:`b^2 - 4ac = D_K`. As usual,
        this represents the ideal :math:`a \mathbb{Z} + (1/2)(-b + \sqrt{D_K}) \mathbb{Z}`.

        ::

        ? K = nfinit(x^2 - 60); K.disc
        %1 = 60
        ? idealhnf(K, qfbprimeform(60,2))
        %2 =
        [2 1]
        
        [0 1]
        ? idealhnf(K, Qfb(1,2,3))
        *** at top-level: idealhnf(K,Qfb(1,2,3
        *** ^--------------------
        *** idealhnf: Qfb(1, 2, 3) has discriminant != 60 in idealhnf.
        '''
        nf = objtogen(nf)
        u = objtogen(u)
        cdef bint _have_v = (v is not None)
        if _have_v:
            v = objtogen(v)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _u = (<Gen>u).g
        cdef GEN _v = NULL
        if _have_v:
            _v = (<Gen>v).g
        cdef GEN _ret = idealhnf0(_nf, _u, _v)
        return new_gen(_ret)

    def idealintersect(self, nf, A, B):
        r'''
        Intersection of the two ideals
        :math:`A` and :math:`B` in the number field :math:`nf`. The result is given in HNF.

        ::

        ? nf = nfinit(x^2+1);
        ? idealintersect(nf, 2, x+1)
        %2 =
        [2 0]
        
        [0 2]

        This function does not apply to general :math:`\mathbb{Z}`-modules, e.g. orders, since its
        arguments are replaced by the ideals they generate. The following script
        intersects :math:`\mathbb{Z}`-modules :math:`A` and :math:`B` given by matrices of compatible
        dimensions with integer coefficients:

        ::

        ZM_intersect(A,B) =
        { my(Ker = matkerint(concat(A,B)));
        mathnf( A * Ker[1..#A,] )
        }
        '''
        nf = objtogen(nf)
        A = objtogen(A)
        B = objtogen(B)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _A = (<Gen>A).g
        cdef GEN _B = (<Gen>B).g
        cdef GEN _ret = idealintersect(_nf, _A, _B)
        return new_gen(_ret)

    def idealinv(self, nf, x):
        r'''
        Inverse of the ideal :math:`x` in the
        number field :math:`nf`, given in HNF. If :math:`x` is an extended
        ideal, its principal part is suitably
        updated: i.e. inverting :math:`[I,t]`, yields :math:`[I^{-1}, 1/t]`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = idealinv(_nf, _x)
        return new_gen(_ret)

    def idealispower(self, nf, A, long n, B=None):
        r'''
        Let :emphasis:`nf` be a number field and :math:`n > 0` be a positive integer.
        Return :math:`1` if the fractional ideal :math:`A = B^n` is an :math:`n`-th power and :math:`0`
        otherwise. If the argument :math:`B` is present, set it to the :math:`n`-th root of :math:`A`,
        in HNF.

        ::

        ? K = nfinit(x^3 - 2);
        ? A = [46875, 30966, 9573; 0, 3, 0; 0, 0, 3];
        ? idealispower(K, A, 3, &B)
        %3 = 1
        ? B
        %4 =
        [75 22 41]
        
        [ 0 1 0]
        
        [ 0 0 1]
        
        ? A = [9375, 2841, 198; 0, 3, 0; 0, 0, 3];
        ? idealispower(K, A, 3)
        %5 = 0
        '''
        nf = objtogen(nf)
        A = objtogen(A)
        cdef bint _have_B = (B is not None)
        if _have_B:
            raise NotImplementedError("optional argument B not available")
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _A = (<Gen>A).g
        cdef GEN * _B = NULL
        cdef long _ret = idealispower(_nf, _A, n, _B)
        clear_stack()
        return _ret

    def ideallist(self, nf, long bound, long flag=4):
        r'''
        Computes the list
        of all ideals of norm less or equal to :emphasis:`bound` in the number field
        :emphasis:`nf`. The result is a row vector with exactly :emphasis:`bound` components.
        Each component is itself a row vector containing the information about
        ideals of a given norm, in no specific order, depending on the value of
        :math:`flag`:

        The possible values of :math:`flag` are:

        0: give the :emphasis:`bid` attached to the ideals, without generators.

        1: as 0, but include the generators in the :emphasis:`bid`.

        2: in this case, :emphasis:`nf` must be a :emphasis:`bnf` with units. Each
        component is of the form :math:`[bid,U]`, where :emphasis:`bid` is as case 0
        and :math:`U` is a vector of discrete logarithms of the units. More precisely, it
        gives the :literal:`ideallog` s with respect to :emphasis:`bid` of :literal:`bnf.tufu`.
        This structure is technical, and only meant to be used in conjunction with
        :literal:`bnrclassnolist` or :literal:`bnrdisclist`.

        3: as 2, but include the generators in the :emphasis:`bid`.

        4: give only the HNF of the ideal.

        ::

        ? nf = nfinit(x^2+1);
        ? L = ideallist(nf, 100);
        ? L[1]
        %3 = [[1, 0; 0, 1]] \\ A single ideal of norm 1
        ? #L[65]
        %4 = 4 \\ There are 4 ideals of norm 4 in Z[i]

        If one wants more information, one could do instead:

        ::

        ? nf = nfinit(x^2+1);
        ? L = ideallist(nf, 100, 0);
        ? l = L[25]; vector(#l, i, l[i].clgp)
        %3 = [[20, [20]], [16, [4, 4]], [20, [20]]]
        ? l[1].mod
        %4 = [[25, 18; 0, 1], []]
        ? l[2].mod
        %5 = [[5, 0; 0, 5], []]
        ? l[3].mod
        %6 = [[25, 7; 0, 1], []]

        where we ask for the structures of the :math:`(\mathbb{Z}[i]/I)^*` for all
        three ideals of norm :math:`25`. In fact, for all moduli with finite part of norm
        :math:`25` and trivial Archimedean part, as the last 3 commands show. See
        :literal:`ideallistarch` to treat general moduli.
        '''
        nf = objtogen(nf)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _ret = ideallist0(_nf, bound, flag)
        return new_gen(_ret)

    def ideallistarch(self, nf, list, arch):
        r'''
        :emphasis:`list` is a vector of vectors of bid's, as output by :literal:`ideallist` with
        flag :math:`0` to :math:`3`. Return a vector of vectors with the same number of
        components as the original :emphasis:`list`. The leaves give information about
        moduli whose finite part is as in original list, in the same order, and
        Archimedean part is now :emphasis:`arch` (it was originally trivial). The
        information contained is of the same kind as was present in the input; see
        :literal:`ideallist`, in particular the meaning of :emphasis:`flag`.

        ::

        ? bnf = bnfinit(x^2-2);
        ? bnf.sign
        %2 = [2, 0] \\ two places at infinity
        ? L = ideallist(bnf, 100, 0);
        ? l = L[98]; vector(#l, i, l[i].clgp)
        %4 = [[42, [42]], [36, [6, 6]], [42, [42]]]
        ? La = ideallistarch(bnf, L, [1,1]); \\ add them to the modulus
        ? l = La[98]; vector(#l, i, l[i].clgp)
        %6 = [[168, [42, 2, 2]], [144, [6, 6, 2, 2]], [168, [42, 2, 2]]]

        Of course, the results above are obvious: adding :math:`t` places at infinity will
        add :math:`t` copies of :math:`\mathbb{Z}/2\mathbb{Z}` to :math:`(\mathbb{Z}_K/f)^*`. The following application
        is more typical:

        ::

        ? L = ideallist(bnf, 100, 2); \\ units are required now
        ? La = ideallistarch(bnf, L, [1,1]);
        ? H = bnrclassnolist(bnf, La);
        ? H[98];
        %4 = [2, 12, 2]
        '''
        nf = objtogen(nf)
        list = objtogen(list)
        arch = objtogen(arch)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _list = (<Gen>list).g
        cdef GEN _arch = (<Gen>arch).g
        cdef GEN _ret = ideallistarch(_nf, _list, _arch)
        return new_gen(_ret)

    def ideallog(self, nf=None, x=None, bid=None):
        r'''
        :math:`nf` is a number field,
        :emphasis:`bid` is as output by :literal:`idealstar(nf, D,...)` and :math:`x` a
        non-necessarily integral element of :emphasis:`nf` which must have valuation
        equal to 0 at all prime ideals in the support of :math:`D`. This function
        computes the discrete logarithm of :math:`x` on the generators given in
        :literal:`:emphasis:`bid`.gen`. In other words, if :math:`g_i` are these generators, of orders
        :math:`d_i` respectively, the result is a column vector of integers :math:`(x_i)` such
        that :math:`0 <= x_i < d_i` and

        .. MATH::

        x = \prod_i g_i^{x_i} (mod ^*D) .

        Note that when the support of :literal:`D` contains places at infinity, this
        congruence implies also sign conditions on the attached real embeddings.
        See :literal:`znlog` for the limitations of the underlying discrete log algorithms.

        When :emphasis:`nf` is omitted, take it to be the rational number field. In that
        case, :math:`x` must be a :literal:`t_INT` and :emphasis:`bid` must have been initialized by
        :literal:`znstar(N,1)`.
        '''
        cdef bint _have_nf = (nf is not None)
        if _have_nf:
            nf = objtogen(nf)
        if x is None:
            raise TypeError("missing required argument: 'x'")
        x = objtogen(x)
        if bid is None:
            raise TypeError("missing required argument: 'bid'")
        bid = objtogen(bid)
        sig_on()
        cdef GEN _nf = NULL
        if _have_nf:
            _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _bid = (<Gen>bid).g
        cdef GEN _ret = ideallog(_nf, _x, _bid)
        return new_gen(_ret)

    def idealmin(self, nf, ix, vdir=None):
        r'''
        :emphasis:`This function is useless and kept for backward compatibility only,
        use :literal:`idealred``. Computes a pseudo-minimum of the ideal :math:`x` in the
        direction :emphasis:`vdir` in the number field :emphasis:`nf`.
        '''
        nf = objtogen(nf)
        ix = objtogen(ix)
        cdef bint _have_vdir = (vdir is not None)
        if _have_vdir:
            vdir = objtogen(vdir)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _ix = (<Gen>ix).g
        cdef GEN _vdir = NULL
        if _have_vdir:
            _vdir = (<Gen>vdir).g
        cdef GEN _ret = idealmin(_nf, _ix, _vdir)
        return new_gen(_ret)

    def idealmul(self, nf, x, y, long flag=0):
        r'''
        Ideal multiplication of the ideals :math:`x` and :math:`y` in the number field
        :emphasis:`nf`; the result is the ideal product in HNF. If either :math:`x` or :math:`y`
        are extended ideals, their principal part is suitably
        updated: i.e. multiplying :math:`[I,t]`, :math:`[J,u]` yields :math:`[IJ, tu]`; multiplying
        :math:`I` and :math:`[J, u]` yields :math:`[IJ, u]`.

        ::

        ? nf = nfinit(x^2 + 1);
        ? idealmul(nf, 2, x+1)
        %2 =
        [4 2]
        
        [0 2]
        ? idealmul(nf, [2, x], x+1) \\ extended ideal * ideal
        %3 = [[4, 2; 0, 2], x]
        ? idealmul(nf, [2, x], [x+1, x]) \\ two extended ideals
        %4 = [[4, 2; 0, 2], [-1, 0]~]

        If :math:`flag` is non-zero, reduce the result using :literal:`idealred`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = idealmul0(_nf, _x, _y, flag)
        return new_gen(_ret)

    def idealnorm(self, nf, x):
        r'''
        Computes the norm of the ideal :math:`x` in the number field :math:`nf`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = idealnorm(_nf, _x)
        return new_gen(_ret)

    def idealnumden(self, nf, x):
        r'''
        Returns :math:`[A,B]`, where :math:`A,B` are coprime integer ideals
        such that :math:`x = A/B`, in the number field :math:`nf`.

        ::

        ? nf = nfinit(x^2+1);
        ? idealnumden(nf, (x+1)/2)
        %2 = [[1, 0; 0, 1], [2, 1; 0, 1]]
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = idealnumden(_nf, _x)
        return new_gen(_ret)

    def idealpow(self, nf, x, k, long flag=0):
        r'''
        Computes the :math:`k`-th power of
        the ideal :math:`x` in the number field :math:`nf`; :math:`k\in\mathbb{Z}`.
        If :math:`x` is an extended
        ideal, its principal part is suitably
        updated: i.e. raising :math:`[I,t]` to the :math:`k`-th power, yields :math:`[I^k, t^k]`.

        If :math:`flag` is non-zero, reduce the result using :literal:`idealred`, :emphasis:`throughout
        the (binary) powering process`; in particular, this is :emphasis:`not` the same
        as :math:`idealpow (nf,x,k)` followed by reduction.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        k = objtogen(k)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _k = (<Gen>k).g
        cdef GEN _ret = idealpow0(_nf, _x, _k, flag)
        return new_gen(_ret)

    def idealprimedec(self, nf, p, long f=0):
        r'''
        Computes the prime ideal
        decomposition of the (positive) prime number :math:`p` in the number field :math:`K`
        represented by :emphasis:`nf`. If a non-prime :math:`p` is given the result is undefined.
        If :math:`f` is present and non-zero, restrict the result to primes of residue
        degree :math:`<= f`.

        The result is a vector of :emphasis:`prid` structures, each representing one of the
        prime ideals above :math:`p` in the number field :math:`nf`. The representation
        :math:`pr = [p,a,e,f,mb]` of a prime ideal means the following: :math:`a`
        is an algebraic integer in the maximal order :math:`\mathbb{Z}_K` and the prime ideal is
        equal to :math:`p = p\mathbb{Z}_K + a\mathbb{Z}_K`;
        :math:`e` is the ramification index; :math:`f` is the residual index;
        finally, :emphasis:`mb` is the multiplication table attached to the algebraic
        integer :math:`b` is such that :math:`p^{-1} = \mathbb{Z}_K+ b/ p\mathbb{Z}_K`, which is used
        internally to compute valuations. In other words if :math:`p` is inert,
        then :emphasis:`mb` is the integer :math:`1`, and otherwise it is a square :literal:`t_MAT`
        whose :math:`j`-th column is :math:`b.nf.zk[j]`.

        The algebraic number :math:`a` is guaranteed to have a
        valuation equal to 1 at the prime ideal (this is automatic if :math:`e > 1`).

        The components of :literal:`pr` should be accessed by member functions: :literal:`pr.p`,
        :literal:`pr.e`, :literal:`pr.f`, and :literal:`pr.gen` (returns the vector :math:`[p,a]`):

        ::

        ? K = nfinit(x^3-2);
        ? P = idealprimedec(K, 5);
        ? #P \\ 2 primes above 5 in Q(2^(1/3))
        %3 = 2
        ? [p1,p2] = P;
        ? [p1.e, p1.f] \\ the first is unramified of degree 1
        %5 = [1, 1]
        ? [p2.e, p2.f] \\ the second is unramified of degree 2
        %6 = [1, 2]
        ? p1.gen
        %7 = [5, [2, 1, 0]~]
        ? nfbasistoalg(K, %[2]) \\ a uniformizer for p1
        %8 = Mod(x + 2, x^3 - 2)
        ? #idealprimedec(K, 5, 1) \\ restrict to f = 1
        %9 = 1 \\ now only p1
        '''
        nf = objtogen(nf)
        p = objtogen(p)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = idealprimedec_limit_f(_nf, _p, f)
        return new_gen(_ret)

    def idealprincipalunits(self, nf, pr, long k):
        r'''
        Given a prime ideal in :literal:`idealprimedec` format,
        returns the multiplicative group :math:`(1 + pr) / (1 + pr^k)` as an
        abelian group. This function is much faster than :literal:`idealstar` when the
        norm of :emphasis:`pr` is large, since it avoids (useless) work in the
        multiplicative group of the residue field.

        ::

        ? K = nfinit(y^2+1);
        ? P = idealprimedec(K,2)[1];
        ? G = idealprincipalunits(K, P, 20);
        ? G.cyc
        %4 = [512, 256, 4] \\ Z/512 x Z/256 x Z/4
        ? G.gen
        %5 = [[-1, -2]~, 1021, [0, -1]~] \\ minimal generators of given order
        '''
        nf = objtogen(nf)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = idealprincipalunits(_nf, _pr, k)
        return new_gen(_ret)

    def idealramgroups(self, nf, gal, pr):
        r'''
        Let :math:`K` be the number field defined by :emphasis:`nf` and assume that :math:`K/\mathbb{Q}` is
        Galois with Galois group :math:`G` given by :literal:`gal = galoisinit(nf)`.
        Let :emphasis:`pr` be the prime ideal :math:`P` in prid format.
        This function returns a vector :math:`g` of subgroups of :literal:`gal`
        as follow:

        - :literal:`g[1]` is the decomposition group of :math:`P`,

        - :literal:`g[2]` is :math:`G_0(P)`, the inertia group of :math:`P`,

        and for :math:`i >= 2`,

        - :literal:`g[i]` is :math:`G_{i-2}(P)`, the :math:`i-2`-th
        ramification group of :math:`P`.

        The length of :math:`g` is the number of non-trivial groups in the
        sequence, thus is :math:`0` if :math:`e = 1` and :math:`f = 1`, and :math:`1` if :math:`f > 1` and :math:`e = 1`.
        The following function computes the cardinality of a subgroup of :math:`G`,
        as given by the components of :math:`g`:

        ::

        card(H) =my(o=H[2]); prod(i=1,#o,o[i]);

        ::

        ? nf=nfinit(x^6+3); gal=galoisinit(nf); pr=idealprimedec(nf,3)[1];
        ? g = idealramgroups(nf, gal, pr);
        ? apply(card,g)
        %3 = [6, 6, 3, 3, 3] \\ cardinalities of the G_i

        ::

        ? nf=nfinit(x^6+108); gal=galoisinit(nf); pr=idealprimedec(nf,2)[1];
        ? iso=idealramgroups(nf,gal,pr)[2]
        %5 = [[Vecsmall([2, 3, 1, 5, 6, 4])], Vecsmall([3])]
        ? nfdisc(galoisfixedfield(gal,iso,1))
        %6 = -3

        The field fixed by the inertia group of :math:`2` is not ramified at
        :math:`2`.
        '''
        nf = objtogen(nf)
        gal = objtogen(gal)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = idealramgroups(_nf, _gal, _pr)
        return new_gen(_ret)

    def idealred(self, nf, I, v=None):
        r'''
        LLL reduction of
        the ideal :math:`I` in the number field :math:`K` attached to :emphasis:`nf`, along the
        direction :math:`v`. The :math:`v` parameter is best left omitted, but if it is present,
        it must be an :math:`nf.r1 + nf.r2`-component vector of
        :emphasis:`non-negative` integers. (What counts is the relative magnitude of the
        entries: if all entries are equal, the effect is the same as if the vector
        had been omitted.)

        This function finds an :math:`a\in K^*` such that :math:`J = (a)I` is
        "small" and integral (see the end for technical details).
        The result is the Hermite normal form of
        the "reduced" ideal :math:`J`.

        ::

        ? K = nfinit(y^2+1);
        ? P = idealprimedec(K,5)[1];
        ? idealred(K, P)
        %3 =
        [1 0]
        
        [0 1]

        More often than not, a principal ideal yields the unit
        ideal as above. This is a quick and dirty way to check if ideals are principal,
        but it is not a necessary condition: a non-trivial result does not prove that
        the ideal is non-principal. For guaranteed results, see :literal:`bnfisprincipal`,
        which requires the computation of a full :literal:`bnf` structure.

        If the input is an extended ideal :math:`[I,s]`, the output is :math:`[J, sa]`; in
        this way, one keeps track of the principal ideal part:

        ::

        ? idealred(K, [P, 1])
        %5 = [[1, 0; 0, 1], [2, -1]~]

        meaning that :math:`P` is generated by :math:`[2, -1]`. The number field element in the
        extended part is an algebraic number in any form :emphasis:`or` a factorization
        matrix (in terms of number field elements, not ideals!). In the latter case,
        elements stay in factored form, which is a convenient way to avoid
        coefficient explosion; see also :literal:`idealpow`.

        :strong:`Technical note.` The routine computes an LLL-reduced
        basis for the lattice :math:`I^{-1}` equipped with the quadratic
        form

        .. MATH::

        \|\| x \|\|_v^2 = \sum_{i = 1}^{r_1+r_2} 2^{v_i}\varepsilon_i\|\sigma_i(x)\|^2,

        where as usual the :math:`\sigma_i` are the (real and) complex embeddings and
        :math:`\varepsilon_i = 1`, resp. :math:`2`, for a real, resp. complex place. The element
        :math:`a` is simply the first vector in the LLL basis. The only reason you may want
        to try to change some directions and set some :math:`v_i != 0` is to randomize
        the elements found for a fixed ideal, which is heuristically useful in index
        calculus algorithms like :literal:`bnfinit` and :literal:`bnfisprincipal`.

        :strong:`Even more technical note.` In fact, the above is a white lie.
        We do not use :math:`\|\|.\|\|_v` exactly but a rescaled rounded variant which
        gets us faster and simpler LLLs. There's no harm since we are not using any
        theoretical property of :math:`a` after all, except that it belongs to :math:`I^{-1}`
        and that :math:`a I` is "expected to be small".
        '''
        nf = objtogen(nf)
        I = objtogen(I)
        cdef bint _have_v = (v is not None)
        if _have_v:
            v = objtogen(v)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _I = (<Gen>I).g
        cdef GEN _v = NULL
        if _have_v:
            _v = (<Gen>v).g
        cdef GEN _ret = idealred0(_nf, _I, _v)
        return new_gen(_ret)

    def idealredmodpower(self, nf, x, unsigned long n, unsigned long B=0):
        r'''
        Let :emphasis:`nf` be a number field, :math:`x` an ideal in :emphasis:`nf` and :math:`n > 0` be a
        positive integer. Return a number field element :math:`b` such that :math:`x b^n = v`
        is small. If :math:`x` is integral, then :math:`v` is also integral.

        More precisely, :literal:`idealnumden` reduces the problem to :math:`x` integral. Then,
        factoring out the prime ideals dividing a rational prime :math:`p <= B`,
        we rewrite :math:`x = I J^n` where the ideals :math:`I` and :math:`J` are both integral and
        :math:`I` is :math:`B`-smooth. Then we return a small element :math:`b` in :math:`J^{-1}`.

        The bound :math:`B` avoids a costly complete factorization of :math:`x`; as soon as the
        :math:`n`-core of :math:`x` is :math:`B`-smooth (i.e., as soon as :math:`I` is :math:`n`-power free),
        then :math:`J` is as large as possible and so is the expected reduction.

        ::

        ? T = x^6+108; nf = nfinit(T); a = Mod(x,T);
        ? setrand(1); u = (2*a^2+a+3)*random(2^1000*x^6)^6;
        ? sizebyte(u)
        %3 = 4864
        ? b = idealredmodpower(nf,u,2);
        ? v2 = nfeltmul(nf,u, nfeltpow(nf,b,2))
        %5 = [34, 47, 15, 35, 9, 3]~
        ? b = idealredmodpower(nf,u,6);
        ? v6 = nfeltmul(nf,u, nfeltpow(nf,b,6))
        %7 = [3, 0, 2, 6, -7, 1]~

        The last element :literal:`v6`, obtained by reducing
        modulo :math:`6`-th powers instead of squares, looks smaller than :literal:`v2`
        but its norm is actually a little larger:

        ::

        ? idealnorm(nf,v2)
        %8 = 81309
        ? idealnorm(nf,v6)
        %9 = 731781
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = idealredmodpower(_nf, _x, n, B)
        return new_gen(_ret)

    def idealstar(self, nf=None, N=None, long flag=1):
        r'''
        Outputs a :literal:`bid` structure,
        necessary for computing in the finite abelian group :math:`G = (\mathbb{Z}_K/N)^*`. Here,
        :emphasis:`nf` is a number field and :math:`N` is a :emphasis:`modulus`: either an ideal in any
        form, or a row vector whose first component is an ideal and whose second
        component is a row vector of :math:`r_1` 0 or 1. Ideals can also be given
        by a factorization into prime ideals, as produced by :literal:`idealfactor`.

        This :emphasis:`bid` is used in :literal:`ideallog` to compute discrete logarithms. It
        also contains useful information which can be conveniently retrieved as
        :literal:`:emphasis:`bid`.mod` (the modulus),
        :literal:`:emphasis:`bid`.clgp` (:math:`G` as a finite abelian group),
        :literal:`:emphasis:`bid`.no` (the cardinality of :math:`G`),
        :literal:`:emphasis:`bid`.cyc` (elementary divisors) and
        :literal:`:emphasis:`bid`.gen` (generators).

        If :math:`flag = 1` (default), the result is a :literal:`bid` structure without
        generators: they are well defined but not explicitly computed, which saves
        time.

        If :math:`flag = 2`, as :math:`flag = 1`, but including generators.

        If :math:`flag = 0`, only outputs :math:`(\mathbb{Z}_K/N)^*` as an abelian group,
        i.e as a 3-component vector :math:`[h,d,g]`: :math:`h` is the order, :math:`d` is the vector of
        SNF cyclic components and :math:`g` the corresponding
        generators.

        If :emphasis:`nf` is omitted, we take it to be the rational number fields, :math:`N` must
        be an integer and we return the structure of :math:`(\mathbb{Z}/N\mathbb{Z})^*`. In other words
        :literal:`idealstar(, N, flag)` is short for

        ::

        idealstar(nfinit(x), N, flag)

        but faster. The alternative syntax :literal:`znstar(N, flag)`
        is also available for an analogous effect but, due to an unfortunate
        historical oversight, the default value of :literal:`flag` is different in
        the two functions (:literal:`znstar` does not initialize by default, you probably
        want :literal:`znstar(N,1)`).
        '''
        cdef bint _have_nf = (nf is not None)
        if _have_nf:
            nf = objtogen(nf)
        if N is None:
            raise TypeError("missing required argument: 'N'")
        N = objtogen(N)
        sig_on()
        cdef GEN _nf = NULL
        if _have_nf:
            _nf = (<Gen>nf).g
        cdef GEN _N = (<Gen>N).g
        cdef GEN _ret = idealstar0(_nf, _N, flag)
        return new_gen(_ret)

    def idealtwoelt(self, nf, x, a=None):
        r'''
        Computes a two-element representation of the ideal :math:`x` in the number
        field :math:`nf`, combining a random search and an approximation theorem; :math:`x`
        is an ideal in any form (possibly an extended ideal, whose principal part is
        ignored)

        - When called as :literal:`idealtwoelt(nf,x)`, the result is a row vector
        :math:`[a,\alpha]` with two components such that :math:`x = a\mathbb{Z}_K+\alpha\mathbb{Z}_K` and :math:`a` is
        chosen to be the positive generator of :math:`x\cap\mathbb{Z}`, unless :math:`x` was given as a
        principal ideal in which case we may choose :math:`a = 0`. The algorithm
        uses a fast lazy factorization of :math:`x\cap \mathbb{Z}` and runs in randomized
        polynomial time.

        ::

        ? K = nfinit(t^5-23);
        ? x = idealhnf(K, t^2*(t+1), t^3*(t+1))
        %2 = \\ some random ideal of norm 552*23
        [552 23 23 529 23]
        
        [ 0 23 0 0 0]
        
        [ 0 0 1 0 0]
        
        [ 0 0 0 1 0]
        
        [ 0 0 0 0 1]
        
        ? [a,alpha] = idealtwoelt(K, x)
        %3 = [552, [23, 0, 1, 0, 0]~]
        ? nfbasistoalg(K, alpha)
        %4 = Mod(t^2 + 23, t^5 - 23)

        - When called as :literal:`idealtwoelt(nf,x,a)` with an explicit non-zero :math:`a`
        supplied as third argument, the function assumes that :math:`a \in x` and returns
        :math:`\alpha\in x` such that :math:`x = a\mathbb{Z}_K + \alpha\mathbb{Z}_K`. Note that we must factor
        :math:`a` in this case, and the algorithm is generally slower than the
        default variant and gives larger generators:

        ::

        ? alpha2 = idealtwoelt(K, x, 552)
        %5 = [-161, -161, -183, -207, 0]~
        ? idealhnf(K, 552, alpha2) == x
        %6 = 1

        Note that, in both cases, the return value is :emphasis:`not`
        recognized as an ideal by GP functions; one must use :literal:`idealhnf` as
        above to recover a valid ideal structure from the two-element representation.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        cdef bint _have_a = (a is not None)
        if _have_a:
            a = objtogen(a)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _a = NULL
        if _have_a:
            _a = (<Gen>a).g
        cdef GEN _ret = idealtwoelt0(_nf, _x, _a)
        return new_gen(_ret)

    def idealval(self, nf, x, pr):
        r'''
        Gives the valuation of the ideal :math:`x` at the prime ideal :emphasis:`pr` in the
        number field :math:`nf`, where :emphasis:`pr` is in :literal:`idealprimedec` format.
        The valuation of the :math:`0` ideal is :literal:`+oo`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = gpidealval(_nf, _x, _pr)
        return new_gen(_ret)

    def imag(self, x):
        r'''
        Imaginary part of :math:`x`. When :math:`x` is a quadratic number, this is the
        coefficient of :math:`\omega` in the "canonical" integral basis :math:`(1,\omega)`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gimag(_x)
        return new_gen(_ret)

    def incgam(self, s, x, g=None, long precision=DEFAULT_BITPREC):
        r'''
        Incomplete gamma function :math:`\int_x^ oo e^{-t}t^{s-1}dt`, extended by
        analytic continuation to all complex :math:`x, s` not both :math:`0`. The relative error
        is bounded in terms of the precision of :math:`s` (the accuracy of :math:`x` is ignored
        when determining the output precision). When :math:`g` is given, assume that
        :math:`g = \Gamma (s)`. For small :math:`\|x\|`, this will speed up the computation.
        '''
        s = objtogen(s)
        x = objtogen(x)
        cdef bint _have_g = (g is not None)
        if _have_g:
            g = objtogen(g)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _g = NULL
        if _have_g:
            _g = (<Gen>g).g
        precision = nbits2prec(precision)
        cdef GEN _ret = incgam0(_s, _x, _g, precision)
        return new_gen(_ret)

    def incgamc(self, s, x, long precision=DEFAULT_BITPREC):
        r'''
        Complementary incomplete gamma function.
        The arguments :math:`x` and :math:`s` are complex numbers such that :math:`s` is not a pole of
        :math:`\Gamma` and :math:`\|x\|/(\|s\|+1)` is not much larger than 1 (otherwise the
        convergence is very slow). The result returned is :math:`\int_0^x
        e^{-t}t^{s-1}dt`.
        '''
        s = objtogen(s)
        x = objtogen(x)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = incgamc(_s, _x, precision)
        return new_gen(_ret)

    def input(self):
        r'''
        Reads a string, interpreted as a GP expression,
        from the input file, usually standard input (i.e. the keyboard). If a
        sequence of expressions is given, the result is the result of the last
        expression of the sequence. When using this instruction, it is useful to
        prompt for the string by using the :literal:`print1` function. Note that in the
        present version 2.19 of :literal:`pari.el`, when using :literal:`gp` under GNU Emacs (see
        ``emacs`` (in the PARI manual)) one :emphasis:`must` prompt for the string, with a string
        which ends with the same prompt as any of the previous ones (a :literal:`"? "`
        will do for instance).
        '''
        sig_on()
        cdef GEN _ret = gp_input()
        return new_gen(_ret)

    def install(self, name, code, gpname=None, lib=None):
        r'''
        Loads from dynamic library :emphasis:`lib` the function :emphasis:`name`. Assigns to it
        the name :emphasis:`gpname` in this :literal:`gp` session, with :emphasis:`prototype`
        :emphasis:`code` (see below). If :emphasis:`gpname` is omitted, uses :emphasis:`name`.
        If :emphasis:`lib` is omitted, all symbols known to :literal:`gp` are available: this
        includes the whole of :literal:`libpari.so` and possibly others (such as
        :literal:`libc.so`).

        Most importantly, :literal:`install` gives you access to all non-static functions
        defined in the PARI library. For instance, the function

        ::

        GEN addii(GEN x, GEN y)

        adds two PARI integers, and is not directly accessible under
        :literal:`gp` (it is eventually called by the :literal:`+` operator of course):

        ::

        ? install("addii", "GG")
        ? addii(1, 2)
        %1 = 3

        It also allows to add external functions to the :literal:`gp` interpreter.
        For instance, it makes the function :literal:`system` obsolete:

        ::

        ? install(system, vs, sys,/*omitted*/)
        ? sys("ls gp*")
        gp.c gp.h gp_rl.c

        This works because :literal:`system` is part of :literal:`libc.so`,
        which is linked to :literal:`gp`. It is also possible to compile a shared library
        yourself and provide it to gp in this way: use :literal:`gp2c`, or do it manually
        (see the :literal:`modules_build` variable in :literal:`pari.cfg` for hints).

        Re-installing a function will print a warning and update the prototype code
        if needed. However, it will not reload a symbol from the library, even if the
        latter has been recompiled.

        :strong:`Prototype.` We only give a simplified description here, covering
        most functions, but there are many more possibilities. The full documentation
        is available in :literal:`libpari.dvi`, see

        ::

        ??prototype

        - First character :literal:`i`, :literal:`l`, :literal:`v` : return type int / long /
        void. (Default: :literal:`GEN`)

        - One letter for each mandatory argument, in the same order as they appear
        in the argument list: :literal:`G` (:literal:`GEN`), :literal:`&`
        (:literal:`GEN*`), :literal:`L` (:literal:`long`), :literal:`s` (:literal:`char *`), :literal:`n`
        (variable).

        - :literal:`p` to supply :literal:`realprecision` (usually :literal:`long prec` in the
        argument list), :literal:`P` to supply :literal:`seriesprecision`
        (usually :literal:`long precdl`).

        We also have special constructs for optional arguments and default
        values:

        - :literal:`DG` (optional :literal:`GEN`, :literal:`NULL` if omitted),

        - :literal:`D&` (optional :literal:`GEN*`, :literal:`NULL` if omitted),

        - :literal:`Dn` (optional variable, :math:`-1` if omitted),

        For instance the prototype corresponding to

        ::

        long issquareall(GEN x, GEN *n = NULL)

        is :literal:`lGD&`.

        :strong:`Caution.` This function may not work on all systems, especially
        when :literal:`gp` has been compiled statically. In that case, the first use of an
        installed function will provoke a Segmentation Fault (this should never
        happen with a dynamically linked executable). If you intend to use this
        function, please check first on some harmless example such as the one above
        that it works properly on your machine.
        '''
        name = to_bytes(name)
        cdef char* _name = <bytes>name
        code = to_bytes(code)
        cdef char* _code = <bytes>code
        cdef char* _gpname
        if gpname is None:
            _gpname = ""
        else:
            gpname = to_bytes(gpname)
            _gpname = <bytes>gpname
        cdef char* _lib
        if lib is None:
            _lib = ""
        else:
            lib = to_bytes(lib)
            _lib = <bytes>lib
        sig_on()
        gpinstall(_name, _code, _gpname, _lib)
        clear_stack()

    def intformal(self, x, v=None):
        r'''
        formal integration of :math:`x` with respect to the variable :math:`v` (wrt.
        the main variable if :math:`v` is omitted). Since PARI cannot represent
        logarithmic or arctangent terms, any such term in the result will yield an
        error:

        ::

        ? intformal(x^2)
        %1 = 1/3*x^3
        ? intformal(x^2, y)
        %2 = y*x^2
        ? intformal(1/x)
        *** at top-level: intformal(1/x)
        *** ^--------------
        *** intformal: domain error in intformal: residue(series, pole) != 0

        The argument :math:`x` can be of any type. When :math:`x` is a rational function, we
        assume that the base ring is an integral domain of characteristic zero.

        By definition, the main variable of a :literal:`t_POLMOD` is the main variable
        among the coefficients from its two polynomial components
        (representative and modulus); in other words, assuming a polmod represents an
        element of :math:`R[X]/(T(X))`, the variable :math:`X` is a mute variable and the
        integral is taken with respect to the main variable used in the base ring :math:`R`.
        In particular, it is meaningless to integrate with respect to the main
        variable of :literal:`x.mod`:

        ::

        ? intformal(Mod(1,x^2+1), 'x)
        *** intformal: incorrect priority in intformal: variable x = x
        '''
        x = objtogen(x)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = integ(_x, _v)
        return new_gen(_ret)

    def intnumgaussinit(self, long n=0, long precision=DEFAULT_BITPREC):
        r'''
        Initialize tables for :math:`n`-point Gauss-Legendre integration of
        a smooth function :math:`f` lon a compact
        interval :math:`[a,b]` at current :literal:`realprecision`. If :math:`n` is omitted, make a
        default choice :math:`n ~ realprecision`, suitable for analytic
        functions on :math:`[-1,1]`. The error is bounded by

        .. MATH::

        ((b-a)^{2n+1} (n!)^4)/((2n+1)[(2n)!]^3) f^{(2n)} (\xi) ,
        a < \xi < b

        so, if the interval length increases, :math:`n` should be increased as well.

        ::

        ? T = intnumgaussinit();
        ? intnumgauss(t=-1,1,exp(t), T) - exp(1)+exp(-1)
        %1 = -5.877471754111437540 E-39
        ? intnumgauss(t=-10,10,exp(t), T) - exp(10)+exp(-10)
        %2 = -8.358367809712546836 E-35
        ? intnumgauss(t=-1,1,1/(1+t^2), T) - Pi/2
        %3 = -9.490148553624725335 E-22
        
        ? T = intnumgaussinit(50);
        ? intnumgauss(t=-1,1,1/(1+t^2), T) - Pi/2
        %5 = -1.1754943508222875080 E-38
        ? intnumgauss(t=-5,5,1/(1+t^2), T) - 2*atan(5)
        %6 = -1.2[...]E-8

        On the other hand, we recommend to split the integral and change variables
        rather than increasing :math:`n` too much, see :literal:`intnumgauss`.
        '''
        sig_on()
        precision = nbits2prec(precision)
        cdef GEN _ret = intnumgaussinit(n, precision)
        return new_gen(_ret)

    def intnuminit(self, a, b, long m=0, long precision=DEFAULT_BITPREC):
        r'''
        Initialize tables for integration from
        :math:`a` to :math:`b`, where :math:`a` and :math:`b` are coded as in :literal:`intnum`. Only the
        compactness, the possible existence of singularities, the speed of decrease
        or the oscillations at infinity are taken into account, and not the values.
        For instance ``intnuminit(-1,1)`` is equivalent to ``intnuminit(0,Pi)``,
        and ``intnuminit([0,-1/2],oo)`` is equivalent to
        ``intnuminit([-1,-1/2], -oo)``; on the other hand, the order matters
        and
        ``intnuminit([0,-1/2], [1,-1/3])`` is :emphasis:`not` equivalent to
        ``intnuminit([0,-1/3], [1,-1/2])`` !

        If :math:`m` is present, it must be non-negative and we multiply the default
        number of sampling points by :math:`2^m` (increasing the running time by a
        similar factor).

        The result is technical and liable to change in the future, but we document
        it here for completeness. Let :math:`x = \phi (t)`, :math:`t\in ]- oo , oo [` be an
        internally chosen change of variable, achieving double exponential decrease of
        the integrand at infinity. The integrator :literal:`intnum` will compute

        .. MATH::

        h \sum_{\|n\| < N} \phi'(nh) F(\phi (nh))

        for some integration step :math:`h` and truncation parameter :math:`N`.
        In basic use, let

        ::

        [h, x0, w0, xp, wp, xm, wm] = intnuminit(a,b);

        - :math:`h` is the integration step

        - :math:`x_0 = \phi (0)` and :math:`w_0 = \phi'(0)`,

        - :emphasis:`xp` contains the :math:`\phi (nh)`, :math:`0 < n < N`,

        - :emphasis:`xm` contains the :math:`\phi (nh)`, :math:`0 < -n < N`, or is empty.

        - :emphasis:`wp` contains the :math:`\phi'(nh)`, :math:`0 < n < N`,

        - :emphasis:`wm` contains the :math:`\phi'(nh)`, :math:`0 < -n < N`, or is empty.

        The arrays :emphasis:`xm` and :emphasis:`wm` are left empty when :math:`\phi` is an odd
        function. In complicated situations when non-default behavior is specified at
        end points, :literal:`intnuminit` may return up to :math:`3` such arrays, corresponding
        to a splitting of up to :math:`3` integrals of basic type.

        If the functions to be integrated later are of the form :math:`F = f(t) k(t,z)`
        for some kernel :math:`k` (e.g. Fourier, Laplace, Mellin,...), it is
        useful to also precompute the values of :math:`f(\phi (nh))`, which is accomplished
        by :literal:`intfuncinit`. The hard part is to determine the behavior
        of :math:`F` at endpoints, depending on :math:`z`.
        '''
        a = objtogen(a)
        b = objtogen(b)
        sig_on()
        cdef GEN _a = (<Gen>a).g
        cdef GEN _b = (<Gen>b).g
        precision = nbits2prec(precision)
        cdef GEN _ret = intnuminit(_a, _b, m, precision)
        return new_gen(_ret)

    def isfundamental(self, D):
        r'''
        True (1) if :math:`D` is equal to 1 or to the discriminant of a quadratic
        field, false (0) otherwise. :math:`D` can be input in factored form as for
        arithmetic functions:

        ::

        ? isfundamental(factor(-8))
        %1 = 1
        \\ count fundamental discriminants up to 10^8
        ? c = 0; forfactored(d = 1, 10^8, if (isfundamental(d), c++)); c
        time = 40,840 ms.
        %2 = 30396325
        ? c = 0; for(d = 1, 10^8, if (isfundamental(d), c++)); c
        time = 1min, 33,593 ms. \\ slower !
        %3 = 30396325
        '''
        D = objtogen(D)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        cdef long _ret = isfundamental(_D)
        clear_stack()
        return _ret

    def ispolygonal(self, x, s, N=None):
        r'''
        True (1) if the integer :math:`x` is an s-gonal number, false (0) if not.
        The parameter :math:`s > 2` must be a :literal:`t_INT`. If :math:`N` is given, set it to :math:`n`
        if :math:`x` is the :math:`n`-th :math:`s`-gonal number.

        ::

        ? ispolygonal(36, 3, &N)
        %1 = 1
        ? N
        '''
        x = objtogen(x)
        s = objtogen(s)
        cdef bint _have_N = (N is not None)
        if _have_N:
            raise NotImplementedError("optional argument N not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _s = (<Gen>s).g
        cdef GEN * _N = NULL
        cdef long _ret = ispolygonal(_x, _s, _N)
        clear_stack()
        return _ret

    def ispower(self, x, k=None, n=None):
        r'''
        If :math:`k` is given, returns true (1) if :math:`x` is a :math:`k`-th power, false
        (0) if not. What it means to be a :math:`k`-th power depends on the type of
        :math:`x`; see :literal:`issquare` for details.

        If :math:`k` is omitted, only integers and fractions are allowed for :math:`x` and the
        function returns the maximal :math:`k >= 2` such that :math:`x = n^k` is a perfect
        power, or 0 if no such :math:`k` exist; in particular :literal:`ispower(-1)`,
        :literal:`ispower(0)`, and :literal:`ispower(1)` all return :math:`0`.

        If a third argument :math:`&n` is given and :math:`x` is indeed a :math:`k`-th power, sets
        :math:`n` to a :math:`k`-th root of :math:`x`.

        For a :literal:`t_FFELT` :literal:`x`, instead of omitting :literal:`k` (which is
        not allowed for this type), it may be natural to set

        ::

        k = (x.p ^ x.f - 1) / fforder(x)
        '''
        x = objtogen(x)
        cdef bint _have_k = (k is not None)
        if _have_k:
            k = objtogen(k)
        cdef bint _have_n = (n is not None)
        if _have_n:
            raise NotImplementedError("optional argument n not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _k = NULL
        if _have_k:
            _k = (<Gen>k).g
        cdef GEN * _n = NULL
        cdef long _ret = ispower(_x, _k, _n)
        clear_stack()
        return _ret

    def ispowerful(self, x):
        r'''
        True (1) if :math:`x` is a powerful integer, false (0) if not;
        an integer is powerful if and only if its valuation at all primes dividing
        :math:`x` is greater than 1.

        ::

        ? ispowerful(50)
        %1 = 0
        ? ispowerful(100)
        %2 = 1
        ? ispowerful(5^3*(10^1000+1)^2)
        %3 = 1
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = ispowerful(_x)
        clear_stack()
        return _ret

    def isprime(self, x, long flag=0):
        r'''
        True (1) if :math:`x` is a prime
        number, false (0) otherwise. A prime number is a positive integer having
        exactly two distinct divisors among the natural numbers, namely 1 and
        itself.

        This routine proves or disproves rigorously that a number is prime, which can
        be very slow when :math:`x` is indeed a large prime integer. For instance
        a :math:`1000` digits prime should require 15 to 30 minutes with default algorithms.
        Use :literal:`ispseudoprime` to quickly check for compositeness. Use
        :literal:`primecert` in order to obtain a primality proof instead of a yes/no
        answer; see also :literal:`factor`.

        The function accepts vector/matrices arguments, and is then
        applied componentwise.

        If :math:`flag = 0`, use a combination of

        - Baillie-Pomerance-Selfridge-Wagstaff compositeness test
        (see :literal:`ispseudoprime`),

        - Selfridge ":math:`p-1`" test if :math:`x-1` is smooth enough,

        - Adleman-Pomerance-Rumely-Cohen-Lenstra (APRCL) for general
        medium-sized :math:`x` (less than 1500 bits),

        - Atkin-Morain's Elliptic Curve Primality Prover (ECPP) for general
        large :math:`x`.

        If :math:`flag = 1`, use Selfridge-Pocklington-Lehmer ":math:`p-1`" test; this requires
        partially factoring various auxilliary integers and is likely to be very slow.

        If :math:`flag = 2`, use APRCL only.

        If :math:`flag = 3`, use ECPP only.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gisprime(_x, flag)
        return new_gen(_ret)

    def isprimepower(self, x, n=None):
        r'''
        If :math:`x = p^k` is a prime power (:math:`p` prime, :math:`k > 0`), return :math:`k`, else
        return 0. If a second argument :math:`&n` is given and :math:`x` is indeed
        the :math:`k`-th power of a prime :math:`p`, sets :math:`n` to :math:`p`.
        '''
        x = objtogen(x)
        cdef bint _have_n = (n is not None)
        if _have_n:
            raise NotImplementedError("optional argument n not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _n = NULL
        cdef long _ret = isprimepower(_x, _n)
        clear_stack()
        return _ret

    def ispseudoprime(self, x, long flag=0):
        r'''
        True (1) if :math:`x` is a strong pseudo
        prime (see below), false (0) otherwise. If this function returns false, :math:`x`
        is not prime; if, on the other hand it returns true, it is only highly likely
        that :math:`x` is a prime number. Use :literal:`isprime` (which is of course much
        slower) to prove that :math:`x` is indeed prime.
        The function accepts vector/matrices arguments, and is then applied
        componentwise.

        If :math:`flag = 0`, checks whether :math:`x` has no small prime divisors (up to :math:`101`
        included) and is a Baillie-Pomerance-Selfridge-Wagstaff pseudo prime.
        Such a pseudo prime passes a Rabin-Miller test for base :math:`2`,
        followed by a Lucas test for the sequence :math:`(P,1)`, where :math:`P >= 3`
        is the smallest odd integer such that :math:`P^2 - 4` is not a square mod :math:`x`.
        (Technically, we are using an "almost extra strong Lucas test" that
        checks whether :math:`V_n` is :math:`± 2`, without computing :math:`U_n`.)

        There are no known composite numbers passing the above test, although it is
        expected that infinitely many such numbers exist. In particular, all
        composites :math:`<= 2^{64}` are correctly detected (checked using
        :literal:`http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html`).

        If :math:`flag > 0`, checks whether :math:`x` is a strong Miller-Rabin pseudo prime for
        :math:`flag` randomly chosen bases (with end-matching to catch square roots of :math:`-1`).
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gispseudoprime(_x, flag)
        return new_gen(_ret)

    def ispseudoprimepower(self, x, n=None):
        r'''
        If :math:`x = p^k` is a pseudo-prime power (:math:`p` pseudo-prime as per
        :literal:`ispseudoprime`, :math:`k > 0`), return :math:`k`, else
        return 0. If a second argument :math:`&n` is given and :math:`x` is indeed
        the :math:`k`-th power of a prime :math:`p`, sets :math:`n` to :math:`p`.

        More precisely, :math:`k` is always the largest integer such that :math:`x = n^k` for
        some integer :math:`n` and, when :math:`n <= 2^{64}` the function returns :math:`k > 0` if and
        only if :math:`n` is indeed prime. When :math:`n > 2^{64}` is larger than the threshold,
        the function may return :math:`1` even though :math:`n` is composite: it only passed
        an :literal:`ispseudoprime(n)` test.
        '''
        x = objtogen(x)
        cdef bint _have_n = (n is not None)
        if _have_n:
            raise NotImplementedError("optional argument n not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _n = NULL
        cdef long _ret = ispseudoprimepower(_x, _n)
        clear_stack()
        return _ret

    def issquare(self, x, n=None):
        r'''
        True (1) if :math:`x` is a square, false (0)
        if not. What "being a square" means depends on the type of :math:`x`: all
        :literal:`t_COMPLEX` are squares, as well as all non-negative :literal:`t_REAL`; for
        exact types such as :literal:`t_INT`, :literal:`t_FRAC` and :literal:`t_INTMOD`, squares are
        numbers of the form :math:`s^2` with :math:`s` in :math:`\mathbb{Z}`, :math:`\mathbb{Q}` and :math:`\mathbb{Z}/N\mathbb{Z}` respectively.

        ::

        ? issquare(3) \\ as an integer
        %1 = 0
        ? issquare(3.) \\ as a real number
        %2 = 1
        ? issquare(Mod(7, 8)) \\ in Z/8Z
        %3 = 0
        ? issquare( 5 + O(13^4) ) \\ in Q_13
        %4 = 0

        If :math:`n` is given, a square root of :math:`x` is put into :math:`n`.

        ::

        ? issquare(4, &n)
        %1 = 1
        ? n
        %2 = 2

        For polynomials, either we detect that the characteristic is 2 (and check
        directly odd and even-power monomials) or we assume that :math:`2` is invertible
        and check whether squaring the truncated power series for the square root
        yields the original input.

        For :literal:`t_POLMOD` :math:`x`, we only support :literal:`t_POLMOD` s of :literal:`t_INTMOD` s
        encoding finite fields, assuming without checking that the intmod modulus
        :math:`p` is prime and that the polmod modulus is irreducible modulo :math:`p`.

        ::

        ? issquare(Mod(Mod(2,3), x^2+1), &n)
        %1 = 1
        ? n
        %2 = Mod(Mod(2, 3)*x, Mod(1, 3)*x^2 + Mod(1, 3))
        '''
        x = objtogen(x)
        cdef bint _have_n = (n is not None)
        if _have_n:
            raise NotImplementedError("optional argument n not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _n = NULL
        cdef long _ret = issquareall(_x, _n)
        clear_stack()
        return _ret

    def issquarefree(self, x):
        r'''
        True (1) if :math:`x` is squarefree, false (0) if not. Here :math:`x` can be an
        integer or a polynomial with coefficients in an integral domain.

        ::

        ? issquarefree(12)
        %1 = 0
        ? issquarefree(6)
        %2 = 1
        ? issquarefree(x^3+x^2)
        %3 = 0
        ? issquarefree(Mod(1,4)*(x^2+x+1)) \\ Z/4Z is not a domain !
        *** at top-level: issquarefree(Mod(1,4)*(x^2+x+1))
        *** ^--------------------------------
        *** issquarefree: impossible inverse in Fp_inv: Mod(2, 4).

        A polynomial is declared squarefree if :literal:`gcd`:math:`(x,x')` is
        :math:`1`. In particular a non-zero polynomial with inexact coefficients is
        considered to be squarefree. Note that this may be inconsistent with
        :literal:`factor`, which first rounds the input to some exact approximation before
        factoring in the apropriate domain; this is correct when the input is not
        close to an inseparable polynomial (the resultant of :math:`x` and :math:`x'` is not
        close to :math:`0`).

        An integer can be input in factored form as in arithmetic functions.

        ::

        ? issquarefree(factor(6))
        %1 = 1
        \\ count squarefree integers up to 10^8
        ? c = 0; for(d = 1, 10^8, if (issquarefree(d), c++)); c
        time = 3min, 2,590 ms.
        %2 = 60792694
        ? c = 0; forfactored(d = 1, 10^8, if (issquarefree(d), c++)); c
        time = 45,348 ms. \\ faster !
        %3 = 60792694
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = issquarefree(_x)
        clear_stack()
        return _ret

    def istotient(self, x, N=None):
        r'''
        True (1) if :math:`x = \phi (n)` for some integer :math:`n`, false (0)
        if not.

        ::

        ? istotient(14)
        %1 = 0
        ? istotient(100)
        %2 = 0

        If :math:`N` is given, set :math:`N = n` as well.

        ::

        ? istotient(4, &n)
        %1 = 1
        ? n
        %2 = 10
        '''
        x = objtogen(x)
        cdef bint _have_N = (N is not None)
        if _have_N:
            raise NotImplementedError("optional argument N not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _N = NULL
        cdef long _ret = istotient(_x, _N)
        clear_stack()
        return _ret

    def kill(self, sym):
        r'''
        Restores the symbol :literal:`sym` to its "undefined" status, and deletes any
        help messages attached to :literal:`sym` using :literal:`addhelp`. Variable names
        remain known to the interpreter and keep their former priority: you cannot
        make a variable "less important" by killing it!

        ::

        ? z = y = 1; y
        %1 = 1
        ? kill(y)
        ? y \\ restored to ``undefined'' status
        %2 = y
        ? variable()
        %3 = [x, y, z] \\ but the variable name y is still known, with y > z !

        For the same reason, killing a user function (which is an ordinary
        variable holding a :literal:`t_CLOSURE`) does not remove its name from the list of
        variable names.

        If the symbol is attached to a variable --- user functions being an
        important special case ---, one may use the quote operator
        :literal:`a = 'a` to reset variables to their starting values. However, this
        will not delete a help message attached to :literal:`a`, and is also slightly
        slower than :literal:`kill(a)`.

        ::

        ? x = 1; addhelp(x, "foo"); x
        %1 = 1
        ? x = 'x; x \\ same as 'kill', except we don't delete help.
        %2 = x
        ? ?x
        foo

        On the other hand, :literal:`kill` is the only way to remove aliases and installed
        functions.

        ::

        ? alias(fun, sin);
        ? kill(fun);
        
        ? install(addii, GG);
        ? kill(addii);
        '''
        sym = to_bytes(sym)
        cdef char* _sym = <bytes>sym
        sig_on()
        kill0(_sym)
        clear_stack()

    def kronecker(self, x, y):
        r'''
        Kronecker symbol :math:`(x\|y)`, where :math:`x` and :math:`y` must be of type integer. By
        definition, this is the extension of Legendre symbol to :math:`\mathbb{Z} x \mathbb{Z}`
        by total multiplicativity in both arguments with the following special rules
        for :math:`y = 0, -1` or :math:`2`:

        - :math:`(x\|0) = 1` if :math:`\|x \|= 1` and :math:`0` otherwise.

        - :math:`(x\|-1) = 1` if :math:`x >= 0` and :math:`-1` otherwise.

        - :math:`(x\|2) = 0` if :math:`x` is even and :math:`1` if :math:`x = 1,-1 mod 8` and :math:`-1`
        if :math:`x = 3,-3 mod 8`.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef long _ret = kronecker(_x, _y)
        clear_stack()
        return _ret

    def lambertw(self, y, long precision=DEFAULT_BITPREC):
        r'''
        Lambert :math:`W` function, solution of the implicit equation :math:`xe^x = y`,
        for :math:`y > 0`.
        '''
        y = objtogen(y)
        sig_on()
        cdef GEN _y = (<Gen>y).g
        precision = nbits2prec(precision)
        cdef GEN _ret = glambertW(_y, precision)
        return new_gen(_ret)

    def laurentseries(self, f, long serprec=-1, M=None, long precision=DEFAULT_BITPREC):
        r'''
        Expand :math:`f` as a Laurent series around :math:`x = 0` to order :math:`M`. This
        function computes :math:`f(x + O(x^n))` until :math:`n` is large enough: it
        must be possible to evaluate :math:`f` on a power series with :math:`0` constant term.

        ::

        ? laurentseries(t->sin(t)/(1-cos(t)), 5)
        %1 = 2*x^-1 - 1/6*x - 1/360*x^3 - 1/15120*x^5 + O(x^6)
        ? laurentseries(log)
        *** at top-level: laurentseries(log)
        *** ^------------------
        *** in function laurentseries: log
        *** ^---
        *** log: domain error in log: series valuation != 0

        Note that individual Laurent coefficients of order :math:`<= M`
        can be retrieved from :math:`s = laurentseries (f,M)` via :literal:`polcoeff(s,i)`
        for any :math:`i <= M`. The series :math:`s` may occasionally be more precise that
        the required :math:`O(x^{M+1})`.

        With respect to successive calls to :literal:`derivnum`,
        :literal:`laurentseries` is both faster and more precise:

        ::

        ? laurentseries(t->log(3+t),1)
        %1 = 1.0986122886681096913952452369225257047 + 1/3*x - 1/18*x^2 + O(x^3)
        ? derivnum(t=0,log(3+t),1)
        %2 = 0.33333333333333333333333333333333333333
        ? derivnum(t=0,log(3+t),2)
        %3 = -0.11111111111111111111111111111111111111
        
        ? f = x->sin(exp(x));
        ? polcoeff(laurentseries(x->f(x+2), 1), 1)
        %5 = 3.3129294231043339804683687620360224365
        ? exp(2) * cos(exp(2));
        %6 = 3.3129294231043339804683687620360224365
        ? derivnum(x = 2, f(x))
        %7 = 3.3129294231043339804683687620360224364 \\ 1 ulp off
        
        ? default(realprecision,115);
        ? for(i=1,10^4, laurentseries(x->f(x+2),1))
        time = 279 ms.
        ? for(i=1,10^4, derivnum(x=2,f(x))) \\ ... and slower
        time = 1,134 ms.
        '''
        f = objtogen(f)
        cdef long _M = -1
        if M is not None:
            _M = get_var(M)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        precision = nbits2prec(precision)
        cdef GEN _ret = laurentseries0(_f, serprec, _M, precision)
        return new_gen(_ret)

    def lcm(self, x, y=None):
        r'''
        Least common multiple of :math:`x` and :math:`y`, i.e. such
        that :math:`\mathrm{lcm} (x,y)*\mathrm{gcd} (x,y) = x*y`, up to units. If :math:`y` is omitted and :math:`x`
        is a vector, returns the :math:`lcm` of all components of :math:`x`.
        For integer arguments, return the non-negative lcm.

        When :math:`x` and :math:`y` are both given and one of them is a vector/matrix type,
        the LCM is again taken recursively on each component, but in a different way.
        If :math:`y` is a vector, resp. matrix, then the result has the same type as :math:`y`,
        and components equal to :literal:`lcm(x, y[i])`, resp. :literal:`lcm(x, y[,i])`. Else
        if :math:`x` is a vector/matrix the result has the same type as :math:`x` and an
        analogous definition. Note that for these types, :literal:`lcm` is not
        commutative.

        Note that :literal:`lcm(v)` is quite different from

        ::

        l = v[1]; for (i = 1, #v, l = lcm(l, v[i]))

        Indeed, :literal:`lcm(v)` is a scalar, but :literal:`l` may not be (if one of
        the :literal:`v[i]` is a vector/matrix). The computation uses a divide-conquer tree
        and should be much more efficient, especially when using the GMP
        multiprecision kernel (and more subquadratic algorithms become available):

        ::

        ? v = vector(10^5, i, random);
        ? lcm(v);
        time = 546 ms.
        ? l = v[1]; for (i = 1, #v, l = lcm(l, v[i]))
        time = 4,561 ms.
        '''
        x = objtogen(x)
        cdef bint _have_y = (y is not None)
        if _have_y:
            y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = NULL
        if _have_y:
            _y = (<Gen>y).g
        cdef GEN _ret = glcm0(_x, _y)
        return new_gen(_ret)

    def length(self, x):
        r'''
        Length of :math:`x`; :literal:`\#`:math:`x` is a shortcut for :literal:`length`:math:`(x)`.
        This is mostly useful for

        - vectors: dimension (0 for empty vectors),

        - lists: number of entries (0 for empty lists),

        - matrices: number of columns,

        - character strings: number of actual characters (without
        trailing :literal:`\\0`, should you expect it from :math:`C` :literal:`char*`).

        ::

        ? #"a string"
        %1 = 8
        ? #[3,2,1]
        %2 = 3
        ? #[]
        %3 = 0
        ? #matrix(2,5)
        %4 = 5
        ? L = List([1,2,3,4]); #L
        %5 = 4

        The routine is in fact defined for arbitrary GP types, but is awkward and
        useless in other cases: it returns the number of non-code words in :math:`x`, e.g.
        the effective length minus 2 for integers since the :literal:`t_INT` type has two code
        words.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = glength(_x)
        clear_stack()
        return _ret

    def lex(self, x, y):
        r'''
        Gives the result of a lexicographic comparison
        between :math:`x` and :math:`y` (as :math:`-1`, :math:`0` or :math:`1`). This is to be interpreted in quite
        a wide sense: It is admissible to compare objects of different types
        (scalars, vectors, matrices), provided the scalars can be compared, as well
        as vectors/matrices of different lengths. The comparison is recursive.

        In case all components are equal up to the smallest length of the operands,
        the more complex is considered to be larger. More precisely, the longest is
        the largest; when lengths are equal, we have matrix :math:`>` vector :math:`>` scalar.
        For example:

        ::

        ? lex([1,3], [1,2,5])
        %1 = 1
        ? lex([1,3], [1,3,-1])
        %2 = -1
        ? lex([1], [[1]])
        %3 = -1
        ? lex([1], [1]~)
        %4 = 0
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef int _ret = lexcmp(_x, _y)
        clear_stack()
        return _ret

    def lfun(self, L, s, long D=0, long precision=DEFAULT_BITPREC):
        r'''
        Compute the L-function value :math:`L(s)`, or if :literal:`D` is set, the
        derivative of order :literal:`D` at :math:`s`. The parameter
        :literal:`L` is either an Lmath, an Ldata (created by :literal:`lfuncreate`, or an
        Linit (created by :literal:`lfuninit`), preferrably the latter if many values
        are to be computed.

        The argument :math:`s` is also allowed to be a power series; for instance, if :math:`s =
        \alpha + x + O(x^n)`, the function returns the Taylor expansion of order :math:`n`
        around :math:`\alpha`. The result is given with absolute error less than :math:`2^{-B}`,
        where :math:`B = realbitprecision`.

        :strong:`Caveat.` The requested precision has a major impact on runtimes.
        It is advised to manipulate precision via :literal:`realbitprecision` as
        explained above instead of :literal:`realprecision` as the latter allows less
        granularity: :literal:`realprecision` increases by increments of 64 bits, i.e. 19
        decimal digits at a time.

        ::

        ? lfun(x^2+1, 2) \\ Lmath: Dedekind zeta for Q(i) at 2
        %1 = 1.5067030099229850308865650481820713960
        
        ? L = lfuncreate(ellinit("5077a1")); \\ Ldata: Hasse-Weil zeta function
        ? lfun(L, 1+x+O(x^4)) \\ zero of order 3 at the central point
        %3 = 0.E-58 - 5.[...] E-40*x + 9.[...] E-40*x^2 + 1.7318[...]*x^3 + O(x^4)
        
        \\ Linit: zeta(1/2+it), |t| < 100, and derivative
        ? L = lfuninit(1, [100], 1);
        ? T = lfunzeros(L, [1,25]);
        %5 = [14.134725[...], 21.022039[...]]
        ? z = 1/2 + I*T[1];
        ? abs( lfun(L, z) )
        %7 = 8.7066865533412207420780392991125136196 E-39
        ? abs( lfun(L, z, 1) )
        %8 = 0.79316043335650611601389756527435211412 \\ simple zero
        '''
        L = objtogen(L)
        s = objtogen(s)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _s = (<Gen>s).g
        cdef GEN _ret = lfun0(_L, _s, D, precision)
        return new_gen(_ret)

    def lfunabelianrelinit(self, bnfL, bnfK, polrel, sdom, long der=0, long precision=DEFAULT_BITPREC):
        r'''
        Returns the :literal:`Linit` structure attached to the Dedekind zeta function
        of the number field :math:`L` (see :literal:`lfuninit`), given a subfield :math:`K` such that
        :math:`L/K` is abelian.
        Here :literal:`polrel` defines :math:`L` over :math:`K`, as usual with the priority of the
        variable of :literal:`bnfK` lower than that of :literal:`polrel`.
        :literal:`sdom` and :literal:`der` are as in :literal:`lfuninit`.

        ::

        ? D = -47; K = bnfinit(y^2-D);
        ? rel = quadhilbert(D); T = rnfequation(K.pol, rel); \\ degree 10
        ? L = lfunabelianrelinit(T,K,rel, [2,0,0]); \\ at 2
        time = 84 ms.
        ? lfun(L, 2)
        %4 = 1.0154213394402443929880666894468182650
        ? lfun(T, 2) \\ using parisize > 300MB
        time = 652 ms.
        %5 = 1.0154213394402443929880666894468182656

        As the example shows, using the (abelian) relative structure
        is more efficient than a direct computation. The difference becomes drastic
        as the absolute degree increases while the subfield degree remains constant.
        '''
        bnfL = objtogen(bnfL)
        bnfK = objtogen(bnfK)
        polrel = objtogen(polrel)
        sdom = objtogen(sdom)
        sig_on()
        cdef GEN _bnfL = (<Gen>bnfL).g
        cdef GEN _bnfK = (<Gen>bnfK).g
        cdef GEN _polrel = (<Gen>polrel).g
        cdef GEN _sdom = (<Gen>sdom).g
        cdef GEN _ret = lfunabelianrelinit(_bnfL, _bnfK, _polrel, _sdom, der, precision)
        return new_gen(_ret)

    def lfunan(self, L, long n, long precision=DEFAULT_BITPREC):
        r'''
        Compute the first :math:`n` terms of the Dirichlet series attached to the
        :math:`L`-function given by :literal:`L` (:literal:`Lmath`, :literal:`Ldata` or :literal:`Linit`).

        ::

        ? lfunan(1, 10) \\ Riemann zeta
        %1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        ? lfunan(5, 10) \\ Dirichlet L-function for kronecker(5,.)
        %2 = [1, -1, -1, 1, 0, 1, -1, -1, 1, 0]
        '''
        L = objtogen(L)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        precision = nbits2prec(precision)
        cdef GEN _ret = lfunan(_L, n, precision)
        return new_gen(_ret)

    def lfunartin(self, nf, gal, rho, long n, long precision=DEFAULT_BITPREC):
        r'''
        Returns the :literal:`Ldata` structure attached to the
        Artin :math:`L`-function provided by the representation :math:`\rho` of the Galois group
        of the extension :math:`K/\mathbb{Q}`, defined over the cyclotomic field :math:`\mathbb{Q} (\zeta_n)`,
        where :emphasis:`nf` is the nfinit structure attached to :math:`K`,
        :emphasis:`gal` is the galoisinit structure attached to :math:`K/\mathbb{Q}`, and :emphasis:`rho` is
        given either

        - by the values of its character on the conjugacy classes
        (see :literal:`galoisconjclasses` and :literal:`galoischartable`)

        - or by the matrices that are the images of the generators
        :literal:`:emphasis:`gal`.gen`.

        Cyclotomic numbers in :literal:`rho` are represented by polynomials, whose
        variable is understood as the complex number :math:`\exp (2 i \pi/n)`.

        In the following example we build the Artin :math:`L`-functions attached to the two
        irreducible degree :math:`2` representations of the dihedral group :math:`D_{10}` defined
        over :math:`\mathbb{Q} (\zeta_5)`, for the extension :math:`H/\mathbb{Q}` where :math:`H` is the Hilbert class
        field of :math:`\mathbb{Q} (\sqrt{-47})`.
        We show numerically some identities involving Dedekind :math:`\zeta` functions and
        Hecke :math:`L` series.

        ::

        ? P = quadhilbert(-47)
        %1 = x^5 + 2*x^4 + 2*x^3 + x^2 - 1
        ? N = nfinit(nfsplitting(P));
        ? G = galoisinit(N); \\ D_10
        ? [T,n] = galoischartable(G);
        ? T \\ columns give the irreducible characters
        %5 =
        [1 1 2 2]
        
        [1 -1 0 0]
        
        [1 1 -y^3 - y^2 - 1 y^3 + y^2]
        
        [1 1 y^3 + y^2 -y^3 - y^2 - 1]
        ? n
        %6 = 5
        ? L2 = lfunartin(N,G, T[,2], n);
        ? L3 = lfunartin(N,G, T[,3], n);
        ? L4 = lfunartin(N,G, T[,4], n);
        ? s = 1 + x + O(x^4);
        ? lfun(-47,s) - lfun(L2,s)
        %11 ~ 0
        ? lfun(1,s)*lfun(-47,s)*lfun(L3,s)^2*lfun(L4,s)^2 - lfun(N,s)
        %12 ~ 0
        ? lfun(1,s)*lfun(L3,s)*lfun(L4,s) - lfun(P,s)
        %13 ~ 0
        ? bnr = bnrinit(bnfinit(x^2+47),1,1);
        ? bnr.cyc
        %15 = [5] \\ Z/5Z: 4 non-trivial ray class characters
        ? lfun([bnr,[1]], s) - lfun(L3, s)
        %16 ~ 0
        ? lfun([bnr,[2]], s) - lfun(L4, s)
        %17 ~ 0
        ? lfun([bnr,[3]], s) - lfun(L3, s)
        %18 ~ 0
        ? lfun([bnr,[4]], s) - lfun(L4, s)
        %19 ~ 0

        The first identity identifies the non-trivial abelian character with
        :math:`(-47,.)`; the second is the factorization of the regular representation of
        :math:`D_{10}`; the third is the factorization of the natural representation of
        :math:`D_{10}\subset S_5`; and the final four are the expressions of the degree :math:`2`
        representations as induced from degree :math:`1` representations.
        '''
        nf = objtogen(nf)
        gal = objtogen(gal)
        rho = objtogen(rho)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _gal = (<Gen>gal).g
        cdef GEN _rho = (<Gen>rho).g
        cdef GEN _ret = lfunartin(_nf, _gal, _rho, n, precision)
        return new_gen(_ret)

    def lfuncheckfeq(self, L, t=None, long precision=DEFAULT_BITPREC):
        r'''
        Given the data attached to an :math:`L`-function (:literal:`Lmath`, :literal:`Ldata`
        or :literal:`Linit`), check whether the functional equation is satisfied.
        This is most useful for an :literal:`Ldata` constructed "by hand", via
        :literal:`lfuncreate`, to detect mistakes.

        If the function has poles, the polar part must be specified. The routine
        returns a bit accuracy :math:`b` such that :math:`\|w - ^{w}\| < 2^{b}`, where :math:`w` is
        the root number contained in :literal:`data`, and

        .. MATH::

        ^{w} = \theta (1/t) t^{-k} / \overline{\theta}(t)

        is a computed value
        derived from the assumed functional equation. If the parameter :math:`t` is
        omitted, we try random samples on the real line in the segment
        :math:`[1, 1.25]`. Of course, a large negative value of the order of
        :literal:`realbitprecision` is expected but if :math:`\overline{\theta}` is very small
        all over the sampled segment, you should first increase
        :literal:`realbitprecision` by :math:`-\log_2 \|\overline{\theta}(t)\|` (which is
        positive if :math:`\theta` is small) to get a meaningful result.

        If :math:`t` is given, it should be close to the unit disc for efficiency and
        such that :math:`\overline{\theta}(t) != 0`. We then check the functional
        equation at that :math:`t`. Again, if :math:`\overline{\theta}(t)` is very small, you
        should first increase :literal:`realbitprecision` to get a useful result.

        ::

        ? \pb 128 \\ 128 bits of accuracy
        ? default(realbitprecision)
        %1 = 128
        ? L = lfuncreate(1); \\ Riemann zeta
        ? lfuncheckfeq(L)
        %3 = -124

        i.e. the given data is consistent to within 4 bits for the
        particular check consisting of estimating the root number from all other
        given quantities. Checking away from the unit disc will either fail with
        a precision error, or give disappointing results (if :math:`\theta (1/t)` is
        large it will be computed with a large absolute error)

        ::

        ? lfuncheckfeq(L, 2+I)
        %4 = -115
        ? lfuncheckfeq(L,10)
        *** at top-level: lfuncheckfeq(L,10)
        *** ^------------------
        *** lfuncheckfeq: precision too low in lfuncheckfeq.
        '''
        L = objtogen(L)
        cdef bint _have_t = (t is not None)
        if _have_t:
            t = objtogen(t)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _t = NULL
        if _have_t:
            _t = (<Gen>t).g
        cdef long _ret = lfuncheckfeq(_L, _t, precision)
        clear_stack()
        return _ret

    def lfunconductor(self, L, ab=None, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Compute the conductor of the given :math:`L`-function
        (if the structure contains a conductor, it is ignored);
        :math:`ab = [a,b]` is the interval where we expect to find the conductor;
        it may be given as a single scalar :math:`b`, in which case we look in :math:`[1,b]`.
        Increasing :literal:`ab` slows down the program but gives better accuracy for the
        result.

        If :literal:`flag` is :math:`0` (default), give either the conductor found as an
        integer, or a vector (possibly empty) of conductors found. If :literal:`flag` is
        :math:`1`, same but give the computed floating point approximations to the
        conductors found, without rounding to integers. It :literal:`flag` is :math:`2`, give
        all the conductors found, even those far from integers.

        :strong:`Caveat.` This is a heuristic program and the result is not
        proven in any way:

        ::

        ? L = lfuncreate(857); \\ Dirichlet L function for kronecker(857,.)
        ? \p19
        realprecision = 19 significant digits
        ? lfunconductor(L)
        %2 = [17, 857]
        ? lfunconductor(L,,1) \\ don't round
        %3 = [16.99999999999999999, 857.0000000000000000]
        
        ? \p38
        realprecision = 38 significant digits
        ? lfunconductor(L)
        %4 = 857

        :strong:`Note.` This program should only be used if the primes dividing the
        conductor are unknown, which is rare. If they are known, a direct
        search through possible prime exponents using :literal:`lfuncheckfeq` will
        be more efficient and rigorous:

        ::

        ? E = ellinit([0,0,0,4,0]); /* Elliptic curve y^2 = x^3+4x */
        ? E.disc \\ |disc E| = 2^12
        %2 = -4096
        \\ create Ldata by hand. Guess that root number is 1 and conductor N
        ? L(N) = lfuncreate([n->ellan(E,n), 0, [0,1], 2, N, 1]);
        ? fordiv(E.disc, d, print(d,": ",lfuncheckfeq(L(d))))
        1: 0
        2: 0
        4: -1
        8: -2
        16: -3
        32: -127
        64: -3
        128: -2
        256: -2
        512: -1
        1024: -1
        2048: 0
        4096: 0
        ? lfunconductor(L(1)) \\ lfunconductor ignores conductor = 1 in Ldata !
        %5 = 32

        The above code assumed that root number was :math:`1`;
        had we set it to :math:`-1`, none of the :literal:`lfuncheckfeq` values would have been
        acceptable:

        ::

        ? L2(N) = lfuncreate([n->ellan(E,n), 0, [0,1], 2, N, -1]);
        ? [ lfuncheckfeq(L2(d)) | d<-divisors(E.disc) ]
        %7 = [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, -1, -1]
        '''
        L = objtogen(L)
        cdef bint _have_ab = (ab is not None)
        if _have_ab:
            ab = objtogen(ab)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _ab = NULL
        if _have_ab:
            _ab = (<Gen>ab).g
        cdef GEN _ret = lfunconductor(_L, _ab, flag, precision)
        return new_gen(_ret)

    def lfuncost(self, L, sdom=None, long der=0, long precision=DEFAULT_BITPREC):
        r'''
        Estimate the cost of running
        :literal:`lfuninit(L,sdom,der)` at current bit precision. Returns :math:`[t,b]`, to
        indicate that :math:`t` coefficients :math:`a_n` will be computed, as well as :math:`t` values of
        :literal:`gammamellininv`, all at bit accuracy :math:`b`.
        A subsequent call to :literal:`lfun` at :math:`s` evaluates a polynomial of degree :math:`t`
        at :math:`\exp (h s)` for some real parameter :math:`h`, at the same bit accuracy :math:`b`.
        If :math:`L` is already an :literal:`Linit`, then :emphasis:`sdom` and :emphasis:`der` are ignored
        and are best left omitted; the bit accuracy is also inferred from :math:`L`: in
        short we get an estimate of the cost of using that particular :literal:`Linit`.

        ::

        ? \pb 128
        ? lfuncost(1, [100]) \\ for zeta(1/2+I*t), |t| < 100
        %1 = [7, 242] \\ 7 coefficients, 242 bits
        ? lfuncost(1, [1/2, 100]) \\ for zeta(s) in the critical strip, |Im s| < 100
        %2 = [7, 246] \\ now 246 bits
        ? lfuncost(1, [100], 10) \\ for zeta(1/2+I*t), |t| < 100
        %3 = [8, 263] \\ 10th derivative increases the cost by a small amount
        ? lfuncost(1, [10^5])
        %3 = [158, 113438] \\ larger imaginary part: huge accuracy increase
        
        ? L = lfuncreate(polcyclo(5)); \\ Dedekind zeta for Q(zeta_5)
        ? lfuncost(L, [100]) \\ at s = 1/2+I*t), |t| < 100
        %5 = [11457, 582]
        ? lfuncost(L, [200]) \\ twice higher
        %6 = [36294, 1035]
        ? lfuncost(L, [10^4]) \\ much higher: very costly !
        %7 = [70256473, 45452]
        ? \pb 256
        ? lfuncost(L, [100]); \\ doubling bit accuracy
        %8 = [17080, 710]

        In fact, some :math:`L` functions can be factorized algebraically
        by the :literal:`lfuninit` call, e.g. the Dedekind zeta function of abelian
        fields, leading to much faster evaluations than the above upper bounds.
        In that case, the function returns a vector of costs as above for each
        individual function in the product actually evaluated:

        ::

        ? L = lfuncreate(polcyclo(5)); \\ Dedekind zeta for Q(zeta_5)
        ? lfuncost(L, [100]) \\ a priori cost
        %2 = [11457, 582]
        ? L = lfuninit(L, [100]); \\ actually perform all initializations
        ? lfuncost(L)
        %4 = [[16, 242], [16, 242], [7, 242]]

        The Dedekind function of this abelian quartic field
        is the product of four Dirichlet :math:`L`-functions attached to the trivial
        character, a non-trivial real character and two complex conjugate
        characters. The non-trivial characters happen to have the same conductor
        (hence same evaluation costs), and correspond to two evaluations only
        since the two conjugate characters are evaluated simultaneously.
        For a total of three :math:`L`-functions evaluations, which explains the three
        components above. Note that the actual cost is much lower than the a priori
        cost in this case.
        '''
        L = objtogen(L)
        cdef bint _have_sdom = (sdom is not None)
        if _have_sdom:
            sdom = objtogen(sdom)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _sdom = NULL
        if _have_sdom:
            _sdom = (<Gen>sdom).g
        cdef GEN _ret = lfuncost0(_L, _sdom, der, precision)
        return new_gen(_ret)

    def lfuncreate(self, obj):
        r'''
        This low-level routine creates :literal:`Ldata` structures, needed by
        :emphasis:`lfun` functions, describing an :math:`L`-function and its functional equation.
        You are urged to use a high-level constructor when one is available,
        and this function accepts them, see :literal:`??lfun`:

        ::

        ? L = lfuncreate(1); \\ Riemann zeta
        ? L = lfuncreate(5); \\ Dirichlet L-function for quadratic character (5/.)
        ? L = lfuncreate(x^2+1); \\ Dedekind zeta for Q(i)
        ? L = lfuncreate(ellinit([0,1])); \\ L-function of E/Q: y^2=x^3+1

        One can then use, e.g., :literal:`Lfun(L,s)` to directly
        evaluate the respective :math:`L`-functions at :math:`s`, or :literal:`lfuninit(L, [c,w,h]`
        to initialize computations in the rectangular box :math:`\Re (s-c) <= w`,
        :math:`\Im (s) <= h`.

        We now describe the low-level interface, used to input non-builtin
        :math:`L`-functions. The input is now a :math:`6` or :math:`7` component vector
        :math:`V = [a, astar, Vga, k, N, eps, poles]`, whose components are as follows:

        - :literal:`V[1] = a` encodes the Dirichlet series coefficients :math:`(a_n)`. The
        preferred format is a closure of arity 1: :literal:`n- > vector(n,i,a(i))` giving
        the vector of the first :math:`n` coefficients. The closure is allowed to return
        a vector of more than :math:`n` coefficients (only the first :math:`n` will be
        considered) or even less than :math:`n`, in which case loss of accuracy will occur
        and a warning that :literal:`\#an` is less than expected is issued. This
        allows to precompute and store a fixed large number of Dirichlet
        coefficients in a vector :math:`v` and use the closure :literal:`n- > v`, which
        does not depend on :math:`n`. As a shorthand for this latter case, you can input
        the vector :math:`v` itself instead of the closure.

        ::

        ? z = lfuncreate([n->vector(n,i,1), 1, [0], 1, 1, 1, 1]); \\ Riemann zeta
        ? lfun(z,2) - Pi^2/6
        %2 = -5.877471754111437540 E-39

        A second format is limited to :math:`L`-functions affording an
        Euler product. It is a closure of arity 2 :literal:`(p,d)- > F(p)` giving the
        local factor :math:`L_p(X)` at :math:`p` as a rational function, to be evaluated at
        :math:`p^{-s}` as in :literal:`direuler`; :math:`d` is set to :literal:`logint`:math:`(n,p)` + 1, where
        :math:`n` is the total number of Dirichlet coefficients :math:`(a_1,...,a_n)` that will
        be computed. In other words, the smallest integer :math:`d` such that :math:`p^d > n`.
        This parameter :math:`d` allows to compute only part of
        :math:`L_p` when :math:`p` is large and :math:`L_p` expensive to compute: any polynomial
        (or :literal:`t_SER`) congruent to :math:`L_p` modulo :math:`X^d` is acceptable since only
        the coefficients of :math:`X^0,..., X^{d-1}` are needed to expand the Dirichlet
        series. The closure can of course ignore this parameter:

        ::

        ? z = lfuncreate([(p,d)->1/(1-x), 1, [0], 1, 1, 1, 1]); \\ Riemann zeta
        ? lfun(z,2) - Pi^2/6
        %4 = -5.877471754111437540 E-39

        One can describe separately the generic local factors coefficients
        and the bad local factors by setting :math:`dir = [F, L_{bad}]`,
        were :math:`L_{bad} = [[p_1,L_{p_1}],...,[p_k,L_{p_k}]]`, where :math:`F`
        describes the generic local factors as above, except that when :math:`p = p_i`
        for some :math:`i <= k`, the coefficient :math:`a_p` is directly set to :math:`L_{p_i}`
        instead of calling :math:`F`.

        ::

        N = 15;
        E = ellinit([1, 1, 1, -10, -10]); \\ = "15a1"
        F(p,d) = 1 / (1 - ellap(E,p)*'x + p*'x^2);
        Lbad = [[3, 1/(1+'x)], [5, 1/(1-'x)]];
        L = lfuncreate([[F,Lbad], 0, [0,1], 2, N, ellrootno(E)]);

        Of course, in this case, :literal:`lfuncreate(E)` is preferable!

        - :literal:`V[2] = astar` is the Dirichlet series coefficients of the dual
        function, encoded as :literal:`a` above. The sentinel values :math:`0` and :math:`1` may
        be used for the special cases where :math:`a = a^*` and :math:`a = \overline{a^*}`,
        respectively.

        - :literal:`V[3] = Vga` is the vector of :math:`\alpha_j` such that the gamma
        factor of the :math:`L`-function is equal to
        

        .. MATH::

        \gamma_A(s) = \prod_{1 <= j <= d}\Gamma_{\mathbb{R}}(s+\alpha_j),

        where :math:`\Gamma_{\mathbb{R}}(s) = \pi^{-s/2}\Gamma (s/2)`.
        This same syntax is used in the :literal:`gammamellininv` functions.
        In particular the length :math:`d` of :literal:`Vga` is the degree of the :math:`L`-function.
        In the present implementation, the :math:`\alpha_j` are assumed to be exact
        rational numbers. However when calling theta functions with :emphasis:`complex`
        (as opposed to real) arguments, determination problems occur which may
        give wrong results when the :math:`\alpha_j` are not integral.

        - :literal:`V[4] = k` is a positive integer :math:`k`. The functional equation relates
        values at :math:`s` and :math:`k-s`. For instance, for an Artin :math:`L`-series such as a
        Dedekind zeta function we have :math:`k = 1`, for an elliptic curve :math:`k = 2`, and
        for a modular form, :math:`k` is its weight. For motivic :math:`L`-functions, the
        :emphasis:`motivic` weight :math:`w` is :math:`w = k-1`.

        By default we assume that :math:`a_n = O_\epsilon (n^{k_1+\epsilon})`, where
        :math:`k_1 = w` and even :math:`k_1 = w/2` when the :math:`L` function has no pole
        (Ramanujan-Petersson). If this is not the case, you can replace the
        :math:`k` argument by a vector :math:`[k,k_1]`, where :math:`k_1` is the upper bound you can
        assume.

        - :literal:`V[5] = N` is the conductor, an integer :math:`N >= 1`, such that
        :math:`\Lambda (s) = N^{s/2}\gamma_A(s)L(s)` with :math:`\gamma_A(s)` as above.

        - :literal:`V[6] = eps` is the root number :math:`\varepsilon`, i.e., the
        complex number (usually of modulus :math:`1`) such that
        :math:`\Lambda (a, k-s) = \varepsilon \Lambda (a^*, s)`.

        - The last optional component :literal:`V[7] = poles` encodes the poles of the
        :math:`L` or :math:`\Lambda`-functions, and is omitted if they have no poles.
        A polar part is given by a list of :math:`2`-component vectors
        :math:`[\beta,P_{\beta}(x)]`, where
        :math:`\beta` is a pole and the power series :math:`P_{\beta}(x)` describes
        the attached polar part, such that :math:`L(s) - P_\beta (s-\beta)` is holomorphic
        in a neighbourhood of :math:`\beta`. For instance :math:`P_\beta = r/x+O(1)` for a
        simple pole at :math:`\beta` or :math:`r_1/x^2+r_2/x+O(1)` for a double pole.
        The type of the list describing the polar part allows to distinguish between
        :math:`L` and :math:`\Lambda`: a :literal:`t_VEC` is attached to :math:`L`, and a :literal:`t_COL`
        is attached to :math:`\Lambda`. Unless :math:`a = \overline{a^*}` (coded by :literal:`astar`
        equal to :math:`0` or :math:`1`), it is mandatory to specify the polar part of :math:`\Lambda`
        rather than those of :math:`L` since the poles of :math:`L^*` cannot be infered from the
        latter ! Whereas the functional equation allows to deduce the polar part of
        :math:`\Lambda^*` from the polar part of :math:`\Lambda`.

        Finally, if :math:`a = \overline{a^*}`, we allow a shortcut to describe
        the frequent situation where :math:`L` has at most simple pole, at :math:`s = k`,
        with residue :math:`r` a complex scalar: you may then input :math:`poles = r`.
        This value :math:`r` can be set to :math:`0` if unknown and it will be computed.
        '''
        obj = objtogen(obj)
        sig_on()
        cdef GEN _obj = (<Gen>obj).g
        cdef GEN _ret = lfuncreate(_obj)
        return new_gen(_ret)

    def lfundiv(self, L1, L2, long precision=DEFAULT_BITPREC):
        r'''
        Creates the :literal:`Ldata` structure (without initialization) corresponding
        to the quotient of the Dirichlet series :math:`L_1` and :math:`L_2` given by
        :literal:`L1` and :literal:`L2`. Assume that :math:`v_z(L_1) >= v_z(L_2)` at all
        complex numbers :math:`z`: the construction may not create new poles, nor increase
        the order of existing ones.
        '''
        L1 = objtogen(L1)
        L2 = objtogen(L2)
        sig_on()
        cdef GEN _L1 = (<Gen>L1).g
        cdef GEN _L2 = (<Gen>L2).g
        cdef GEN _ret = lfundiv(_L1, _L2, precision)
        return new_gen(_ret)

    def lfunetaquo(self, M):
        r'''
        Returns the :literal:`Ldata` structure attached to the :math:`L` function
        attached to the modular form
        :math:`z:--->\prod_{i = 1}^n \eta (M_{i,1} z)^{M_{i,2}}`
        It is currently assumed that :math:`f` is a self-dual cuspidal form on
        :math:`\Gamma_0(N)` for some :math:`N`.
        For instance, the :math:`L`-function :math:`\sum \tau (n) n^{-s}`
        attached to Ramanujan's :math:`\Delta` function is encoded as follows

        ::

        ? L = lfunetaquo(Mat([1,24]));
        ? lfunan(L, 100) \\ first 100 values of tau(n)

        For convenience, a :literal:`t_VEC` is also accepted instead of
        a factorization matrix with a single row:

        ::

        ? L = lfunetaquo([1,24]); \\ same as above
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = lfunetaquo(_M)
        return new_gen(_ret)

    def lfungenus2(self, F):
        r'''
        Returns the :literal:`Ldata` structure attached to the :math:`L` function
        attached to the genus-2 curve defined by :math:`y^2 = F(x)` or
        :math:`y^2+Q(x) y = P(x)` if :math:`F = [P,Q]`.
        Currently, the model needs to be minimal at 2, and if the conductor
        is even, its valuation at :math:`2` might be incorrect (a warning is issued).
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = lfungenus2(_F)
        return new_gen(_ret)

    def lfunhardy(self, L, t, long precision=DEFAULT_BITPREC):
        r'''
        Variant of the Hardy :math:`Z`-function given by :literal:`L`, used for
        plotting or locating zeros of :math:`L(k/2+it)` on the critical line.
        The precise definition is as
        follows: if as usual :math:`k/2` is the center of the critical strip, :math:`d` is the
        degree, :math:`\alpha_j` the entries of :literal:`Vga` giving the gamma factors,
        and :math:`\varepsilon` the root number, then if we set
        :math:`s = k/2+it = \rho e^{i\theta}` and
        :math:`E = (d(k/2-1)+\sum_{1 <= j <= d}\alpha_j)/2`, the computed function at :math:`t` is
        equal to

        .. MATH::

        Z(t) = \varepsilon^{-1/2}\Lambda (s).\|s\|^{-E}e^{dt\theta/2} ,

        which is a real function of :math:`t` for self-dual :math:`\Lambda`,
        vanishing exactly when :math:`L(k/2+it)` does on the critical line. The
        normalizing factor :math:`\|s\|^{-E}e^{dt\theta/2}` compensates the
        exponential decrease of :math:`\gamma_A(s)` as :math:`t\to oo` so that
        :math:`Z(t) ~ 1`.

        ::

        ? T = 100; \\ maximal height
        ? L = lfuninit(1, [T]); \\ initialize for zeta(1/2+it), |t|<T
        ? \p19 \\ no need for large accuracy
        ? ploth(t = 0, T, lfunhardy(L,t))

        Using :literal:`lfuninit` is critical for this particular
        applications since thousands of values are computed. Make sure to initialize
        up to the maximal :math:`t` needed: otherwise expect to see many warnings for
        unsufficient initialization and suffer major slowdowns.
        '''
        L = objtogen(L)
        t = objtogen(t)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _t = (<Gen>t).g
        cdef GEN _ret = lfunhardy(_L, _t, precision)
        return new_gen(_ret)

    def lfuninit(self, L, sdom, long der=0, long precision=DEFAULT_BITPREC):
        r'''
        Initalization function for all functions linked to the
        computation of the :math:`L`-function :math:`L(s)` encoded by :literal:`L`, where
        :math:`s` belongs to the rectangular domain :math:`sdom = [center,w,h]`
        centered on the real axis, :math:`\|\Re (s)-center\| <= w`, :math:`\|\Im (s)\| <= h`,
        where all three components of :literal:`sdom` are real and :math:`w`, :math:`h` are
        non-negative. :literal:`der` is the maximum order of derivation that will be used.
        The subdomain :math:`[k/2, 0, h]` on the critical line (up to height :math:`h`)
        can be encoded as :math:`[h]` for brevity. The subdomain :math:`[k/2, w, h]`
        centered on the critical line can be encoded as :math:`[w, h]` for brevity.

        The argument :literal:`L` is an :literal:`Lmath`, an :literal:`Ldata` or an :literal:`Linit`. See
        :literal:`??Ldata` and :literal:`??lfuncreate` for how to create it.

        The height :math:`h` of the domain is a :emphasis:`crucial` parameter: if you only
        need :math:`L(s)` for real :math:`s`, set :math:`h` to 0.
        The running time is roughly proportional to

        .. MATH::

        (B / d+\pi h/4)^{d/2+3}N^{1/2},

        where :math:`B` is the default bit accuracy, :math:`d` is the degree of the
        :math:`L`-function, and :math:`N` is the conductor (the exponent :math:`d/2+3` is reduced
        to :math:`d/2+2` when :math:`d = 1` and :math:`d = 2`). There is also a dependency on :math:`w`,
        which is less crucial, but make sure to use the smallest rectangular
        domain that you need.

        ::

        ? L0 = lfuncreate(1); \\ Riemann zeta
        ? L = lfuninit(L0, [1/2, 0, 100]); \\ for zeta(1/2+it), |t| < 100
        ? lfun(L, 1/2 + I)
        ? L = lfuninit(L0, [100]); \\ same as above !
        '''
        L = objtogen(L)
        sdom = objtogen(sdom)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _sdom = (<Gen>sdom).g
        cdef GEN _ret = lfuninit0(_L, _sdom, der, precision)
        return new_gen(_ret)

    def lfunlambda(self, L, s, long D=0, long precision=DEFAULT_BITPREC):
        r'''
        Compute the completed :math:`L`-function :math:`\Lambda (s) = N^{s/2}\gamma (s)L(s)`,
        or if :literal:`D` is set, the derivative of order :literal:`D` at :math:`s`.
        The parameter :literal:`L` is either an :literal:`Lmath`, an :literal:`Ldata` (created by
        :literal:`lfuncreate`, or an :literal:`Linit` (created by :literal:`lfuninit`), preferrably the
        latter if many values are to be computed.

        The result is given with absolute error less than :math:`2^{-B}\|\gamma (s)N^{s/2}\|`,
        where :math:`B = realbitprecision`.
        '''
        L = objtogen(L)
        s = objtogen(s)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _s = (<Gen>s).g
        cdef GEN _ret = lfunlambda0(_L, _s, D, precision)
        return new_gen(_ret)

    def lfunmf(self, mf, F=None, long precision=DEFAULT_BITPREC):
        r'''
        If :math:`F` is a modular form in :literal:`mf`, output the L-functions
        corresponding to its :math:`[\mathbb{Q} (F):\mathbb{Q} (\chi)]` complex embeddings, ready for use with
        the :literal:`lfun` package. If :math:`F` is omitted, output the :math:`L`-functions attached
        to all eigenforms in the new space; the result is a vector whose length is
        the number of Galois orbits of newforms. Each entry contains the vector of
        :math:`L`-functions corresponding to the :math:`d` complex embeddings of an orbit of
        dimension :math:`d` over :math:`\mathbb{Q} (\chi)`.

        ::

        ? mf = mfinit([35,2],0);mffields(mf)
        %1 = [y, y^2 - y - 4]
        ? f = mfeigenbasis(mf)[2]; mfparams(f) \\ orbit of dimension two
        %2 = [35, 2, 1, y^2 - y - 4]
        ? [L1,L2] = lfunmf(mf, f); \\ Two L-functions
        ? lfun(L1,1)
        %4 = 0.81018461849460161754947375433874745585
        ? lfun(L2,1)
        %5 = 0.46007635204895314548435893464149369804
        ? [ lfun(L,1) | L <- concat(lfunmf(mf)) ]
        %6 = [0.70291..., 0.81018..., 0.46007...]

        The :literal:`concat` instruction concatenates the vectors
        corresponding to the various (here two) orbits, so that we obtain the vector
        of all the :math:`L`-functions attached to eigenforms.
        '''
        mf = objtogen(mf)
        cdef bint _have_F = (F is not None)
        if _have_F:
            F = objtogen(F)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _F = NULL
        if _have_F:
            _F = (<Gen>F).g
        cdef GEN _ret = lfunmf(_mf, _F, precision)
        return new_gen(_ret)

    def lfunmfspec(self, L, long precision=DEFAULT_BITPREC):
        r'''
        Returns :literal:`[valeven,valodd,omminus,omplus]`,
        where :literal:`valeven` (resp., :literal:`valodd`) is the vector of even (resp., odd)
        periods of the modular form given by :literal:`L`, and :literal:`omminus` and
        :literal:`omplus` the corresponding real numbers :math:`\omega^-` and :math:`\omega^+`
        normalized in a noncanonical way. For the moment, only for modular forms of even weight.
        '''
        L = objtogen(L)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _ret = lfunmfspec(_L, precision)
        return new_gen(_ret)

    def lfunmul(self, L1, L2, long precision=DEFAULT_BITPREC):
        r'''
        Creates the :literal:`Ldata` structure (without initialization) corresponding
        to the product of the Dirichlet series given by :literal:`L1` and
        :literal:`L2`.
        '''
        L1 = objtogen(L1)
        L2 = objtogen(L2)
        sig_on()
        cdef GEN _L1 = (<Gen>L1).g
        cdef GEN _L2 = (<Gen>L2).g
        cdef GEN _ret = lfunmul(_L1, _L2, precision)
        return new_gen(_ret)

    def lfunorderzero(self, L, long m=-1, long precision=DEFAULT_BITPREC):
        r'''
        Computes the order of the possible zero of the :math:`L`-function at the
        center :math:`k/2` of the critical strip; return :math:`0` if :math:`L(k/2)` does not vanish.

        If :math:`m` is given and has a non-negative value, assumes the order is at most :math:`m`.
        Otherwise, the algorithm chooses a sensible default:

        - if the :math:`L` argument is an :literal:`Linit`, assume that a multiple zero at
        :math:`s = k / 2` has order less than or equal to the maximal allowed derivation
        order.

        - else assume the order is less than :math:`4`.

        You may explicitly increase this value using optional argument :math:`m`; this
        overrides the default value above. (Possibly forcing a recomputation
        of the :literal:`Linit`.)
        '''
        L = objtogen(L)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef long _ret = lfunorderzero(_L, m, precision)
        clear_stack()
        return _ret

    def lfunqf(self, Q, long precision=DEFAULT_BITPREC):
        r'''
        Returns the :literal:`Ldata` structure attached to the :math:`\Theta` function
        of the lattice attached to the definite positive quadratic form :math:`Q`.

        ::

        ? L = lfunqf(matid(2));
        ? lfunqf(L,2)
        %2 = 6.0268120396919401235462601927282855839
        ? lfun(x^2+1,2)*4
        %3 = 6.0268120396919401235462601927282855839
        '''
        Q = objtogen(Q)
        sig_on()
        cdef GEN _Q = (<Gen>Q).g
        precision = nbits2prec(precision)
        cdef GEN _ret = lfunqf(_Q, precision)
        return new_gen(_ret)

    def lfunrootres(self, data, long precision=DEFAULT_BITPREC):
        r'''
        Given the :literal:`Ldata` attached to an :math:`L`-function (or the output of
        :literal:`lfunthetainit`), compute the root number and the residues.

        The output is a 3-component vector
        :math:`[[[a_1,r_1],...,[a_n, r_n], [[b_1, R_1],...,[b_m, R_m]], w]`,
        where :math:`r_i` is the
        polar part of :math:`L(s)` at :math:`a_i`, :math:`R_i` is is the polar part of :math:`\Lambda (s)` at
        :math:`b_i` or :math:`[0,0,r]` if there is no pole,
        and :math:`w` is the root number. In the present implementation,

        - either the polar part must be completely known (and is then arbitrary):
        the function determines the root number,

        ::

        ? L = lfunmul(1,1); \\ zeta^2
        ? [r,R,w] = lfunrootres(L);
        ? r \\ single pole at 1, double
        %3 = [[1, 1.[...]*x^-2 + 1.1544[...]*x^-1 + O(x^0)]]
        ? w
        %4 = 1
        ? R \\ double pole at 0 and 1
        %5 = [[1,[...]], [0,[...]]

        - or at most a single pole is allowed: the function computes both
        the root number and the residue (:math:`0` if no pole).
        '''
        data = objtogen(data)
        sig_on()
        cdef GEN _data = (<Gen>data).g
        cdef GEN _ret = lfunrootres(_data, precision)
        return new_gen(_ret)

    def lfunsympow(self, E, unsigned long m):
        r'''
        Returns the :literal:`Ldata` structure attached to the :math:`L` function
        attached to the :math:`m`-th symmetric power of the elliptic curve :math:`E` defined over
        the rationals.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = lfunsympow(_E, m)
        return new_gen(_ret)

    def lfuntheta(self, data, t, long m=0, long precision=DEFAULT_BITPREC):
        r'''
        Compute the value of the :math:`m`-th derivative
        at :math:`t` of the theta function attached to the :math:`L`-function given by :literal:`data`.
        :literal:`data` can be either the standard :math:`L`-function data, or the output of
        :literal:`lfunthetainit`. The result is given with absolute error less than
        :math:`2^{-B}`, where :math:`B = realbitprecision`.

        The theta function is defined by the formula
        :math:`\Theta (t) = \sum_{n >= 1}a(n)K(nt/\sqrt (N))`, where :math:`a(n)` are the coefficients
        of the Dirichlet series, :math:`N` is the conductor, and :math:`K` is the inverse Mellin
        transform of the gamma product defined by the :literal:`Vga` component.
        Its Mellin transform is equal to :math:`\Lambda (s)-P(s)`, where :math:`\Lambda (s)`
        is the completed :math:`L`-function and the rational function :math:`P(s)` its polar part.
        In particular, if the :math:`L`-function is the :math:`L`-function of a modular form
        :math:`f(\tau) = \sum_{n >= 0}a(n)q^n` with :math:`q = \exp (2\pi i\tau)`, we have
        :math:`\Theta (t) = 2(f(it/\sqrt{N})-a(0))`. Note that :math:`a(0) = -L(f,0)` in this case.
        '''
        data = objtogen(data)
        t = objtogen(t)
        sig_on()
        cdef GEN _data = (<Gen>data).g
        cdef GEN _t = (<Gen>t).g
        cdef GEN _ret = lfuntheta(_data, _t, m, precision)
        return new_gen(_ret)

    def lfunthetacost(self, L, tdom=None, long m=0, long precision=DEFAULT_BITPREC):
        r'''
        This function estimates the cost of running
        :literal:`lfunthetainit(L,tdom,m)` at current bit precision. Returns the number of
        coefficients :math:`a_n` that would be computed. This also estimates the
        cost of a subsequent evaluation :literal:`lfuntheta`, which must compute
        that many values of :literal:`gammamellininv` at the current bit precision.
        If :math:`L` is already an :literal:`Linit`, then :emphasis:`tdom` and :math:`m` are ignored
        and are best left omitted: we get an estimate of the cost of using that
        particular :literal:`Linit`.

        ::

        ? \pb 1000
        ? L = lfuncreate(1); \\ Riemann zeta
        ? lfunthetacost(L); \\ cost for theta(t), t real >= 1
        %1 = 15
        ? lfunthetacost(L, 1 + I); \\ cost for theta(1+I). Domain error !
        *** at top-level: lfunthetacost(1,1+I)
        *** ^--------------------
        *** lfunthetacost: domain error in lfunthetaneed: arg t > 0.785
        ? lfunthetacost(L, 1 + I/2) \\ for theta(1+I/2).
        %2 = 23
        ? lfunthetacost(L, 1 + I/2, 10) \\ for theta^((10))(1+I/2).
        %3 = 24
        ? lfunthetacost(L, [2, 1/10]) \\ cost for theta(t), |t| >= 2, |arg(t)| < 1/10
        %4 = 8
        
        ? L = lfuncreate( ellinit([1,1]) );
        ? lfunthetacost(L) \\ for t >= 1
        %6 = 2471
        '''
        L = objtogen(L)
        cdef bint _have_tdom = (tdom is not None)
        if _have_tdom:
            tdom = objtogen(tdom)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _tdom = NULL
        if _have_tdom:
            _tdom = (<Gen>tdom).g
        cdef long _ret = lfunthetacost0(_L, _tdom, m, precision)
        clear_stack()
        return _ret

    def lfunthetainit(self, L, tdom=None, long m=0, long precision=DEFAULT_BITPREC):
        r'''
        Initalization function for evaluating the :math:`m`-th derivative of theta
        functions with argument :math:`t` in domain :emphasis:`tdom`. By default (:emphasis:`tdom`
        omitted), :math:`t` is real, :math:`t >= 1`. Otherwise, :emphasis:`tdom` may be

        - a positive real scalar :math:`\rho`: :math:`t` is real, :math:`t >= \rho`.

        - a non-real complex number: compute at this particular :math:`t`; this
        allows to compute :math:`\theta (z)` for any complex :math:`z` satisfying :math:`\|z\| >= \|t\|`
        and :math:`\|\arg z\| <= \|\arg t\|`; we must have :math:`\|2 \arg z / d\| < \pi/2`, where
        :math:`d` is the degree of the :math:`\Gamma` factor.

        - a pair :math:`[\rho,\alpha]`: assume that :math:`\|t\| >= \rho` and :math:`\|\arg t\| \leq
        \alpha`; we must have :math:`\|2\alpha / d\| < \pi/2`, where :math:`d` is the degree of
        the :math:`\Gamma` factor.

        ::

        ? \p500
        ? L = lfuncreate(1); \\ Riemann zeta
        ? t = 1+I/2;
        ? lfuntheta(L, t); \\ direct computation
        time = 30 ms.
        ? T = lfunthetainit(L, 1+I/2);
        time = 30 ms.
        ? lfuntheta(T, t); \\ instantaneous

        The :math:`T` structure would allow to quickly compute :math:`\theta (z)`
        for any :math:`z` in the cone delimited by :math:`t` as explained above. On the other hand

        ::

        ? lfuntheta(T,I)
        *** at top-level: lfuntheta(T,I)
        *** ^--------------
        *** lfuntheta: domain error in lfunthetaneed: arg t > 0.785398163397448

        The initialization is equivalent to

        ::

        ? lfunthetainit(L, [abs(t), arg(t)])
        '''
        L = objtogen(L)
        cdef bint _have_tdom = (tdom is not None)
        if _have_tdom:
            tdom = objtogen(tdom)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _tdom = NULL
        if _have_tdom:
            _tdom = (<Gen>tdom).g
        cdef GEN _ret = lfunthetainit(_L, _tdom, m, precision)
        return new_gen(_ret)

    def lfuntwist(self, L, chi):
        r'''
        Creates the Ldata structure (without initialization) corresponding to the
        twist of L by the primitive character attached to the Dirichlet character
        :literal:`chi`. The conductor of the character must be coprime to the conductor
        of the L-function :math:`L`.
        '''
        L = objtogen(L)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = lfuntwist(_L, _chi)
        return new_gen(_ret)

    def lfunzeros(self, L, lim, long divz=8, long precision=DEFAULT_BITPREC):
        r'''
        :literal:`lim` being either a positive upper limit or a non-empty real
        interval inside :math:`[0,+ oo [`, computes an
        ordered list of zeros of :math:`L(s)` on the critical line up to the given
        upper limit or in the given interval. Use a naive algorithm which may miss
        some zeros: it assumes that two consecutive zeros at height :math:`T >= 1`
        differ at least by :math:`2\pi/\omega`, where

        .. MATH::

        \omega := divz.(d\log (T/2\pi) +d+ 2\log (N/(\pi/2)^d)).

        To use a finer search mesh, set divz to some integral value
        larger than the default ( = 8).

        ::

        ? lfunzeros(1, 30) \\ zeros of Rieman zeta up to height 30
        %1 = [14.134[...], 21.022[...], 25.010[...]]
        ? #lfunzeros(1, [100,110]) \\ count zeros with 100 <= Im(s) <= 110
        %2 = 4

        The algorithm also assumes that all zeros are simple except
        possibly on the real axis at :math:`s = k/2` and that there are no poles in the
        search interval. (The possible zero at :math:`s = k/2` is repeated according to
        its multiplicity.)

        Should you pass an :literal:`Linit` argument to the function, beware that the
        algorithm needs at least

        ::

        L = lfuninit(Ldata, [T+1])

        where :math:`T` is the upper bound of the interval defined by
        :literal:`lim`: this allows to detect zeros near :math:`T`. Make sure that your
        :literal:`Linit` domain contains this one, i.e. a domain :math:`[1,T+1]` is fine but
        :math:`[0, T]` is not! The algorithm assumes that a multiple zero at :math:`s = k / 2`
        has order less than or equal to the maximal derivation order allowed by the
        :literal:`Linit`. You may increase that value in the :literal:`Linit` but this is
        costly: only do it for zeros of low height or in :literal:`lfunorderzero` instead.
        '''
        L = objtogen(L)
        lim = objtogen(lim)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _lim = (<Gen>lim).g
        cdef GEN _ret = lfunzeros(_L, _lim, divz, precision)
        return new_gen(_ret)

    def lift(self, x, v=None):
        r'''
        If :math:`v` is omitted, lifts intmods from :math:`\mathbb{Z}/n\mathbb{Z}` in :math:`\mathbb{Z}`,
        :math:`p`-adics from :math:`\mathbb{Q}_p` to :math:`\mathbb{Q}` (as :literal:`truncate`), and polmods to
        polynomials. Otherwise, lifts only polmods whose modulus has main
        variable :math:`v`. :literal:`t_FFELT` are not lifted, nor are List elements: you may
        convert the latter to vectors first, or use :literal:`apply(lift,L)`. More
        generally, components for which such lifts are meaningless (e.g. character
        strings) are copied verbatim.

        ::

        ? lift(Mod(5,3))
        %1 = 2
        ? lift(3 + O(3^9))
        %2 = 3
        ? lift(Mod(x,x^2+1))
        %3 = x
        ? lift(Mod(x,x^2+1))
        %4 = x

        Lifts are performed recursively on an object components, but only
        by :emphasis:`one level`: once a :literal:`t_POLMOD` is lifted, the components of
        the result are :emphasis:`not` lifted further.

        ::

        ? lift(x * Mod(1,3) + Mod(2,3))
        %4 = x + 2
        ? lift(x * Mod(y,y^2+1) + Mod(2,3))
        %5 = y*x + Mod(2, 3) \\ do you understand this one?
        ? lift(x * Mod(y,y^2+1) + Mod(2,3), 'x)
        %6 = Mod(y, y^2 + 1)*x + Mod(Mod(2, 3), y^2 + 1)
        ? lift(%, y)
        %7 = y*x + Mod(2, 3)

        To recursively lift all components not only by one level,
        but as long as possible, use :literal:`liftall`. To lift only :literal:`t_INTMOD` s and
        :literal:`t_PADIC` s components, use :literal:`liftint`. To lift only :literal:`t_POLMOD` s
        components, use :literal:`liftpol`. Finally, :literal:`centerlift` allows to lift
        :literal:`t_INTMOD` s and :literal:`t_PADIC` s using centered residues (lift of smallest
        absolute value).
        '''
        x = objtogen(x)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = lift0(_x, _v)
        return new_gen(_ret)

    def liftall(self, x):
        r'''
        Recursively lift all components of :math:`x` from :math:`\mathbb{Z}/n\mathbb{Z}` to :math:`\mathbb{Z}`,
        from :math:`\mathbb{Q}_p` to :math:`\mathbb{Q}` (as :literal:`truncate`), and polmods to
        polynomials. :literal:`t_FFELT` are not lifted, nor are List elements: you may
        convert the latter to vectors first, or use :literal:`apply(liftall,L)`. More
        generally, components for which such lifts are meaningless (e.g. character
        strings) are copied verbatim.

        ::

        ? liftall(x * (1 + O(3)) + Mod(2,3))
        %1 = x + 2
        ? liftall(x * Mod(y,y^2+1) + Mod(2,3)*Mod(z,z^2))
        %2 = y*x + 2*z
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = liftall(_x)
        return new_gen(_ret)

    def liftint(self, x):
        r'''
        Recursively lift all components of :math:`x` from :math:`\mathbb{Z}/n\mathbb{Z}` to :math:`\mathbb{Z}` and
        from :math:`\mathbb{Q}_p` to :math:`\mathbb{Q}` (as :literal:`truncate`).
        :literal:`t_FFELT` are not lifted, nor are List elements: you may
        convert the latter to vectors first, or use :literal:`apply(liftint,L)`. More
        generally, components for which such lifts are meaningless (e.g. character
        strings) are copied verbatim.

        ::

        ? liftint(x * (1 + O(3)) + Mod(2,3))
        %1 = x + 2
        ? liftint(x * Mod(y,y^2+1) + Mod(2,3)*Mod(z,z^2))
        %2 = Mod(y, y^2 + 1)*x + Mod(Mod(2*z, z^2), y^2 + 1)
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = liftint(_x)
        return new_gen(_ret)

    def liftpol(self, x):
        r'''
        Recursively lift all components of :math:`x` which are polmods to
        polynomials. :literal:`t_FFELT` are not lifted, nor are List elements: you may
        convert the latter to vectors first, or use :literal:`apply(liftpol,L)`. More
        generally, components for which such lifts are meaningless (e.g. character
        strings) are copied verbatim.

        ::

        ? liftpol(x * (1 + O(3)) + Mod(2,3))
        %1 = (1 + O(3))*x + Mod(2, 3)
        ? liftpol(x * Mod(y,y^2+1) + Mod(2,3)*Mod(z,z^2))
        %2 = y*x + Mod(2, 3)*z
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = liftpol(_x)
        return new_gen(_ret)

    def limitnum(self, expr, long k=0, alpha=None, long precision=DEFAULT_BITPREC):
        r'''
        Lagrange-Zagier numerical extrapolation of :emphasis:`expr`, corresponding to a
        sequence
        :math:`u_n`, either given by a closure :literal:`n- > u(n)` or by a vector of values
        I.e., assuming that :math:`u_n` tends to a finite limit :math:`\ell`, try to determine
        :math:`\ell`. This routine is purely numerical and heuristic, thus may or may not
        work on your examples; :math:`k` is ignored if :math:`u` is given by a vector,
        and otherwise is a multiplier such that we extrapolate from :math:`u(kn)`.

        Assume that :math:`u_n` has an asymptotic expansion in :math:`n^{-\alpha}` :

        .. MATH::

        u_n = \ell + \sum_{i >= 1} a_i n^{-i\alpha}

        for some :math:`a_i`.

        ::

        ? limitnum(n -> n*sin(1/n))
        %1 = 1.0000000000000000000000000000000000000
        
        ? limitnum(n -> (1+1/n)^n) - exp(1)
        %2 = 0.E-37
        
        ? limitnum(n -> 2^(4*n+1)*(n!)^4 / (2*n)! /(2*n+1)! )
        %3 = 3.1415926535897932384626433832795028842
        ? Pi
        %4 = 3.1415926535897932384626433832795028842

        If :math:`u_n` is given by a vector, it must be long enough for the extrapolation
        to make sense: at least :math:`k` times the current :literal:`realprecision`. The
        preferred format is thus a closure, although it becomes inconvenient
        when :math:`u_n` cannot be directly computed in time polynomial in :math:`\log n`,
        for instance if it is defined as a sum or by induction. In that case,
        passing a vector of values is the best option. It usually pays off to
        interpolate :math:`u(kn)` for some :math:`k > 1`:

        ::

        ? limitnum(vector(10,n,(1+1/n)^n))
        *** ^--------------------
        *** limitnum: non-existent component in limitnum: index < 20
        \\ at this accuracy, we must have at least 20 values
        ? limitnum(vector(20,n,(1+1/n)^n)) - exp(1)
        %5 = -2.05... E-20
        ? limitnum(vector(20,n, m=10*n;(1+1/m)^m)) - exp(1) \\ better accuracy
        %6 = 0.E-37
        
        ? v = vector(20); s = 0;
        ? for(i=1,#v, s += 1/i; v[i]= s - log(i));
        ? limitnum(v) - Euler
        %9 = -1.6... E-19
        
        ? V = vector(200); s = 0;
        ? for(i=1,#V, s += 1/i; V[i]= s);
        ? v = vector(#V \ 10, i, V[10*i] - log(10*i));
        ? limitnum(v) - Euler
        %13 = 6.43... E-29
        '''
        expr = objtogen(expr)
        cdef bint _have_alpha = (alpha is not None)
        if _have_alpha:
            alpha = objtogen(alpha)
        sig_on()
        cdef GEN _expr = (<Gen>expr).g
        cdef GEN _alpha = NULL
        if _have_alpha:
            _alpha = (<Gen>alpha).g
        precision = nbits2prec(precision)
        cdef GEN _ret = limitnum0(_expr, k, _alpha, precision)
        return new_gen(_ret)

    def lindep(self, v, long flag=0):
        r'''
        finds a small non-trivial integral linear
        combination between components of :math:`v`. If none can be found return an empty
        vector.

        If :math:`v` is a vector with real/complex entries we use a floating point
        (variable precision) LLL algorithm. If :math:`flag = 0` the accuracy is chosen
        internally using a crude heuristic. If :math:`flag > 0` the computation is done with
        an accuracy of :math:`flag` decimal digits. To get meaningful results in the latter
        case, the parameter :math:`flag` should be smaller than the number of correct
        decimal digits in the input.

        ::

        ? lindep([sqrt(2), sqrt(3), sqrt(2)+sqrt(3)])
        %1 = [-1, -1, 1]~

        If :math:`v` is :math:`p`-adic, :math:`flag` is ignored and the algorithm LLL-reduces a
        suitable (dual) lattice.

        ::

        ? lindep([1, 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)])
        %2 = [1, -2]~

        If :math:`v` is a matrix (or a vector of column vectors, or a vector of row
        vectors), :math:`flag` is ignored and the function returns a non trivial kernel
        vector if one exists, else an empty vector.

        ::

        ? lindep([1,2,3;4,5,6;7,8,9])
        %3 = [1, -2, 1]~
        ? lindep([[1,0], [2,0]])
        %4 = [2, -1]~
        ? lindep([[1,0], [0,1]])
        %5 = []~

        If :math:`v` contains polynomials or power series over some base field, finds a
        linear relation with coefficients in the field.

        ::

        ? lindep([x*y, x^2 + y, x^2*y + x*y^2, 1])
        %4 = [y, y, -1, -y^2]~

        For better control, it is preferable to use :literal:`t_POL` rather
        than :literal:`t_SER` in the input, otherwise one gets a linear combination which is
        :math:`t`-adically small, but not necessarily :math:`0`. Indeed, power series are first
        converted to the minimal absolute accuracy occurring among the entries of :math:`v`
        (which can cause some coefficients to be ignored), then truncated to
        polynomials:

        ::

        ? v = [t^2+O(t^4), 1+O(t^2)]; L=lindep(v)
        %1 = [1, 0]~
        ? v*L
        %2 = t^2+O(t^4) \\ small but not 0
        '''
        v = objtogen(v)
        sig_on()
        cdef GEN _v = (<Gen>v).g
        cdef GEN _ret = lindep0(_v, flag)
        return new_gen(_ret)

    def listinsert(self, L, x, long n):
        r'''
        Inserts the object :math:`x` at
        position :math:`n` in :math:`L` (which must be of type :literal:`t_LIST`). This has
        complexity :math:`O(\#L - n + 1)`: all the
        remaining elements of :emphasis:`list` (from position :math:`n+1` onwards) are shifted
        to the right.
        '''
        L = objtogen(L)
        x = objtogen(x)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = listinsert(_L, _x, n)
        return new_gen(_ret)

    def listkill(self, L):
        r'''
        Obsolete, retained for backward compatibility. Just use :literal:`L = List()`
        instead of :literal:`listkill(L)`. In most cases, you won't even need that, e.g.
        local variables are automatically cleared when a user function returns.
        '''
        from warnings import warn
        warn('the PARI/GP function listkill is obsolete (2007-08-10)', DeprecationWarning)
        L = objtogen(L)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        listkill(_L)
        clear_stack()

    def listpop(self, list, long n=0):
        r'''
        Removes the :math:`n`-th element of the list
        :emphasis:`list` (which must be of type :literal:`t_LIST`). If :math:`n` is omitted,
        or greater than the list current length, removes the last element.
        If the list is already empty, do nothing. This runs in time :math:`O(\#L - n + 1)`.
        '''
        list = objtogen(list)
        sig_on()
        cdef GEN _list = (<Gen>list).g
        listpop0(_list, n)
        clear_stack()

    def listput(self, list, x, long n=0):
        r'''
        Sets the :math:`n`-th element of the list
        :emphasis:`list` (which must be of type :literal:`t_LIST`) equal to :math:`x`. If :math:`n` is omitted,
        or greater than the list length, appends :math:`x`. The function returns the
        inserted element.

        ::

        ? L = List();
        ? listput(L, 1)
        %2 = 1
        ? listput(L, 2)
        %3 = 2
        ? L
        %4 = List([1, 2])

        You may put an element into an occupied cell (not changing the
        list length), but it is easier to use the standard :literal:`list[n] = x`
        construct.

        ::

        ? listput(L, 3, 1) \\ insert at position 1
        %5 = 3
        ? L
        %6 = List([3, 2])
        ? L[2] = 4 \\ simpler
        %7 = List([3, 4])
        ? L[10] = 1 \\ can't insert beyond the end of the list
        *** at top-level: L[10]=1
        *** ^------
        *** non-existent component: index > 2
        ? listput(L, 1, 10) \\ but listput can
        %8 = 1
        ? L
        %9 = List([3, 2, 1])

        This function runs in time :math:`O(\#L)` in the worst case (when the list must
        be reallocated), but in time :math:`O(1)` on average: any number of successive
        :literal:`listput` s run in time :math:`O(\#L)`, where :math:`\#L` denotes the list
        :emphasis:`final` length.
        '''
        list = objtogen(list)
        x = objtogen(x)
        sig_on()
        cdef GEN _list = (<Gen>list).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = listput0(_list, _x, n)
        return new_gen(_ret)

    def listsort(self, L, long flag=0):
        r'''
        Sorts the :literal:`t_LIST` :emphasis:`list` in place, with respect to the (somewhat
        arbitrary) universal comparison function :literal:`cmp`. In particular, the
        ordering is the same as for sets and :literal:`setsearch` can be used on a sorted
        list.

        ::

        ? L = List([1,2,4,1,3,-1]); listsort(L); L
        %1 = List([-1, 1, 1, 2, 3, 4])
        ? setsearch(L, 4)
        %2 = 6
        ? setsearch(L, -2)
        %3 = 0

        This is faster than the :literal:`vecsort` command since the list
        is sorted in place: no copy is made. No value returned.

        If :math:`flag` is non-zero, suppresses all repeated coefficients.
        '''
        L = objtogen(L)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        listsort(_L, flag)
        clear_stack()

    def lngamma(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of the logarithm of the gamma function of :math:`x`. This
        function is analytic on the complex plane with non-positive integers
        removed, and can have much larger arguments than :literal:`gamma` itself.

        For :math:`x` a power series such that :math:`x(0)` is not a pole of :literal:`gamma`,
        compute the Taylor expansion. (PARI only knows about regular power series
        and can't include logarithmic terms.)

        ::

        ? lngamma(1+x+O(x^2))
        %1 = -0.57721566490153286060651209008240243104*x + O(x^2)
        ? lngamma(x+O(x^2))
        *** at top-level: lngamma(x+O(x^2))
        *** ^-----------------
        *** lngamma: domain error in lngamma: valuation != 0
        ? lngamma(-1+x+O(x^2))
        *** lngamma: Warning: normalizing a series with 0 leading term.
        *** at top-level: lngamma(-1+x+O(x^2))
        *** ^--------------------
        *** lngamma: domain error in intformal: residue(series, pole) != 0
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = glngamma(_x, precision)
        return new_gen(_ret)

    def localbitprec(self, long p):
        r'''
        Set the real precision to :math:`p` bits in the dynamic scope. All computations
        are performed as if :literal:`realbitprecision` was :math:`p`:
        transcendental constants (e.g. :literal:`Pi`) and
        conversions from exact to floating point inexact data use :math:`p` bits, as well as
        iterative routines implicitly using a floating point
        accuracy as a termination criterion (e.g. :literal:`solve` or :literal:`intnum`).
        But :literal:`realbitprecision` itself is unaffected
        and is "unmasked" when we exit the dynamic (:emphasis:`not` lexical) scope.
        In effect, this is similar to

        ::

        my(bit = default(realbitprecision));
        default(realbitprecision,p);
        ...
        default(realbitprecision, bit);

        but is both less cumbersome, cleaner (no need to manipulate
        a global variable, which in fact never changes and is only temporarily masked)
        and more robust: if the above computation is interrupted or an exception
        occurs, :literal:`realbitprecision` will not be restored as intended.

        Such :literal:`localbitprec` statements can be nested, the innermost one taking
        precedence as expected. Beware that :literal:`localbitprec` follows the semantic of
        :literal:`local`, not :literal:`my`: a subroutine called from :literal:`localbitprec` scope
        uses the local accuracy:

        ::

        ? f()=bitprecision(1.0);
        ? f()
        %2 = 128
        ? localbitprec(1000); f()
        %3 = 1024

        Note that the bit precision of :emphasis:`data` (:literal:`1.0` in the
        above example) increases by steps of 64 (32 on a 32-bit machine) so we get
        :math:`1024` instead of the expected :math:`1000`; :literal:`localbitprec` bounds the
        relative error exactly as specified in functions that support that
        granularity (e.g. :literal:`lfun`), and rounded to the next multiple of 64
        (resp. 32) everywhere else.

        :strong:`Warning.` Changing :literal:`realbitprecision` or :literal:`realprecision`
        in programs is deprecated in favor of :literal:`localbitprec` and
        :literal:`localprec`. Think about the :literal:`realprecision` and
        :literal:`realbitprecision` defaults as interactive commands for the :literal:`gp`
        interpreter, best left out of GP programs. Indeed, the above rules imply that
        mixing both constructs yields surprising results:

        ::

        ? \p38
        ? localprec(19); default(realprecision,1000); Pi
        %1 = 3.141592653589793239
        ? \p
        realprecision = 1001 significant digits (1000 digits displayed)

        Indeed, :literal:`realprecision` itself is ignored within
        :literal:`localprec` scope, so :literal:`Pi` is computed to a low accuracy. And when
        we leave the :literal:`localprec` scope, :literal:`realprecision` only regains precedence,
        it is not "restored" to the original value.
        '''
        sig_on()
        localbitprec(p)
        clear_stack()

    def localprec(self, long p):
        r'''
        Set the real precision to :math:`p` in the dynamic scope. All computations
        are performed as if :literal:`realprecision` was :math:`p`:
        transcendental constants (e.g. :literal:`Pi`) and
        conversions from exact to floating point inexact data use :math:`p` decimal
        digits, as well as iterative routines implicitly using a floating point
        accuracy as a termination criterion (e.g. :literal:`solve` or :literal:`intnum`).
        But :literal:`realprecision` itself is unaffected
        and is "unmasked" when we exit the dynamic (:emphasis:`not` lexical) scope.
        In effect, this is similar to

        ::

        my(prec = default(realprecision));
        default(realprecision,p);
        ...
        default(realprecision, prec);

        but is both less cumbersome, cleaner (no need to manipulate
        a global variable, which in fact never changes and is only temporarily masked)
        and more robust: if the above computation is interrupted or an exception
        occurs, :literal:`realprecision` will not be restored as intended.

        Such :literal:`localprec` statements can be nested, the innermost one taking
        precedence as expected. Beware that :literal:`localprec` follows the semantic of
        :literal:`local`, not :literal:`my`: a subroutine called from :literal:`localprec` scope
        uses the local accuracy:

        ::

        ? f()=precision(1.);
        ? f()
        %2 = 38
        ? localprec(19); f()
        %3 = 19

        :strong:`Warning.` Changing :literal:`realprecision` itself in programs is
        now deprecated in favor of :literal:`localprec`. Think about the
        :literal:`realprecision` default as an interactive command for the :literal:`gp`
        interpreter, best left out of GP programs. Indeed, the above rules
        imply that mixing both constructs yields surprising results:

        ::

        ? \p38
        ? localprec(19); default(realprecision,100); Pi
        %1 = 3.141592653589793239
        ? \p
        realprecision = 115 significant digits (100 digits displayed)

        Indeed, :literal:`realprecision` itself is ignored within
        :literal:`localprec` scope, so :literal:`Pi` is computed to a low accuracy. And when
        we leave :literal:`localprec` scope, :literal:`realprecision` only regains precedence,
        it is not "restored" to the original value.
        '''
        sig_on()
        localprec(p)
        clear_stack()

    def log(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of the natural logarithm of
        :math:`x \in \mathbb{C}^*`, i.e. such that :math:`\Im (\log (x))\in ]-\pi,\pi]`.
        The branch cut lies
        along the negative real axis, continuous with quadrant 2, i.e. such that
        :math:`\lim_{b\to 0^+} \log (a+bi) = \log a` for :math:`a \in\mathbb{R}^*`. The result is complex
        (with imaginary part equal to :math:`\pi`) if :math:`x\in \mathbb{R}` and :math:`x < 0`. In general,
        the algorithm uses the formula

        .. MATH::

        \log (x) ~ (\pi)/(2agm(1, 4/s)) - m \log 2,

        if :math:`s = x 2^m` is large enough. (The result is exact to :math:`B` bits provided
        :math:`s > 2^{B/2}`.) At low accuracies, the series expansion near :math:`1` is used.

        :math:`p`-adic arguments are also accepted for :math:`x`, with the convention that
        :math:`\log (p) = 0`. Hence in particular :math:`\exp (\log (x))/x` is not in general equal to
        1 but to a :math:`(p-1)`-th root of unity (or :math:`±1` if :math:`p = 2`) times a power of :math:`p`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = glog(_x, precision)
        return new_gen(_ret)

    def log1p(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Return :math:`\log (1+x)`, computed in a way that is also accurate
        when the real part of :math:`x` is near :math:`0`. This is the reciprocal function
        of :literal:`expm1`:math:`(x) = \exp (x)-1`.

        ::

        ? default(realprecision, 10000); x = Pi*1e-100;
        ? (expm1(log1p(x)) - x) / x
        %2 = -7.668242895059371866 E-10019
        ? (log1p(expm1(x)) - x) / x
        %3 = -7.668242895059371866 E-10019

        When :math:`x` is small, this function is both faster and more
        accurate than :math:`\log (1+x)`:

        ::

        ? \p38
        ? x = 1e-20;
        ? localprec(100); c = log1p(x); \\ reference point
        ? a = log1p(x); abs((a - c)/c)
        %6 = 0.E-38
        ? b = log(1+x); abs((b - c)/c) \\ slightly less accurate
        %7 = 1.5930919111324522770 E-38
        ? for (i=1,10^5,log1p(x))
        time = 81 ms.
        ? for (i=1,10^5,log(1+x))
        time = 100 ms. \\ slower, too
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = glog1p(_x, precision)
        return new_gen(_ret)

    def logint(self, x, b, z=None):
        r'''
        Return the largest integer :math:`e` so that :math:`b^e <= x`, where the
        parameters :math:`b > 1` and :math:`x > 0` are both integers. If the parameter :math:`z` is
        present, set it to :math:`b^e`.

        ::

        ? logint(1000, 2)
        %1 = 9
        ? 2^9
        %2 = 512
        ? logint(1000, 2, &z)
        %3 = 9
        ? z
        %4 = 512

        The number of digits used to write :math:`b` in base :math:`x` is
        :literal:`1 + logint(x,b)`:

        ::

        ? #digits(1000!, 10)
        %5 = 2568
        ? logint(1000!, 10)
        %6 = 2567

        This function may conveniently replace

        ::

        floor( log(x) / log(b) )

        which may not give the correct answer since PARI
        does not guarantee exact rounding.
        '''
        x = objtogen(x)
        b = objtogen(b)
        cdef bint _have_z = (z is not None)
        if _have_z:
            raise NotImplementedError("optional argument z not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN * _z = NULL
        cdef long _ret = logint0(_x, _b, _z)
        clear_stack()
        return _ret

    def mapdelete(self, M, x):
        r'''
        Removes :math:`x` from the domain of the map :math:`M`.

        ::

        ? M = Map(["a",1; "b",3; "c",7]);
        ? mapdelete(M,"b");
        ? Mat(M)
        ["a" 1]
        
        ["c" 7]
        '''
        M = objtogen(M)
        x = objtogen(x)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _x = (<Gen>x).g
        mapdelete(_M, _x)
        clear_stack()

    def mapget(self, M, x):
        r'''
        Returns the image of :math:`x` by the map :math:`M`.

        ::

        ? M=Map(["a",23;"b",43]);
        ? mapget(M,"a")
        %2 = 23
        ? mapget(M,"b")
        %3 = 43

        Raises an exception when the key :math:`x` is not present in :math:`M`.

        ::

        ? mapget(M,"c")
        *** at top-level: mapget(M,"c")
        *** ^-------------
        *** mapget: non-existent component in mapget: index not in map
        '''
        M = objtogen(M)
        x = objtogen(x)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = mapget(_M, _x)
        return new_gen(_ret)

    def mapisdefined(self, M, x, z=None):
        r'''
        Returns true (:math:`1`) if :literal:`x` has an image by the map :math:`M`, false (:math:`0`)
        otherwise. If :literal:`z` is present, set :literal:`z` to the image of :math:`x`, if it exists.

        ::

        ? M1 = Map([1, 10; 2, 20]);
        ? mapisdefined(M1,3)
        %1 = 0
        ? mapisdefined(M1, 1, &z)
        %2 = 1
        ? z
        %3 = 10

        ::

        ? M2 = Map(); N = 19;
        ? for (a=0, N-1, mapput(M2, a^3%N, a));
        ? {for (a=0, N-1,
        if (mapisdefined(M2, a, &b),
        printf("%d is the cube of %d mod %d\n",a,b,N)));}
        0 is the cube of 0 mod 19
        1 is the cube of 11 mod 19
        7 is the cube of 9 mod 19
        8 is the cube of 14 mod 19
        11 is the cube of 17 mod 19
        12 is the cube of 15 mod 19
        18 is the cube of 18 mod 19
        '''
        M = objtogen(M)
        x = objtogen(x)
        cdef bint _have_z = (z is not None)
        if _have_z:
            raise NotImplementedError("optional argument z not available")
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _z = NULL
        cdef int _ret = mapisdefined(_M, _x, _z)
        clear_stack()
        return _ret

    def mapput(self, M, x, y):
        r'''
        Associates :math:`x` to :math:`y` in the map :math:`M`. The value :math:`y` can be retrieved
        with :literal:`mapget`.

        ::

        ? M = Map();
        ? mapput(M, "foo", 23);
        ? mapput(M, 7718, "bill");
        ? mapget(M, "foo")
        %4 = 23
        ? mapget(M, 7718)
        %5 = "bill"
        ? Vec(M) \\ keys
        %6 = [7718, "foo"]
        ? Mat(M)
        %7 =
        [ 7718 "bill"]
        
        ["foo" 23]
        '''
        M = objtogen(M)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        mapput(_M, _x, _y)
        clear_stack()

    def matadjoint(self, M, long flag=0):
        r'''
        adjoint matrix of :math:`M`, i.e. a matrix :math:`N`
        of cofactors of :math:`M`, satisfying :math:`M*N = \det (M)*\mathrm{Id}`. :math:`M` must be a
        (non-necessarily invertible) square matrix of dimension :math:`n`.
        If :math:`flag` is 0 or omitted, we try to use Leverrier-Faddeev's algorithm,
        which assumes that :math:`n!` invertible. If it fails or :math:`flag = 1`,
        compute :math:`T = charpoly (M)` independently first and return
        :math:`(-1)^{n-1} (T(x)-T(0))/x` evaluated at :math:`M`.

        ::

        ? a = [1,2,3;3,4,5;6,7,8] * Mod(1,4);
        %2 =
        [Mod(1, 4) Mod(2, 4) Mod(3, 4)]
        
        [Mod(3, 4) Mod(0, 4) Mod(1, 4)]
        
        [Mod(2, 4) Mod(3, 4) Mod(0, 4)]

        Both algorithms use :math:`O(n^4)` operations in the base ring, and are usually
        slower than computing the characteristic polynomial or the inverse of :math:`M`
        directly.
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = matadjoint0(_M, flag)
        return new_gen(_ret)

    def matalgtobasis(self, nf, x):
        r'''
        This function is deprecated, use :literal:`apply`.

        :math:`nf` being a number field in :literal:`nfinit` format, and :math:`x` a
        (row or column) vector or matrix, apply :literal:`nfalgtobasis` to each entry
        of :math:`x`.
        '''
        from warnings import warn
        warn('the PARI/GP function matalgtobasis is obsolete (2016-08-08)', DeprecationWarning)
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = matalgtobasis(_nf, _x)
        return new_gen(_ret)

    def matbasistoalg(self, nf, x):
        r'''
        This function is deprecated, use :literal:`apply`.

        :math:`nf` being a number field in :literal:`nfinit` format, and :math:`x` a
        (row or column) vector or matrix, apply :literal:`nfbasistoalg` to each entry
        of :math:`x`.
        '''
        from warnings import warn
        warn('the PARI/GP function matbasistoalg is obsolete (2016-08-08)', DeprecationWarning)
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = matbasistoalg(_nf, _x)
        return new_gen(_ret)

    def matcompanion(self, x):
        r'''
        The left companion matrix to the non-zero polynomial :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = matcompanion(_x)
        return new_gen(_ret)

    def matconcat(self, v):
        r'''
        Returns a :literal:`t_MAT` built from the entries of :math:`v`, which may
        be a :literal:`t_VEC` (concatenate horizontally), a :literal:`t_COL` (concatenate
        vertically), or a :literal:`t_MAT` (concatenate vertically each column, and
        concatenate vertically the resulting matrices). The entries of :math:`v` are always
        considered as matrices: they can themselves be :literal:`t_VEC` (seen as a row
        matrix), a :literal:`t_COL` seen as a column matrix), a :literal:`t_MAT`, or a scalar (seen
        as an :math:`1 x 1` matrix).

        ::

        ? A=[1,2;3,4]; B=[5,6]~; C=[7,8]; D=9;
        ? matconcat([A, B]) \\ horizontal
        %1 =
        [1 2 5]
        
        [3 4 6]
        ? matconcat([A, C]~) \\ vertical
        %2 =
        [1 2]
        
        [3 4]
        
        [7 8]
        ? matconcat([A, B; C, D]) \\ block matrix
        %3 =
        [1 2 5]
        
        [3 4 6]
        
        [7 8 9]

        If the dimensions of the entries to concatenate do not match up, the above
        rules are extended as follows:

        - each entry :math:`v_{i,j}` of :math:`v` has a natural length and height: :math:`1 x
        1` for a scalar, :math:`1 x n` for a :literal:`t_VEC` of length :math:`n`, :math:`n x 1`
        for a :literal:`t_COL`, :math:`m x n` for an :math:`m x n` :literal:`t_MAT`

        - let :math:`H_i` be the maximum over :math:`j` of the lengths of the :math:`v_{i,j}`,
        let :math:`L_j` be the maximum over :math:`i` of the heights of the :math:`v_{i,j}`.
        The dimensions of the :math:`(i,j)`-th block in the concatenated matrix are
        :math:`H_i x L_j`.

        - a scalar :math:`s = v_{i,j}` is considered as :math:`s` times an identity matrix
        of the block dimension :math:`\min (H_i,L_j)`

        - blocks are extended by 0 columns on the right and 0 rows at the
        bottom, as needed.

        ::

        ? matconcat([1, [2,3]~, [4,5,6]~]) \\ horizontal
        %4 =
        [1 2 4]
        
        [0 3 5]
        
        [0 0 6]
        ? matconcat([1, [2,3], [4,5,6]]~) \\ vertical
        %5 =
        [1 0 0]
        
        [2 3 0]
        
        [4 5 6]
        ? matconcat([B, C; A, D]) \\ block matrix
        %6 =
        [5 0 7 8]
        
        [6 0 0 0]
        
        [1 2 9 0]
        
        [3 4 0 9]
        ? U=[1,2;3,4]; V=[1,2,3;4,5,6;7,8,9];
        ? matconcat(matdiagonal([U, V])) \\ block diagonal
        %7 =
        [1 2 0 0 0]
        
        [3 4 0 0 0]
        
        [0 0 1 2 3]
        
        [0 0 4 5 6]
        
        [0 0 7 8 9]
        '''
        v = objtogen(v)
        sig_on()
        cdef GEN _v = (<Gen>v).g
        cdef GEN _ret = matconcat(_v)
        return new_gen(_ret)

    def matdet(self, x, long flag=0):
        r'''
        Determinant of the square matrix :math:`x`.

        If :math:`flag = 0`, uses an appropriate algorithm depending on the coefficients:

        - integer entries: modular method due to Dixon, Pernet and Stein.

        - real or :math:`p`-adic entries: classical Gaussian elimination using maximal
        pivot.

        - intmod entries: classical Gaussian elimination using first non-zero
        pivot.

        - other cases: Gauss-Bareiss.

        If :math:`flag = 1`, uses classical Gaussian elimination with appropriate pivoting
        strategy (maximal pivot for real or :math:`p`-adic coefficients). This is usually
        worse than the default.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = det0(_x, flag)
        return new_gen(_ret)

    def matdetint(self, B):
        r'''
        Let :math:`B` be an :math:`m x n` matrix with integer coefficients. The
        :emphasis:`determinant` :math:`D` of the lattice generated by the columns of :math:`B` is
        the square root of :math:`\det (B^T B)` if :math:`B` has maximal rank :math:`m`, and :math:`0`
        otherwise.

        This function uses the Gauss-Bareiss algorithm to compute a positive
        :emphasis:`multiple` of :math:`D`. When :math:`B` is square, the function actually returns
        :math:`D = \|\det B\|`.

        This function is useful in conjunction with :literal:`mathnfmod`, which needs to
        know such a multiple. If the rank is maximal and the matrix non-square,
        you can obtain :math:`D` exactly using

        ::

        matdet( mathnfmod(B, matdetint(B)) )

        Note that as soon as one of the dimensions gets large (:math:`m` or :math:`n` is larger
        than 20, say), it will often be much faster to use :literal:`mathnf(B, 1)` or
        :literal:`mathnf(B, 4)` directly.
        '''
        B = objtogen(B)
        sig_on()
        cdef GEN _B = (<Gen>B).g
        cdef GEN _ret = detint(_B)
        return new_gen(_ret)

    def matdetmod(self, x, d):
        r'''
        Given a matrix :math:`x` with :literal:`t_INT` entries and :math:`d` an arbitrary positive
        integer, return the determinant of :math:`x` modulo :math:`d`.

        ::

        ? A = [4,2,3; 4,5,6; 7,8,9]
        
        ? matdetmod(A,27)
        %2 = 9

        Note that using the generic function :literal:`matdet` on a matrix with
        :literal:`t_INTMOD` entries uses Gaussian reduction and will fail in general when
        the modulus is not prime.

        ::

        ? matdet(A * Mod(1,27))
        *** at top-level: matdet(A*Mod(1,27))
        *** ^------------------
        *** matdet: impossible inverse in Fl_inv: Mod(3, 27).
        '''
        x = objtogen(x)
        d = objtogen(d)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _d = (<Gen>d).g
        cdef GEN _ret = matdetmod(_x, _d)
        return new_gen(_ret)

    def matdiagonal(self, x):
        r'''
        :math:`x` being a vector, creates the diagonal matrix
        whose diagonal entries are those of :math:`x`.

        ::

        ? matdiagonal([1,2,3]);
        %1 =
        [1 0 0]
        
        [0 2 0]
        
        [0 0 3]

        Block diagonal matrices are easily created using
        :literal:`matconcat`:

        ::

        ? U=[1,2;3,4]; V=[1,2,3;4,5,6;7,8,9];
        ? matconcat(matdiagonal([U, V]))
        %1 =
        [1 2 0 0 0]
        
        [3 4 0 0 0]
        
        [0 0 1 2 3]
        
        [0 0 4 5 6]
        
        [0 0 7 8 9]
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = diagonal(_x)
        return new_gen(_ret)

    def mateigen(self, x, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Returns the (complex) eigenvectors of :math:`x` as columns of a matrix.
        If :math:`flag = 1`, return :math:`[L,H]`, where :math:`L` contains the
        eigenvalues and :math:`H` the corresponding eigenvectors; multiple eigenvalues are
        repeated according to the eigenspace dimension (which may be less
        than the eigenvalue multiplicity in the characteristic polynomial).

        This function first computes the characteristic polynomial of :math:`x` and
        approximates its complex roots :math:`(\lambda_i)`, then tries to compute the
        eigenspaces as kernels of the :math:`x - \lambda_i`. This algorithm is
        ill-conditioned and is likely to miss kernel vectors if some roots of the
        characteristic polynomial are close, in particular if it has multiple roots.

        ::

        ? A = [13,2; 10,14]; mateigen(A)
        %1 =
        [-1/2 2/5]
        
        [ 1 1]
        ? [L,H] = mateigen(A, 1);
        ? L
        %3 = [9, 18]
        ? H
        %4 =
        [-1/2 2/5]
        
        [ 1 1]

        For symmetric matrices, use :literal:`qfjacobi` instead; for Hermitian matrices,
        compute

        ::

        A = real(x);
        B = imag(x);
        y = matconcat([A, -B; B, A]);

        and apply :literal:`qfjacobi` to :math:`y`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = mateigen(_x, flag, precision)
        return new_gen(_ret)

    def matfrobenius(self, M, long flag=0, v=None):
        r'''
        Returns the Frobenius form of
        the square matrix :literal:`M`. If :math:`flag = 1`, returns only the elementary divisors as
        a vector of polynomials in the variable :literal:`v`. If :math:`flag = 2`, returns a
        two-components vector [F,B] where :literal:`F` is the Frobenius form and :literal:`B` is
        the basis change so that :math:`M = B^{-1}FB`.
        '''
        M = objtogen(M)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = matfrobenius(_M, flag, _v)
        return new_gen(_ret)

    def mathess(self, x):
        r'''
        Returns a matrix similar to the square matrix :math:`x`, which is in upper Hessenberg
        form (zero entries below the first subdiagonal).
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = hess(_x)
        return new_gen(_ret)

    def mathilbert(self, long n):
        r'''
        :math:`x` being a :literal:`long`, creates the
        Hilbert matrixof order :math:`x`, i.e. the matrix whose coefficient
        (:math:`i`,:math:`j`) is :math:`1/ (i+j-1)`.
        '''
        sig_on()
        cdef GEN _ret = mathilbert(n)
        return new_gen(_ret)

    def mathnf(self, M, long flag=0):
        r'''
        Let :math:`R` be a Euclidean ring, equal to :math:`\mathbb{Z}` or to :math:`K[X]` for some field
        :math:`K`. If :math:`M` is a (not necessarily square) matrix with entries in :math:`R`, this
        routine finds the :emphasis:`upper triangular` Hermite normal form of :math:`M`.
        If the rank of :math:`M` is equal to its number of rows, this is a square
        matrix. In general, the columns of the result form a basis of the :math:`R`-module
        spanned by the columns of :math:`M`.

        The values of :math:`flag` are:

        - 0 (default): only return the Hermite normal form :math:`H`

        - 1 (complete output): return :math:`[H,U]`, where :math:`H` is the Hermite
        normal form of :math:`M`, and :math:`U` is a transformation matrix such that :math:`MU = [0\|H]`.
        The matrix :math:`U` belongs to :math:`GL(R)`. When :math:`M` has a large kernel, the
        entries of :math:`U` are in general huge.

        For these two values, we use a naive algorithm, which behaves well
        in small dimension only. Larger values correspond to different algorithms,
        are restricted to :emphasis:`integer` matrices, and all output the unimodular
        matrix :math:`U`. From now on all matrices have integral entries.

        - :math:`flag = 4`, returns :math:`[H,U]` as in "complete output" above, using a
        variant of LLL reduction along the way. The matrix :math:`U` is provably
        small in the :math:`L_2` sense, and often close to optimal; but the
        reduction is in general slow, although provably polynomial-time.

        If :math:`flag = 5`, uses Batut's algorithm and output :math:`[H,U,P]`, such that :math:`H` and
        :math:`U` are as before and :math:`P` is a permutation of the rows such that :math:`P` applied
        to :math:`MU` gives :math:`H`. This is in general faster than :math:`flag = 4` but the matrix :math:`U`
        is usually worse; it is heuristically smaller than with the default algorithm.

        When the matrix is dense and the dimension is large (bigger than 100, say),
        :math:`flag = 4` will be fastest. When :math:`M` has maximal rank, then

        ::

        H = mathnfmod(M, matdetint(M))

        will be even faster. You can then recover :math:`U` as :math:`M^{-1}H`.

        ::

        ? M = matrix(3,4,i,j,random([-5,5]))
        %1 =
        [ 0 2 3 0]
        
        [-5 3 -5 -5]
        
        [ 4 3 -5 4]
        
        ? [H,U] = mathnf(M, 1);
        ? U
        %3 =
        [-1 0 -1 0]
        
        [ 0 5 3 2]
        
        [ 0 3 1 1]
        
        [ 1 0 0 0]
        
        ? H
        %5 =
        [19 9 7]
        
        [ 0 9 1]
        
        [ 0 0 1]
        
        ? M*U
        %6 =
        [0 19 9 7]
        
        [0 0 9 1]
        
        [0 0 0 1]

        For convenience, :math:`M` is allowed to be a :literal:`t_VEC`, which is then
        automatically converted to a :literal:`t_MAT`, as per the :literal:`Mat` function.
        For instance to solve the generalized extended gcd problem, one may use

        ::

        ? v = [116085838, 181081878, 314252913,10346840];
        ? [H,U] = mathnf(v, 1);
        ? U
        %2 =
        [ 103 -603 15 -88]
        
        [-146 13 -1208 352]
        
        [ 58 220 678 -167]
        
        [-362 -144 381 -101]
        ? v*U
        %3 = [0, 0, 0, 1]

        This also allows to input a matrix as a :literal:`t_VEC` of
        :literal:`t_COL` s of the same length (which :literal:`Mat` would concatenate to
        the :literal:`t_MAT` having those columns):

        ::

        ? v = [[1,0,4]~, [3,3,4]~, [0,-4,-5]~]; mathnf(v)
        %1 =
        [47 32 12]
        
        [ 0 1 0]
        
        [ 0 0 1]
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = mathnf0(_M, flag)
        return new_gen(_ret)

    def mathnfmod(self, x, d):
        r'''
        If :math:`x` is a (not necessarily square) matrix of
        maximal rank with integer entries, and :math:`d` is a multiple of the (non-zero)
        determinant of the lattice spanned by the columns of :math:`x`, finds the
        :emphasis:`upper triangular` Hermite normal form of :math:`x`.

        If the rank of :math:`x` is equal to its number of rows, the result is a square
        matrix. In general, the columns of the result form a basis of the lattice
        spanned by the columns of :math:`x`. Even when :math:`d` is known, this is in general
        slower than :literal:`mathnf` but uses much less memory.
        '''
        x = objtogen(x)
        d = objtogen(d)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _d = (<Gen>d).g
        cdef GEN _ret = hnfmod(_x, _d)
        return new_gen(_ret)

    def mathnfmodid(self, x, d):
        r'''
        Outputs the (upper triangular)
        Hermite normal form of :math:`x` concatenated with the diagonal
        matrix with diagonal :math:`d`. Assumes that :math:`x` has integer entries.
        Variant: if :math:`d` is an integer instead of a vector, concatenate :math:`d` times the
        identity matrix.

        ::

        ? m=[0,7;-1,0;-1,-1]
        %1 =
        [ 0 7]
        
        [-1 0]
        
        [-1 -1]
        ? mathnfmodid(m, [6,2,2])
        %2 =
        [2 1 1]
        
        [0 1 0]
        
        [0 0 1]
        ? mathnfmodid(m, 10)
        %3 =
        [10 7 3]
        
        [ 0 1 0]
        
        [ 0 0 1]
        '''
        x = objtogen(x)
        d = objtogen(d)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _d = (<Gen>d).g
        cdef GEN _ret = hnfmodid(_x, _d)
        return new_gen(_ret)

    def mathouseholder(self, Q, v):
        r'''
        applies a sequence :math:`Q` of Householder
        transforms, as returned by :literal:`matqr`:math:`(M,1)` to the vector or matrix :math:`v`.
        '''
        Q = objtogen(Q)
        v = objtogen(v)
        sig_on()
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _v = (<Gen>v).g
        cdef GEN _ret = mathouseholder(_Q, _v)
        return new_gen(_ret)

    def matid(self, long n):
        r'''
        Creates the :math:`n x n` identity matrix.
        '''
        sig_on()
        cdef GEN _ret = matid(n)
        return new_gen(_ret)

    def matimage(self, x, long flag=0):
        r'''
        Gives a basis for the image of the
        matrix :math:`x` as columns of a matrix. A priori the matrix can have entries of
        any type. If :math:`flag = 0`, use standard Gauss pivot. If :math:`flag = 1`, use
        :literal:`matsupplement` (much slower: keep the default flag!).
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = matimage0(_x, flag)
        return new_gen(_ret)

    def matimagecompl(self, x):
        r'''
        Gives the vector of the column indices which
        are not extracted by the function :literal:`matimage`, as a permutation
        (:literal:`t_VECSMALL`). Hence the number of
        components of :literal:`matimagecompl(x)` plus the number of columns of
        :literal:`matimage(x)` is equal to the number of columns of the matrix :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = imagecompl(_x)
        return new_gen(_ret)

    def matimagemod(self, x, d, U=None):
        r'''
        Gives a Howell basis (unique representation for submodules of :math:`(\mathbb{Z}/d\mathbb{Z})^n`)
        for the image of the matrix :math:`x` modulo :math:`d` as columns of a matrix :math:`H`. The
        matrix :math:`x` must have :literal:`t_INT` entries, and :math:`d` can be an arbitrary positive
        integer. If :math:`U` is present, set it to a matrix such that :math:`AU = H`.

        ::

        ? A = [2,1;0,2];
        ? matimagemod(A,6,&U)
        %2 =
        [1 0]
        
        [0 2]
        
        ? U
        %3 =
        [5 1]
        
        [3 4]
        
        ? (A*U)%6
        %4 =
        [1 0]
        
        [0 2]

        :strong:`Caveat.` In general the number of columns of the Howell form is not
        the minimal number of generators of the submodule. Example:

        ::

        ? matimagemod([1;2],4)
        %5 =
        [2 1]
        
        [0 2]

        :strong:`Caveat 2.` In general the matrix :math:`U` is not invertible, even if :math:`A`
        and :math:`H` have the same size. Example:

        ::

        ? matimagemod([4,1;0,4],8,&U)
        %6 =
        [2 1]
        
        [0 4]
        
        ? U
        %7 =
        [0 0]
        
        [2 1]
        '''
        x = objtogen(x)
        d = objtogen(d)
        cdef bint _have_U = (U is not None)
        if _have_U:
            raise NotImplementedError("optional argument U not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _d = (<Gen>d).g
        cdef GEN * _U = NULL
        cdef GEN _ret = matimagemod(_x, _d, _U)
        return new_gen(_ret)

    def matindexrank(self, M):
        r'''
        :math:`M` being a matrix of rank :math:`r`, returns a vector with two
        :literal:`t_VECSMALL` components :math:`y` and :math:`z` of length :math:`r` giving a list of rows
        and columns respectively (starting from 1) such that the extracted matrix
        obtained from these two vectors using :math:`vecextract (M,y,z)` is
        invertible. The vectors :math:`y` and :math:`z` are sorted in increasing order.
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = indexrank(_M)
        return new_gen(_ret)

    def matintersect(self, x, y):
        r'''
        :math:`x` and :math:`y` being two matrices with the same
        number of rows each of whose columns are independent, finds a basis of the
        :math:`\mathbb{Q}`-vector space equal to the intersection of the spaces spanned by the
        columns of :math:`x` and :math:`y` respectively. The faster function
        :literal:`idealintersect` can be used to intersect fractional ideals (projective
        :math:`\mathbb{Z}_K` modules of rank :math:`1`); the slower but much more general function
        :literal:`nfhnf` can be used to intersect general :math:`\mathbb{Z}_K`-modules.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = intersect(_x, _y)
        return new_gen(_ret)

    def matinverseimage(self, x, y):
        r'''
        Given a matrix :math:`x` and
        a column vector or matrix :math:`y`, returns a preimage :math:`z` of :math:`y` by :math:`x` if one
        exists (i.e such that :math:`x z = y`), an empty vector or matrix otherwise. The
        complete inverse image is :math:`z + Ker x`, where a basis of the kernel of
        :math:`x` may be obtained by :literal:`matker`.

        ::

        ? M = [1,2;2,4];
        ? matinverseimage(M, [1,2]~)
        %2 = [1, 0]~
        ? matinverseimage(M, [3,4]~)
        %3 = []~ \\ no solution
        ? matinverseimage(M, [1,3,6;2,6,12])
        %4 =
        [1 3 6]
        
        [0 0 0]
        ? matinverseimage(M, [1,2;3,4])
        %5 = [;] \\ no solution
        ? K = matker(M)
        %6 =
        [-2]
        
        [1]
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = inverseimage(_x, _y)
        return new_gen(_ret)

    def matinvmod(self, x, d):
        r'''
        Computes a left inverse of the matrix :math:`x` modulo :math:`d`. The matrix :math:`x` must
        have :literal:`t_INT` entries, and :math:`d` can be an arbitrary positive integer.

        ::

        ? A = [3,1,2;1,2,1;3,1,1];
        ? U = matinvmod(A,6)
        %2 =
        [1 1 3]
        
        [2 3 5]
        
        [1 0 5]
        
        ? (U*A)%6
        %3 =
        [1 0 0]
        
        [0 1 0]
        
        [0 0 1]
        ? matinvmod(A,5)
        *** at top-level: matinvmod(A,5)
        *** ^--------------
        *** matinvmod: impossible inverse in gen_inv: 0.
        '''
        x = objtogen(x)
        d = objtogen(d)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _d = (<Gen>d).g
        cdef GEN _ret = matinvmod(_x, _d)
        return new_gen(_ret)

    def matisdiagonal(self, x):
        r'''
        Returns true (1) if :math:`x` is a diagonal matrix, false (0) if not.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef int _ret = isdiagonal(_x)
        clear_stack()
        return _ret

    def matker(self, x, long flag=0):
        r'''
        Gives a basis for the kernel of the matrix :math:`x` as columns of a matrix.
        The matrix can have entries of any type, provided they are compatible with
        the generic arithmetic operations (:math:`+`, :math:`x` and :math:`/`).

        If :math:`x` is known to have integral entries, set :math:`flag = 1`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = matker0(_x, flag)
        return new_gen(_ret)

    def matkerint(self, x, long flag=0):
        r'''
        Gives an LLL-reduced :math:`\mathbb{Z}`-basis
        for the lattice equal to the kernel of the matrix :math:`x` with rational entries.

        :emphasis:`flag` is deprecated, kept for backward compatibility.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = matkerint0(_x, flag)
        return new_gen(_ret)

    def matkermod(self, x, d, im=None):
        r'''
        Gives a Howell basis (unique representation for submodules of :math:`(\mathbb{Z}/d\mathbb{Z})^n`,
        cf. :literal:`matimagemod`) for the kernel of the matrix :math:`x` modulo :math:`d` as columns
        of a matrix. The matrix :math:`x` must have :literal:`t_INT` entries, and :math:`d` can be an
        arbitrary positive integer. If :math:`im` is present, set it to a basis of the image
        of :math:`x` (which is computed on the way).

        ::

        ? A = [1,2,3;5,1,4]
        %1 =
        [1 2 3]
        
        [5 1 4]
        
        ? K = matkermod(A,6)
        %2 =
        [2 1]
        
        [2 1]
        
        [0 3]
        
        ? (A*K)%6
        %3 =
        [0 0]
        
        [0 0]
        '''
        x = objtogen(x)
        d = objtogen(d)
        cdef bint _have_im = (im is not None)
        if _have_im:
            raise NotImplementedError("optional argument im not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _d = (<Gen>d).g
        cdef GEN * _im = NULL
        cdef GEN _ret = matkermod(_x, _d, _im)
        return new_gen(_ret)

    def matmuldiagonal(self, x, d):
        r'''
        Product of the matrix :math:`x` by the diagonal
        matrix whose diagonal entries are those of the vector :math:`d`. Equivalent to,
        but much faster than :math:`x*matdiagonal (d)`.
        '''
        x = objtogen(x)
        d = objtogen(d)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _d = (<Gen>d).g
        cdef GEN _ret = matmuldiagonal(_x, _d)
        return new_gen(_ret)

    def matmultodiagonal(self, x, y):
        r'''
        Product of the matrices :math:`x` and :math:`y` assuming that the result is a
        diagonal matrix. Much faster than :math:`x*y` in that case. The result is
        undefined if :math:`x*y` is not diagonal.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = matmultodiagonal(_x, _y)
        return new_gen(_ret)

    def matpascal(self, long n, q=None):
        r'''
        Creates as a matrix the lower triangular
        Pascal triangle of order :math:`x+1` (i.e. with binomial coefficients
        up to :math:`x`). If :math:`q` is given, compute the :math:`q`-Pascal triangle (i.e. using
        :math:`q`-binomial coefficients).
        '''
        cdef bint _have_q = (q is not None)
        if _have_q:
            q = objtogen(q)
        sig_on()
        cdef GEN _q = NULL
        if _have_q:
            _q = (<Gen>q).g
        cdef GEN _ret = matqpascal(n, _q)
        return new_gen(_ret)

    def matpermanent(self, x):
        r'''
        Permanent of the square matrix :math:`x` using Ryser's formula in Gray code
        order.

        ::

        ? n = 20; m = matrix(n,n,i,j, i!=j);
        ? matpermanent(m)
        %2 = 895014631192902121
        ? n! * sum(i=0,n, (-1)^i/i!)
        %3 = 895014631192902121

        This function runs in time :math:`O(2^n n)` for a matrix of size
        :math:`n` and is not implemented for :math:`n` large.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = matpermanent(_x)
        return new_gen(_ret)

    def matqr(self, M, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Returns :math:`[Q,R]`, the QR-decomposition of the square invertible
        matrix :math:`M` with real entries: :math:`Q` is orthogonal and :math:`R` upper triangular. If
        :math:`flag = 1`, the orthogonal matrix is returned as a sequence of Householder
        transforms: applying such a sequence is stabler and faster than
        multiplication by the corresponding :math:`Q` matrix.
        More precisely, if

        ::

        [Q,R] = matqr(M);
        [q,r] = matqr(M, 1);

        then :math:`r = R` and :literal:`mathouseholder`:math:`(q, M)` is
        (close to) :math:`R`; furthermore

        ::

        mathouseholder(q, matid(#M)) == Q~

        the inverse of :math:`Q`. This function raises an error if the
        precision is too low or :math:`x` is singular.
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        precision = nbits2prec(precision)
        cdef GEN _ret = matqr(_M, flag, precision)
        return new_gen(_ret)

    def matrank(self, x):
        r'''
        Rank of the matrix :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = rank(_x)
        clear_stack()
        return _ret

    def matrixqz(self, A, p=None):
        r'''
        :math:`A` being an :math:`m x n` matrix in :math:`M_{m,n}(\mathbb{Q})`, let
        :math:`Im_\mathbb{Q} A` (resp. :math:`Im_\mathbb{Z} A`) the :math:`\mathbb{Q}`-vector space
        (resp. the :math:`\mathbb{Z}`-module) spanned by the columns of :math:`A`. This function has
        varying behavior depending on the sign of :math:`p`:

        If :math:`p >= 0`, :math:`A` is assumed to have maximal rank :math:`n <= m`. The function
        returns a matrix :math:`B\in M_{m,n}(\mathbb{Z})`, with :math:`Im_\mathbb{Q} B = Im_\mathbb{Q} A`,
        such that the GCD of all its :math:`n x n` minors is coprime to
        :math:`p`; in particular, if :math:`p = 0` (default), this GCD is :math:`1`.

        ::

        ? minors(x) = vector(#x[,1], i, matdet(x[^i,]));
        ? A = [3,1/7; 5,3/7; 7,5/7]; minors(A)
        %1 = [4/7, 8/7, 4/7] \\ determinants of all 2x2 minors
        ? B = matrixqz(A)
        %2 =
        [3 1]
        
        [5 2]
        
        [7 3]
        ? minors(%)
        %3 = [1, 2, 1] \\ B integral with coprime minors

        If :math:`p = -1`, returns the HNF basis of the lattice :math:`\mathbb{Z}^n \cap Im_\mathbb{Z} A`.

        If :math:`p = -2`, returns the HNF basis of the lattice :math:`\mathbb{Z}^n \cap Im_\mathbb{Q} A`.

        ::

        ? matrixqz(A,-1)
        %4 =
        [8 5]
        
        [4 3]
        
        [0 1]
        
        ? matrixqz(A,-2)
        %5 =
        [2 -1]
        
        [1 0]
        
        [0 1]
        '''
        A = objtogen(A)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _ret = matrixqz0(_A, _p)
        return new_gen(_ret)

    def matsize(self, x):
        r'''
        :math:`x` being a vector or matrix, returns a row vector
        with two components, the first being the number of rows (1 for a row vector),
        the second the number of columns (1 for a column vector).
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = matsize(_x)
        return new_gen(_ret)

    def matsnf(self, X, long flag=0):
        r'''
        If :math:`X` is a (singular or non-singular) matrix outputs the vector of
        elementary divisors of :math:`X`, i.e. the diagonal of the
        Smith normal form of :math:`X`, normalized so that :math:`d_n \| d_{n-1} \|
        ... \| d_1`.

        The binary digits of :emphasis:`flag` mean:

        1 (complete output): if set, outputs :math:`[U,V,D]`, where :math:`U` and :math:`V` are two
        unimodular matrices such that :math:`UXV` is the diagonal matrix :math:`D`. Otherwise
        output only the diagonal of :math:`D`. If :math:`X` is not a square matrix, then :math:`D`
        will be a square diagonal matrix padded with zeros on the left or the top.

        2 (generic input): if set, allows polynomial entries, in which case the
        input matrix must be square. Otherwise, assume that :math:`X` has integer
        coefficients with arbitrary shape.

        4 (cleanup): if set, cleans up the output. This means that elementary
        divisors equal to :math:`1` will be deleted, i.e. outputs a shortened vector :math:`D'`
        instead of :math:`D`. If complete output was required, returns :math:`[U',V',D']` so
        that :math:`U'XV' = D'` holds. If this flag is set, :math:`X` is allowed to be of the
        form `vector of elementary divisors' or :math:`[U,V,D]` as would normally be output with the cleanup flag
        unset.
        '''
        X = objtogen(X)
        sig_on()
        cdef GEN _X = (<Gen>X).g
        cdef GEN _ret = matsnf0(_X, flag)
        return new_gen(_ret)

    def matsolve(self, M, B):
        r'''
        Let :math:`M` be a left-invertible matrix and :math:`B` a column vector
        such that there exists a solution :math:`X` to the system of linear equations
        :math:`MX = B`; return the (unique) solution :math:`X`. This has the same effect as, but
        is faster, than :math:`M^{-1}*B`. Uses Dixon :math:`p`-adic lifting method if :math:`M` and
        :math:`B` are integral and Gaussian elimination otherwise. When there is no
        solution, the function returns an :math:`X` such that :math:`MX - B` is non-zero
        although it has at least :math:`\#M` zero entries:

        ::

        ? M = [1,2;3,4;5,6];
        ? B = [4,6,8]~; X = matsolve(M, B)
        %2 = [-2, 3]~
        ? M*X == B
        %3 = 1
        ? B = [1,2,4]~; X = matsolve(M, [1,2,4]~)
        %4 = [0, 1/2]~
        ? M*X - B
        %5 = [0, 0, -1]~

        Raises an exception if :math:`M` is not left-invertible, even if
        there is a solution:

        ::

        ? M = [1,1;1,1]; matsolve(M, [1,1]~)
        *** at top-level: matsolve(M,[1,1]~)
        *** ^------------------
        *** matsolve: impossible inverse in gauss: [1, 1; 1, 1].

        The function also works when :math:`B` is a matrix and we return
        the unique matrix solution :math:`X` provided it exists.
        '''
        M = objtogen(M)
        B = objtogen(B)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _B = (<Gen>B).g
        cdef GEN _ret = gauss(_M, _B)
        return new_gen(_ret)

    def matsolvemod(self, M, D, B, long flag=0):
        r'''
        :math:`M` being any integral matrix,
        :math:`D` a column vector of non-negative integer moduli, and :math:`B` an integral
        column vector, gives an integer solution to the system of congruences
        :math:`\sum_i m_{i,j}x_j = b_i (mod d_i)` if one exists, otherwise returns
        zero. Shorthand notation: :math:`B` (resp. :math:`D`) can be given as a single integer,
        in which case all the :math:`b_i` (resp. :math:`d_i`) above are taken to be equal to :math:`B`
        (resp. :math:`D`).

        ::

        ? M = [1,2;3,4];
        ? matsolvemod(M, [3,4]~, [1,2]~)
        %2 = [10, 0]~
        ? matsolvemod(M, 3, 1) \\ M X = [1,1]~ over F_3
        %3 = [2, 1]~
        ? matsolvemod(M, [3,0]~, [1,2]~) \\ x + 2y = 1 (mod 3), 3x + 4y = 2 (in Z)
        %4 = [6, -4]~

        If :math:`flag = 1`, all solutions are returned in the form of a two-component row
        vector :math:`[x,u]`, where :math:`x` is an integer solution to the system of
        congruences and :math:`u` is a matrix whose columns give a basis of the homogeneous
        system (so that all solutions can be obtained by adding :math:`x` to any linear
        combination of columns of :math:`u`). If no solution exists, returns zero.
        '''
        M = objtogen(M)
        D = objtogen(D)
        B = objtogen(B)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _D = (<Gen>D).g
        cdef GEN _B = (<Gen>B).g
        cdef GEN _ret = matsolvemod(_M, _D, _B, flag)
        return new_gen(_ret)

    def matsupplement(self, x):
        r'''
        Assuming that the columns of the matrix :math:`x`
        are linearly independent (if they are not, an error message is issued), finds
        a square invertible matrix whose first columns are the columns of :math:`x`,
        i.e. supplement the columns of :math:`x` to a basis of the whole space.

        ::

        ? matsupplement([1;2])
        %1 =
        [1 0]
        
        [2 1]

        Raises an error if :math:`x` has 0 columns, since (due to a long standing design
        bug), the dimension of the ambient space (the number of rows) is unknown in
        this case:

        ::

        ? matsupplement(matrix(2,0))
        *** at top-level: matsupplement(matrix
        *** ^--------------------
        *** matsupplement: sorry, suppl [empty matrix] is not yet implemented.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = suppl(_x)
        return new_gen(_ret)

    def mattranspose(self, x):
        r'''
        Transpose of :math:`x` (also :math:`x~`).
        This has an effect only on vectors and matrices.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gtrans(_x)
        return new_gen(_ret)

    def max(self, x, y):
        r'''
        Creates the maximum of :math:`x` and :math:`y` when they can be compared.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = gmax(_x, _y)
        return new_gen(_ret)

    def mfDelta(self):
        r'''
        Mf structure corresponding to the Ramanujan Delta function :math:`\Delta`.

        ::

        ? mfcoefs(mfDelta(),4)
        %1 = [0, 1, -24, 252, -1472]
        '''
        sig_on()
        cdef GEN _ret = mfDelta()
        return new_gen(_ret)

    def mfEH(self, k):
        r'''
        :math:`k` being in :math:`1/2+\mathbb{Z}`, returns the Cohen-Eisenstein series :math:`H_k` of
        weight :math:`k` on :math:`\Gamma_0(4)`.

        ::

        ? H = mfEH(13/2); mfcoefs(H,4)
        %1 = [691/32760, -1/252, 0, 0, -2017/252]

        The coefficients of :math:`H` are given by the Cohen-Hurwitz function
        :math:`H(k-1/2,N)` and can be obtained for moderately large values of :math:`N` (the
        algorithm uses :math:`~{O}(N)` time):

        ::

        ? mfcoef(H,10^5+1)
        time = 55 ms.
        %2 = -12514802881532791504208348
        ? mfcoef(H,10^7+1)
        time = 6,044 ms.
        %3 = -1251433416009877455212672599325104476
        '''
        k = objtogen(k)
        sig_on()
        cdef GEN _k = (<Gen>k).g
        cdef GEN _ret = mfEH(_k)
        return new_gen(_ret)

    def mfEk(self, long k):
        r'''
        Mf structure corresponding to the standard Eisenstein series :math:`E_k`.

        ::

        ? mfcoefs(mfEk(8),4)
        %1 = [1, 480, 61920, 1050240, 7926240]
        '''
        sig_on()
        cdef GEN _ret = mfEk(k)
        return new_gen(_ret)

    def mfTheta(self, psi=None):
        r'''
        The unary theta function corresponding to the primitive Dirichlet
        character :math:`\psi`, hence of weight :math:`1/2` if :math:`\psi` is even, of weight :math:`3/2`
        if :math:`\psi` is odd.

        ::

        ? Ser(mfcoefs(mfTheta(),30))
        %1 = 1 + 2*x + 2*x^4 + 2*x^9 + 2*x^16 + 2*x^25 + O(x^31)
        ? Ser(mfcoefs(mfTheta(8),30))
        %2 = 2*x - 2*x^9 - 2*x^25 + O(x^31)
        ? Ser(mfcoefs(mfTheta(-8),30))
        %3 = 2*x + 6*x^9 - 10*x^25 + O(x^31)
        '''
        cdef bint _have_psi = (psi is not None)
        if _have_psi:
            psi = objtogen(psi)
        sig_on()
        cdef GEN _psi = NULL
        if _have_psi:
            _psi = (<Gen>psi).g
        cdef GEN _ret = mfTheta(_psi)
        return new_gen(_ret)

    def mfatkin(self, mfatk, F):
        r'''
        Given a :literal:`mfatk` output by :literal:`mfatk = mfatkininit(mf,Q)` and
        a modular form :math:`F` belonging to the pace :literal:`mf`, returns the modular
        form :math:`C*F\|W_Q`, which has :literal:`polmod` coefficients in :math:`\mathbb{Q} (F)`;
        :literal:`mfatk[3]` gives the constant :math:`C`, and :literal:`mfatk[1]` gives
        the modular form space to which :math:`F\|W_Q` belongs (or is set to :math:`0` if
        it is :literal:`mf`).

        ::

        ? mf = mfinit([35,2],0); vecF = mfbasis(mf); F = vecF[1];
        ? mfcoefs(F, 4)
        %2 = [0, 3, -1, 0, 3]
        ? mfatk = mfatkininit(mf,7);
        ? wF = mfatkin(mfatk, F); mfcoefs(wF, 4)
        %4 = [0, 1, -1, -2, 7]
        ? mfatk = mfatkininit(mf,35);
        ? wF = mfatkin(mfatk, F); mfcoefs(wF, 4)
        %6 = [0, -3, 1, 0, -3]
        '''
        mfatk = objtogen(mfatk)
        F = objtogen(F)
        sig_on()
        cdef GEN _mfatk = (<Gen>mfatk).g
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfatkin(_mfatk, _F)
        return new_gen(_ret)

    def mfatkineigenvalues(self, mf, long Q, long precision=DEFAULT_BITPREC):
        r'''
        Given a modular form space :literal:`mf` of integral weight :math:`k` and a primitive
        divisor :math:`Q` of the level :math:`N` of :literal:`mf`, outputs the Atkin-Lehner
        eigenvalues of :math:`w_Q` on the new space, grouped by orbit. If :math:`\chi` is a
        (trivial or) quadratic character defined modulo :math:`N/Q`, the result is rounded
        and the eigenvalues are :math:`± i^k`.

        ::

        ? mf = mfinit([35,2],0); mffields(mf)
        %1 = [y, y^2 - y - 4] \\ two orbits, dimension 1 and 2
        ? mfatkineigenvalues(mf,5)
        %2 = [[1], [-1, -1]]
        ? mf = mfinit([12,7,Mod(3,4)],0);
        ? mfatkineigenvalues(mf,3)
        %4 = [[I, -I, -I, I, I, -I]] \\ one orbit

        If you want the eigenvalues on a larger space than the new space,
        e.g. the full space, you can directly call :literal:`[mfB,M,C] = mfatkininit` and
        compute the eigenvalues as the roots of the characteristic polynomial of
        :math:`M/C`, i.e. by dividing the roots of :literal:`charpoly(M)` by :math:`C`. Note that the
        characteristic polynomial is computed exactly since :math:`M` has coefficients in
        :math:`\mathbb{Q} (\chi)`, whereas :math:`C` may be given by a complex number. If the coefficients
        of the characteristic polynomial are polmods modulo :math:`T` they must be embedded
        to :math:`\mathbb{C}` first using :literal:`subst(lift(), t, exp(2*I*Pi/n))`, when :math:`T` is
        :literal:`poliscyclo(n)`; note that :math:`T = mf.mod`.
        '''
        mf = objtogen(mf)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        precision = nbits2prec(precision)
        cdef GEN _ret = mfatkineigenvalues(_mf, Q, precision)
        return new_gen(_ret)

    def mfatkininit(self, mf, long Q, long precision=DEFAULT_BITPREC):
        r'''
        Given a modular form space with parameters :math:`N,k,\chi` and a
        primitive divisor :math:`Q` of the level :math:`N`, initializes data necessary for
        working with the Atkin-Lehner operator :math:`W_Q`, for now only the function
        :literal:`mfatkin`. We write :math:`\chi ~ \chi_Q \chi_{N/Q}` where
        the two characters are primitive with (coprime) conductors dividing
        :math:`Q` and :math:`N/Q` respectively. For :math:`F\in M_k(\Gamma_0(N),\chi)`,
        the form :math:`F \| W_Q` still has level :math:`N` and weight :math:`k` but its
        Nebentypus may no longer be :math:`\chi`: it becomes :math:`\overline{\chi_Q} \chi_{N/Q})`
        if :math:`k` is integral and :math:`\overline{\chi_Q} \chi_{N/Q})(4Q/.)` if not.

        The result is a technical 4-component vector :literal:`[mfB, CM, C, mf]`, where

        - :literal:`mfB` encodes the modular form space to which
        :math:`F\|W_Q` belongs when :math:`F \in M_k(\Gamma_0(N), \chi)`: an :literal:`mfinit`
        corresponding to a new Nebentypus or the integer :math:`0` when the character does
        not change. This does not depend on :math:`F`.

        - :literal:`CM` is the matrix of :math:`W_Q` on the bases of :literal:`mf` and :literal:`mfB`
        multiplied by a normalizing constant :math:`C(k,\chi,Q)`. This matrix has polmod
        coefficients in :math:`\mathbb{Q} (\chi)`.

        - :literal:`C` is the complex constant :math:`C(k,\chi,Q)`. For :math:`k`
        integral, let :math:`A(k,\chi, Q) = Q^{\varepsilon}/g(\chi_Q)`, where
        :math:`\varepsilon = 0` for :math:`k` even and :math:`1/2` for :math:`k` odd and
        where :math:`g(\chi_Q)` is the Gauss sum attached to :math:`\chi_Q`). (A similar, more
        complicated, definition holds in half-integral weight depending on the parity
        of :math:`k - 1/2`.) Then if :math:`M` denotes the matrix of :math:`W_Q` on the bases
        of :literal:`mf` and :literal:`mfB`, :math:`A.M` has coefficients in :math:`\mathbb{Q} (\chi)`.
        If :math:`A` is rational, we let :math:`C = 1` and :math:`C = A` as a floating point complex
        number otherwise, and finally :math:`MC := M.C`.

        ::

        ? mf=mfinit([32,4],0); [mfB,MC,C]=mfatkininit(mf,32); MC
        %1 =
        [5/16 11/2 55/8]
        
        [ 1/8 0 -5/4]
        
        [1/32 -1/4 11/16]
        
        ? C
        %2 = 1
        ? mf=mfinit([32,4,8],0); [mfB,MC,C]=mfatkininit(mf,32); MC
        %3 =
        [ 1/8 -7/4]
        
        [-1/16 -1/8]
        ? C
        %4 = 0.35355339059327376220042218105242451964
        ? algdep(C,2) \\ C = 1/sqrt(8)
        %5 = 8*x^2 - 1
        '''
        mf = objtogen(mf)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        precision = nbits2prec(precision)
        cdef GEN _ret = mfatkininit(_mf, Q, precision)
        return new_gen(_ret)

    def mfbasis(self, NK, long space=4):
        r'''
        If :math:`NK = [N,k,CHI]` as in :literal:`mfinit`, gives a basis of the
        corresponding subspace of :math:`M_k(\Gamma_0(N),\chi)`. :math:`NK` can also be the
        output of :literal:`mfinit`, in which case :literal:`space` can be omitted.
        To obtain the eigenforms, use :literal:`mfeigenbasis`.

        If :literal:`space` is a full space :math:`M_k`, the output is the union of first, a
        basis of the space of Eisenstein series, and second, a basis of the cuspidal
        space.

        ::

        ? see(L) = apply(f->mfcoefs(f,3), L);
        ? mf = mfinit([35,2],0);
        ? see( mfbasis(mf) )
        %2 = [[0, 3, -1, 0], [0, -1, 9, -8], [0, 0, -8, 10]]
        ? see( mfeigenbasis(mf) )
        %3 = [[0, 1, 0, 1], [Mod(0, z^2 - z - 4), Mod(1, z^2 - z - 4), \
        Mod(-z, z^2 - z - 4), Mod(z - 1, z^2 - z - 4)]]
        ? mf = mfinit([35,2]);
        ? see( mfbasis(mf) )
        %5 = [[1/6, 1, 3, 4], [1/4, 1, 3, 4], [17/12, 1, 3, 4], \
        [0, 3, -1, 0], [0, -1, 9, -8], [0, 0, -8, 10]]
        ? see( mfbasis([48,4],0) )
        %6 = [[0, 3, 0, -3], [0, -3, 0, 27], [0, 2, 0, 30]]
        '''
        NK = objtogen(NK)
        sig_on()
        cdef GEN _NK = (<Gen>NK).g
        cdef GEN _ret = mfbasis(_NK, space)
        return new_gen(_ret)

    def mfbd(self, F, long d):
        r'''
        :math:`F` being a generalized modular form, return :math:`B(d)(F)`, where :math:`B(d)` is
        the expanding operator :math:`\tau:---> d\tau`.

        ::

        ? D2=mfbd(mfDelta(),2); mfcoefs(D2, 6)
        %1 = [0, 0, 1, 0, -24, 0, 252]
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfbd(_F, d)
        return new_gen(_ret)

    def mfbracket(self, F, G, long m=0):
        r'''
        Compute the :math:`m`-th Rankin-Cohen bracket of the generalized modular
        forms :math:`F` and :math:`G`.

        ::

        ? E4 = mfEk(4); E6 = mfEk(6);
        ? D1 = mfbracket(E4,E4,2); mfcoefs(D1,5)/4800
        %2 = [0, 1, -24, 252, -1472, 4830]
        ? D2 = mfbracket(E4,E6,1); mfcoefs(D2,10)/(-3456)
        %3 = [0, 1, -24, 252, -1472, 4830]
        '''
        F = objtogen(F)
        G = objtogen(G)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _G = (<Gen>G).g
        cdef GEN _ret = mfbracket(_F, _G, m)
        return new_gen(_ret)

    def mfcoef(self, F, long n):
        r'''
        Compute the :math:`n`-th Fourier coefficient of the generalized modular form :math:`F`.
        Note that this is the :math:`n+1`-st component of the vector
        :literal:`mfcoefs(F,n)` as well as the second component of :literal:`mfcoefs(F,1,n)`.

        ::

        ? mfcoef(mfDelta(),10)
        %1 = -115920
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfcoef(_F, n)
        return new_gen(_ret)

    def mfcoefs(self, F, long n, long d=1):
        r'''
        Compute the vector of Fourier coefficients :math:`[a[0],a[d],...,a[nd]]` of the
        generalized modular form :math:`F`; :math:`d` must be positive and :math:`d = 1` by default.

        ::

        ? D = mfDelta();
        ? mfcoefs(D,10)
        %2 = [0, 1, -24, 252, -1472, 4830, -6048, -16744, 84480, -113643, -115920]
        ? mfcoefs(D,5,2)
        %3 = [0, -24, -1472, -6048, 84480, -115920]
        ? mfcoef(D,10)
        %4 = -115920

        This function also applies when :math:`F` is a modular form space as output by
        :literal:`mfinit`; it then returns the matrix whose columns give the Fourier
        expansions of the elements of :literal:`mfbasis`:math:`(F)`:

        ::

        ? mf = mfinit([1,12]);
        ? mfcoefs(mf,5)
        %2 =
        [691/65520 0]
        
        [ 1 1]
        
        [ 2049 -24]
        
        [ 177148 252]
        
        [ 4196353 -1472]
        
        [ 48828126 4830]
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfcoefs(_F, n, d)
        return new_gen(_ret)

    def mfconductor(self, mf, F):
        r'''
        :literal:`mf` being output by :literal:`mfinit` for the cuspidal space and
        :math:`F` a modular form, gives the smallest level on which :math:`F` is defined.

        ::

        ? mf=mfinit([96,6],1); vF = mfbasis(mf); mfdim(mf)
        %1 = 72
        ? vector(10,i, mfconductor(mf, vF[i]))
        %2 = [3, 6, 12, 24, 48, 96, 4, 8, 12, 16]
        '''
        mf = objtogen(mf)
        F = objtogen(F)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _F = (<Gen>F).g
        cdef long _ret = mfconductor(_mf, _F)
        clear_stack()
        return _ret

    def mfcosets(self, N):
        r'''
        List of right cosets of :math:`\Gamma_0(N) \\Gamma`, i.e., matrices
        :math:`\gamma_j \in \Gamma` such that :math:`\Gamma = \bigsqcup_j \Gamma_0(N) \gamma_j`.
        The :math:`\gamma_j` are chosen in the form :math:`[a,b;c,d]` with :math:`c \| N`.
        :math:`N` can be either a positive integer or a modular form space.

        ::

        ? mfcosets(4)
        %1 = [[0, -1; 1, 0], [1, 0; 1, 1], [0, -1; 1, 2], [0, -1; 1, 3],\
        [1, 0; 2, 1], [1, 0; 4, 1]]

        :strong:`Warning.` in the present implementation, the trivial coset is
        represented by :math:`[1,0;N,1]` and is the last in the list.
        '''
        N = objtogen(N)
        sig_on()
        cdef GEN _N = (<Gen>N).g
        cdef GEN _ret = mfcosets(_N)
        return new_gen(_ret)

    def mfcuspisregular(self, NK, cusp):
        r'''
        In the space defined by :literal:`NK = [N,k,CHI]` or :literal:`NK = mf`,
        determine if :literal:`cusp` in canonical format (oo or denominator
        dividing :math:`N`) is regular or not.

        ::

        ? mfcuspisregular([4,3,-4],1/2)
        %1 = 0
        '''
        NK = objtogen(NK)
        cusp = objtogen(cusp)
        sig_on()
        cdef GEN _NK = (<Gen>NK).g
        cdef GEN _cusp = (<Gen>cusp).g
        cdef long _ret = mfcuspisregular(_NK, _cusp)
        clear_stack()
        return _ret

    def mfcusps(self, N):
        r'''
        List of cusps of :math:`\Gamma_0(N)` in the form :math:`a/b` with :math:`b \| N`.
        :math:`N` can be either an integer of a modular form space.

        ::

        ? mfcusps(24)
        %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/8, 1/12, 1/24]
        '''
        N = objtogen(N)
        sig_on()
        cdef GEN _N = (<Gen>N).g
        cdef GEN _ret = mfcusps(_N)
        return new_gen(_ret)

    def mfcuspval(self, mf, F, cusp, long precision=DEFAULT_BITPREC):
        r'''
        Valuation of modular form :math:`F` in the space :literal:`mf` at
        :literal:`cusp`, which can be either :math:`oo` or any rational number, and the
        result is either a rational number or :math:`oo` if :math:`F` is zero. If :math:`\mathbb{Q} (F)
        != \mathbb{Q} (\chi)`, return the vector of valuations attached to the
        :math:`[\mathbb{Q} (F):\mathbb{Q} (chi)]` complex embeddings of :math:`F`.

        ::

        ? T=mfTheta();mf=mfinit([12,1/2]);mfcusps(12)
        %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/12]
        ? apply(x->mfcuspval(mf,T,x),%1)
        %2 = [0, 1/4, 0, 0, 1/4, 0]
        ? mf=mfinit([12,6,12],1);F=mfbasis(mf)[5];
        ? apply(x->mfcuspval(mf,F,x),%1)
        %4 = [1/12, 1/6, 1/2, 2/3, 1/2, 2]
        ? mf=mfinit([12,3,-4],1);F=mfbasis(mf)[1];
        ? apply(x->mfcuspval(mf,F,x),%1)
        %6 = [1/12, 1/6, 1/4, 2/3, 1/2, 1]
        
        ? mf = mfinit([625,2],0); [F] = mfeigenbasis(mf); mfparams(F)
        %7 = [625, 2, 1, y^2 - y - 1] \\ [Q(F):Q(chi)] = poldegree(y^2-y-1)
        ? mfcuspval(mf, F, 1/25)
        %8 = [1, 2] \\ one conjugate has valuation 1, and the other is 2
        ? mfcuspval(mf, F, 1/5)
        %9 = [1/25, 1/25]
        '''
        mf = objtogen(mf)
        F = objtogen(F)
        cusp = objtogen(cusp)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _F = (<Gen>F).g
        cdef GEN _cusp = (<Gen>cusp).g
        cdef GEN _ret = mfcuspval(_mf, _F, _cusp, precision)
        return new_gen(_ret)

    def mfcuspwidth(self, N, cusp):
        r'''
        Width of :literal:`cusp` in :math:`\Gamma_0(N)`, :math:`N` being either an integer or a
        modular form space.

        ::

        ? mfcusps(12)
        %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/12]
        ? [mfcuspwidth(12,c) | c <- mfcusps(12)]
        %2 = [12, 3, 4, 3, 1, 1]
        ? mfcuspwidth(12, oo)
        %3 = 1
        '''
        N = objtogen(N)
        cusp = objtogen(cusp)
        sig_on()
        cdef GEN _N = (<Gen>N).g
        cdef GEN _cusp = (<Gen>cusp).g
        cdef long _ret = mfcuspwidth(_N, _cusp)
        clear_stack()
        return _ret

    def mfderiv(self, F, long m=1):
        r'''
        :math:`m`-th formal derivative of the power series corresponding to
        the generalized modular form :math:`F`, with respect to the differential operator
        :math:`qd/dq` (default :math:`m = 1`).

        ::

        ? D=mfDelta();
        ? mfcoefs(D, 4)
        %2 = [0, 1, -24, 252, -1472]
        ? mfcoefs(mfderiv(D), 4)
        %3 = [0, 1, -48, 756, -5888]
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfderiv(_F, m)
        return new_gen(_ret)

    def mfderivE2(self, F, long m=1):
        r'''
        Compute the Serre derivative :math:`(q.d/dq)F - kE_2F/12`
        of the generalized modular form :math:`F`, which has weight :math:`k+2`;
        if :math:`F` is a true modular form, then its Serre derivative is also modular.
        If :math:`m > 1`, compute the :math:`m`-th iterate, of weight :math:`k + 2m`.

        ::

        ? mfcoefs(mfderivE2(mfEk(4)),5)*(-3)
        %1 = [1, -504, -16632, -122976, -532728]
        ? mfcoefs(mfEk(6),5)
        %2 = [1, -504, -16632, -122976, -532728]
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfderivE2(_F, m)
        return new_gen(_ret)

    def mfdescribe(self, F, G=None):
        r'''
        Gives a human-readable description of :math:`F`, which is either a modular
        form space or a generalized modular form. If the address of :math:`G` is given,
        puts into :math:`G` the vector of parameters of the outmost operator defining :math:`F`
        (the empty vector if :math:`F` is a leaf or a modular form space).

        ::

        ? E1 = mfeisenstein(4,-3,-4); mfdescribe(E1)
        %1 = "F_4(-3, -4)"
        ? E2 = mfeisenstein(3,5,-7); mfdescribe(E2)
        %2 = "F_3(5, -7)"
        ? E3 = mfderivE2(mfmul(E1,E2), 3); mfdescribe(E3,&G)
        %3 = "DERE2^3(MUL(F_4(-3, -4), F_3(5, -7)))"
        ? mfdescribe(G[1][1])
        %4 = "MUL(F_4(-3, -4), F_3(5, -7))"
        ? G[2]
        %5 = 3
        ? for (i = 0, 4, mf = mfinit([37,4],i); print(mfdescribe(mf)));
        S_4^new(G_0(37, 1))
        S_4(G_0(37, 1))
        S_4^old(G_0(37, 1))
        E_4(G_0(37, 1))
        M_4(G_0(37, 1))
        '''
        F = objtogen(F)
        cdef bint _have_G = (G is not None)
        if _have_G:
            raise NotImplementedError("optional argument G not available")
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN * _G = NULL
        cdef GEN _ret = mfdescribe(_F, _G)
        return new_gen(_ret)

    def mfdim(self, NK, long space=4):
        r'''
        If :math:`NK = [N,k,CHI]` as in :literal:`mfinit`, gives the dimension of the
        corresponding subspace of :math:`M_k(\Gamma_0(N),\chi)`. :math:`NK` can also be the
        output of :literal:`mfinit`, in which case space must be omitted.

        The subspace is described by the small integer :literal:`space`: :math:`0` for the
        newspace :math:`S_k^{new}(\Gamma_0(N),\chi)`, :math:`1` for the cuspidal
        space :math:`S_k`, :math:`2` for the oldspace :math:`S_k^{old}`, :math:`3` for the space of
        Eisenstein series :math:`E_k` and :math:`4` for the full space :math:`M_k`.

        :strong:`Wildcards.`
        As in :literal:`mfinit`, :emphasis:`CHI` may be the wildcard 0
        (all Galois orbits of characters); in this case, the output is a vector of
        :math:`[order, conrey, dim, dimdih]` corresponding
        to the non-trivial spaces, where

        - :emphasis:`order` is the order of the character,

        - :emphasis:`conrey` its Conrey label from which the character may be recovered
        via :literal:`znchar`:math:`(conrey)`,

        - :emphasis:`dim` the dimension of the corresponding space,

        - :emphasis:`dimdih` the dimension of the subspace of dihedral forms
        corresponding to Hecke characters if :math:`k = 1` (this is not implemented for
        the old space and set to :math:`-1` for the time being) and 0 otherwise.

        The spaces are sorted by increasing order of the character; the characters are
        taken up to Galois conjugation and the Conrey number is the minimal one among
        Galois conjugates. In weight :math:`1`, this is only implemented when
        the space is 0 (newspace), 1 (cusp space), 2(old space) or 3(Eisenstein
        series).

        :strong:`Wildcards for sets of characters.` :emphasis:`CHI` may be a set
        of characters, and we return the set of :math:`[dim,dimdih]`.

        :strong:`Wildcard for :math:`M_k(\Gamma_1(N))`.`
        Additionally, the wildcard :math:`CHI = -1` is available in which case we
        output the total dimension of the corresponding
        subspace of :math:`M_k(\Gamma_1(N))`. In weight :math:`1`, this is not implemented
        when the space is 4 (fullspace).

        ::

        ? mfdim([23,2], 0) \\ new space
        %1 = 2
        ? mfdim([96,6], 0)
        %2 = 10
        ? mfdim([10^9,4], 3) \\ Eisenstein space
        %1 = 40000
        ? mfdim([10^9+7,4], 3)
        %2 = 2
        ? mfdim([68,1,-1],0)
        %3 = 3
        ? mfdim([68,1,0],0)
        %4 = [[2, Mod(67, 68), 1, 1], [4, Mod(47, 68), 1, 1]]
        ? mfdim([124,1,0],0)
        %5 = [[6, Mod(67, 124), 2, 0]]

        This last example shows that there exists a nondihedral form of weight 1
        in level 124.
        '''
        NK = objtogen(NK)
        sig_on()
        cdef GEN _NK = (<Gen>NK).g
        cdef GEN _ret = mfdim(_NK, space)
        return new_gen(_ret)

    def mfdiv(self, F, G):
        r'''
        Given two generalized modular forms :math:`F` and :math:`G`, compute :math:`F/G` assuming
        that the quotient will not have poles at infinity. If this is the
        case, use :literal:`mfshift` before doing the division.

        ::

        ? D = mfDelta(); \\ Delta
        ? H = mfpow(mfEk(4), 3);
        ? J = mfdiv(H, D)
        *** at top-level: J=mfdiv(H,mfdeltac
        *** ^--------------------
        *** mfdiv: domain error in mfdiv: ord(G) > ord(F)
        ? J = mfdiv(H, mfshift(D,1));
        ? mfcoefs(J, 4)
        %4 = [1, 744, 196884, 21493760, 864299970]
        '''
        F = objtogen(F)
        G = objtogen(G)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _G = (<Gen>G).g
        cdef GEN _ret = mfdiv(_F, _G)
        return new_gen(_ret)

    def mfeigenbasis(self, mf):
        r'''
        Vector of the eigenforms for the space :literal:`mf`.
        The initial basis of forms computed by :literal:`mfinit` before splitting
        is also available via :literal:`mfbasis`.

        ::

        ? mf = mfinit([26,2],0);
        ? see(L) = for(i=1,#L,print(mfcoefs(L[i],6)));
        ? see( mfeigenbasis(mf) )
        [0, 1, -1, 1, 1, -3, -1]
        [0, 1, 1, -3, 1, -1, -3]
        ? see( mfbasis(mf) )
        [0, 2, 0, -2, 2, -4, -4]
        [0, -2, -4, 10, -2, 0, 8]

        The eigenforms are internally expressed as (algebraic) linear combinations of
        :literal:`mfbasis(mf)` and it is very inefficient to compute many coefficients
        of those forms individually: you should rather use :literal:`mfcoefs(mf)`
        to expand the basis once and for all, then multiply by :literal:`mftobasis(mf,f)`
        for the forms you're interested in:

        ::

        ? mf = mfinit([96,6],0); B = mfeigenbasis(mf); #B
        %1 = 8;
        ? vector(#B, i, mfcoefs(B[i],1000)); \\ expanded individually: slow
        time = 7,881 ms.
        ? M = mfcoefs(mf, 1000); \\ initialize once
        time = 982 ms.
        ? vector(#B, i, M * mftobasis(mf,B[i])); \\ then expand: much faster
        time = 623 ms.

        When the eigenforms are defined over an extension field of :math:`\mathbb{Q} (\chi)` for a
        non-rational character, their coefficients are hard to read and you may want
        to lift them or to express them in an absolute number field. In the
        construction below :math:`T` defines :math:`\mathbb{Q} (f)` over :math:`\mathbb{Q}`, :math:`a` is the image of the
        generator :literal:`Mod`:math:`(t, t^2+t+1)` of :math:`\mathbb{Q} (\chi)` in :math:`\mathbb{Q} (f)`
        and :math:`y - ka` is the image of the root :math:`y` of :literal:`f.mod`:

        ::

        ? mf = mfinit([31, 2, Mod(25,31)], 0); [f] = mfeigenbasis(mf);
        ? f.mod
        %2 = Mod(1, t^2 + t + 1)*y^2 + Mod(2*t + 2, t^2 + t + 1)
        ? v = liftpol(mfcoefs(f,5))
        %3 = [0, 1, (-t - 1)*y - 1, t*y + (t + 1), (2*t + 2)*y + 1, t]
        ? [T,a,k] = rnfequation(mf.mod, f.mod, 1)
        %4 = [y^4 + 2*y^2 + 4, Mod(-1/2*y^2 - 1, y^4 + 2*y^2 + 4), 0]
        ? liftpol(substvec(v, [t,y], [a, y-k*a]))
        %5 = [0, 1, 1/2*y^3 - 1, -1/2*y^3 - 1/2*y^2 - y, -y^3 + 1, -1/2*y^2 - 1]

        Beware that the meaning of :math:`y` has changed in the last line
        is different: it now represents of root of :math:`T`, no longer of :literal:`f.mod`
        (the notions coincide if :math:`k = 0` as here but it will not always be the case).
        This can be avoided with an extra variable substitution, for instance

        ::

        ? [T,a,k] = rnfequation(mf.mod, subst(f.mod,'y,'x), 1)
        %6 = [x^4 + 2*x^2 + 4, Mod(-1/2*x^2 - 1, x^4 + 2*x^2 + 4), 0]
        ? liftpol(substvec(v, [t,y], [a, x-k*a]))
        %7 = [0, 1, 1/2*x^3 - 1, -1/2*x^3 - 1/2*x^2 - x, -x^3 + 1, -1/2*x^2 - 1]
        '''
        mf = objtogen(mf)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _ret = mfeigenbasis(_mf)
        return new_gen(_ret)

    def mfeigensearch(self, NK, AP=None):
        r'''
        Search for a normalized rational eigen cuspform with quadratic
        character given restrictions on a few initial coefficients. The meaning of
        the parameters is as follows:

        - :literal:`NK` governs the limits of the search: it is of the form
        :math:`[N,k]`: search for given level :math:`N`, weight :math:`k` and quadratic
        character; note that the character :math:`(D/.)` is uniquely determined by :math:`(N,k)`.
        The level :math:`N` can be replaced by a vector of allowed levels.

        - :literal:`AP` is the search criterion, which can be omitted: a list of
        pairs :math:`[..., [p,a_p],...]`, where :math:`p` is a prime number and :math:`a_p` is
        either a :literal:`t_INT` (the :math:`p`-th Fourier coefficient must match :math:`a_p` exactly)
        or a :literal:`t_INTMOD` :literal:`Mod`:math:`(a,b)` (the :math:`p`-th coefficient must be congruent
        to :math:`a` modulo :math:`b`).

        The result is a vector of newforms :math:`f` matching the search criteria, sorted
        by increasing level then increasing :math:`\|D\|`.

        ::

        ? #mfeigensearch([[1..80],2], [[2,2],[3,-1]])
        %1 = 1
        ? #mfeigensearch([[1..80],2], [[2,2],[5,2]])
        %2 = 1
        ? v = mfeigensearch([[1..20],2], [[3,Mod(2,3)],[7,Mod(5,7)]]); #v
        %3 = 1
        ? F=v[1]; [mfparams(F)[1], mfcoefs(F,15)]
        %4 = [11, [0, 1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1]]
        '''
        NK = objtogen(NK)
        cdef bint _have_AP = (AP is not None)
        if _have_AP:
            AP = objtogen(AP)
        sig_on()
        cdef GEN _NK = (<Gen>NK).g
        cdef GEN _AP = NULL
        if _have_AP:
            _AP = (<Gen>AP).g
        cdef GEN _ret = mfeigensearch(_NK, _AP)
        return new_gen(_ret)

    def mfeisenstein(self, long k, CHI1=None, CHI2=None):
        r'''
        Create the Eisenstein series :math:`E_k(\chi_1,\chi_2)`, where :math:`k >= 1`,
        :math:`\chi_i` are Dirichlet characters and an omitted character is considered as
        trivial.

        ::

        ? CHI = Mod(3,4);
        ? E = mfeisenstein(3, CHI);
        ? mfcoefs(E, 6)
        %2 = [-1/4, 1, 1, -8, 1, 26, -8]
        ? CHI2 = Mod(4,5);
        ? mfcoefs(mfeisenstein(3,CHI,CHI2), 6)
        %3 = [0, 1, -1, -10, 1, 25, 10]
        ? mfcoefs(mfeisenstein(4,CHI,CHI), 6)
        %4 = [0, 1, 0, -28, 0, 126, 0]
        ? mfcoefs(mfeisenstein(4), 6)
        %5 = [1/240, 1, 9, 28, 73, 126, 252]

        Note that :literal:`meisenstein`:math:`(k)` is 0 for :math:`k` odd and
        :math:`-B_{k}/(2k).E_k` for :math:`k` even, where

        .. MATH::

        E_k(q) = 1 - (2k/B_k)\sum_{n >= 1} \sigma_{k-1}(n) q^n

        is the standard Eisenstein series. In other words it is normalized so that its
        linear coefficient is :math:`1`.
        '''
        cdef bint _have_CHI1 = (CHI1 is not None)
        if _have_CHI1:
            CHI1 = objtogen(CHI1)
        cdef bint _have_CHI2 = (CHI2 is not None)
        if _have_CHI2:
            CHI2 = objtogen(CHI2)
        sig_on()
        cdef GEN _CHI1 = NULL
        if _have_CHI1:
            _CHI1 = (<Gen>CHI1).g
        cdef GEN _CHI2 = NULL
        if _have_CHI2:
            _CHI2 = (<Gen>CHI2).g
        cdef GEN _ret = mfeisenstein(k, _CHI1, _CHI2)
        return new_gen(_ret)

    def mfembed(self, f, v=None, long precision=DEFAULT_BITPREC):
        r'''
        Let :math:`f` be a generalized modular form with parameters :math:`[N,k,\chi,P]` (see
        :literal:`mfparams`, we denote :math:`\mathbb{Q} (\chi)` the subfield of :math:`\mathbb{C}` generated by the
        values of :math:`\chi` and :math:`\mathbb{Q} (f)` the field of definition of :math:`f`. In this context
        :math:`\mathbb{Q} (\chi)` has a single canonical complex embeding given by
        :math:`s: Mod(t, polcyclo(n,t)) :--->\exp (2i\pi/n)` and the number field
        :math:`\mathbb{Q} (f)` has :math:`[\mathbb{Q} (f):\mathbb{Q} (\chi)]` induced embeddings attached to the complex
        roots of the polynomial :math:`s(P)`. If :math:`\mathbb{Q} (f)` is stricly larger than :math:`\mathbb{Q} (\chi)`
        we only allow an :math:`f` which is an eigenform, produced by :literal:`mfeigenbasis`.

        This function is meant to create embeddings of :math:`\mathbb{Q} (f)` and/or apply them
        to the object :math:`v`, typically a vector of Fourier coefficients of :math:`f`
        from :literal:`mfcoefs`.

        - If :math:`v` is omitted and :math:`f` is a modular form as above, we return the
        embedding of :math:`\mathbb{Q} (\chi)` if :math:`\mathbb{Q} (\chi) = \mathbb{Q} (f)` and a vector containing
        :math:`[\mathbb{Q} (f):\mathbb{Q} (\chi)]` embeddings of :math:`\mathbb{Q} (f)` otherwise.

        - If :math:`v` is given, it must be a scalar in :math:`\mathbb{Q} (f)`, or a vector/matrix of
        such, we apply the embeddings coefficientwise and return either
        a single result if :math:`\mathbb{Q} (f) = \mathbb{Q} (\chi)` and a vector of :math:`[\mathbb{Q} (f):\mathbb{Q} (\chi)]`
        results otherwise.

        - Finally :math:`f` can be replaced by a single embedding produced by
        :literal:`mfembed`:math:`(f)` (:math:`v` was omitted) and we apply that particular embedding
        to :math:`v`.

        ::

        ? mf = mfinit([35,2,Mod(11,35)], 0);
        ? [f] = mfbasis(mf);
        ? f.mod \\ Q (chi) = Q (zeta_3)
        %3 = t^2 + t + 1
        ? v = mfcoefs(f,5); lift(v) \\ coefficients in Q (chi)
        %4 = [0, 2, -2*t - 2, 2*t, 2*t, -2*t - 2]
        ? mfembed(f, v) \\ single embedding
        %5 = [0, 2, -1 - 1.7320...*I, -1 + 1.73205...*I, -1 + 1.7320...*I, ...]
        
        ? [F] = mfeigenbasis(mf);
        ? mffields(mf)
        %7 = [y^2 + Mod(-2*t, t^2 + t + 1)] \\ [Q (f):Q (chi)] = 2
        ? V = liftpol( mfcoefs(F,5) );
        %8 = [0, 1, y + (-t - 1), (t + 1)*y + t, (-2*t - 2)*y + t, -t - 1]
        ? vall = mfembed(F, V); #vall
        %9 = 2 \\ 2 embeddings, both applied to V
        ? vall[1] \\ the first
        %10 = [0, 1, -1.2071... - 2.0907...*I, 0.2071... - 0.3587...*I, ...]
        ? vall[2] \\ and the second one
        %11 = [0, 1, 0.2071... + 0.3587...*I, -1.2071... + 2.0907...*I, ...]
        
        ? vE = mfembed(F); #vE \\ same 2 embeddings
        %12 = 2
        ? mfembed(vE[1], V) \\ apply first embedding to V
        %13 = [0, 1, -1.2071... - 2.0907...*I, 0.2071... - 0.3587...*I, ...]

        For convenience, we also allow a modular form space from :literal:`mfinit`
        instead of :math:`f`, corresponding to the single embedding of :math:`\mathbb{Q} (\chi)`.

        ::

        ? [mfB,MC,C] = mfatkininit(mf,7); MC \\ coefs in Q (chi)
        %13 =
        [ Mod(2/7*t, t^2 + t + 1) Mod(-1/7*t - 2/7, t^2 + t + 1)]
        
        [Mod(-1/7*t - 2/7, t^2 + t + 1) Mod(2/7*t, t^2 + t + 1)]
        
        ? C \\ normalizing constant
        %14 = 0.33863... - 0.16787*I
        ? M = mfembed(mf, MC) / C \\ the true matrix for the action of w_7
        [-0.6294... + 0.4186...*I -0.3625... - 0.5450...*I]
        
        [-0.3625... - 0.5450...*I -0.6294... + 0.4186...*I]
        
        ? exponent(M*conj(M) - 1) \\ M * conj(M) is close to 1
        %16 = -126
        '''
        f = objtogen(f)
        cdef bint _have_v = (v is not None)
        if _have_v:
            v = objtogen(v)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _v = NULL
        if _have_v:
            _v = (<Gen>v).g
        precision = nbits2prec(precision)
        cdef GEN _ret = mfembed0(_f, _v, precision)
        return new_gen(_ret)

    def mfeval(self, mf, F, vtau, long precision=DEFAULT_BITPREC):
        r'''
        Computes the numerical value of the modular form :math:`F`, belonging
        to :emphasis:`mf`, at the complex number :literal:`vtau` or the vector :literal:`vtau`
        of complex numbers in the completed upper-half plane. The result is given
        with absolute error less than :math:`2^{-B}`, where :math:`B = realbitprecision`.

        If the field of definition :math:`\mathbb{Q} (F)` is larger than :math:`\mathbb{Q} (\chi)` then :math:`F` may be
        embedded into :math:`\mathbb{C}` in :math:`d = [\mathbb{Q} (F):\mathbb{Q} (\chi)]` ways, in which case a vector of
        the :math:`d` results is returned.

        ::

        ? mf = mfinit([11,2],0); F = mfbasis(mf)[1]; mfparams(F)
        %1 = [11, 2, 1, y] \\ Q(F) = Q(chi) = Q
        ? mfeval(mf,F,I/2)
        %2 = 0.039405471130100890402470386372028382117
        ? mf = mfinit([35,2],0); F = mfeigenbasis(mf)[2]; mfparams(F)
        %3 = [35, 2, 1, y^2 - y - 4] \\ [Q(F) : Q(chi)] = 2
        ? mfeval(mf,F,I/2)
        %4 = [0.045..., 0.0385...] \\ sigma_1(F) and sigma_2(F) at I/2
        ? mf = mfinit([12,4],1); F = mfbasis(mf)[1];
        ? mfeval(mf, F, 0.318+10^(-7)*I)
        %6 = 3.379... E-21 + 6.531... E-21*I \\ instantaneous !

        In order to maximize the imaginary part of the argument,
        the function computes :math:`(f \| _k \gamma)(\gamma^{-1}.\tau)` for a
        suitable :math:`\gamma` not necessarily in :math:`\Gamma_0(N)` (in which case :math:`f \|
        \gamma` is evaluated using :literal:`mfslashexpansion`).

        ::

        ? T = mfTheta(); mf = mfinit(T); mfeval(mf,T,[0,1/2,1,oo])
        %1 = [1/2 - 1/2*I, 0, 1/2 - 1/2*I, 1]
        '''
        mf = objtogen(mf)
        F = objtogen(F)
        vtau = objtogen(vtau)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _F = (<Gen>F).g
        cdef GEN _vtau = (<Gen>vtau).g
        cdef GEN _ret = mfeval(_mf, _F, _vtau, precision)
        return new_gen(_ret)

    def mffields(self, mf):
        r'''
        Given :literal:`mf` as output by :literal:`mfinit` with parameters
        :math:`(N,k,\chi)`, returns the vector of polynomials defining each Galois orbit of
        newforms over :math:`\mathbb{Q} (\chi)`.

        ::

        ? mf = mfinit([35,2],0); mffields(mf)
        %1 = [y, y^2 - y - 4]

        Here the character is trivial so :math:`\mathbb{Q} (\chi) = \mathbb{Q})` and there
        are 3 newforms: one is rational (corresponding to :math:`y`), the other two are
        conjugate and defined over the quadratic field :math:`\mathbb{Q}[y]/(y^2-y-4)`.

        ::

        ? [G,chi] = znchar(Mod(3,35));
        ? zncharconductor(G,chi)
        %2 = 35
        ? charorder(G,chi)
        %3 = 12
        ? mf = mfinit([35, 2, [G,chi]],0); mffields(mf)
        %4 = [y, y]

        Here the character is primitive of order 12 and the two newforms are
        defined over :math:`\mathbb{Q} (\chi) = \mathbb{Q} (\zeta_{12})`.

        ::

        ? mf = mfinit([35, 2, Mod(13,35)],0); mffields(mf)
        %3 = [y^2 + Mod(5*t, t^2 + 1)]

        This time the character has order 4 and there are two conjugate
        newforms over :math:`\mathbb{Q} (\chi) = Q(i)`.
        '''
        mf = objtogen(mf)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _ret = mffields(_mf)
        return new_gen(_ret)

    def mffromell(self, E):
        r'''
        :math:`E` being an elliptic curve defined over :math:`Q` given by an
        integral model in :literal:`ellinit` format, computes a 3-component vector
        :literal:`[mf,F,v]`, where :math:`F` is the newform corresponding to :math:`E` by
        modularity, :literal:`mf` is the newspace to which :math:`F` belongs, and
        :literal:`v` gives the coefficients of :math:`F` on :literal:`mfbasis(mf)`.

        ::

        ? E = ellinit("26a1");
        ? [mf,F,co] = mffromell(E);
        ? co
        %2 = [3/4, 1/4]~
        ? mfcoefs(F, 5)
        %3 = [0, 1, -1, 1, 1, -3]
        ? ellan(E, 5)
        %4 = [1, -1, 1, 1, -3]
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = mffromell(_E)
        return new_gen(_ret)

    def mffrometaquo(self, eta, long flag=0):
        r'''
        Modular form corresponding to the eta quotient matrix :literal:`eta`.
        If the valuation :math:`v` at infinity is fractional, return :math:`0`. If the eta
        quotient is not holomorphic but simply meromorphic, return :math:`0` if
        :literal:`flag = 0`, return the eta quotient (divided by :math:`q` to the power :math:`-v` if
        :math:`v < 0`, i.e., with valuation :math:`0`) if flag is set.

        ::

        ? mffrometaquo(Mat([1,1]),1)
        %1 = 0
        ? mfcoefs(mffrometaquo(Mat([1,24])),6)
        %2 = [0, 1, -24, 252, -1472, 4830, -6048]
        ? mfcoefs(mffrometaquo([1,1;23,1]),10)
        %3 = [0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0]
        ? F = mffrometaquo([1,2;2,-1]); mfparams(F)
        %4 = [16,1/2,1,y]
        ? mfcoefs(F,10)
        %5 = [1, -2, 0, 0, 2, 0, 0, 0, 0, -2, 0]
        ? mffrometaquo(Mat([1,-24]))
        %6 = 0
        ? f = mffrometaquo(Mat([1,-24]),1); mfcoefs(f,6)
        %7 = [1, 24, 324, 3200, 25650, 176256, 1073720]

        For convenience, a :literal:`t_VEC` is also accepted instead of
        a factorization matrix with a single row:

        ::

        ? f = mffrometaquo([1,24]); \\ also valid
        '''
        eta = objtogen(eta)
        sig_on()
        cdef GEN _eta = (<Gen>eta).g
        cdef GEN _ret = mffrometaquo(_eta, flag)
        return new_gen(_ret)

    def mffromlfun(self, L, long precision=DEFAULT_BITPREC):
        r'''
        Let :math:`L` being an :math:`L`-function in any of the :literal:`lfun` formats representing
        a self-dual modular form (for instance an eigenform). Return
        :literal:`[NK,space,v]` when :literal:`mf = mfinit(NK,space)` is the modular
        form space containing the form and :literal:`mftobasis(mf, v)` will represent it
        on the space basis. If :math:`L` has rational coefficients, this will be enough
        to recognize the modular form in :emphasis:`mf`:

        ::

        ? L = lfuncreate(x^2+1);
        ? lfunan(L,10)
        %2 = [1, 1, 0, 1, 2, 0, 0, 1, 1, 2]
        ? [NK,space,v] = mffromlfun(L); NK
        %4 = [4, 1, -4]
        ? mf=mfinit(NK,space); w = mftobasis(mf,v)
        %5 = [1.0000000000000000000000000000000000000]~
        ? [f] = mfbasis(mf); mfcoefs(f,10) \\ includes a_0 !
        %6 = [1/4, 1, 1, 0, 1, 2, 0, 0, 1, 1, 2]

        If :math:`L` has inexact complex coefficients, one can for instance
        compute an eigenbasis for :emphasis:`mf` and check whether one of the attached
        :math:`L`-function is reasonably close to :math:`L`. In the example, we cheat by
        producing the :math:`L` function from an eigenform in a known space, but the
        function does not use this information:

        ::

        ? mf = mfinit([32,6,Mod(5,32)],0);
        ? [poldegree(K) | K<-mffields(mf)]
        %2 = [19] \\ one orbit, [Q(F) : Q(chi)] = 19
        ? L = lfunmf(mf)[1][1]; \\ one of the 19 L-functions attached to F
        ? lfunan(L,3)
        %4 = [1, 5.654... - 0.1812...*I, -7.876... - 19.02...*I]
        ? [NK,space,v] = mffromlfun(L); NK
        %5 = [32, 6, Mod(5, 32)]
        ? vL = concat(lfunmf(mf)); \\ L functions for all cuspidal eigenforms
        ? an = lfunan(L,10);
        ? for (i = 1, #vL, if (normlp(lfunan(vL[i],10) - an, oo) < 1e-10, print(i)));
        1
        '''
        L = objtogen(L)
        sig_on()
        cdef GEN _L = (<Gen>L).g
        precision = nbits2prec(precision)
        cdef GEN _ret = mffromlfun(_L, precision)
        return new_gen(_ret)

    def mffromqf(self, Q, P=None):
        r'''
        :math:`Q` being an even integral positive definite quadratic form
        and :math:`P` a homogeneous spherical polynomial for :math:`Q`, computes
        a 3-component vector :math:`[mf,F,v]`, where :math:`F` is the theta function
        corresponding to :math:`(Q,P)`, :emphasis:`mf` is the corresponding space of modular
        forms (from :literal:`mfinit`), and :math:`v` gives the coefficients of :math:`F` on
        :literal:`mfbasis(mf)`.

        ::

        ? [mf,F,v] = mffromqf(2*matid(10)); v
        %1 = [64/5, 4/5, 32/5]~
        ? mfcoefs(F, 5)
        %2 = [1, 20, 180, 960, 3380, 8424]
        ? mfcoef(F, 10000) \\ number of ways of writing 10000 as sum of 10 squares
        %3 = 128205250571893636
        ? mfcoefs(F, 10000); \\ fast !
        time = 220ms
        ? [mf,F,v] = mffromqf([2,0;0,2],x^4-6*x^2*y^2+y^4);
        ? mfcoefs(F,10)
        %6 = [0, 4, -16, 0, 64, -56, 0, 0, -256, 324, 224]
        ? mfcoef(F,100000) \\ instantaneous
        %7 = 41304367104

        Odd dimensions are supported, corresponding to forms of half-integral weight:

        ::

        ? [mf,F,v] = mffromqf(2*matid(3));
        ? mfisequal(F, mfpow(mfTheta(),3))
        %2 = 1
        ? mfcoefs(F, 32) \\ illustrate Legendre's 3-square theorem
        %3 = [ 1,
        6, 12, 8, 6, 24, 24, 0, 12,
        30, 24, 24, 8, 24, 48, 0, 6,
        48, 36, 24,24, 48, 24, 0, 24,
        30, 72, 32, 0, 72, 48, 0, 12]
        '''
        Q = objtogen(Q)
        cdef bint _have_P = (P is not None)
        if _have_P:
            P = objtogen(P)
        sig_on()
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _P = NULL
        if _have_P:
            _P = (<Gen>P).g
        cdef GEN _ret = mffromqf(_Q, _P)
        return new_gen(_ret)

    def mfgaloistype(self, NK, F=None):
        r'''
        :literal:`NK` being either :literal:`[N,1,CHI]` or an :literal:`mf` output by
        :literal:`mfinit` in weight :math:`1`, gives the vector of types of Galois
        representations attached to each cuspidal eigenform,
        unless the modular form :literal:`F` is specified, in which case only for :literal:`F`
        (note that it is not tested whether :literal:`F` belongs to the correct modular
        form space, nor whether it is a cuspidal eigenform). Types :math:`A_4`, :math:`S_4`,
        :math:`A_5` are represented by minus their cardinality :math:`-12`, :math:`-24`, or :math:`-60`,
        and type :math:`D_n` is represented by its cardinality, the integer :math:`2n`:

        ::

        ? mfgaloistype([124,1, Mod(67,124)]) \\ A4
        %1 = [-12]
        ? mfgaloistype([148,1, Mod(105,148)]) \\ S4
        %2 = [-24]
        ? mfgaloistype([633,1, Mod(71,633)]) \\ D10, A5
        %3 = [10, -60]
        ? mfgaloistype([239,1, -239]) \\ D6, D10, D30
        %4 = [6, 10, 30]
        ? mfgaloistype([71,1, -71])
        %5 = [14]
        ? mf = mfinit([239,1, -239],0); F = mfeigenbasis(mf)[2];
        ? mfgaloistype(mf, F)
        %7 = 10
        '''
        NK = objtogen(NK)
        cdef bint _have_F = (F is not None)
        if _have_F:
            F = objtogen(F)
        sig_on()
        cdef GEN _NK = (<Gen>NK).g
        cdef GEN _F = NULL
        if _have_F:
            _F = (<Gen>F).g
        cdef GEN _ret = mfgaloistype(_NK, _F)
        return new_gen(_ret)

    def mfhecke(self, mf, F, long n):
        r'''
        :math:`F` being a modular form in modular form space :emphasis:`mf`, returns
        :math:`T(n)F`, where :math:`T(n)` is the :math:`n`-th Hecke operator.

        :strong:`Warning.` If :math:`F` is of level :math:`M < N`, then :math:`T(n)F`
        is in general not the same in :math:`M_k(\Gamma_0(M),\chi)` and in
        :math:`M_k(\Gamma_0(N),\chi)`. We take :math:`T(n)` at the same level as the one used in
        :literal:`mf`.

        ::

        ? mf = mfinit([26,2],0); F = mfbasis(mf)[1]; mftobasis(mf,F)
        %1 = [1, 0]~
        ? G2 = mfhecke(mf,F,2); mftobasis(mf,G2)
        %2 = [0, 1]~
        ? G5 = mfhecke(mf,F,5); mftobasis(mf,G5)
        %3 = [-2, 1]~

        Modular forms of half-integral weight are supported, in
        which case :math:`n` must be a perfect square, else :math:`T_n` will act as :math:`0` (the
        operator :math:`T_p` for :math:`p \| N` is not supported yet):

        ::

        ? F = mfpow(mfTheta(),3); mf = mfinit(F);
        ? mfisequal(mfhecke(mf,F,9), mflinear([F],[4]))
        %2 = 1

        (:math:`F` is an eigenvector of all :math:`T_{p^2}`, with eigenvalue :math:`p+1` for
        odd :math:`p`.)

        :strong:`Warning.` When :math:`n` is a large composite, resp. the square of a large
        composite in half-integral weight, it is in general more efficient to use
        :literal:`mfheckemat` on the :literal:`mftobasis` coefficients:

        ::

        ? mfcoefs(mfhecke(mf,F,3^10), 10)
        time = 917 ms.
        %3 = [324, 1944, 3888, 2592, 1944, 7776, 7776, 0, 3888, 9720, 7776]
        ? M = mfheckemat(mf,3^10) \\ instantaneous
        %4 =
        [324]
        ? G = mflinear(mf, M*mftobasis(mf,F));
        ? mfcoefs(G, 10) \\ instantaneous
        %6 = [324, 1944, 3888, 2592, 1944, 7776, 7776, 0, 3888, 9720, 7776]
        '''
        mf = objtogen(mf)
        F = objtogen(F)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfhecke(_mf, _F, n)
        return new_gen(_ret)

    def mfheckemat(self, mf, vecn):
        r'''
        If :literal:`vecn` is an integer, matrix of the Hecke operator :math:`T(n)` on the
        basis formed by :literal:`mfbasis(mf)`. If it is a vector, vector of
        such matrices, usually faster than calling each one individually.

        ::

        ? mf=mfinit([32,4],0); mfheckemat(mf,3)
        %1 =
        [0 44 0]
        
        [1 0 -10]
        
        [0 -2 0]
        ? mfheckemat(mf,[5,7])
        %2 = [[0, 0, 220; 0, -10, 0; 1, 0, 12], [0, 88, 0; 2, 0, -20; 0, -4, 0]]
        '''
        mf = objtogen(mf)
        vecn = objtogen(vecn)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _vecn = (<Gen>vecn).g
        cdef GEN _ret = mfheckemat(_mf, _vecn)
        return new_gen(_ret)

    def mfinit(self, NK, long space=4):
        r'''
        Create the space of modular forms corresponding to the data contained in
        :literal:`NK` and :literal:`space`. :literal:`NK` is a vector which can be
        either :math:`[N,k]` (:math:`N` level, :math:`k` weight) corresponding to a subspace of
        :math:`M_k(\Gamma_0(N))`, or :math:`[N,k,CHI]` (:emphasis:`CHI` a character)
        corresponding to a subspace of :math:`M_k(\Gamma_0(N),\chi)`. Alternatively,
        it can be a modular form :math:`F` or modular form space, in which case we use
        :literal:`mfparams` to define the space parameters.

        The subspace is described by the small integer :literal:`space`: :math:`0` for the
        newspace :math:`S_k^{new}(\Gamma_0(N),\chi)`, :math:`1` for the cuspidal
        space :math:`S_k`, :math:`2` for the oldspace :math:`S_k^{old}`, :math:`3` for the space of
        Eisenstein series :math:`E_k` and :math:`4` for the full space :math:`M_k`.

        :strong:`Wildcards.` For given level and weight, it is advantageous to
        compute simultaneously spaces attached to different Galois orbits
        of characters, especially in weight :math:`1`. The parameter :emphasis:`CHI` may be set
        to 0 (wildcard), in which case we return a vector of all :literal:`mfinit` (s) of
        non trivial spaces in :math:`S_k(\Gamma_1(N))`, one for each Galois orbit
        (see :literal:`znchargalois`). One may also set :emphasis:`CHI` to a vector of
        characters and we return a vector of all mfinits of subspaces of
        :math:`M_k(G_0(N),\chi)` for :math:`\chi` in the list, in the same order. In weight :math:`1`,
        only :math:`S_1^{new}`, :math:`S_1` and :math:`E_1` support wildcards.

        The output is a technical structure :math:`S`, or a vector of structures if
        :emphasis:`CHI` was a wildcard, which contains the following information:
        :math:`[N,k,\chi]` is given by :literal:`mfparams`:math:`(S)`, the space
        dimension is :literal:`mfdim`:math:`(S)` and a :math:`\mathbb{C}`-basis for the space is
        :literal:`mfbasis`:math:`(S)`. The structure is entirely algebraic and does not depend
        on the current :literal:`realbitprecision`.

        ::

        ? S = mfinit([36,2], 0); \\ new space
        ? mfdim(S)
        %2 = 1
        ? mfparams
        %3 = [36, 2, 1, y] \\ trivial character
        ? f = mfbasis(S)[1]; mfcoefs(f,10)
        %4 = [0, 1, 0, 0, 0, 0, 0, -4, 0, 0, 0]
        
        ? vS = mfinit([36,2,0],0); \\ with wildcard
        ? #vS
        %6 = 4 \\ 4 non trivial spaces (mod Galois action)
        ? apply(mfdim,vS)
        %7 = [1, 2, 1, 4]
        ? mfdim([36,2,0], 0)
        %8 = [[1, Mod(1, 36), 1, 0], [2, Mod(35, 36), 2, 0], [3, Mod(13, 36), 1, 0],
        [6, Mod(11, 36), 4, 0]]
        '''
        NK = objtogen(NK)
        sig_on()
        cdef GEN _NK = (<Gen>NK).g
        cdef GEN _ret = mfinit(_NK, space)
        return new_gen(_ret)

    def mfisCM(self, F):
        r'''
        Tests whether the eigenform :math:`F` is a CM form. The answer
        is :math:`0` if it is not, and if it is, either the unique negative discriminant
        of the CM field, or the pair of two negative discriminants of CM fields,
        this latter case occurring only in weight :math:`1` when the projective image is
        :math:`D_2 = C_2 x C_2`, i.e., coded :math:`4` by :literal:`mfgaloistype`.

        ::

        ? F = mffromell(ellinit([0,1]))[2]; mfisCM(F)
        %1 = -3
        ? mf = mfinit([39,1,-39],0); F=mfeigenbasis(mf)[1]; mfisCM(F)
        %2 = Vecsmall([-3, -39])
        ? mfgaloistype(mf)
        %3 = [4]
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfisCM(_F)
        return new_gen(_ret)

    def mfisequal(self, F, G, long lim=0):
        r'''
        Checks whether the modular forms :math:`F` and :math:`G` are equal. If :literal:`lim`
        is nonzero, only check equality of the first :math:`lim+1` Fourier coefficients
        and the function then also applies to generalized modular forms.

        ::

        ? D = mfDelta(); F = mfderiv(D);
        ? G = mfmul(mfEk(2), D);
        ? mfisequal(F, G)
        %2 = 1
        '''
        F = objtogen(F)
        G = objtogen(G)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _G = (<Gen>G).g
        cdef long _ret = mfisequal(_F, _G, lim)
        clear_stack()
        return _ret

    def mfkohnenbasis(self, mf):
        r'''
        :literal:`mf` being a cuspidal space of half-integral weight :math:`k >= 3/2`
        with level :math:`N` and character :math:`\chi`, gives a
        basis :math:`B` of the Kohnen :math:`+`-space of :literal:`mf` as a matrix whose columns are
        the coefficients of :math:`B` on the basis of :literal:`mf`. The conductor of either
        :math:`\chi` or :math:`\chi.(-4/.)` must divide :math:`N/4`.

        ::

        ? mf = mfinit([36,5/2],1); K = mfkohnenbasis(mf); K~
        %1 =
        [-1 0 0 2 0 0]
        
        [ 0 0 0 0 1 0]
        ? (mfcoefs(mf,20) * K)~
        %4 =
        [0 -1 0 0 2 0 0 0 0 0 0 0 0 -6 0 0 8 0 0 0 0]
        
        [0 0 0 0 0 1 0 0 -2 0 0 0 0 0 0 0 0 1 0 0 2]
        
        ? mf = mfinit([40,3/2,8],1); mfkohnenbasis(mf)
        *** at top-level: mfkohnenbasis(mf)
        *** ^-----------------
        *** mfkohnenbasis: incorrect type in mfkohnenbasis [incorrect CHI] (t_VEC).

        In the final example both :math:`\chi = (8/.)` and :math:`\chi.(-4/.)`
        have conductor :math:`8`, which does not divide N/4 = 10.
        '''
        mf = objtogen(mf)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _ret = mfkohnenbasis(_mf)
        return new_gen(_ret)

    def mfkohnenbijection(self, mf):
        r'''
        :literal:`mf` being a cuspidal space of half-integral weight, returns
        :literal:`[mf2,M,K,shi]`, where :math:`M` is a matrix giving a Hecke-module
        isomorphism from the cuspidal space :literal:`mf2` giving
        :math:`S_{2k-1}(\Gamma_0(N),\chi^2)` to the
        Kohnen :math:`+`-space :math:`S_k^+(\Gamma_0(4N),\chi)`, :literal:`K` represents a basis :math:`B`
        of the Kohnen :math:`+`-space as a matrix whose columns are the coefficients of :math:`B`
        on the basis of :literal:`mf`, and :literal:`shi` gives the linear combination of
        Shimura lifts giving :math:`M^{-1}`.

        ::

        ? mf=mfinit([60,5/2],1); [mf2,M,K,shi]=mfkohnenbijection(mf); M
        %1 =
        [ -5/14 -1/14 1/2 3/2]
        
        [ 37/84 -1/84 1/2 1/2]
        
        [-17/84 5/84 -3/2 -9/2]
        
        [ 0 0 -1/2 -1/2]
        
        ? shi
        %2 = Vecsmall([1, 5])

        This last command shows that the map giving the bijection is the sum of the
        Shimura lift with :math:`D = 1` and the one with :math:`D = 5`.

        Since it gives a bijection of Hecke modules, this matrix can be used to
        transport modular form data from the easily computed space of level :math:`N`
        and weight :math:`2k-1` to the more difficult space of level :math:`4N` and weight
        :math:`k`: matrices of Hecke operators, new space, splitting into eigenspaces and
        eigenforms. Examples:

        ::

        ? K^(-1)*mfheckemat(mf,121)*K /* matrix of T_11^2 on K. Slowish. */
        time = 1,280 ms.
        %1 =
        [ 48 24 24 24]
        
        [ 0 32 0 -20]
        
        [-48 -72 -40 -72]
        
        [ 0 0 0 52]
        ? M*mfheckemat(mf2,11)*M^(-1) /* instantaneous via T_11 on S_{2k-1} */
        time = 0 ms.
        %2 =
        [ 48 24 24 24]
        
        [ 0 32 0 -20]
        
        [-48 -72 -40 -72]
        
        [ 0 0 0 52]
        ? mf20=mfinit(mf2,0); [mftobasis(mf2,b) | b<-mfbasis(mf20)]
        %3 = [[0, 0, 1, 0]~, [0, 0, 0, 1]~]
        ? F1=M*[0,0,1,0]~
        %4 = [1/2, 1/2, -3/2, -1/2]~
        ? F2=M*[0,0,0,1]~
        %5 = [3/2, 1/2, -9/2, -1/2]
        ? K*F1
        %6 = [1, 0, 0, 1, 1, 0, 0, 1, -3, 0, 0, -3, 0, 0]~
        ? K*F2
        %7 = [3, 0, 0, 3, 1, 0, 0, 1, -9, 0, 0, -3, 0, 0]~

        This gives a basis of the new space of :math:`S_{5/2}^+(\Gamma_0(60))` expressed
        on the initial basis of :math:`S_{5/2}(\Gamma_0(60))`. If we want the eigenforms, we
        write instead:

        ::

        ? BE=mfeigenbasis(mf20);[E1,E2]=apply(x->K*M*mftobasis(mf2,x),BE)
        %1 = [[1, 0, 0, 1, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0]~,\
        [0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -3, 0, 0]~
        ? EI1 = mflinear(mf, E1); EI2=mflinear(mf, E2);

        These are the two eigenfunctions in the space :literal:`mf`, the first (resp.,
        second) will have Shimura image a multiple of :math:`BE[1]` (resp., :math:`BE[2]`).
        The function :literal:`mfkohneneigenbasis` does this directly.
        '''
        mf = objtogen(mf)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _ret = mfkohnenbijection(_mf)
        return new_gen(_ret)

    def mfkohneneigenbasis(self, mf, bij):
        r'''
        :literal:`mf` being a cuspidal space of half-integral weight :math:`k >= 3/2` and
        :literal:`bij` being the output of :literal:`mfkohnenbijection(mf)`, outputs a
        :math:`3`-component vector :literal:`[mf0,BNEW,BEIGEN]`, where :literal:`BNEW` and
        :literal:`BEIGEN` are two matrices whose columns are the coefficients
        of a basis of the Kohnen new space and of the eigenforms on the basis of
        :literal:`mf` respectively, and :literal:`mf0` is the corresponding new space of
        integral weight :math:`2k-1`.

        ::

        ? mf=mfinit([44,5/2],1);bij=mfkohnenbijection(mf);
        ? [mf0,BN,BE]=mfkohneneigenbasis(mf,bij);
        ? BN~
        %2 =
        [2 0 0 -2 2 0 -8]
        
        [2 0 0 4 14 0 -32]
        
        ? BE~
        %3 = [Mod(1, y^2 - 3) Mod(0, y^2 - 3) Mod(0, y^2 - 3) Mod(y - 1, y^2 - 3)\
        Mod(2*y + 1, y^2 - 3) Mod(0, y^2 - 3) Mod(-4*y - 4, y^2 - 3)]
        ? lift(mfcoefs(mf,20)*BE[,1])
        %4 = [0, 1, 0, 0, y - 1, 2*y + 1, 0, 0, 0, -4*y - 4, 0, 0,\
        -5*y + 3, 0, 0, 0, -6, 0, 0, 0, 7*y + 9]~
        '''
        mf = objtogen(mf)
        bij = objtogen(bij)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _bij = (<Gen>bij).g
        cdef GEN _ret = mfkohneneigenbasis(_mf, _bij)
        return new_gen(_ret)

    def mflinear(self, vF, v):
        r'''
        :literal:`vF` being a vector of generalized modular forms and :literal:`v`
        a vector of coefficients of same length, compute the linear
        combination of the entries of :literal:`vF` with coefficients :literal:`v`.
        :strong:`Note.` Use this in particular to subtract two forms :math:`F` and :math:`G`
        (with :math:`vF = [F,G]` and :math:`v = [1,-1]`), or to multiply an form by
        a scalar :math:`\lambda` (with :math:`vF = [F]` and :math:`v = [\lambda]`).

        ::

        ? D = mfDelta(); G = mflinear([D],[-3]);
        ? mfcoefs(G,4)
        %2 = [0, -3, 72, -756, 4416]

        For user convenience, we allow

        - a modular form space :literal:`mf` as a :literal:`vF` argument, which is
        understood as :literal:`mfbasis(mf)`;

        - in this case, we also allow a modular form :math:`f` as :math:`v`, which
        is understood as :literal:`mftobasis`:math:`(mf, f)`.

        ::

        ? T = mfpow(mfTheta(),7); F = mfShimura(T,-3); \\ Shimura lift for D=-3
        ? mfcoefs(F,8)
        %2 = [-5/9, 280, 9240, 68320, 295960, 875280, 2254560, 4706240, 9471000]
        ? mf = mfinit(F); G = mflinear(mf,F);
        ? mfcoefs(G,8)
        %4 = [-5/9, 280, 9240, 68320, 295960, 875280, 2254560, 4706240, 9471000]

        This last construction allows to replace a general modular
        form by a simpler linear combination of basis functions, which is often
        more efficient:

        ::

        ? T10=mfpow(mfTheta(),10); mfcoef(T10, 10^4) \\ direct evaluation
        time = 399 ms.
        %5 = 128205250571893636
        ? mf=mfinit(T10); F=mflinear(mf,T10); \\ instantaneous
        ? mfcoef(F, 10^4) \\ after linearization
        time = 67 ms.
        %7 = 128205250571893636
        '''
        vF = objtogen(vF)
        v = objtogen(v)
        sig_on()
        cdef GEN _vF = (<Gen>vF).g
        cdef GEN _v = (<Gen>v).g
        cdef GEN _ret = mflinear(_vF, _v)
        return new_gen(_ret)

    def mfmanin(self, FS, long precision=DEFAULT_BITPREC):
        r'''
        Given the modular symbol :math:`FS` associated to an eigenform :math:`F` by
        :literal:`mfsymbol(mf,F)`, computes the even and odd special polynomials as well
        as the even and odd periods :math:`\omega^+` and :math:`\omega^-` as a vector
        :math:`[[P^+,P^-],[\omega^+,\omega^-,r]]`, where
        :math:`r = \Im (\omega^+\overline{\omega^-})/ < F,F >`. If :math:`F` has several embeddings
        into :math:`\mathbb{C}`, give the vector of results corresponding to each embedding.

        ::

        ? D=mfDelta(); mf=mfinit(D); DS=mfsymbol(mf,D);
        ? [pols,oms]=mfmanin(DS); pols
        %2 = [[4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x],\
        [-36*x^10 + 691*x^8 - 2073*x^6 + 2073*x^4 - 691*x^2 + 36]]
        ? oms
        %3 = [0.018538552324740326472516069364750571812,\
        -0.00033105361053212432521308691198949874026*I, 4096/691]
        ? mf=mfinit([11,2],0); F=mfeigenbasis(mf)[1]; FS=mfsymbol(mf,F);
        ? [pols,oms]=mfmanin(FS);pols
        %5 = [[0, 0, 0, 1, 1, 0, 0, -1, -1, 0, 0, 0],\
        [2, 0, 10, 5, -5, -10, -10, -5, 5, 10, 0, -2]]
        ? oms[3]
        %6 = 24/5
        '''
        FS = objtogen(FS)
        sig_on()
        cdef GEN _FS = (<Gen>FS).g
        cdef GEN _ret = mfmanin(_FS, precision)
        return new_gen(_ret)

    def mfmul(self, F, G):
        r'''
        Multiply the two generalized modular forms :math:`F` and :math:`G`.

        ::

        ? E4 = mfEk(4); G = mfmul(mfmul(E4,E4),E4);
        ? mfcoefs(G, 4)
        %2 = [1, 720, 179280, 16954560, 396974160]
        ? mfcoefs(mfpow(E4,3), 4)
        %3 = [1, 720, 179280, 16954560, 396974160]
        '''
        F = objtogen(F)
        G = objtogen(G)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _G = (<Gen>G).g
        cdef GEN _ret = mfmul(_F, _G)
        return new_gen(_ret)

    def mfnumcusps(self, N):
        r'''
        Number of cusps of :math:`\Gamma_0(N)`

        ::

        ? mfnumcusps(24)
        %1 = 8
        ? mfcusps(24)
        %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/8, 1/12, 1/24]
        '''
        N = objtogen(N)
        sig_on()
        cdef GEN _N = (<Gen>N).g
        cdef GEN _ret = mfnumcusps(_N)
        return new_gen(_ret)

    def mfparams(self, F):
        r'''
        If :math:`F` is a modular form space, returns :literal:`[N,k,CHI,space]`, level,
        weight, character, and space code. If :math:`F` is a generalized modular form,
        returns :literal:`[N,k,CHI,P]`, where :math:`P` is the (polynomial giving the) field of
        definition of :math:`F`: in that case the level :math:`N` may be a multiple of the
        level of :math:`F` and the polynomial :math:`P` may define a larger field than :math:`\mathbb{Q} (F)`.
        If you want the true level of :math:`F` from this result, use
        :literal:`mfconductor(mfinit(F),F)`. The polynomial :math:`P` defines an extension of
        :math:`\mathbb{Q} (\chi) = \mathbb{Q}[t]/(\Phi (t))` for the cyclotomic polynomial of order
        :math:`f(\chi)`; it has coefficients in that number field (polmods in :math:`t`).

        In contrast with :literal:`mfparams(f)[4]` which always gives the polynomial
        :math:`P` defining the relative extension :math:`\mathbb{Q} (f)/\mathbb{Q} (\chi)`, the member function
        :literal:`:math:`f`.mod` returns the polynomial used to define :math:`\mathbb{Q} (f)` over :math:`\mathbb{Q}`
        (either a cyclotomic polynomial or a polynomial with cyclotomic
        coefficients).

        ::

        ? E1 = mfeisenstein(4,-3,-4); E2 = mfeisenstein(3,5,-7); E3 = mfmul(E1,E2);
        ? apply(mfparams, [E1,E2,E3])
        %2 = [[12, 4, 12, y], [35, 3, -35, y], [420, 7, -420, y]]
        
        ? mf = mfinit([36,2,Mod(13,36)],0); [f] = mfeigenbasis(mf); mfparams(mf)
        %3 = [36, 2, Mod(13, 36), 0]
        ? mfparams(f)
        %4 = [36, 2, Mod(13, 36), y]
        ? f.mod
        %5 = t^2 + t + 1
        
        ? mf = mfinit([36,4,Mod(13,36)],0); [f] = mfeigenbasis(mf);
        ? mfparams(f)
        %7 = [36, 4, Mod(13, 36), y^3 + Mod(2*t - 2, t^2 + t + 1)*y^2
        + Mod(-4*t + 6, t^2+t+1)*y + Mod(10*t - 1, t^2+t+1)]
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfparams(_F)
        return new_gen(_ret)

    def mfperiodpol(self, mf, f, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Period polynomial of the cuspidal part of the form :math:`f`, in other words
        :math:`\int_0^{i oo }(X-\tau)^{k-2}f(\tau)d\tau`. If :literal:`flag` is :math:`0`, ordinary
        period polynomial. If it is :math:`1` or :math:`-1`, even or odd part of that polynomial.
        :math:`f` can also be the modular symbol output by :literal:`mfsymbol` (mf,f).

        ::

        ? D = mfDelta(); mf = mfinit(D,0);
        ? PP = mfperiodpol(mf, D, -1); PP/=polcoeff(PP, 1); bestappr(PP)
        %1 = x^9 - 25/4*x^7 + 21/2*x^5 - 25/4*x^3 + x
        ? PM = mfperiodpol(mf, D, 1); PM/=polcoeff(PM, 0); bestappr(PM)
        %2 = -x^10 + 691/36*x^8 - 691/12*x^6 + 691/12*x^4 - 691/36*x^2 + 1
        '''
        mf = objtogen(mf)
        f = objtogen(f)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _f = (<Gen>f).g
        cdef GEN _ret = mfperiodpol(_mf, _f, flag, precision)
        return new_gen(_ret)

    def mfperiodpolbasis(self, long k, long flag=0):
        r'''
        Basis of period polynomials for weight k. If flag = 1 or :math:`-1`, basis of
        odd or even period polynomials.

        ::

        ? mfperiodpolbasis(12,1)
        %1 = [x^8 - 3*x^6 + 3*x^4 - x^2, x^10 - 1]
        ? mfperiodpolbasis(12,-1)
        %2 = [4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x]
        '''
        sig_on()
        cdef GEN _ret = mfperiodpolbasis(k, flag)
        return new_gen(_ret)

    def mfpetersson(self, fs, gs=None):
        r'''
        Petersson scalar product of the modular forms :math:`f` and :math:`g` belonging to
        the same modular form space :literal:`mf`, given by the corresponding
        "modular symbols" :literal:`fs` and :literal:`gs` output by :literal:`mfsymbol`
        (also in weight :math:`1` and half-integral weight, where symbols do not exist).
        If :literal:`gs` is omitted it is understood to be equal to :literal:`fs`.
        The scalar product is normalized by the factor :math:`1/[\Gamma:\Gamma_0(N)]`.
        Note that :math:`f` and :math:`g` can both be noncuspidal, in which case the program
        returns an error if the product is divergent.
        If the fields of definition :math:`\mathbb{Q} (f)` and :math:`\mathbb{Q} (g)` are equal to :math:`\mathbb{Q} (\chi)`
        the result is a scalar. If :math:`[\mathbb{Q} (f):\mathbb{Q} (\chi)] = d > 1` and
        :math:`[\mathbb{Q} (g):\mathbb{Q} (\chi)] = e > 1` the result is a :math:`d x e` matrix corresponding
        to all the embeddings of :math:`f` and :math:`g`. In the intermediate cases :math:`d = 1` or
        :math:`e = 1` the result is a row or column vector.

        ::

        ? D=mfDelta(); mf=mfinit(D); DS=mfsymbol(mf,D); mfpetersson(DS)
        %1 = 1.0353620568043209223478168122251645932 E-6
        ? mf=mfinit([11,6],0);B=mfeigenbasis(mf);BS=vector(#B,i,mfsymbol(mf,B[i]));
        ? mfpetersson(BS[1])
        %3 = 1.6190120685220988139111708455305245466 E-5
        ? mfpetersson(BS[1],BS[2])
        %4 = [-3.826479006582967148 E-42 - 2.801547395385577002 E-41*I,\
        1.6661127341163336125 E-41 + 1.1734725972345985061 E-41*I,\
        0.E-42 - 6.352626992842664490 E-41*I]~
        ? mfpetersson(BS[2])
        %5 =
        [ 2.7576133733... E-5 2.0... E-42 6.3... E-43 ]
        
        [ -4.1... E-42 6.77837030070... E-5 3.3...E-42 ]
        
        [ -6.32...E-43 3.6... E-42 2.27268958069... E-5]
        
        ? mf=mfinit([23,2],0); F=mfeigenbasis(mf)[1]; FS=mfsymbol(mf,F);
        ? mfpetersson(FS)
        %5 =
        [0.0039488965740025031688548076498662860143 -3.56 ... E-40]
        
        [ -3.5... E-40 0.0056442542987647835101583821368582485396]

        Noncuspidal example:

        ::

        ? E1=mfeisenstein(5,1,-3);E2=mfeisenstein(5,-3,1);
        ? mf=mfinit([12,5,-3]); cusps=mfcusps(12);
        ? apply(x->mfcuspval(mf,E1,x),cusps)
        %3 = [0, 0, 1, 0, 1, 1]
        ? apply(x->mfcuspval(mf,E2,x),cusps)
        %4 = [1/3, 1/3, 0, 1/3, 0, 0]
        ? E1S=mfsymbol(mf,E1);E2S=mfsymbol(mf,E2);
        ? mfpetersson(E1S,E2S)
        %6 = -1.884821671646... E-5 - 1.9... E-43*I

        Weight 1 and 1/2-integral weight example:

        ::

        ? mf=mfinit([23,1,-23],1);F=mfbasis(mf)[1];FS=mfsymbol(mf,F);
        ? mfpetersson(mf,FS)
        %2 = 0.035149946790370230814006345508484787443
        ? mf=mfinit([4,9/2],1);F=mfbasis(mf)[1];FS=mfsymbol(mf,F);
        ? mfpetersson(FS)
        %4 = 0.00015577084407139192774373662467908966030
        '''
        fs = objtogen(fs)
        cdef bint _have_gs = (gs is not None)
        if _have_gs:
            gs = objtogen(gs)
        sig_on()
        cdef GEN _fs = (<Gen>fs).g
        cdef GEN _gs = NULL
        if _have_gs:
            _gs = (<Gen>gs).g
        cdef GEN _ret = mfpetersson(_fs, _gs)
        return new_gen(_ret)

    def mfpow(self, F, long n):
        r'''
        Compute :math:`F^n`, where :math:`n` is an integer and :math:`F` is a generalized modular
        form:

        ::

        ? G = mfpow(mfEk(4), 3); \\ E4^3
        ? mfcoefs(G, 4)
        %2 = [1, 720, 179280, 16954560, 396974160]
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfpow(_F, n)
        return new_gen(_ret)

    def mfsearch(self, NK, V, long space=4):
        r'''
        :literal:`NK` being of the form :literal:`[N,k]` with :math:`k` possibly half-integral,
        search for a modular form with rational coefficients, of weight :math:`k` and
        level :math:`N`, whose initial coefficients :math:`a(0)`,... are equal to :math:`V`;
        :literal:`space` specifies the modular form spaces in which to search, in
        :literal:`mfinit` or :literal:`mfdim` notation. The output is a list of matching forms
        with that given level and weight. Note that the character is of the form
        :math:`(D/.)`, where :math:`D` is a (positive or negative) fundamental discriminant
        dividing :math:`N`. The forms are sorted by increasing :math:`\|D\|`.

        The parameter :math:`N` can be replaced by a vector of allowed levels, in which
        case the list of forms is sorted by increasing level, then increasing :math:`\|D\|`.
        If a form is found at level :math:`N`, any multiple of :math:`N` with the same :math:`D` is not
        considered. Some useful possibilities are

        - :literal:`[:math:`N_1`..:math:`N_2`]`: all levels between :math:`N_1` and :math:`N_2`,
        endpoints included;

        - :literal:`:math:`F` * [:math:`N_1`..:math:`N_2`]`: same but levels divisible by :math:`F`;

        - :literal:`divisors`:math:`(N_0)`: all levels dividing :math:`N_0`.

        Note that this is different from :literal:`mfeigensearch`, which only searches
        for rational eigenforms.

        ::

        ? F = mfsearch([[1..40], 2], [0,1,2,3,4], 1); #F
        %1 = 3
        ? [ mfparams(f) | f <- F ]
        %2 = [[38, 2, 1, y], [40, 2, 8, y], [40, 2, 40, y]]
        ? mfcoefs(F[1],10)
        %3 = [0, 1, 2, 3, 4, -5, -8, 1, -7, -5, 7]
        '''
        NK = objtogen(NK)
        V = objtogen(V)
        sig_on()
        cdef GEN _NK = (<Gen>NK).g
        cdef GEN _V = (<Gen>V).g
        cdef GEN _ret = mfsearch(_NK, _V, space)
        return new_gen(_ret)

    def mfshift(self, F, long s):
        r'''
        Divide the generalized modular form :math:`F` by :math:`q^s`, omitting the remainder
        if there is one. One can have :math:`s < 0`.

        ::

        ? D=mfDelta(); mfcoefs(mfshift(D,1), 4)
        %1 = [1, -24, 252, -1472, 4830]
        ? mfcoefs(mfshift(D,2), 4)
        %2 = [-24, 252, -1472, 4830, -6048]
        ? mfcoefs(mfshift(D,-1), 4)
        %3 = [0, 0, 1, -24, 252]
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfshift(_F, s)
        return new_gen(_ret)

    def mfshimura(self, mf, F, long D=1):
        r'''
        :math:`F` being a modular form of half-integral weight :math:`k >= 3/2` and :math:`D` a
        (not necessarily fundamental) discriminant of suitable sign, returns the
        Shimura lift :math:`G` of weight :math:`2k-1` corresponding to :math:`D`. The sign of :math:`D`
        should be equal to :math:`(-1)^{k-1/2}\epsilon`, where :math:`\epsilon = 1` if :math:`\chi` is
        defined modulo :math:`N/4`, :math:`\epsilon = -1` if :math:`(-4/.)\chi` is defined modulo
        :math:`N/4` (and error otherwise). This function returns :math:`[mf2,G,v]`
        where :emphasis:`mf2` is a modular form space containing :math:`G` and :math:`v` expresses :math:`G`
        in terms of :literal:`mfbasis`:math:`(mf2)`; so that :math:`G` is
        :literal:`mflinear`:math:`(mf2,v)`. By extension, we allow :math:`D` to be a positive
        squarefree integer, but in that case if :math:`(-1)^{k-1/2}\epsilon.D` is not a
        discriminant, the Kohnen :math:`+`-space will in general not be sent to
        level :math:`N/4` but only :math:`N/2`.

        ::

        ? F = mfpow(mfTheta(), 7); mf = mfinit(F);
        ? [mf2, G, v] = mfshimura(mf, F, -3); mfcoefs(G,5)
        %2 = [-5/9, 280, 9240, 68320, 295960, 875280]
        ? mfparams(G)
        %3 = [1, 6, 1, y]
        ? mfparams(mf2)
        %4 = [2, 6, 1, 4] \\ it may happen that G has lower level than expected
        ? v
        %5 = [280, 0]~
        ? mfcoefs(mf2, 5)
        %6 =
        [-1/504 -1/504]
        
        [ 1 0]
        
        [ 33 1]
        
        [ 244 0]
        
        [ 1057 33]
        
        [ 3126 0]
        ? mf = mfinit([60,5/2],1); F = mflinear(mf,mfkohnenbasis(mf)[,1]);
        ? mfparams(mfshimura(mf,F,1)[2])
        %8 = [15, 4, 1, y]
        ? mfparams(mfshimura(mf,F,6)[2])
        %9 = [30, 4, 1, y]
        '''
        mf = objtogen(mf)
        F = objtogen(F)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mfshimura(_mf, _F, D)
        return new_gen(_ret)

    def mfslashexpansion(self, mf, f, g, long n, long flrat, params=None, long precision=DEFAULT_BITPREC):
        r'''
        Let :emphasis:`mf` be a modular form space in leven :math:`N`, :math:`f` a modular form
        belonging to :emphasis:`mf` and let :math:`g` be in :math:`M_2^+(Q)`. This function
        computes the Fourier expansion of :math:`f\|_k g` to :math:`n` terms. We first describe
        the behaviour when :literal:`flrat` is 0: the result is a
        vector :math:`v` of floating point complex numbers such that

        .. MATH::

        f\|_k g(\tau) = q^\alpha \sum_{m >= 0} v[m+1] q^{m/w},

        where :math:`q = e(\tau)`, :math:`w` is the width of the cusp :math:`g(i oo )`
        (namely :math:`(N/(c^2,N)` if :math:`g` is integral) and :math:`\alpha` is a rational number.
        If :literal:`params` is given, it is set to the parameters :math:`[\alpha,w,
        matid (2)]`.

        If :literal:`flrat` is 1, the program tries to rationalize the expression, i.e.,
        to express the coefficients as rational numbers or polmods. We
        write :math:`g = \lambda.M.A` where :math:`\lambda \in \mathbb{Q}^*`,
        :math:`M\in SL_2(\mathbb{Z})` and :math:`A = [a,b;0,d]` is upper triangular,
        integral and primitive with :math:`a > 0`, :math:`d > 0` and :math:`0 <= b < d`. Let
        :math:`\alpha` and :math:`w` by the parameters attached to the expansion of
        :math:`F := f \|_k M` as above, i.e.

        .. MATH::

        F(\tau) = q^\alpha \sum_{m >= 0} v[m+1] q^{m/w}.

        The function returns the expansion :math:`v` of :math:`F = f \|_k M` and sets
        the parameters to :math:`[\alpha, w, A]`. Finally, the desired expansion is
        :math:`(a/d)^{k/2} F(\tau + b/d)`. The latter is identical to the returned
        expansion when :math:`A` is the identity, i.e. when :math:`g\in PSL_2(\mathbb{Z})`.
        If this is not the case, the expansion differs from :math:`v` by the multiplicative
        constant :math:`(a/d)^{k/2} e(\alpha b/(dw))` and a twist by a root of unity
        :math:`q^{1/w} \to e(b/(dw)) q^{1/w}`. The complications introduced by this extra
        matrix :math:`A` allow to recognize the coefficients in a much smaller cyclotomic
        field, hence to obtain a simpler description overall. (Note that this
        rationalization step may result in an error if the program cannot perform it.)

        ::

        ? mf = mfinit([32,4],0); f = mfbasis(mf)[1];
        ? mfcoefs(f, 10)
        %2 = [0, 3, 0, 0, 0, 2, 0, 0, 0, 47, 0]
        ? mfatk = mfatkininit(mf,32); mfcoefs(mfatkin(mfatk,f),10) / mfatk[3]
        %3 = [0, 1, 0, 16, 0, 22, 0, 32, 0, -27, 0]
        ? mfatk[3] \\ here normalizing constant C = 1, but need in general
        %4 = 1
        ? mfslashexpansion(mf,f,[0,-1;1,0],10,1,&params) * 32^(4/2)
        %5 = [0, 1, 0, 16, 0, 22, 0, 32, 0, -27, 0]
        ? params
        %6 = [0, 32, [1, 0; 0, 1]]
        
        ? mf = mfinit([12,8],0); f = mfbasis(mf)[1];
        ? mfslashexpansion(mf,f,[1,0;2,1],7,0)
        %7 = [0, 0, 0, 0.6666666... + 0.E-38*I, 0, -3.999999... + 6.92820...*I, 0,\
        -11.99999999... - 20.78460969...*I]
        ? mfslashexpansion(mf,f,[1,0;2,1],7,1, &params)
        %8 = [0, 0, 0, 2/3, 0, Mod(8*t, t^2+t+1), 0, Mod(-24*t-24, t^2+t+1)]
        ? params
        %9 = [0, 3, [1, 0; 0, 1]]

        If :math:`[\mathbb{Q} (f):\mathbb{Q} (\chi)] > 1`, the coefficients may be polynomials in :math:`y`,
        where :math:`y` is any root of the polynomial giving the field of definition of
        :math:`f` (:literal:`f.mod` or :literal:`mfparams(f)[4]`).

        ::

        ? mf=mfinit([23,2],0);f=mfeigenbasis(mf)[1];
        ? mfcoefs(f,5)
        %1 = [Mod(0, y^2 - y - 1), Mod(1, y^2 - y - 1), Mod(-y, y^2 - y - 1),\
        Mod(2*y - 1, y^2 - y - 1), Mod(y - 1, y^2 - y - 1), Mod(-2*y, y^2 - y - 1)]
        ? mfslashexpansion(mf,f,[1,0;0,1],5,1)
        %2 = [0, 1, -y, 2*y - 1, y - 1, -2*y]
        ? mfslashexpansion(mf,f,[0,-1;1,0],5,1)
        %3 = [0, -1/23, 1/23*y, -2/23*y + 1/23, -1/23*y + 1/23, 2/23*y]
        '''
        mf = objtogen(mf)
        f = objtogen(f)
        g = objtogen(g)
        cdef bint _have_params = (params is not None)
        if _have_params:
            raise NotImplementedError("optional argument params not available")
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _f = (<Gen>f).g
        cdef GEN _g = (<Gen>g).g
        cdef GEN * _params = NULL
        precision = nbits2prec(precision)
        cdef GEN _ret = mfslashexpansion(_mf, _f, _g, n, flrat, _params, precision)
        return new_gen(_ret)

    def mfspace(self, mf, f=None):
        r'''
        Identify the modular space :emphasis:`mf`, resp. the modular form :math:`f` in
        :emphasis:`mf` if present, as the flag given to :literal:`mfinit`.
        Returns 0 (newspace), 1 (cuspidal space), 2 (old space),
        3 (Eisenstein space) or 4 (full space).

        ::

        ? mf = mfinit([1,12],1); mfspace(mf)
        %1 = 1
        ? mfspace(mf, mfDelta())
        %2 = 0 \\ new space

        This function returns :math:`-1` when the form :math:`f` is modular
        but does not belong to the space.

        ::

        ? mf = mfinit([1,2]; mfspace(mf, mfEk(2))
        %3 = -1

        When :math:`f` is not modular and is for instance only quasi-modular, the
        function returns nonsense:

        ::

        ? M6 = mfinit([1,6]);
        ? dE4 = mfderiv(mfEk(4)); \\ not modular !
        ? mfspace(M6,dE4) \\ asserts (wrongly) that E4' belongs to new space
        %3 = 0
        '''
        mf = objtogen(mf)
        cdef bint _have_f = (f is not None)
        if _have_f:
            f = objtogen(f)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _f = NULL
        if _have_f:
            _f = (<Gen>f).g
        cdef long _ret = mfspace(_mf, _f)
        clear_stack()
        return _ret

    def mfsplit(self, mf, long dimlim=0, long flag=0):
        r'''
        :literal:`mf` from :literal:`mfinit` with integral weight containing the new space
        (either the new space itself or the cuspidal space or the full space), and
        preferably the newspace itself for efficiency, split the space into Galois
        orbits of eigenforms of the newspace, satisfying various restrictions.

        The functions returns :math:`[vF, vK]`, where :math:`vF` gives (Galois orbit of)
        eigenforms and :math:`vK` is a list of polynomials defining each Galois orbit.
        The eigenforms are given in :literal:`mftobasis` format, i.e. as a matrix
        whose columns give the forms with respect to :literal:`mfbasis(mf)`.

        If :literal:`dimlim` is set, only the Galois orbits of dimension :math:`<= dimlim`
        are computed (i.e. the rational eigenforms if :math:`dimlim = 1` and the
        character is real). This can considerably speed up the function when a Galois
        orbit is defined over a large field.

        :literal:`flag` speeds up computations when the dimension is large: if :math:`flag = d > 0`,
        when the dimension of the eigenspace is :math:`> d`, only the Galois polynomial is
        computed.

        Note that the function :literal:`mfeigenbasis` returns all eigenforms in an
        easier to use format (as modular forms which can be input as is in other
        functions); :literal:`mfsplit` is only useful when you can restrict
        to orbits of small dimensions, e.g. rational eigenforms.

        ::

        ? mf=mfinit([11,2],0); f=mfeigenbasis(mf)[1]; mfcoefs(f,16)
        %1 = [0, 1, -2, -1, ...]
        ? mf=mfinit([23,2],0); f=mfeigenbasis(mf)[1]; mfcoefs(f,16)
        %2 = [Mod(0, z^2 - z - 1), Mod(1, z^2 - z - 1), Mod(-z, z^2 - z - 1), ...]
        ? mf=mfinit([179,2],0); apply(poldegree, mffields(mf))
        %3 = [1, 3, 11]
        ? mf=mfinit([719,2],0);
        ? [vF,vK] = mfsplit(mf, 5); \\ fast when restricting to small orbits
        time = 192 ms.
        ? #vF \\ a single orbit
        %5 = 1
        ? poldegree(vK[1]) \\ of dimension 5
        %6 = 5
        ? [vF,vK] = mfsplit(mf); \\ general case is slow
        time = 2,104 ms.
        ? apply(poldegree,vK)
        %8 = [5, 10, 45] \\ because degree 45 is large...
        '''
        mf = objtogen(mf)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _ret = mfsplit(_mf, dimlim, flag)
        return new_gen(_ret)

    def mfsturm(self, NK):
        r'''
        Gives the Sturm bound for modular forms on :math:`\Gamma_0(N)` and
        weight :math:`k`, i.e., an upper bound for the order of the zero at infinity of
        a nonzero form. :literal:`NK` is either

        - a pair :math:`[N,k]`,

        - or the output of :literal:`mfinit` in which case the exact upper bound
        is returned.

        ::

        ? NK = [96,6]; mfsturm(NK)
        %1 = 97
        ? mf=mfinit(NK,1); mfsturm(mf)
        %2 = 76
        ? mfdim(NK,0) \\ new space
        %3 = 72
        '''
        NK = objtogen(NK)
        sig_on()
        cdef GEN _NK = (<Gen>NK).g
        cdef long _ret = mfsturm(_NK)
        clear_stack()
        return _ret

    def mfsymbol(self, mf, f=None, long precision=DEFAULT_BITPREC):
        r'''
        Initialize data for working with all period polynomials of the modular
        form :math:`f`: this is essential for efficiency for functions such as
        :literal:`mfsymboleval`, :literal:`mfmanin`, and :literal:`mfpetersson`. An :literal:`mfsymbol`
        contains an :literal:`mf` structure and can always be used whenever an :literal:`mf`
        would be needed.

        ::

        ? mf=mfinit([23,2],0);F=mfeigenbasis(mf)[1];
        ? FS=mfsymbol(mf,F);
        ? mfsymboleval(FS,[0,oo])
        %3 = [8.762565143790690142 E-39 + 0.0877907874...*I,
        -5.617375463602574564 E-39 + 0.0716801031...*I]
        ? mfpetersson(FS)
        %4 =
        [0.0039488965740025031688548076498662860143 1.2789721111175127425 E-40]
        
        [1.2630501762985554269 E-40 0.0056442542987647835101583821368582485396]

        By abuse of language, initialize data for working with :literal:`mfpetersson` in
        weight :math:`1` and half-integral weight (where no symbol exist); the :literal:`mf`
        argument may be an :literal:`mfsymbol` attached to a form on the space,
        which avoids recomputing data independent of the form.

        ::

        ? mf=mfinit([12,9/2],1); F=mfbasis(mf);
        ? fs=mfsymbol(mf,F[1]);
        time = 476 ms
        ? mfpetersson(fs)
        %2 = 1.9722437519492014682047692073275406145 E-5
        ? f2s = mfsymbol(mf,F[2]);
        time = 484 ms.
        ? mfpetersson(f2s)
        %4 = 1.2142222531326333658647877864573002476 E-5
        ? gs = mfsymbol(fs,F[2]); \\ re-use existing symbol, a little faster
        time = 430 ms.
        ? mfpetersson(gs) == %4 \\ same value
        %6 = 1

        For simplicity, we also allow :literal:`mfsymbol(f)` instead of
        :literal:`mfsymbol(mfinit(f), f)`:
        '''
        mf = objtogen(mf)
        cdef bint _have_f = (f is not None)
        if _have_f:
            f = objtogen(f)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _f = NULL
        if _have_f:
            _f = (<Gen>f).g
        cdef GEN _ret = mfsymbol(_mf, _f, precision)
        return new_gen(_ret)

    def mfsymboleval(self, fs, path, ga=None, long precision=DEFAULT_BITPREC):
        r'''
        Evaluation of the modular symbol :math:`fs` (corresponding to the modular
        form :math:`f`) output by :literal:`mfsymbol` on the given path :literal:`path`, where
        :literal:`path` is either a vector :math:`[s_1,s_2]` or an integral matrix :math:`[a,b;c,d]`
        representing the path :math:`[a/c,b/d]`. In both cases :math:`s_1` or :math:`s_2` (or :math:`a/c` or
        :math:`b/d`) can also be elements of the upper half-plane.
        To avoid possibly lengthy :literal:`mfsymbol` computations, the program also
        accepts :math:`fs` of the form :literal:`[mf,F]`, but in that case :math:`s_1` and :math:`s_2`
        are limited to :literal:`oo` and elements of the upper half-plane.
        The result is the polynomial equal to
        :math:`\int_{s_1}^{s_2}(X-\tau)^{k-2}F(\tau)d\tau`, the integral being
        computed along a geodesic joining :math:`s_1` and :math:`s_2`. If :literal:`ga` in :math:`GL_2^+(\mathbb{Q})`
        is given, replace :math:`F` by :math:`F\|_{k}\gamma`. Note that if the integral diverges,
        the result will be a rational function.
        If the field of definition :math:`\mathbb{Q} (f)` is larger than :math:`\mathbb{Q} (\chi)` then :math:`f` can be
        embedded into :math:`\mathbb{C}` in :math:`d = [\mathbb{Q} (f):\mathbb{Q} (\chi)]` ways, in which case a vector of
        the :math:`d` results is returned.

        ::

        ? mf=mfinit([35,2],1);f=mfbasis(mf)[1];fs=mfsymbol(mf,f);
        ? mfsymboleval(fs,[0,oo])
        %1 = 0.31404011074188471664161704390256378537*I
        ? mfsymboleval(fs,[1,3;2,5])
        %2 = -0.1429696291... - 0.2619975641...*I
        ? mfsymboleval(fs,[I,2*I])
        %3 = 0.00088969563028739893631700037491116258378*I
        ? E2=mfEk(2);E22=mflinear([E2,mfbd(E2,2)],[1,-2]);mf=mfinit(E22);
        ? E2S = mfsymbol(mf,E22);
        ? mfsymboleval(E2S,[0,1])
        %6 = (-1.00000...*x^2 + 1.00000...*x - 0.50000...)/(x^2 - x)

        The rational function which is given in case the integral diverges is
        easy to interpret. For instance:

        ::

        ? E4=mfEk(4);mf=mfinit(E4);ES=mfsymbol(mf,E4);
        ? mfsymboleval(ES,[I,oo])
        %2 = 1/3*x^3 - 0.928067...*I*x^2 - 0.833333...*x + 0.234978...*I
        ? mfsymboleval(ES,[0,I])
        %3 = (-0.234978...*I*x^3 - 0.833333...*x^2 + 0.928067...*I*x + 0.333333...)/x

        :literal:`mfsymboleval(ES,[a,oo])` is the limit as :math:`T\to oo` of

        .. MATH::

        \int_a^{iT}(X-\tau)^{k-2}F(\tau)d\tau + a(0)(X-iT)^{k-1}/(k-1) ,

        where :math:`a(0)` is the :math:`0`th coefficient of :math:`F` at infinity. Similarly,
        :literal:`mfsymboleval(ES,[0,a])` is the limit as :math:`T\to oo` of

        .. MATH::

        \int_{i/T}^a(X-\tau)^{k-2}F(\tau)d\tau+b(0)(1+iTX)^{k-1}/(k-1) ,

        where :math:`b(0)` is the :math:`0`th coefficient of :math:`F\|_{k} S` at infinity.
        '''
        fs = objtogen(fs)
        path = objtogen(path)
        cdef bint _have_ga = (ga is not None)
        if _have_ga:
            ga = objtogen(ga)
        sig_on()
        cdef GEN _fs = (<Gen>fs).g
        cdef GEN _path = (<Gen>path).g
        cdef GEN _ga = NULL
        if _have_ga:
            _ga = (<Gen>ga).g
        cdef GEN _ret = mfsymboleval(_fs, _path, _ga, precision)
        return new_gen(_ret)

    def mftaylor(self, F, long n, long flreal=0, long precision=DEFAULT_BITPREC):
        r'''
        :math:`F` being a form in :math:`M_k(SL_2(\mathbb{Z}))`, computes the first :math:`n+1`
        canonical Taylor expansion of :math:`F` around :math:`\tau = I`. If :literal:`flreal = 0`,
        computes only an algebraic equivalence class. If :literal:`flreal` is set,
        compute :math:`p_n` such that for :math:`\tau` close enough to :math:`I` we have

        .. MATH::

        f(\tau) = (2I/(\tau+I))^k\sum_{n >= 0}p_n((\tau-I)/(\tau+I))^n .

        ::

        ? D=mfDelta();
        ? mftaylor(D,8)
        %2 = [1/1728, 0, -1/20736, 0, 1/165888, 0, 1/497664, 0, -11/3981312]
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        precision = nbits2prec(precision)
        cdef GEN _ret = mftaylor(_F, n, flreal, precision)
        return new_gen(_ret)

    def mftobasis(self, mf, F, long flag=0):
        r'''
        Coefficients of the form :math:`F` on the basis given by :literal:`mfbasis(mf)`.
        A :math:`q`-expansion or vector of coefficients
        can also be given instead of :math:`F`, but in this case an error message may occur
        if the expansion is too short. An error message is also given if :math:`F` does not
        belong to the modular form space. If :literal:`flag` is set, instead of
        error messages the output is an affine space of solutions if a :math:`q`-expansion
        or vector of coefficients is given, or the empty column otherwise.

        ::

        ? mf = mfinit([26,2],0); mfdim(mf)
        %1 = 2
        ? F = mflinear(mf,[a,b]); mftobasis(mf,F)
        %2 = [a, b]~

        A :math:`q`-expansion or vector of coefficients can also be given instead of :math:`F`.

        ::

        ? Th = 1 + 2*sum(n=1, 8, q^(n^2), O(q^80));
        ? mf = mfinit([4,5,Mod(3,4)]);
        ? mftobasis(mf, Th^10)
        %3 = [64/5, 4/5, 32/5]~

        If :math:`F` does not belong to the corresponding space, the result is incorrect
        and simply matches the coefficients of :math:`F` up to some bound, and
        the function may either return an empty column or an error message.
        If :literal:`flag` is set, there are no error messages, and the result is
        an empty column if :math:`F` is a modular form; if :math:`F` is supplied via a series
        or vector of coefficients which does not contain enough information to force
        a unique (potential) solution, the function returns :math:`[v,K]` where :math:`v` is a
        solution and :math:`K` is a matrix of maximal rank describing the affine space of
        potential solutions :math:`v + K.x`.

        ::

        ? mf = mfinit([4,12],1);
        ? mftobasis(mf, q-24*q^2+O(q^3), 1)
        %2 = [[43/64, -63/8, 800, 21/64]~, [1, 0; 24, 0; 2048, 768; -1, 0]]
        ? mftobasis(mf, [0,1,-24,252], 1)
        %3 = [[1, 0, 1472, 0]~, [0; 0; 768; 0]]
        ? mftobasis(mf, [0,1,-24,252,-1472], 1)
        %4 = [1, 0, 0, 0]~ \\ now uniquely determined
        ? mftobasis(mf, [0,1,-24,252,-1472,0], 1)
        %5 = [1, 0, 0, 0]~ \\ wrong result: no such form exists
        ? mfcoefs(mflinear(mf,%), 5) \\ double check
        %6 = [0, 1, -24, 252, -1472, 4830]
        ? mftobasis(mf, [0,1,-24,252,-1472,0])
        *** at top-level: mftobasis(mf,[0,1,
        *** ^--------------------
        *** mftobasis: domain error in mftobasis: form does not belong to space
        ? mftobasis(mf, mfEk(10))
        *** at top-level: mftobasis(mf,mfEk(
        *** ^--------------------
        *** mftobasis: domain error in mftobasis: form does not belong to space
        ? mftobasis(mf, mfEk(10), 1)
        %7 = []~
        '''
        mf = objtogen(mf)
        F = objtogen(F)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mftobasis(_mf, _F, flag)
        return new_gen(_ret)

    def mftocoset(self, long N, M, Lcosets):
        r'''
        :math:`M` being a matrix in :math:`SL_2(Z)` and :literal:`Lcosets` being
        :literal:`mfcosets(N)`, a list of right cosets of :math:`\Gamma_0(N)`,
        find the coset to which :math:`M` belongs. The output is a pair
        :math:`[\gamma,i]` such that :math:`M = \gamma Lcosets[i]`, :math:`\gamma\in\Gamma_0(N)`.

        ::

        ? N = 4; L = mfcosets(N);
        ? mftocoset(N, [1,1;2,3], L)
        %2 = [[-1, 1; -4, 3], 5]
        '''
        M = objtogen(M)
        Lcosets = objtogen(Lcosets)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _Lcosets = (<Gen>Lcosets).g
        cdef GEN _ret = mftocoset(N, _M, _Lcosets)
        return new_gen(_ret)

    def mftonew(self, mf, F):
        r'''
        :literal:`mf` being being a full or cuspidal space with parameters :math:`[N,k,\chi]`
        and :math:`F` a cusp form in that space, returns a vector of 3-component vectors
        :math:`[M,d,G]`, where :math:`f(\chi) \| M \| N`, :math:`d \| N/M`, and :math:`G` is a form
        in :math:`S_k^{new}(\Gamma_0(M),\chi)` such that :math:`F` is equal to the sum of
        the :math:`B(d)(G)` over all these 3-component vectors.

        ::

        ? mf = mfinit([96,6],1); F = mfbasis(mf)[60]; s = mftonew(mf,F); #s
        %1 = 1
        ? [M,d,G] = s[1]; [M,d]
        %2 = [48, 2]
        ? mfcoefs(F,10)
        %3 = [0, 0, -160, 0, 0, 0, 0, 0, 0, 0, -14400]
        ? mfcoefs(G,10)
        %4 = [0, 0, -160, 0, 0, 0, 0, 0, 0, 0, -14400]
        '''
        mf = objtogen(mf)
        F = objtogen(F)
        sig_on()
        cdef GEN _mf = (<Gen>mf).g
        cdef GEN _F = (<Gen>F).g
        cdef GEN _ret = mftonew(_mf, _F)
        return new_gen(_ret)

    def mftraceform(self, NK, long space=0):
        r'''
        If :math:`NK = [N,k,CHI,.]` as in :literal:`mfinit` with :math:`k` integral, gives the
        trace form in the corresponding subspace of :math:`S_k(\Gamma_0(N),\chi)`.
        The supported values for :literal:`space` are 0: the newspace (default),
        1: the full cuspidal space.

        ::

        ? F = mftraceform([23,2]); mfcoefs(F,16)
        %1 = [0, 2, -1, 0, -1, -2, -5, 2, 0, 4, 6, -6, 5, 6, 4, -10, -3]
        ? F = mftraceform([23,1,-23]); mfcoefs(F,16)
        %2 = [0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, -1]
        '''
        NK = objtogen(NK)
        sig_on()
        cdef GEN _NK = (<Gen>NK).g
        cdef GEN _ret = mftraceform(_NK, space)
        return new_gen(_ret)

    def mftwist(self, F, D):
        r'''
        :math:`F` being a generalized modular form, returns the twist of :math:`F` by the
        integer :math:`D`, i.e., the form :math:`G` such that
        :literal:`mfcoef(G,n) = `:math:`(D/n)`:literal:`mfcoef(F,n)`, where :math:`(D/n)` is the Kronecker
        symbol.

        ::

        ? mf = mfinit([11,2],0); F = mfbasis(mf)[1]; mfcoefs(F, 5)
        %1 = [0, 1, -2, -1, 2, 1]
        ? G = mftwist(F,-3); mfcoefs(G, 5)
        %2 = [0, 1, 2, 0, 2, -1]
        ? mf2 = mfinit([99,2],0); mftobasis(mf2, G)
        %3 = [1/3, 0, 1/3, 0]~

        Note that twisting multiplies the level by :math:`D^2`. In
        particular it is not an involution:

        ::

        ? H = mftwist(G,-3); mfcoefs(H, 5)
        %4 = [0, 1, -2, 0, 2, 1]
        ? mfparams(G)
        %5 = [99, 2, 1, y]
        '''
        F = objtogen(F)
        D = objtogen(D)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _D = (<Gen>D).g
        cdef GEN _ret = mftwist(_F, _D)
        return new_gen(_ret)

    def min(self, x, y):
        r'''
        Creates the maximum of :math:`x` and :math:`y` when they can be compared.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = gmin(_x, _y)
        return new_gen(_ret)

    def minpoly(self, A, v=None):
        r'''
        minimal polynomial
        of :math:`A` with respect to the variable :math:`v`., i.e. the monic polynomial :math:`P`
        of minimal degree (in the variable :math:`v`) such that :math:`P(A) = 0`.
        '''
        A = objtogen(A)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _ret = minpoly(_A, _v)
        return new_gen(_ret)

    def modreverse(self, z):
        r'''
        Let :math:`z = Mod(A, T)` be a polmod, and :math:`Q` be its minimal
        polynomial, which must satisfy :math:`deg(Q) = deg(T)`.
        Returns a "reverse polmod" :literal:`Mod(B, Q)`, which is a root of :math:`T`.

        This is quite useful when one changes the generating element in algebraic
        extensions:

        ::

        ? u = Mod(x, x^3 - x -1); v = u^5;
        ? w = modreverse(v)
        %2 = Mod(x^2 - 4*x + 1, x^3 - 5*x^2 + 4*x - 1)

        which means that :math:`x^3 - 5x^2 + 4x -1` is another defining polynomial for the
        cubic field

        .. MATH::

        \mathbb{Q} (u) = \mathbb{Q}[x]/(x^3 - x - 1) = \mathbb{Q}[x]/(x^3 - 5x^2 + 4x - 1) = \mathbb{Q} (v),

        and that :math:`u \to v^2 - 4v + 1` gives an explicit isomorphism. From this, it is
        easy to convert elements between the :math:`A(u)\in \mathbb{Q} (u)` and :math:`B(v)\in \mathbb{Q} (v)`
        representations:

        ::

        ? A = u^2 + 2*u + 3; subst(lift(A), 'x, w)
        %3 = Mod(x^2 - 3*x + 3, x^3 - 5*x^2 + 4*x - 1)
        ? B = v^2 + v + 1; subst(lift(B), 'x, v)
        %4 = Mod(26*x^2 + 31*x + 26, x^3 - x - 1)

        If the minimal polynomial of :math:`z` has lower degree than expected, the routine
        fails

        ::

        ? u = Mod(-x^3 + 9*x, x^4 - 10*x^2 + 1)
        ? modreverse(u)
        *** modreverse: domain error in modreverse: deg(minpoly(z)) < 4
        *** Break loop: type 'break' to go back to GP prompt
        break> Vec( dbg_err() ) \\ ask for more info
        ["e_DOMAIN", "modreverse", "deg(minpoly(z))", "<", 4,
        Mod(-x^3 + 9*x, x^4 - 10*x^2 + 1)]
        break> minpoly(u)
        x^2 - 8
        '''
        z = objtogen(z)
        sig_on()
        cdef GEN _z = (<Gen>z).g
        cdef GEN _ret = modreverse(_z)
        return new_gen(_ret)

    def moebius(self, x):
        r'''
        Moebius :math:`\mu`-function of :math:`\|x\|`; :math:`x` must be a non-zero integer.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = moebius(_x)
        clear_stack()
        return _ret

    def msatkinlehner(self, M, long Q, H=None):
        r'''
        Let :math:`M` be a full modular symbol space of level :math:`N`,
        as given by :literal:`msinit`, let :math:`Q \| N`, :math:`(Q,N/Q) = 1`,
        and let :math:`H` be a subspace stable under the Atkin-Lehner involution :math:`w_Q`.
        Return the matrix of :math:`w_Q` acting on :math:`H` (:math:`M` if omitted).

        ::

        ? M = msinit(36,2); \\ M_2(Gamma_0(36))
        ? w = msatkinlehner(M,4); w^2 == 1
        %2 = 1
        ? #w \\ involution acts on a 13-dimensional space
        %3 = 13
        ? M = msinit(36,2, -1); \\ M_2(Gamma_0(36))^-
        ? w = msatkinlehner(M,4); w^2 == 1
        %5 = 1
        ? #w
        %6 = 4
        '''
        M = objtogen(M)
        cdef bint _have_H = (H is not None)
        if _have_H:
            H = objtogen(H)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _H = NULL
        if _have_H:
            _H = (<Gen>H).g
        cdef GEN _ret = msatkinlehner(_M, Q, _H)
        return new_gen(_ret)

    def mscuspidal(self, M, long flag=0):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        return its cuspidal part :math:`S`. If :math:`flag = 1`, return
        :math:`[S,E]` its decomposition into cuspidal and Eisenstein parts.

        A subspace is given by a structure allowing quick projection and
        restriction of linear operators; its first component is
        a matrix with integer coefficients whose columns form a :math:`\mathbb{Q}`-basis of
        the subspace.

        ::

        ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+
        ? [S,E] = mscuspidal(M, 1);
        ? E[1] \\ 2-dimensional
        %3 =
        [0 -10]
        
        [0 -15]
        
        [0 -3]
        
        [1 0]
        
        ? S[1] \\ 1-dimensional
        %4 =
        [ 3]
        
        [30]
        
        [ 6]
        
        [-8]
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = mscuspidal(_M, flag)
        return new_gen(_ret)

    def msdim(self, M):
        r'''
        :math:`M` being a full modular symbol space or subspace, for instance
        as given by :literal:`msinit` or :literal:`mscuspidal`, return
        its dimension as a :math:`\mathbb{Q}`-vector space.

        ::

        ? M = msinit(11,4); msdim(M)
        %1 = 6
        ? M = msinit(11,4,1); msdim(M)
        %2 = 4 \\ dimension of the '+' part
        ? [S,E] = mscuspidal(M,1);
        ? [msdim(S), msdim(E)]
        %4 = [2, 2]

        Note that :literal:`mfdim([N,k])` is going to be much faster if
        you only need the dimension of the space and not really to work with it.
        This function is only useful to quickly check the dimension of an existing
        space.
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef long _ret = msdim(_M)
        clear_stack()
        return _ret

    def mseisenstein(self, M):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        return its Eisenstein subspace.
        A subspace is given by a structure allowing quick projection and
        restriction of linear operators; its first component is
        a matrix with integer coefficients whose columns form a :math:`\mathbb{Q}`-basis of
        the subspace.
        This is the same basis as given by the second component of
        :literal:`mscuspidal`:math:`(M, 1)`.

        ::

        ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+
        ? E = mseisenstein(M);
        ? E[1] \\ 2-dimensional
        %3 =
        [0 -10]
        
        [0 -15]
        
        [0 -3]
        
        [1 0]
        
        ? E == mscuspidal(M,1)[2]
        %4 = 1
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = mseisenstein(_M)
        return new_gen(_ret)

    def mseval(self, M, s, p=None):
        r'''
        Let :math:`\Delta := Div^0(\mathbb{P}^1 (\mathbb{Q}))`.
        Let :math:`M` be a full modular symbol space, as given by :literal:`msinit`,
        let :math:`s` be a modular symbol from :math:`M`, i.e. an element
        of :math:`\text{Hom}_G(\Delta, V)`, and let :math:`p = [a,b] \in \Delta` be a path between
        two elements in :math:`\mathbb{P}^1(\mathbb{Q})`, return :math:`s(p)\in V`. The path extremities :math:`a` and
        :math:`b` may be given as :literal:`t_INT`, :literal:`t_FRAC` or :math:`oo = (1:0)`; it
        is also possible to describe the path by a :math:`2 x 2` integral matrix
        whose columns give the two cusps. The symbol :math:`s` is either

        - a :literal:`t_COL` coding a modular symbol in terms of
        the fixed basis of :math:`\text{Hom}_G(\Delta,V)` chosen in :math:`M`; if :math:`M` was
        initialized with a non-zero :emphasis:`sign` (:math:`+` or :math:`-`), then either the
        basis for the full symbol space or the :math:`±`-part can be used (the dimension
        being used to distinguish the two).

        - a :literal:`t_MAT` whose columns encode modular symbols as above. This is
        much faster than evaluating individual symbols on the same path :math:`p`
        independently.

        - a :literal:`t_VEC` :math:`(v_i)` of elements of :math:`V`, where the :math:`v_i = s(g_i)` give
        the image of the generators :math:`g_i` of :math:`\Delta`, see :literal:`mspathgens`.
        We assume that :math:`s` is a proper symbol, i.e. that the :math:`v_i` satisfy
        the :literal:`mspathgens` relations.

        If :math:`p` is omitted, convert a single symbol :math:`s` to the second form: a vector
        of the :math:`s(g_i)`. A :literal:`t_MAT` is converted to a vector of such.

        ::

        ? M = msinit(2,8,1); \\ M_8(Gamma_0(2))^+
        ? g = mspathgens(M)[1]
        %2 = [[+oo, 0], [0, 1]]
        ? N = msnew(M)[1]; #N \\ Q-basis of new subspace, dimension 1
        %3 = 1
        ? s = N[,1] \\ t_COL representation
        %4 = [-3, 6, -8]~
        ? S = mseval(M, s) \\ t_VEC representation
        %5 = [64*x^6-272*x^4+136*x^2-8, 384*x^5+960*x^4+192*x^3-672*x^2-432*x-72]
        ? mseval(M,s, g[1])
        %6 = 64*x^6 - 272*x^4 + 136*x^2 - 8
        ? mseval(M,S, g[1])
        %7 = 64*x^6 - 272*x^4 + 136*x^2 - 8

        Note that the symbol should have values in
        :math:`V = \mathbb{Q}[x,y]_{k-2}`, we return the de-homogenized values corresponding to :math:`y
        = 1` instead.
        '''
        M = objtogen(M)
        s = objtogen(s)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _s = (<Gen>s).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _ret = mseval(_M, _s, _p)
        return new_gen(_ret)

    def msfromcusp(self, M, c):
        r'''
        Returns the modular symbol attached to the cusp
        :math:`c`, where :math:`M` is a modular symbol space of level :math:`N`, attached to
        :math:`G = \Gamma_0(N)`. The cusp :math:`c` in :math:`\mathbb{P}^1(\mathbb{Q})/G` is given either as :literal:`oo`
        (:math:`= (1:0)`) or as a rational number :math:`a/b` (:math:`= (a:b)`). The attached symbol maps
        the path :math:`[b] - [a] \in Div^0 (\mathbb{P}^1(\mathbb{Q}))` to :math:`E_c(b) - E_c(a)`, where
        :math:`E_c(r)` is :math:`0` when :math:`r != c` and :math:`X^{k-2} \| \gamma_r` otherwise, where
        :math:`\gamma_r.r = (1:0)`. These symbols span the Eisenstein subspace
        of :math:`M`.

        ::

        ? M = msinit(2,8); \\ M_8(Gamma_0(2))
        ? E = mseisenstein(M);
        ? E[1] \\ two-dimensional
        %3 =
        [0 -10]
        
        [0 -15]
        
        [0 -3]
        
        [1 0]
        
        ? s = msfromcusp(M,oo)
        %4 = [0, 0, 0, 1]~
        ? mseval(M, s)
        %5 = [1, 0]
        ? s = msfromcusp(M,1)
        %6 = [-5/16, -15/32, -3/32, 0]~
        ? mseval(M,s)
        %7 = [-x^6, -6*x^5 - 15*x^4 - 20*x^3 - 15*x^2 - 6*x - 1]

        In case :math:`M` was initialized with a non-zero :emphasis:`sign`, the symbol is given
        in terms of the fixed basis of the whole symbol space, not the :math:`+` or :math:`-`
        part (to which it need not belong).

        ::

        ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+
        ? E = mseisenstein(M);
        ? E[1] \\ still two-dimensional, in a smaller space
        %3 =
        [ 0 -10]
        
        [ 0 3]
        
        [-1 0]
        
        ? s = msfromcusp(M,oo) \\ in terms of the basis for M_8(Gamma_0(2)) !
        %4 = [0, 0, 0, 1]~
        ? mseval(M, s) \\ same symbol as before
        %5 = [1, 0]
        '''
        M = objtogen(M)
        c = objtogen(c)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _c = (<Gen>c).g
        cdef GEN _ret = msfromcusp(_M, _c)
        return new_gen(_ret)

    def msfromell(self, E, long sign=0):
        r'''
        Let :math:`E/\mathbb{Q}` be an elliptic curve of conductor :math:`N`. For :math:`\varepsilon =
        ±1`, we define the (cuspidal, new) modular symbol :math:`x^\varepsilon` in
        :math:`H^1_c(X_0(N),\mathbb{Q})^\varepsilon` attached to
        :math:`E`. For all primes :math:`p` not dividing :math:`N` we have
        :math:`T_p(x^\varepsilon) = a_p x^\varepsilon`, where :math:`a_p = p+1-\#E(\mathbb{F}_p)`.

        Let :math:`\Omega^ += E.omega[1]` be the real period of :math:`E`
        (integration of the Néron differential :math:`dx/(2y+a_1x+a3)` on the connected
        component of :math:`E(\mathbb{R})`, i.e. the generator of :math:`H_1(E,\mathbb{Z})^+`) normalized by
        :math:`\Omega^+ > 0`. Let :math:`i\Omega^-` the integral on a generator of :math:`H_1(E,\mathbb{Z})^-` with
        :math:`\Omega^- \in \mathbb{R}_{ > 0}`. If :math:`c_ oo` is the number of connected components of
        :math:`E(\mathbb{R})`, :math:`\Omega^-` is equal to :math:`(-2/c_ oo ) x imag(E.omega[2])`.
        The complex modular symbol is defined by

        .. MATH::

        F: \delta \to 2i\pi \int_{\delta} f(z) dz

        The modular symbols :math:`x^\varepsilon` are normalized so that
        :math:`F = x^+ \Omega^+ + x^- i\Omega^-`. In particular, we have

        .. MATH::

        x^+([0]-[ oo ]) = L(E,1) / \Omega^+,

        which defines :math:`x^{±}` unless :math:`L(E,1) = 0`. Furthermore, for all fundamental
        discriminants :math:`D` such that :math:`\varepsilon.D > 0`, we also have

        .. MATH::

        \sum_{0 <= a < \|D\|} (D\|a) x^\varepsilon ([a/\|D\|]-[ oo ])
        = L(E,(D\|.),1) / \Omega^{\varepsilon},

        where :math:`(D\|.)` is the Kronecker symbol. The period :math:`\Omega^-` is also
        :math:`2/c_ oo x` the real period of the twist
        :math:`E^{(-4)} = elltwist(E,-4)`.

        This function returns the pair :math:`[M, x]`, where :math:`M` is
        :literal:`msinit`:math:`(N,2)` and :math:`x` is :math:`x^{sign}` as above when :math:`sign =
        ±1`, and :math:`x = [x^+,x^-, L_E]` when :emphasis:`sign` is :math:`0`, where :math:`L_E`
        is a matrix giving the canonical :math:`\mathbb{Z}`-lattice attached to :math:`E` in the sense
        of :literal:`mslattice` applied to :math:`\mathbb{Q} x^+ + \mathbb{Q} x^-`. Explicitly, it
        is generated by :math:`(x^{+},x^{-})` when :math:`E(\mathbb{R})` has two connected components
        and by :math:`(x^{+} - x^{-},2x^-)` otherwise.

        The modular symbols :math:`x^±` are given as a :literal:`t_COL` (in terms
        of the fixed basis of :math:`\text{Hom}_G(\Delta,\mathbb{Q})` chosen in :math:`M`).

        ::

        ? E=ellinit([0,-1,1,-10,-20]); \\ X_0(11)
        ? [M,xp]= msfromell(E,1);
        ? xp
        %3 = [1/5, -1/2, -1/2]~
        ? [M,x]= msfromell(E);
        ? x \\ x^+, x^- and L_E
        %5 = [[1/5, -1/2, -1/2]~, [0, 1/2, -1/2]~, [1/5, 0; -1, 1; 0, -1]]
        ? p = 23; (mshecke(M,p) - ellap(E,p))*x[1]
        %6 = [0, 0, 0]~ \\ true at all primes, including p = 11; same for x[2]
        ? (mshecke(M,p) - ellap(E,p))*x[3] == 0
        %7 = 1

        Instead of a single curve :math:`E`, one may use instead a vector
        of :emphasis:`isogenous` curves. The function then returns :math:`M` and the
        vector of attached modular symbols.
        '''
        E = objtogen(E)
        sig_on()
        cdef GEN _E = (<Gen>E).g
        cdef GEN _ret = msfromell(_E, sign)
        return new_gen(_ret)

    def msfromhecke(self, M, v, H=None):
        r'''
        Given a msinit :math:`M` and a vector :math:`v` of pairs :math:`[p, P]` (where :math:`p` is prime
        and :math:`P` is a polynomial with integer coefficients), return a basis of all
        modular symbols such that :math:`P(T_p)(s) = 0`. If :math:`H` is present, it must
        be a Hecke-stable subspace and we restrict to :math:`s \in H`. When :math:`T_p` has
        a rational eigenvalue and :math:`P(x) = x-a_p` has degree :math:`1`, we also accept the
        integer :math:`a_p` instead of :math:`P`.

        ::

        ? E = ellinit([0,-1,1,-10,-20]) \\11a1
        ? ellap(E,2)
        %2 = -2
        ? ellap(E,3)
        %3 = -1
        ? M = msinit(11,2);
        ? S = msfromhecke(M, [[2,-2],[3,-1]])
        %5 =
        [ 1 1]
        
        [-5 0]
        
        [ 0 -5]
        ? mshecke(M, 2, S)
        %6 =
        [-2 0]
        
        [ 0 -2]
        
        ? M = msinit(23,4);
        ? S = msfromhecke(M, [[5, x^4-14*x^3-244*x^2+4832*x-19904]]);
        ? factor( charpoly(mshecke(M,5,S)) )
        %9 =
        [x^4 - 14*x^3 - 244*x^2 + 4832*x - 19904 2]
        '''
        M = objtogen(M)
        v = objtogen(v)
        cdef bint _have_H = (H is not None)
        if _have_H:
            H = objtogen(H)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _v = (<Gen>v).g
        cdef GEN _H = NULL
        if _have_H:
            _H = (<Gen>H).g
        cdef GEN _ret = msfromhecke(_M, _v, _H)
        return new_gen(_ret)

    def msgetlevel(self, M):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`, return
        its level :math:`N`.
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef long _ret = msgetlevel(_M)
        clear_stack()
        return _ret

    def msgetsign(self, M):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`, return
        its sign: :math:`±1` or 0 (unset).

        ::

        ? M = msinit(11,4, 1);
        ? msgetsign(M)
        %2 = 1
        ? M = msinit(11,4);
        ? msgetsign(M)
        %4 = 0
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef long _ret = msgetsign(_M)
        clear_stack()
        return _ret

    def msgetweight(self, M):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`, return
        its weight :math:`k`.

        ::

        ? M = msinit(11,4);
        ? msgetweight(M)
        %2 = 4
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef long _ret = msgetweight(_M)
        clear_stack()
        return _ret

    def mshecke(self, M, long p, H=None):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        :math:`p` being a prime number, and :math:`H` being a Hecke-stable subspace (:math:`M` if
        omitted) return the matrix of :math:`T_p` acting on :math:`H`
        (:math:`U_p` if :math:`p` divides :math:`N`). Result is undefined if :math:`H` is not stable
        by :math:`T_p` (resp. :math:`U_p`).

        ::

        ? M = msinit(11,2); \\ M_2(Gamma_0(11))
        ? T2 = mshecke(M,2)
        %2 =
        [3 0 0]
        
        [1 -2 0]
        
        [1 0 -2]
        ? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+
        ? T2 = mshecke(M,2)
        %4 =
        [ 3 0]
        
        [-1 -2]
        
        ? N = msnew(M)[1] \\ Q-basis of new cuspidal subspace
        %5 =
        [-2]
        
        [-5]
        
        ? p = 1009; mshecke(M, p, N) \\ action of T_1009 on N
        %6 =
        [-10]
        ? ellap(ellinit("11a1"), p)
        %7 = -10
        '''
        M = objtogen(M)
        cdef bint _have_H = (H is not None)
        if _have_H:
            H = objtogen(H)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _H = NULL
        if _have_H:
            _H = (<Gen>H).g
        cdef GEN _ret = mshecke(_M, p, _H)
        return new_gen(_ret)

    def msinit(self, G, V, long sign=0):
        r'''
        Given :math:`G` a finite index subgroup of :math:`SL(2,\mathbb{Z})`
        and a finite dimensional representation :math:`V` of :math:`GL(2,\mathbb{Q})`, creates a
        space of modular symbols, the :math:`G`-module :math:`\text{Hom}_G(Div^0(\mathbb{P}^1
        (\mathbb{Q})), V)`. This is canonically isomorphic to :math:`H^1_c(X(G), V)`, and allows to
        compute modular forms for :math:`G`. If :emphasis:`sign` is present and non-zero, it
        must be :math:`±1` and we consider the subspace defined by :math:`Ker (\sigma -
        sign)`, where :math:`\sigma` is induced by :literal:`[-1,0;0,1]`. Currently the
        only supported groups are the :math:`\Gamma_0(N)`, coded by the integer :math:`N > 0`.
        The only supported representation is :math:`V_k = \mathbb{Q}[X,Y]_{k-2}`, coded by the
        integer :math:`k >= 2`.

        ::

        ? M = msinit(11,2); msdim(M) \\ Gamma0(11), weight 2
        %1 = 3
        ? mshecke(M,2) \\ T_2 acting on M
        %2 =
        [3 1 1]
        
        [0 -2 0]
        
        [0 0 -2]
        ? msstar(M) \\ * involution
        %3 =
        [1 0 0]
        
        [0 0 1]
        
        [0 1 0]
        
        ? Mp = msinit(11,2, 1); msdim(Mp) \\ + part
        %4 = 2
        ? mshecke(Mp,2) \\ T_2 action on M^+
        %5 =
        [3 2]
        
        [0 -2]
        ? msstar(Mp)
        %6 =
        [1 0]
        
        [0 1]
        '''
        G = objtogen(G)
        V = objtogen(V)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _V = (<Gen>V).g
        cdef GEN _ret = msinit(_G, _V, sign)
        return new_gen(_ret)

    def msissymbol(self, M, s):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        check whether :math:`s` is a modular symbol attached to :math:`M`. If :math:`A` is a matrix,
        check whether its columns represent modular symbols and return a :math:`0-1`
        vector.

        ::

        ? M = msinit(7,8, 1); \\ M_8(Gamma_0(7))^+
        ? A = msnew(M)[1];
        ? s = A[,1];
        ? msissymbol(M, s)
        %4 = 1
        ? msissymbol(M, A)
        %5 = [1, 1, 1]
        ? S = mseval(M,s);
        ? msissymbol(M, S)
        %7 = 1
        ? [g,R] = mspathgens(M); g
        %8 = [[+oo, 0], [0, 1/2], [1/2, 1]]
        ? #R \\ 3 relations among the generators g_i
        %9 = 3
        ? T = S; T[3]++; \\ randomly perturb S(g_3)
        ? msissymbol(M, T)
        %11 = 0 \\ no longer satisfies the relations
        '''
        M = objtogen(M)
        s = objtogen(s)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _s = (<Gen>s).g
        cdef GEN _ret = msissymbol(_M, _s)
        return new_gen(_ret)

    def mslattice(self, M, H=None):
        r'''
        Let :math:`\Delta := Div^0(\mathbb{P}^1(\mathbb{Q}))` and :math:`V_k = \mathbb{Q}[x,y]_{k-2}`.
        Let :math:`M` be a full modular symbol space, as given by :literal:`msinit`
        and let :math:`H` be a subspace, e.g. as given by :literal:`mscuspidal`.
        This function returns a canonical :math:`\mathbb{Z}`
        structure on :math:`H` defined as follows.
        Consider the map :math:`c: M = \text{Hom}_{\Gamma_0(N)}(\Delta, V_k) \to
        H^1(\Gamma_0(N), V_k)` given by
        :math:`\phi :--->class (\gamma \to \phi ({0, \gamma^{-1} 0}))`.
        Let :math:`L_k = \mathbb{Z}[x,y]_{k-2}` be the natural :math:`\mathbb{Z}`-structure of :math:`V_k`. The result of
        :literal:`mslattice` is a :math:`\mathbb{Z}`-basis of the inverse image by :math:`c` of
        :math:`H^1(\Gamma_0(N), L_k)` in the space of modular symbols generated by :math:`H`.

        For user convenience, :math:`H` can be defined by a matrix representing the
        :math:`\mathbb{Q}`-basis of :math:`H` (in terms of the canonical :math:`\mathbb{Q}`-basis of :math:`M` fixed by
        :literal:`msinit` and used to represent modular symbols).

        If omitted, :math:`H` is the cuspidal part of :math:`M` as given by :literal:`mscuspidal`.
        The Eisenstein part :math:`\text{Hom}_{\Gamma_0(N)}(Div(\mathbb{P}^1(\mathbb{Q})), V_k)` is in
        the kernel of :math:`c`, so the result has no meaning for the Eisenstein part
        :literal:`H`.

        ::

        ? M=msinit(11,2);
        ? [S,E] = mscuspidal(M,1); S[1] \\ a primitive Q-basis of S
        %2 =
        [ 1 1]
        [-5 0]
        [ 0 -5]
        ? mslattice(M,S)
        %3 =
        [-1/5 -1/5]
        [ 1 0]
        [ 0 1]
        ? mslattice(M,E)
        %4 =
        [1]
        [0]
        [0]
        ? M=msinit(5,4);
        ? S=mscuspidal(M); S[1]
        %6 =
        [ 7 20]
        [ 3 3]
        [-10 -23]
        [-30 -30]
        ? mslattice(M,S)
        %7 =
        [-1/10 -11/130]
        [ 0 -1/130]
        [ 1/10 6/65]
        [ 0 1/13]
        '''
        M = objtogen(M)
        cdef bint _have_H = (H is not None)
        if _have_H:
            H = objtogen(H)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _H = NULL
        if _have_H:
            _H = (<Gen>H).g
        cdef GEN _ret = mslattice(_M, _H)
        return new_gen(_ret)

    def msnew(self, M):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        return the :emphasis:`new` part of its cuspidal subspace. A subspace is given by
        a structure allowing quick projection and restriction of linear operators;
        its first component is a matrix with integer coefficients whose columns form
        a :math:`\mathbb{Q}`-basis of the subspace.

        ::

        ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+
        ? N = msnew(M);
        ? #N[1] \\ 6-dimensional
        %3 = 6
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = msnew(_M)
        return new_gen(_ret)

    def msomseval(self, Mp, PHI, path):
        r'''
        Return the vectors of moments of the :math:`p`-adic distribution attached
        to the path :literal:`path` by the overconvergent modular symbol :literal:`PHI`.

        ::

        ? M = msinit(3,6,1);
        ? Mp= mspadicinit(M,5,10);
        ? phi = [5,-3,-1]~;
        ? msissymbol(M,phi)
        %4 = 1
        ? PHI = mstooms(Mp,phi);
        ? ME = msomseval(Mp,PHI,[oo, 0]);
        '''
        Mp = objtogen(Mp)
        PHI = objtogen(PHI)
        path = objtogen(path)
        sig_on()
        cdef GEN _Mp = (<Gen>Mp).g
        cdef GEN _PHI = (<Gen>PHI).g
        cdef GEN _path = (<Gen>path).g
        cdef GEN _ret = msomseval(_Mp, _PHI, _path)
        return new_gen(_ret)

    def mspadicL(self, mu, s=None, long r=0):
        r'''
        Returns the value (or :math:`r`-th derivative)
        on a character :math:`\chi^s` of :math:`\mathbb{Z}_p^*` of the :math:`p`-adic :math:`L`-function
        attached to :literal:`mu`.

        Let :math:`\Phi` be the :math:`p`-adic distribution-valued overconvergent symbol
        attached to a modular symbol :math:`\phi` for :math:`\Gamma_0(N)` (eigenvector for
        :math:`T_N(p)` for the eigenvalue :math:`a_p`). Then :math:`L_p(\Phi,\chi^s) = L_p(\mu,s)` is the
        :math:`p`-adic :math:`L` function defined by

        .. MATH::

        L_p(\Phi,\chi^s) = \int_{\mathbb{Z}_p^*} \chi^s(z) d\mu (z)

        where :math:`\mu` is the distribution on :math:`\mathbb{Z}_p^*` defined by the restriction of
        :math:`\Phi ([ oo ]-[0])` to :math:`\mathbb{Z}_p^*`. The :math:`r`-th derivative is taken in
        direction :math:`<\chi>`:

        .. MATH::

        L_p^{(r)}(\Phi,\chi^s) = \int_{\mathbb{Z}_p^*} \chi^s(z) (\log z)^r d\mu (z).

        In the argument list,

        - :literal:`mu` is as returned by :literal:`mspadicmoments` (distributions
        attached to :math:`\Phi` by restriction to discs :math:`a + p^\nu\mathbb{Z}_p`, :math:`(a,p) = 1`).

        - :math:`s = [s_1,s_2]` with :math:`s_1 \in \mathbb{Z} \subset \mathbb{Z}_p` and :math:`s_2 mod p-1` or
        :math:`s_2 mod 2` for :math:`p = 2`, encoding the :math:`p`-adic character :math:`\chi^s := <
        \chi >^{s_1} \tau^{s_2}`; here :math:`\chi` is the cyclotomic character from
        :math:`Gal(\mathbb{Q}_p(\mu_{p^ oo })/\mathbb{Q}_p)` to :math:`\mathbb{Z}_p^*`, and :math:`\tau` is the
        Teichmüller character (for :math:`p > 2` and the character of order 2 on
        :math:`(\mathbb{Z}/4\mathbb{Z})^*` if :math:`p = 2`); for convenience, the character :math:`[s,s]` can also be
        represented by the integer :math:`s`.

        When :math:`a_p` is a :math:`p`-adic unit, :math:`L_p` takes its values in :math:`\mathbb{Q}_p`.
        When :math:`a_p` is not a unit, it takes its values in the
        two-dimensional :math:`\mathbb{Q}_p`-vector space :math:`D_{cris}(M(\phi))` where :math:`M(\phi)` is
        the "motive" attached to :math:`\phi`, and we return the two :math:`p`-adic components
        with respect to some fixed :math:`\mathbb{Q}_p`-basis.

        ::

        ? M = msinit(3,6,1); phi=[5, -3, -1]~;
        ? msissymbol(M,phi)
        %2 = 1
        ? Mp = mspadicinit(M, 5, 4);
        ? mu = mspadicmoments(Mp, phi); \\ no twist
        \\ End of initializations
        
        ? mspadicL(mu,0) \\ L_p(chi^0)
        %5 = 5 + 2*5^2 + 2*5^3 + 2*5^4 + ...
        ? mspadicL(mu,1) \\ L_p(chi), zero for parity reasons
        %6 = [O(5^13)]~
        ? mspadicL(mu,2) \\ L_p(chi^2)
        %7 = 3 + 4*5 + 4*5^2 + 3*5^5 + ...
        ? mspadicL(mu,[0,2]) \\ L_p(tau^2)
        %8 = 3 + 5 + 2*5^2 + 2*5^3 + ...
        ? mspadicL(mu, [1,0]) \\ L_p(<chi>)
        %9 = 3*5 + 2*5^2 + 5^3 + 2*5^7 + 5^8 + 5^10 + 2*5^11 + O(5^13)
        ? mspadicL(mu,0,1) \\ L_p'(chi^0)
        %10 = 2*5 + 4*5^2 + 3*5^3 + ...
        ? mspadicL(mu, 2, 1) \\ L_p'(chi^2)
        %11 = 4*5 + 3*5^2 + 5^3 + 5^4 + ...

        Now several quadratic twists: :literal:`mstooms` is indicated.

        ::

        ? PHI = mstooms(Mp,phi);
        ? mu = mspadicmoments(Mp, PHI, 12); \\ twist by 12
        ? mspadicL(mu)
        %14 = 5 + 5^2 + 5^3 + 2*5^4 + ...
        ? mu = mspadicmoments(Mp, PHI, 8); \\ twist by 8
        ? mspadicL(mu)
        %16 = 2 + 3*5 + 3*5^2 + 2*5^4 + ...
        ? mu = mspadicmoments(Mp, PHI, -3); \\ twist by -3 < 0
        ? mspadicL(mu)
        %18 = O(5^13) \\ always 0, phi is in the + part and D < 0

        One can locate interesting symbols of level :math:`N` and weight :math:`k` with
        :literal:`msnew` and :literal:`mssplit`. Note that instead of a symbol, one can
        input a 1-dimensional Hecke-subspace from :literal:`mssplit`: the function will
        automatically use the underlying basis vector.

        ::

        ? M=msinit(5,4,1); \\ M_4(Gamma_0(5))^+
        ? L = mssplit(M, msnew(M)); \\ list of irreducible Hecke-subspaces
        ? phi = L[1]; \\ one Galois orbit of newforms
        ? #phi[1] \\... this one is rational
        %4 = 1
        ? Mp = mspadicinit(M, 3, 4);
        ? mu = mspadicmoments(Mp, phi);
        ? mspadicL(mu)
        %7 = 1 + 3 + 3^3 + 3^4 + 2*3^5 + 3^6 + O(3^9)
        
        ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+
        ? Mp = mspadicinit(M, 3, 4);
        ? L = mssplit(M, msnew(M));
        ? phi = L[1]; #phi[1] \\ ... this one is two-dimensional
        %11 = 2
        ? mu = mspadicmoments(Mp, phi);
        *** at top-level: mu=mspadicmoments(Mp,ph
        *** ^--------------------
        *** mspadicmoments: incorrect type in mstooms [dim_Q (eigenspace) > 1]
        '''
        mu = objtogen(mu)
        cdef bint _have_s = (s is not None)
        if _have_s:
            s = objtogen(s)
        sig_on()
        cdef GEN _mu = (<Gen>mu).g
        cdef GEN _s = NULL
        if _have_s:
            _s = (<Gen>s).g
        cdef GEN _ret = mspadicL(_mu, _s, r)
        return new_gen(_ret)

    def mspadicinit(self, M, long p, long n, long flag=-1):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`, and :math:`p`
        a prime, initialize technical data needed to compute with overconvergent
        modular symbols, modulo :math:`p^n`. If :math:`flag` is unset, allow
        all symbols; else initialize only for a restricted range of symbols
        depending on :math:`flag`: if :math:`flag = 0` restrict to ordinary symbols, else
        restrict to symbols :math:`\phi` such that :math:`T_p(\phi) = a_p \phi`,
        with :math:`v_p(a_p) >= flag`, which is faster as :math:`flag` increases.
        (The fastest initialization is obtained for :math:`flag = 0` where we only allow
        ordinary symbols.) For supersingular eigensymbols, such that :math:`p \| a_p`, we
        must further assume that :math:`p` does not divide the level.

        ::

        ? E = ellinit("11a1");
        ? [M,phi] = msfromell(E,1);
        ? ellap(E,3)
        %3 = -1
        ? Mp = mspadicinit(M, 3, 10, 0); \\ commit to ordinary symbols
        ? PHI = mstooms(Mp,phi);

        If we restrict the range of allowed symbols with :emphasis:`flag` (for faster
        initialization), exceptions will occur if :math:`v_p(a_p)` violates this bound:

        ::

        ? E = ellinit("15a1");
        ? [M,phi] = msfromell(E,1);
        ? ellap(E,7)
        %3 = 0
        ? Mp = mspadicinit(M,7,5,0); \\ restrict to ordinary symbols
        ? PHI = mstooms(Mp,phi)
        *** at top-level: PHI=mstooms(Mp,phi)
        *** ^---------------
        *** mstooms: incorrect type in mstooms [v_p(ap) > mspadicinit flag] (t_VEC).
        ? Mp = mspadicinit(M,7,5); \\ no restriction
        ? PHI = mstooms(Mp,phi);

        This function uses :math:`O(N^2(n+k)^2p)` memory, where :math:`N` is the
        level of :math:`M`.
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = mspadicinit(_M, p, n, flag)
        return new_gen(_ret)

    def mspadicmoments(self, Mp, PHI, long D=1):
        r'''
        Given :literal:`Mp` from :literal:`mspadicinit`, an overconvergent
        eigensymbol :literal:`PHI` from :literal:`mstooms` and a fundamental discriminant
        :math:`D` coprime to :math:`p`,
        let :math:`PHI^D` denote the twisted symbol. This function computes
        the distribution :math:`\mu = PHI^D([0] - oo ]) \| \mathbb{Z}_p^*` restricted
        to :math:`\mathbb{Z}_p^*`. More precisely, it returns
        the moments of the :math:`p-1` distributions :math:`PHI^D([0]-[ oo ])
        | (a + p\mathbb{Z}_p)`, :math:`0 < a < p`.
        We also allow :literal:`PHI` to be given as a classical
        symbol, which is then lifted to an overconvergent symbol by :literal:`mstooms`;
        but this is wasteful if more than one twist is later needed.

        The returned data :math:`\mu` (:math:`p`-adic distributions attached to :literal:`PHI`)
        can then be used in :literal:`mspadicL` or :literal:`mspadicseries`.
        This precomputation allows to quickly compute derivatives of different
        orders or values at different characters.

        ::

        ? M = msinit(3,6, 1);
        ? phi = [5,-3,-1]~;
        ? msissymbol(M, phi)
        %3 = 1
        ? p = 5; mshecke(M,p) * phi \\ eigenvector of T_5, a_5 = 6
        %4 = [30, -18, -6]~
        ? Mp = mspadicinit(M, p, 10, 0); \\ restrict to ordinary symbols, mod p^10
        ? PHI = mstooms(Mp, phi);
        ? mu = mspadicmoments(Mp, PHI);
        ? mspadicL(mu)
        %8 = 5 + 2*5^2 + 2*5^3 + ...
        ? mu = mspadicmoments(Mp, PHI, 12); \\ twist by 12
        ? mspadicL(mu)
        %10 = 5 + 5^2 + 5^3 + 2*5^4 + ...
        '''
        Mp = objtogen(Mp)
        PHI = objtogen(PHI)
        sig_on()
        cdef GEN _Mp = (<Gen>Mp).g
        cdef GEN _PHI = (<Gen>PHI).g
        cdef GEN _ret = mspadicmoments(_Mp, _PHI, D)
        return new_gen(_ret)

    def mspadicseries(self, mu, long i=0):
        r'''
        Let :math:`\Phi` be the :math:`p`-adic distribution-valued overconvergent symbol
        attached to a modular symbol :math:`\phi` for :math:`\Gamma_0(N)` (eigenvector for
        :math:`T_N(p)` for the eigenvalue :math:`a_p`).
        If :math:`\mu` is the distribution on :math:`\mathbb{Z}_p^*` defined by the restriction of
        :math:`\Phi ([ oo ]-[0])` to :math:`\mathbb{Z}_p^*`, let

        .. MATH::

        ^{L}_p(\mu,\tau^{i})(x)
        = \int_{\mathbb{Z}_p^*} \tau^i(t) (1+x)^{\log_p(t)/\log_p(u)}d\mu (t)

        Here, :math:`\tau` is the Teichmüller character and :math:`u` is a specific
        multiplicative generator of :math:`1+2p\mathbb{Z}_p`. (Namely :math:`1+p` if :math:`p > 2` or :math:`5`
        if :math:`p = 2`.) To explain
        the formula, let :math:`G_ oo := Gal(\mathbb{Q} (\mu_{p^{ oo }})/ \mathbb{Q})`,
        let :math:`\chi:G_ oo \to \mathbb{Z}_p^*` be the cyclotomic character (isomorphism)
        and :math:`\gamma` the element of :math:`G_ oo` such that :math:`\chi (\gamma) = u`;
        then
        :math:`\chi (\gamma)^{\log_p(t)/\log_p(u)} = < t >`.

        The :math:`p`-padic precision of individual terms is maximal given the precision of
        the overconvergent symbol :math:`\mu`.

        ::

        ? [M,phi] = msfromell(ellinit("17a1"),1);
        ? Mp = mspadicinit(M, 5,7);
        ? mu = mspadicmoments(Mp, phi,1); \\ overconvergent symbol
        ? mspadicseries(mu)
        %4 = (4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + 4*5^6 + 3*5^7 + O(5^9)) \
        + (3 + 3*5 + 5^2 + 5^3 + 2*5^4 + 5^6 + O(5^7))*x \
        + (2 + 3*5 + 5^2 + 4*5^3 + 2*5^4 + O(5^5))*x^2 \
        + (3 + 4*5 + 4*5^2 + O(5^3))*x^3 \
        + (3 + O(5))*x^4 + O(x^5)

        An example with non-zero Teichmüller:

        ::

        ? [M,phi] = msfromell(ellinit("11a1"),1);
        ? Mp = mspadicinit(M, 3,10);
        ? mu = mspadicmoments(Mp, phi,1);
        ? mspadicseries(mu, 2)
        %4 = (2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + 3^7 + 3^10 + 3^11 + O(3^12)) \
        + (1 + 3 + 2*3^2 + 3^3 + 3^5 + 2*3^6 + 2*3^8 + O(3^9))*x \
        + (1 + 2*3 + 3^4 + 2*3^5 + O(3^6))*x^2 \
        + (3 + O(3^2))*x^3 + O(x^4)

        Supersingular example (not checked)

        ::

        ? E = ellinit("17a1"); ellap(E,3)
        %1 = 0
        ? [M,phi] = msfromell(E,1);
        ? Mp = mspadicinit(M, 3,7);
        ? mu = mspadicmoments(Mp, phi,1);
        ? mspadicseries(mu)
        %5 = [(2*3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 3^6 + O(3^7)) \
        + (2 + 3^3 + O(3^5))*x \
        + (1 + 2*3 + O(3^2))*x^2 + O(x^3),\
        (3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 3^6 + O(3^7)) \
        + (1 + 2*3 + 2*3^2 + 3^3 + 2*3^4 + O(3^5))*x \
        + (3^-2 + 3^-1 + O(3^2))*x^2 + O(3^-2)*x^3 + O(x^4)]

        Example with a twist:

        ::

        ? E = ellinit("11a1");
        ? [M,phi] = msfromell(E,1);
        ? Mp = mspadicinit(M, 3,10);
        ? mu = mspadicmoments(Mp, phi,5); \\ twist by 5
        ? L = mspadicseries(mu)
        %5 = (2*3^2 + 2*3^4 + 3^5 + 3^6 + 2*3^7 + 2*3^10 + O(3^12)) \
        + (2*3^2 + 2*3^6 + 3^7 + 3^8 + O(3^9))*x \
        + (3^3 + O(3^6))*x^2 + O(3^2)*x^3 + O(x^4)
        ? mspadicL(mu)
        %6 = [2*3^2 + 2*3^4 + 3^5 + 3^6 + 2*3^7 + 2*3^10 + O(3^12)]~
        ? ellpadicL(E,3,10,,5)
        %7 = 2 + 2*3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 2*3^7 + O(3^10)
        ? mspadicseries(mu,1) \\ must be 0
        %8 = O(3^12) + O(3^9)*x + O(3^6)*x^2 + O(3^2)*x^3 + O(x^4)
        '''
        mu = objtogen(mu)
        sig_on()
        cdef GEN _mu = (<Gen>mu).g
        cdef GEN _ret = mspadicseries(_mu, i)
        return new_gen(_ret)

    def mspathgens(self, M):
        r'''
        Let :math:`\Delta := Div^0(\mathbb{P}^1(\mathbb{Q}))`.
        Let :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        return a set of :math:`\mathbb{Z}[G]`-generators for :math:`\Delta`. The output
        is :math:`[g,R]`, where :math:`g` is a minimal system of generators and :math:`R`
        the vector of :math:`\mathbb{Z}[G]`-relations between the given generators. A
        relation is coded by a vector of pairs :math:`[a_i,i]` with :math:`a_i\in \mathbb{Z}[G]`
        and :math:`i` the index of a generator, so that :math:`\sum_i a_i g[i] = 0`.

        An element :math:`[v]-[u]` in :math:`\Delta` is coded by the "path" :math:`[u,v]`,
        where :literal:`oo` denotes the point at infinity :math:`(1:0)` on the projective
        line.
        An element of :math:`\mathbb{Z}[G]` is either an integer :math:`n` (:math:`= n [id_2]`) or a
        "factorization matrix": the first column contains distinct elements :math:`g_i`
        of :math:`G` and the second integers :math:`n_i` and the matrix codes :math:`\sum n_i [g_i]`:

        ::

        ? M = msinit(11,8); \\ M_8(Gamma_0(11))
        ? [g,R] = mspathgens(M);
        ? g
        %3 = [[+oo, 0], [0, 1/3], [1/3, 1/2]] \\ 3 paths
        ? #R \\ a single relation
        %4 = 1
        ? r = R[1]; #r \\ ...involving all 3 generators
        %5 = 3
        ? r[1]
        %6 = [[1, 1; [1, 1; 0, 1], -1], 1]
        ? r[2]
        %7 = [[1, 1; [7, -2; 11, -3], -1], 2]
        ? r[3]
        %8 = [[1, 1; [8, -3; 11, -4], -1], 3]

        The given relation is of the form :math:`\sum_i (1-\gamma_i) g_i = 0`, with
        :math:`\gamma_i\in \Gamma_0(11)`. There will always be a single relation involving
        all generators (corresponding to a round trip along all cusps), then
        relations involving a single generator (corresponding to :math:`2` and :math:`3`-torsion
        elements in the group:

        ::

        ? M = msinit(2,8); \\ M_8(Gamma_0(2))
        ? [g,R] = mspathgens(M);
        ? g
        %3 = [[+oo, 0], [0, 1]]

        Note that the output depends only on the group :math:`G`, not on the
        representation :math:`V`.
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = mspathgens(_M)
        return new_gen(_ret)

    def mspathlog(self, M, p):
        r'''
        Let :math:`\Delta := Div^0(\mathbb{P}^1(\mathbb{Q}))`.
        Let :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        encoding fixed :math:`\mathbb{Z}[G]`-generators :math:`(g_i)` of :math:`\Delta` (see :literal:`mspathgens`).
        A path :math:`p = [a,b]` between two elements in :math:`\mathbb{P}^1(\mathbb{Q})` corresponds to
        :math:`[b]-[a]\in \Delta`. The path extremities :math:`a` and :math:`b` may be given as
        :literal:`t_INT`, :literal:`t_FRAC` or :math:`oo = (1:0)`. Finally, we also allow
        to input a path as a :math:`2 x 2` integer matrix, whose first
        and second column give :math:`a` and :math:`b` respectively, with the convention
        :math:`[x,y]~ = (x:y)` in :math:`\mathbb{P}^1(\mathbb{Q})`.

        Returns :math:`(p_i)` in :math:`\mathbb{Z}[G]` such that :math:`p = \sum_i p_i g_i`.

        ::

        ? M = msinit(2,8); \\ M_8(Gamma_0(2))
        ? [g,R] = mspathgens(M);
        ? g
        %3 = [[+oo, 0], [0, 1]]
        ? p = mspathlog(M, [1/2,2/3]);
        ? p[1]
        %5 =
        [[1, 0; 2, 1] 1]
        
        ? p[2]
        %6 =
        [[1, 0; 0, 1] 1]
        
        [[3, -1; 4, -1] 1]
        ? mspathlog(M, [1,2;2,3]) == p \\ give path via a 2x2 matrix
        %7 = 1

        Note that the output depends only on the group :math:`G`, not on the
        representation :math:`V`.
        '''
        M = objtogen(M)
        p = objtogen(p)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = mspathlog(_M, _p)
        return new_gen(_ret)

    def mspetersson(self, M, F=None, G=None):
        r'''
        :math:`M` being a full modular symbol space for :math:`\Gamma = \Gamma_0(N)`,
        as given by :literal:`msinit`,
        calculate the intersection product :math:`{F, G}` of modular symbols :math:`F` and :math:`G`
        on :math:`M = \text{Hom}_{\Gamma}(\Delta, V_k)` extended to an hermitian bilinear
        form on :math:`M \otimes \mathbb{C}` whose radical is the Eisenstein subspace of :math:`M`.

        Suppose that :math:`f_1` and :math:`f_2` are two parabolic forms. Let :math:`F_1`
        and :math:`F_2` be the attached modular symbols

        .. MATH::

        F_i(\delta) = \int_{\delta} f_i(z).(z X + Y)^{k-2} dz

        and let :math:`F^{\mathbb{R}}_1`, :math:`F^{\mathbb{R}}_2` be the attached real modular symbols

        .. MATH::

        F^{\mathbb{R}}_i(\delta) = \int_{\delta}
        \Re (f_i(z).(z X + Y)^{k-2} dz)

        Then we have

        .. MATH::

        \{ F^{\mathbb{R}}_1, F^{\mathbb{R}}_2 } = -2 (2i)^{k-2}.
        \Im ( < f_1,f_2 > _{Petersson})

        and

        .. MATH::

        { F_1, \bar{F_2} } = (2i)^{k-2} < f_1,f_2 > _{Petersson}

        In weight 2, the intersection product :math:`{F, G}` has integer values on the
        :math:`\mathbb{Z}`-structure on :math:`M` given by :literal:`mslattice` and defines a Riemann form on
        :math:`H^1_{par}(\Gamma,\mathbb{R})`.

        For user convenience, we allow :math:`F` and :math:`G` to be matrices and return the
        attached Gram matrix. If :math:`F` is omitted: treat it as the full modular space
        attached to :math:`M`; if :math:`G` is omitted, take it equal to :math:`F`.

        ::

        ? M = msinit(37,2);
        ? C = mscuspidal(M)[1];
        ? mspetersson(M, C)
        %3 =
        [ 0 -17 -8 -17]
        [17 0 -8 -25]
        [ 8 8 0 -17]
        [17 25 17 0]
        ? mspetersson(M, mslattice(M,C))
        %4 =
        [0 -1 0 -1]
        [1 0 0 -1]
        [0 0 0 -1]
        [1 1 1 0]
        ? E = ellinit("33a1");
        ? [M,xpm] = msfromell(E); [xp,xm,L] = xpm;
        ? mspetersson(M, mslattice(M,L))
        %7 =
        [0 -3]
        [3 0]
        ? ellmoddegree(E)
        %8 = [3, -126]

        The coefficient :math:`3` in the matrix is the degree of the
        modular parametrization.
        '''
        M = objtogen(M)
        cdef bint _have_F = (F is not None)
        if _have_F:
            F = objtogen(F)
        cdef bint _have_G = (G is not None)
        if _have_G:
            G = objtogen(G)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _F = NULL
        if _have_F:
            _F = (<Gen>F).g
        cdef GEN _G = NULL
        if _have_G:
            _G = (<Gen>G).g
        cdef GEN _ret = mspetersson(_M, _F, _G)
        return new_gen(_ret)

    def mspolygon(self, M, long flag=0):
        r'''
        Given an integer :math:`N > 1`, return an hyperbolic polygon (Farey symbol)
        attached to the group :math:`\Gamma_0(N)`. More precisely,

        - its vertices are an ordered list in :math:`\mathbb{P}^{1}(\mathbb{Q})`, forming a system of
        representatives of cusps,

        - its edges are hyperbolic arcs joining two consecutive vertices,

        - given a path :math:`(a,b)` between two elements of :math:`\mathbb{P}^{1}(\mathbb{Q})`, let
        :math:`\overline{(a,b)} = (b,a)` be the opposite path. There is an involution :math:`e
        \to e^*` on the edges, where :math:`e^*` is :math:`\Gamma_0(N)` equivalent to
        :math:`\overline{e}`, i.e. there exist :math:`\gamma_e \in \Gamma_0(N)` such that :math:`e =
        \gamma_e \overline{e^*}`.

        The polygon is given by

        - the list :math:`E` of its consecutive edges as matrices in :math:`M_2(\mathbb{Z})`;

        - the permutation :math:`A` attached to the involution, such that
        :literal:`A[i]` is the index of :math:`e^*` in :math:`E` if :math:`e = E[i]` is the :math:`i`-th edge;

        - the list :math:`G` of pairing matrices between :math:`e` and
        :math:`\overline{e^*}`, i.e. the matrices :math:`\gamma_e\in \Gamma_0(N)` such that :math:`e =
        \gamma_e \overline{e^*}`. If :math:`e = E[i]`, then :math:`\gamma_e = G[i]`.
        Remark that :math:`\gamma_{e^*} = \gamma_e^{-1}` if :math:`e != e^*`; modulo these
        trivial relations, the pairing matrices form a system of independant
        generators of :math:`\Gamma_0(N)/{1,-1}`. Note that :math:`\gamma_e` is elliptic if and only if
        :math:`e^ *= e`.

        The above data yields a fundamental domain for :math:`\Gamma_0(N)` acting
        on Poincaré's half-plane: take the convex hull of the polygon defined by

        - the edges in :math:`E` such that :math:`e != e^*` or :math:`e^ *= e`, where the pairing
        matrix :math:`\gamma_e` has order :math:`2`;

        - the edges :math:`(r,t)` and :math:`(t,s)` where the edge :math:`e = (r,s) \in E` is such
        that :math:`e = e^*` and :math:`\gamma_e` has order :math:`3` and the triangle :math:`(r,t,s)`
        is the image of :math:`(0,\exp (2i\pi/3), oo )` by some element of :math:`PSL_2(\mathbb{Q})`
        formed around the edge.

        Binary digits of flag mean:

        1: return a normalized hyperbolic polygon if set, else a polygon with
        unimodular edges (matrices of determinant :math:`1`). A polygon is normalized
        in the sense of compact orientable surfaces if the distance :math:`d(a,a^*)` between
        an edge :math:`a` and its image by the involution :math:`a^*` is less than 2, with
        equality if and only if :math:`a` is :emphasis:`linked` with another edge :math:`b`
        (:math:`a`, :math:`b`, :math:`a^*` et :math:`b^*` appear consecutively in :math:`E` up to cyclic
        permutation). In particular, the vertices of all edges such that that
        :math:`d(a,a^*) != 1` (distance is 0 or 2) are all equivalent to :math:`0` modulo
        :math:`\Gamma_0(N)`. The external vertices of :math:`a a^*` such that :math:`d(a,a^*) = 1` are
        also equivalent to :math:`0`; the internal vertices :math:`a\cap a^*` (a single point),
        together with :math:`0`, form a system of representatives of the cusps of
        :math:`\Gamma_0(N)\\mathbb{P}^{1}(\mathbb{Q})`. This is useful to compute the homology group
        :math:`H_1(X_0(N),\mathbb{Z})` as it gives a symplectic basis for the intersection pairing.
        In this case, the number of parabolic matrices (trace 2) in the system of
        generators :math:`G` is :math:`2(t-1)`, where :math:`t` is the number of non equivalent cusps
        for :math:`\Gamma_0(N)`.

        2: add graphical representations (in LaTeX form) for the hyperbolic polygon
        in Poincaré's half-space and the involution :math:`a\to a^*` of the Farey symbol.
        The corresponding character strings can be written to file and included in a
        LaTeX document provided the preamble contains
        :literal:`\\usepackage{ tikz}`.

        ::

        ? [V,A,G] = mspolygon(3);
        ? V
        %2 = [[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 1]]
        ? A
        %3 = Vecsmall([2, 1, 3])
        ? G
        %4 = [[-1, -1; 0, -1], [1, -1; 0, 1], [1, -1; 3, -2]]
        ? [V,A,G, D1,D2] = mspolygon(11,2); \\ D1 and D2 contains pictures
        ? {write("F.tex",
        "\\documentclass{article}\\usepackage{tikz}\\begin{document}"
        D1, "\n",
        D2,
        "\\end{document}");}
        
        ? [V1,A1] = mspolygon(6,1); \\ normalized
        ? V1
        %8 = [[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 3],
        [1, -2; 3, -5], [-2, 1; -5, 2], [1, -1; 2, -1]]
        ? A1
        %9 = Vecsmall([2, 1, 4, 3, 6, 5])
        
        ? [V0,A0] = mspolygon(6); \\ not normalized V[3]^* = V[6], d(V[3],V[6]) = 3
        ? A0
        %11 = Vecsmall([2, 1, 6, 5, 4, 3])
        
        ? [V,A] = mspolygon(14, 1);
        ? A
        %13 = Vecsmall([2, 1, 4, 3, 6, 5, 9, 10, 7, 8])

        One can see from this last example that the (normalized) polygon has the form

        .. MATH::

        (a_1, a_1^*, a_2, a_2^*, a_3, a_3^*, a_4, a_5, a_4^*, a_5^*),

        that :math:`X_0(14)` is of genus 1 (in general the genus is the number of blocks
        of the form :math:`aba^*b^*`), has no elliptic points (:math:`A` has no fixed point)
        and 4 cusps (number of blocks of the form :math:`aa^*` plus 1). The vertices
        of edges :math:`a_4` and :math:`a_5` all project to :math:`0` in :math:`X_0(14)`: the paths :math:`a_4`
        and :math:`a_5` project as loops in :math:`X_0(14)` and give a symplectic basis of the
        homology :math:`H_1(X_0(14),\mathbb{Z})`.

        ::

        ? [V,A] = mspolygon(15);
        ? apply(matdet, V) \\ all unimodular
        %2 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        ? [V,A] = mspolygon(15,1);
        ? apply(matdet, V) \\ normalized polygon but no longer unimodular edges
        %4 = [1, 1, 1, 1, 2, 2, 47, 11, 47, 11]
        '''
        M = objtogen(M)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = mspolygon(_M, flag)
        return new_gen(_ret)

    def msqexpansion(self, M, projH, long serprec=-1):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        and :emphasis:`projH` being a projector on a Hecke-simple subspace (as given
        by :literal:`mssplit`), return the Fourier coefficients :math:`a_n`, :math:`n <= B` of the
        corresponding normalized newform. If :math:`B` is omitted, use
        :literal:`seriesprecision`.

        This function uses a naive :math:`O(B^2 d^3)`
        algorithm, where :math:`d = O(kN)` is the dimension of :math:`M_k(\Gamma_0(N))`.

        ::

        ? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+
        ? L = mssplit(M, msnew(M));
        ? msqexpansion(M,L[1], 20)
        %3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2]
        ? ellan(ellinit("11a1"), 20)
        %4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2]

        The shortcut :literal:`msqexpansion(M, s, B)` is available for
        a symbol :math:`s`, provided it is a Hecke eigenvector:

        ::

        ? E = ellinit("11a1");
        ? [M,S] = msfromell(E); [sp,sm] = S;
        ? msqexpansion(M,sp,10) \\ in the + eigenspace
        %3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2]
        ? msqexpansion(M,sm,10) \\ in the - eigenspace
        %4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2]
        ? ellan(E, 10)
        %5 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2]
        '''
        M = objtogen(M)
        projH = objtogen(projH)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _projH = (<Gen>projH).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = msqexpansion(_M, _projH, serprec)
        return new_gen(_ret)

    def mssplit(self, M, H=None, long dimlim=0):
        r'''
        Let :math:`M` denote a full modular symbol space, as given by :literal:`msinit`:math:`(N,k,1)`
        or :math:`msinit (N,k,-1)` and let :math:`H` be a Hecke-stable subspace of
        :literal:`msnew`:math:`(M)` (the full new subspace if :math:`H` is omitted). This function
        splits :math:`H` into Hecke-simple subspaces. If :literal:`dimlim` is present and
        positive, restrict to subspaces of dimension :math:`<= dimlim`. A subspace
        is given by a structure allowing quick projection and restriction of linear
        operators; its first component is a matrix with integer coefficients whose
        columns form a :math:`\mathbb{Q}`-basis of the subspace.

        ::

        ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+
        ? L = mssplit(M); \\ split msnew(M)
        ? #L
        %3 = 2
        ? f = msqexpansion(M,L[1],5); f[1].mod
        %4 = x^2 + 8*x - 44
        ? lift(f)
        %5 = [1, x, -6*x - 27, -8*x - 84, 20*x - 155]
        ? g = msqexpansion(M,L[2],5); g[1].mod
        %6 = x^4 - 558*x^2 + 140*x + 51744

        To a Hecke-simple subspace corresponds an orbit of
        (normalized) newforms, defined over a number field. In the above example,
        we printed the polynomials defining the said fields, as well as the first
        5 Fourier coefficients (at the infinite cusp) of one such form.
        '''
        M = objtogen(M)
        cdef bint _have_H = (H is not None)
        if _have_H:
            H = objtogen(H)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _H = NULL
        if _have_H:
            _H = (<Gen>H).g
        cdef GEN _ret = mssplit(_M, _H, dimlim)
        return new_gen(_ret)

    def msstar(self, M, H=None):
        r'''
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        return the matrix of the :literal:`*` involution, induced by complex conjugation,
        acting on the (stable) subspace :math:`H` (:math:`M` if omitted).

        ::

        ? M = msinit(11,2); \\ M_2(Gamma_0(11))
        ? w = msstar(M);
        ? w^2 == 1
        %3 = 1
        '''
        M = objtogen(M)
        cdef bint _have_H = (H is not None)
        if _have_H:
            H = objtogen(H)
        sig_on()
        cdef GEN _M = (<Gen>M).g
        cdef GEN _H = NULL
        if _have_H:
            _H = (<Gen>H).g
        cdef GEN _ret = msstar(_M, _H)
        return new_gen(_ret)

    def mstooms(self, Mp, phi):
        r'''
        Given :literal:`Mp` from :literal:`mspadicinit`, lift the (classical) eigen symbol
        :literal:`phi` to a :math:`p`-adic distribution-valued overconvergent symbol in the
        sense of Pollack and Stevens. More precisely, let :math:`\phi` belong to the space
        :math:`W` of modular symbols of level :math:`N`, :math:`v_p(N) <= 1`, and weight :math:`k` which is
        an eigenvector for the Hecke operator :math:`T_N(p)` for a non-zero eigenvalue
        :math:`a_p` and let :math:`N_0 = lcm(N,p)`.

        Under the action of :math:`T_{N_0}(p)`, :math:`\phi` generates a subspace :math:`W_\phi` of
        dimension :math:`1` (if :math:`p \| N`) or :math:`2` (if :math:`p` does not divide :math:`N`) in the
        space of modular symbols of level :math:`N_0`.

        Let :math:`V_p = [p,0;0,1]` and :math:`C_p = [a_p,p^{k-1};-1,0]`.
        When :math:`p` does not divide :math:`N` and :math:`a_p` is divisible by :math:`p`, :literal:`mstooms`
        returns the lift :math:`\Phi` of :math:`(\phi,\phi\|_k V_p)` such that

        .. MATH::

        T_{N_0}(p) \Phi = C_p \Phi

        When :math:`p` does not divide :math:`N` and :math:`a_p` is not divisible by :math:`p`, :literal:`mstooms`
        returns the lift :math:`\Phi` of :math:`\phi - \alpha^{-1} \phi\|_k V_p`
        which is an eigenvector of :math:`T_{N_0}(p)` for the unit eigenvalue
        where :math:`\alpha^2 - a_p \alpha + p^{k-1} = 0`.

        The resulting overconvergent eigensymbol can then be used in
        :literal:`mspadicmoments`, then :literal:`mspadicL` or :literal:`mspadicseries`.

        ::

        ? M = msinit(3,6, 1); p = 5;
        ? Tp = mshecke(M, p); factor(charpoly(Tp))
        %2 =
        [x - 3126 2]
        
        [ x - 6 1]
        ? phi = matker(Tp - 6)[,1] \\ generator of p-Eigenspace, a_p = 6
        %3 = [5, -3, -1]~
        ? Mp = mspadicinit(M, p, 10, 0); \\ restrict to ordinary symbols, mod p^10
        ? PHI = mstooms(Mp, phi);
        ? mu = mspadicmoments(Mp, PHI);
        ? mspadicL(mu)
        %7 = 5 + 2*5^2 + 2*5^3 + ...

        A non ordinary symbol.

        ::

        ? M = msinit(4,6,1); p = 3;
        ? Tp = mshecke(M, p); factor(charpoly(Tp))
        %2 =
        [x - 244 3]
        
        [ x + 12 1]
        ? phi = matker(Tp + 12)[,1] \\ a_p = -12 is divisible by p = 3
        %3 = [-1/32, -1/4, -1/32, 1]~
        ? msissymbol(M,phi)
        %4 = 1
        ? Mp = mspadicinit(M,3,5,0);
        ? PHI = mstooms(Mp,phi);
        *** at top-level: PHI=mstooms(Mp,phi)
        *** ^---------------
        *** mstooms: incorrect type in mstooms [v_p(ap) > mspadicinit flag] (t_VEC).
        ? Mp = mspadicinit(M,3,5,1);
        ? PHI = mstooms(Mp,phi);
        '''
        Mp = objtogen(Mp)
        phi = objtogen(phi)
        sig_on()
        cdef GEN _Mp = (<Gen>Mp).g
        cdef GEN _phi = (<Gen>phi).g
        cdef GEN _ret = mstooms(_Mp, _phi)
        return new_gen(_ret)

    def newtonpoly(self, x, p):
        r'''
        Gives the vector of the slopes of the Newton
        polygon of the polynomial :math:`x` with respect to the prime number :math:`p`. The :math:`n`
        components of the vector are in decreasing order, where :math:`n` is equal to the
        degree of :math:`x`. Vertical slopes occur iff the constant coefficient of :math:`x` is
        zero and are denoted by :literal:`+oo`.
        '''
        x = objtogen(x)
        p = objtogen(p)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = newtonpoly(_x, _p)
        return new_gen(_ret)

    def nextprime(self, x):
        r'''
        Finds the smallest pseudoprime (see
        :literal:`ispseudoprime`) greater than or equal to :math:`x`. :math:`x` can be of any real
        type. Note that if :math:`x` is a pseudoprime, this function returns :math:`x` and not
        the smallest pseudoprime strictly larger than :math:`x`. To rigorously prove that
        the result is prime, use :literal:`isprime`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = nextprime(_x)
        return new_gen(_ret)

    def nfalgtobasis(self, nf, x):
        r'''
        Given an algebraic number :math:`x` in the number field :math:`nf`,
        transforms it to a column vector on the integral basis :literal:`:emphasis:`nf`.zk`.

        ::

        ? nf = nfinit(y^2 + 4);
        ? nf.zk
        %2 = [1, 1/2*y]
        ? nfalgtobasis(nf, [1,1]~)
        %3 = [1, 1]~
        ? nfalgtobasis(nf, y)
        %4 = [0, 2]~
        ? nfalgtobasis(nf, Mod(y, y^2+4))
        %5 = [0, 2]~

        This is the inverse function of :literal:`nfbasistoalg`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = algtobasis(_nf, _x)
        return new_gen(_ret)

    def nfbasis(self, T):
        r'''
        Let :math:`T(X)` be an irreducible polynomial with integral coefficients. This
        function returns an integral basis of the number field defined by :math:`T`,
        that is a :math:`\mathbb{Z}`-basis of its maximal order. The basis elements are given as
        elements in :math:`\mathbb{Q}[X]/(T)`:

        ::

        ? nfbasis(x^2 + 1)
        %1 = [1, x]

        This function uses a modified version of the round 4 algorithm,
        due to David Ford, Sebastian Pauli and Xavier Roblot.

        :strong:`Local basis, orders maximal at certain primes.`

        Obtaining the maximal order is hard: it requires factoring the discriminant
        :math:`D` of :math:`T`. Obtaining an order which is maximal at a finite explicit set of
        primes is easy, but it may then be a strict suborder of the maximal order. To
        specify that we are interested in a given set of places only, we can replace
        the argument :math:`T` by an argument :math:`[T,listP]`, where :emphasis:`listP` encodes
        the primes we are interested in: it must be a factorization matrix, a vector
        of integers or a single integer.

        - Vector: we assume that it contains distinct :emphasis:`prime` numbers.

        - Matrix: we assume that it is a two-column matrix of a
        (partial) factorization of :math:`D`; namely the first column contains
        distinct :emphasis:`primes` and the second one the valuation of :math:`D` at each of
        these primes.

        - Integer :math:`B`: this is replaced by the vector of primes up to :math:`B`. Note
        that the function will use at least :math:`O(B)` time: a small value, about
        :math:`10^5`, should be enough for most applications. Values larger than :math:`2^{32}`
        are not supported.

        In all these cases, the primes may or may not divide the discriminant :math:`D`
        of :math:`T`. The function then returns a :math:`\mathbb{Z}`-basis of an order whose index is
        not divisible by any of these prime numbers. The result is actually a global
        integral basis if all prime divisors of the :emphasis:`field` discriminant are
        included! Note that :literal:`nfinit` has built-in support for such
        a check:

        ::

        ? K = nfinit([T, listP]);
        ? nfcertify(K) \\ we computed an actual maximal order
        %2 = [];

        The first line initializes a number field structure
        incorporating :literal:`nfbasis([T, listP]` in place of a proven integral basis.
        The second line certifies that the resulting structure is correct. This
        allows to create an :literal:`nf` structure attached to the number field :math:`K =
        \mathbb{Q}[X]/(T)`, when the discriminant of :math:`T` cannot be factored completely,
        whereas the prime divisors of :math:`\mathrm{disc} K` are known.

        Of course, if :emphasis:`listP` contains a single prime number :math:`p`,
        the function returns a local integral basis for :math:`\mathbb{Z}_p[X]/(T)`:

        ::

        ? nfbasis(x^2+x-1001)
        %1 = [1, 1/3*x - 1/3]
        ? nfbasis( [x^2+x-1001, [2]] )
        %2 = [1, x]

        :strong:`The Buchmann-Lenstra algorithm.`

        We now complicate the picture: it is in fact allowed to include
        :emphasis:`composite` numbers instead of primes
        in :literal:`listP` (Vector or Matrix case), provided they are pairwise coprime.
        The result will still be a correct integral basis :emphasis:`if`
        the field discriminant factors completely over the actual primes in the list.
        Adding a composite :math:`C` such that :math:`C^2` :emphasis:`divides` :math:`D` may help because
        when we consider :math:`C` as a prime and run the algorithm, two good things can
        happen: either we
        succeed in proving that no prime dividing :math:`C` can divide the index
        (without actually needing to find those primes), or the computation
        exhibits a non-trivial zero divisor, thereby factoring :math:`C` and
        we go on with the refined factorization. (Note that including a :math:`C`
        such that :math:`C^2` does not divide :math:`D` is useless.) If neither happen, then the
        computed basis need not generate the maximal order. Here is an example:

        ::

        ? B = 10^5;
        ? P = factor(poldisc(T), B)[,1]; \\ primes <= B dividing D + cofactor
        ? basis = nfbasis([T, listP])
        ? disc = nfdisc([T, listP])

        We obtain the maximal order and its discriminant if the
        field discriminant factors
        completely over the primes less than :math:`B` (together with the primes
        contained in the :literal:`addprimes` table). This can be tested as follows:

        ::

        check = factor(disc, B);
        lastp = check[-1..-1,1];
        if (lastp > B && !setsearch(addprimes(), lastp),
        warning("nf may be incorrect!"))

        This is a sufficient but not a necessary condition, hence the warning,
        instead of an error. N.B. :literal:`lastp` is the last entry
        in the first column of the :literal:`check` matrix, i.e. the largest prime
        dividing :literal:`nf.disc` if :math:`<= B` or if it belongs to the prime table.

        The function :literal:`nfcertify` speeds up and automates the above process:

        ::

        ? B = 10^5;
        ? nf = nfinit([T, B]);
        ? nfcertify(nf)
        %3 = [] \\ nf is unconditionally correct
        ? basis = nf.zk;
        ? disc = nf.disc;
        '''
        T = objtogen(T)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = nfbasis_gp(_T)
        return new_gen(_ret)

    def nfbasistoalg(self, nf, x):
        r'''
        Given an algebraic number :math:`x` in the number field :emphasis:`nf`, transforms it
        into :literal:`t_POLMOD` form.

        ::

        ? nf = nfinit(y^2 + 4);
        ? nf.zk
        %2 = [1, 1/2*y]
        ? nfbasistoalg(nf, [1,1]~)
        %3 = Mod(1/2*y + 1, y^2 + 4)
        ? nfbasistoalg(nf, y)
        %4 = Mod(y, y^2 + 4)
        ? nfbasistoalg(nf, Mod(y, y^2+4))
        %5 = Mod(y, y^2 + 4)

        This is the inverse function of :literal:`nfalgtobasis`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = basistoalg(_nf, _x)
        return new_gen(_ret)

    def nfcertify(self, nf):
        r'''
        :math:`nf` being as output by
        :literal:`nfinit`, checks whether the integer basis is known unconditionally.
        This is in particular useful when the argument to :literal:`nfinit` was of the
        form :math:`[T, listP]`, specifying a finite list of primes when
        :math:`p`-maximality had to be proven, or a list of coprime integers to which
        Buchmann-Lenstra algorithm was to be applied.

        The function returns a vector of coprime composite integers. If this vector
        is empty, then :literal:`nf.zk` and :literal:`nf.disc` are correct. Otherwise, the
        result is dubious. In order to obtain a certified result, one must completely
        factor each of the given integers, then :literal:`addprime` each of their prime
        factors, then check whether :literal:`nfdisc(nf.pol)` is equal to :literal:`nf.disc`.
        '''
        nf = objtogen(nf)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _ret = nfcertify(_nf)
        return new_gen(_ret)

    def nfcompositum(self, nf, P, Q, long flag=0):
        r'''
        Let :emphasis:`nf` be a number field structure attached to the field :math:`K`
        and let :math:`P` and :math:`Q`
        be squarefree polynomials in :math:`K[X]` in the same variable. Outputs
        the simple factors of the étale :math:`K`-algebra :math:`A = K[X, Y] / (P(X), Q(Y))`.
        The factors are given by a list of polynomials :math:`R` in :math:`K[X]`, attached to
        the number field :math:`K[X]/ (R)`, and sorted by increasing degree (with respect
        to lexicographic ordering for factors of equal degrees). Returns an error if
        one of the polynomials is not squarefree.

        Note that it is more efficient to reduce to the case where :math:`P` and :math:`Q` are
        irreducible first. The routine will not perform this for you, since it may be
        expensive, and the inputs are irreducible in most applications anyway. In
        this case, there will be a single factor :math:`R` if and only if the number
        fields defined by :math:`P` and :math:`Q` are linearly disjoint (their intersection is
        :math:`K`).

        The binary digits of :math:`flag` mean

        1: outputs a vector of 4-component vectors :math:`[R,a,b,k]`, where :math:`R`
        ranges through the list of all possible compositums as above, and :math:`a`
        (resp. :math:`b`) expresses the root of :math:`P` (resp. :math:`Q`) as an element of
        :math:`K[X]/(R)`. Finally, :math:`k` is a small integer such that :math:`b + ka = X` modulo
        :math:`R`.

        2: assume that :math:`P` and :math:`Q` define number fields that are linearly disjoint:
        both polynomials are irreducible and the corresponding number fields
        have no common subfield besides :math:`K`. This allows to save a costly
        factorization over :math:`K`. In this case return the single simple factor
        instead of a vector with one element.

        A compositum is often defined by a complicated polynomial, which it is
        advisable to reduce before further work. Here is an example involving
        the field :math:`K(\zeta_5, 5^{1/10})`, :math:`K = \mathbb{Q} (\sqrt{5})`:

        ::

        ? K = nfinit(y^2-5);
        ? L = nfcompositum(K, x^5 - y, polcyclo(5), 1); \\ list of [R,a,b,k]
        ? [R, a] = L[1]; \\ pick the single factor, extract R,a (ignore b,k)
        ? lift(R) \\ defines the compositum
        %4 = x^10 + (-5/2*y + 5/2)*x^9 + (-5*y + 20)*x^8 + (-20*y + 30)*x^7 + \
        (-45/2*y + 145/2)*x^6 + (-71/2*y + 121/2)*x^5 + (-20*y + 60)*x^4 + \
        (-25*y + 5)*x^3 + 45*x^2 + (-5*y + 15)*x + (-2*y + 6)
        ? a^5 - y \\ a fifth root of y
        %5 = 0
        ? [T, X] = rnfpolredbest(K, R, 1);
        ? lift(T) \\ simpler defining polynomial for K[x]/(R)
        %7 = x^10 + (-11/2*y + 25/2)
        ? liftall(X) \\  root of R in K[x]/(T(x))
        %8 = (3/4*y + 7/4)*x^7 + (-1/2*y - 1)*x^5 + 1/2*x^2 + (1/4*y - 1/4)
        ? a = subst(a.pol, 'x, X); \\ a in the new coordinates
        ? liftall(a)
        %10 = (-3/4*y - 7/4)*x^7 - 1/2*x^2
        ? a^5 - y
        %11 = 0

        The main variables of :math:`P` and :math:`Q` must be the same and have higher priority
        than that of :emphasis:`nf` (see :literal:`varhigher` and :literal:`varlower`).
        '''
        nf = objtogen(nf)
        P = objtogen(P)
        Q = objtogen(Q)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _ret = nfcompositum(_nf, _P, _Q, flag)
        return new_gen(_ret)

    def nfdetint(self, nf, x):
        r'''
        Given a pseudo-matrix :math:`x`, computes a
        non-zero ideal contained in (i.e. multiple of) the determinant of :math:`x`. This
        is particularly useful in conjunction with :literal:`nfhnfmod`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = nfdetint(_nf, _x)
        return new_gen(_ret)

    def nfdisc(self, T):
        r'''
        field discriminant of the number field defined by the integral,
        preferably monic, irreducible polynomial :math:`T(X)`. Returns the discriminant of
        the number field :math:`\mathbb{Q}[X]/(T)`, using the Round :math:`4` algorithm.

        :strong:`Local discriminants, valuations at certain primes.`

        As in :literal:`nfbasis`, the argument :math:`T` can be replaced by :math:`[T,listP]`,
        where :literal:`listP` is as in :literal:`nfbasis`: a vector of
        pairwise coprime integers (usually distinct primes), a factorization matrix,
        or a single integer. In that case, the function returns the discriminant of
        an order whose basis is given by :literal:`nfbasis(T,listP)`, which need not be
        the maximal order, and whose valuation at a prime entry in :literal:`listP` is the
        same as the valuation of the field discriminant.

        In particular, if :literal:`listP` is :math:`[p]` for a prime :math:`p`, we can
        return the :math:`p`-adic discriminant of the maximal order of :math:`\mathbb{Z}_p[X]/(T)`,
        as a power of :math:`p`, as follows:

        ::

        ? padicdisc(T,p) = p^valuation(nfdisc([T,[p]]), p);
        ? nfdisc(x^2 + 6)
        %2 = -24
        ? padicdisc(x^2 + 6, 2)
        %3 = 8
        ? padicdisc(x^2 + 6, 3)
        %4 = 3

        The following function computes the discriminant of the
        maximal order under the assumption that :math:`P` is a vector of prime numbers
        containing (at least) all prime divisors of the field discriminant:

        ::

        globaldisc(T, P) =
        { my (D = nfdisc([T, P]));
        sign(D) * factorback(P, [valuation(D,p) | p <-P]);
        }
        ? globaldisc(x^2 + 6, [2, 3, 5])
        %1 = -24
        '''
        T = objtogen(T)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = nfdisc(_T)
        return new_gen(_ret)

    def nfeltadd(self, nf, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in
        :emphasis:`nf`, computes their sum :math:`x+y` in the number field :math:`nf`.

        ::

        ? nf = nfinit(1+x^2);
        ? nfeltadd(nf, 1, x) \\ 1 + I
        %2 = [1, 1]~
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = nfadd(_nf, _x, _y)
        return new_gen(_ret)

    def nfeltdiv(self, nf, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in
        :emphasis:`nf`, computes their quotient :math:`x/y` in the number field :math:`nf`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = nfdiv(_nf, _x, _y)
        return new_gen(_ret)

    def nfeltdiveuc(self, nf, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in
        :emphasis:`nf`, computes an algebraic integer :math:`q` in the number field :math:`nf`
        such that the components of :math:`x-qy` are reasonably small. In fact, this is
        functionally identical to :literal:`round(nfdiv(:emphasis:`nf`,x,y))`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = nfdiveuc(_nf, _x, _y)
        return new_gen(_ret)

    def nfeltdivmodpr(self, nf, x, y, pr):
        r'''
        This function is obsolete, use :literal:`nfmodpr`.

        Given two elements :math:`x`
        and :math:`y` in :emphasis:`nf` and :emphasis:`pr` a prime ideal in :literal:`modpr` format (see
        :literal:`nfmodprinit`), computes their quotient :math:`x / y` modulo the prime ideal
        :emphasis:`pr`.
        '''
        from warnings import warn
        warn('the PARI/GP function nfeltdivmodpr is obsolete (2016-08-09)', DeprecationWarning)
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = nfdivmodpr(_nf, _x, _y, _pr)
        return new_gen(_ret)

    def nfeltdivrem(self, nf, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in
        :emphasis:`nf`, gives a two-element row vector :math:`[q,r]` such that :math:`x = qy+r`, :math:`q` is
        an algebraic integer in :math:`nf`, and the components of :math:`r` are
        reasonably small.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = nfdivrem(_nf, _x, _y)
        return new_gen(_ret)

    def nfeltembed(self, nf, x, pl=None, long precision=DEFAULT_BITPREC):
        r'''
        Given an element :math:`x` in the number field :emphasis:`nf`, return
        the (real or) complex embeddings of :math:`x` specified by optional argument
        :emphasis:`pl`, at the current :literal:`realprecision`:

        - :emphasis:`pl` omitted: return the vector of embeddings at all :math:`r_1+r_2`
        places;

        - :emphasis:`pl` an integer between :math:`1` and :math:`r_1+r_2`: return the
        :math:`i`-th embedding of :math:`x`, attached to the :math:`i`-th root of :literal:`nf.pol`,
        i.e. :literal:`nf.roots:math:`[i]``;

        - :emphasis:`pl` a vector or :literal:`t_VECSMALL`: return the vector of embeddings; the :math:`i`-th
        entry gives the embedding at the place attached to the :math:`pl[i]`-th real
        root of :literal:`nf.pol`.

        ::

        ? nf = nfinit('y^3 - 2);
        ? nf.sign
        %2 = [1, 1]
        ? nfeltembed(nf, 'y)
        %3 = [1.25992[...], -0.62996[...] + 1.09112[...]*I]]
        ? nfeltembed(nf, 'y, 1)
        %4 = 1.25992[...]
        ? nfeltembed(nf, 'y, 3) \\ there are only 2 arch. places
        *** at top-level: nfeltembed(nf,'y,3)
        *** ^-----------------
        *** nfeltembed: domain error in nfeltembed: index > 2
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        cdef bint _have_pl = (pl is not None)
        if _have_pl:
            pl = objtogen(pl)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _pl = NULL
        if _have_pl:
            _pl = (<Gen>pl).g
        precision = nbits2prec(precision)
        cdef GEN _ret = nfeltembed(_nf, _x, _pl, precision)
        return new_gen(_ret)

    def nfeltmod(self, nf, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in
        :emphasis:`nf`, computes an element :math:`r` of :math:`nf` of the form :math:`r = x-qy` with
        :math:`q` and algebraic integer, and such that :math:`r` is small. This is functionally
        identical to

        .. MATH::

        x - nfmul(nf,round(nfdiv(nf,x,y)),y).
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = nfmod(_nf, _x, _y)
        return new_gen(_ret)

    def nfeltmul(self, nf, x, y):
        r'''
        Given two elements :math:`x` and :math:`y` in
        :emphasis:`nf`, computes their product :math:`x*y` in the number field :math:`nf`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = nfmul(_nf, _x, _y)
        return new_gen(_ret)

    def nfeltmulmodpr(self, nf, x, y, pr):
        r'''
        This function is obsolete, use :literal:`nfmodpr`.

        Given two elements :math:`x` and
        :math:`y` in :emphasis:`nf` and :emphasis:`pr` a prime ideal in :literal:`modpr` format (see
        :literal:`nfmodprinit`), computes their product :math:`x*y` modulo the prime ideal
        :emphasis:`pr`.
        '''
        from warnings import warn
        warn('the PARI/GP function nfeltmulmodpr is obsolete (2016-08-09)', DeprecationWarning)
        nf = objtogen(nf)
        x = objtogen(x)
        y = objtogen(y)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = nfmulmodpr(_nf, _x, _y, _pr)
        return new_gen(_ret)

    def nfeltnorm(self, nf, x):
        r'''
        Returns the absolute norm of :math:`x`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = nfnorm(_nf, _x)
        return new_gen(_ret)

    def nfeltpow(self, nf, x, k):
        r'''
        Given an element :math:`x` in :emphasis:`nf`, and a positive or negative integer :math:`k`,
        computes :math:`x^k` in the number field :math:`nf`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        k = objtogen(k)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _k = (<Gen>k).g
        cdef GEN _ret = nfpow(_nf, _x, _k)
        return new_gen(_ret)

    def nfeltpowmodpr(self, nf, x, k, pr):
        r'''
        This function is obsolete, use :literal:`nfmodpr`.

        Given an element :math:`x` in :emphasis:`nf`, an integer :math:`k` and a prime ideal
        :emphasis:`pr` in :literal:`modpr` format
        (see :literal:`nfmodprinit`), computes :math:`x^k` modulo the prime ideal :emphasis:`pr`.
        '''
        from warnings import warn
        warn('the PARI/GP function nfeltpowmodpr is obsolete (2016-08-09)', DeprecationWarning)
        nf = objtogen(nf)
        x = objtogen(x)
        k = objtogen(k)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _k = (<Gen>k).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = nfpowmodpr(_nf, _x, _k, _pr)
        return new_gen(_ret)

    def nfeltreduce(self, nf, a, id):
        r'''
        Given an ideal :emphasis:`id` in
        Hermite normal form and an element :math:`a` of the number field :math:`nf`,
        finds an element :math:`r` in :math:`nf` such that :math:`a-r` belongs to the ideal
        and :math:`r` is small.
        '''
        nf = objtogen(nf)
        a = objtogen(a)
        id = objtogen(id)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _id = (<Gen>id).g
        cdef GEN _ret = nfreduce(_nf, _a, _id)
        return new_gen(_ret)

    def nfeltreducemodpr(self, nf, x, pr):
        r'''
        This function is obsolete, use :literal:`nfmodpr`.

        Given an element :math:`x` of the number field :math:`nf` and a prime ideal
        :emphasis:`pr` in :literal:`modpr` format compute a canonical representative for the
        class of :math:`x` modulo :emphasis:`pr`.
        '''
        from warnings import warn
        warn('the PARI/GP function nfeltreducemodpr is obsolete (2016-08-09)', DeprecationWarning)
        nf = objtogen(nf)
        x = objtogen(x)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = nfreducemodpr(_nf, _x, _pr)
        return new_gen(_ret)

    def nfeltsign(self, nf, x, pl=None):
        r'''
        Given an element :math:`x` in the number field :emphasis:`nf`, returns the signs of
        the real embeddings of :math:`x` specified by optional argument :emphasis:`pl`:

        - :emphasis:`pl` omitted: return the vector of signs at all :math:`r_1` real places;

        - :emphasis:`pl` an integer between :math:`1` and :math:`r_1`: return the sign of the
        :math:`i`-th embedding of :math:`x`, attached to the :math:`i`-th real root of :literal:`nf.pol`,
        i.e. :literal:`nf.roots:math:`[i]``;

        - :emphasis:`pl` a vector or :literal:`t_VECSMALL`: return the vector of signs; the :math:`i`-th
        entry gives the sign at the real place attached to the :math:`pl[i]`-th real
        root of :literal:`nf.pol`.

        ::

        ? nf = nfinit(polsubcyclo(11,5,'y)); \\ Q(cos(2 pi/11))
        ? nf.sign
        %2 = [5, 0]
        ? x = Mod('y, nf.pol);
        ? nfeltsign(nf, x)
        %4 = [-1, -1, -1, 1, 1]
        ? nfeltsign(nf, x, 1)
        %5 = -1
        ? nfeltsign(nf, x, [1..4])
        %6 = [-1, -1, -1, 1]
        ? nfeltsign(nf, x, 6) \\ there are only 5 real embeddings
        *** at top-level: nfeltsign(nf,x,6)
        *** ^-----------------
        *** nfeltsign: domain error in nfeltsign: index > 5
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        cdef bint _have_pl = (pl is not None)
        if _have_pl:
            pl = objtogen(pl)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _pl = NULL
        if _have_pl:
            _pl = (<Gen>pl).g
        cdef GEN _ret = nfeltsign(_nf, _x, _pl)
        return new_gen(_ret)

    def nfelttrace(self, nf, x):
        r'''
        Returns the absolute trace of :math:`x`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = nftrace(_nf, _x)
        return new_gen(_ret)

    def nfeltval(self, nf, x, pr, y=None):
        r'''
        Given an element :math:`x` in
        :emphasis:`nf` and a prime ideal :emphasis:`pr` in the format output by
        :literal:`idealprimedec`, computes the valuation :math:`v` at :emphasis:`pr` of the
        element :math:`x`. The valuation of :math:`0` is :literal:`+oo`.

        ::

        ? nf = nfinit(x^2 + 1);
        ? P = idealprimedec(nf, 2)[1];
        ? nfeltval(nf, x+1, P)
        %3 = 1

        This particular valuation can also be obtained using
        :literal:`idealval(:emphasis:`nf`,x,:emphasis:`pr`)`, since :math:`x` is then converted to a
        principal ideal.

        If the :math:`y` argument is present, sets :math:`y = x \tau^v`, where :math:`\tau` is a
        fixed "anti-uniformizer" for :emphasis:`pr`: its valuation at :emphasis:`pr` is :math:`-1`;
        its valuation is :math:`0` at other prime ideals dividing :literal:`:emphasis:`pr`.p` and
        nonnegative at all other primes. In other words :math:`y` is the part of :math:`x`
        coprime to :emphasis:`pr`. If :math:`x` is an algebraic integer, so is :math:`y`.

        ::

        ? nfeltval(nf, x+1, P, &y); y
        %4 = [0, 1]~

        For instance if :math:`x = \prod_i x_i^{e_i}` is known to be coprime to :emphasis:`pr`,
        where the :math:`x_i` are algebraic integers and :math:`e_i\in\mathbb{Z}` then,
        if :math:`v_i = nfeltval (nf, x_i, pr, &y_i)`, we still
        have :math:`x = \prod_i y_i^{e_i}`, where the :math:`y_i` are still algebraic integers
        but now all of them are coprime to :emphasis:`pr`. They can then be mapped to
        the residue field of :emphasis:`pr` more efficiently than if the product had
        been expanded beforehand: we can reduce mod :emphasis:`pr` after each ring
        operation.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        pr = objtogen(pr)
        cdef bint _have_y = (y is not None)
        if _have_y:
            raise NotImplementedError("optional argument y not available")
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN * _y = NULL
        cdef GEN _ret = gpnfvalrem(_nf, _x, _pr, _y)
        return new_gen(_ret)

    def nffactor(self, nf, T):
        r'''
        Factorization of the univariate
        polynomial :math:`T` over the number field :math:`nf` given by :literal:`nfinit`; :math:`T`
        has coefficients in :math:`nf` (i.e. either scalar, polmod, polynomial or
        column vector). The factors are sorted by increasing degree.

        The main variable of :math:`nf` must be of :emphasis:`lower`
        priority than that of :math:`T`, see ``priority`` (in the PARI manual). However if
        the polynomial defining the number field occurs explicitly in the
        coefficients of :math:`T` as modulus of a :literal:`t_POLMOD` or as a :literal:`t_POL`
        coefficient, its main variable must be :emphasis:`the same` as the main variable
        of :math:`T`. For example,

        ::

        ? nf = nfinit(y^2 + 1);
        ? nffactor(nf, x^2 + y); \\ OK
        ? nffactor(nf, x^2 + Mod(y, y^2+1)); \\  OK
        ? nffactor(nf, x^2 + Mod(z, z^2+1)); \\  WRONG

        It is possible to input a defining polynomial for :emphasis:`nf`
        instead, but this is in general less efficient since parts of an :literal:`nf`
        structure will then be computed internally. This is useful in two
        situations: when you do not need the :literal:`nf` elsewhere, or when you cannot
        initialize an :literal:`nf` due to integer factorization difficulties when
        attempting to compute the field discriminant and maximal order. In all
        cases, the function runs in polynomial time using Belabas's variant
        of van Hoeij's algorithm, which copes with hundreds of modular factors.

        :strong:`Caveat.` :literal:`nfinit([T, listP])` allows to compute in polynomial
        time a conditional :emphasis:`nf` structure, which sets :literal:`nf.zk` to an order
        which is not guaranteed to be maximal at all primes. Always either use
        :literal:`nfcertify` first (which may not run in polynomial time) or make sure
        to input :literal:`nf.pol` instead of the conditional :emphasis:`nf`: :literal:`nffactor` is
        able to recover in polynomial time in this case, instead of potentially
        missing a factor.
        '''
        nf = objtogen(nf)
        T = objtogen(T)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = nffactor(_nf, _T)
        return new_gen(_ret)

    def nffactorback(self, nf, f, e=None):
        r'''
        Gives back the :emphasis:`nf` element corresponding to a factorization.
        The integer :math:`1` corresponds to the empty factorization.

        If :math:`e` is present, :math:`e` and :math:`f` must be vectors of the same length (:math:`e` being
        integral), and the corresponding factorization is the product of the
        :math:`f[i]^{e[i]}`.

        If not, and :math:`f` is vector, it is understood as in the preceding case with :math:`e`
        a vector of 1s: we return the product of the :math:`f[i]`. Finally, :math:`f` can be a
        regular factorization matrix.

        ::

        ? nf = nfinit(y^2+1);
        ? nffactorback(nf, [3, y+1, [1,2]~], [1, 2, 3])
        %2 = [12, -66]~
        ? 3 * (I+1)^2 * (1+2*I)^3
        %3 = 12 - 66*I
        '''
        nf = objtogen(nf)
        f = objtogen(f)
        cdef bint _have_e = (e is not None)
        if _have_e:
            e = objtogen(e)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _f = (<Gen>f).g
        cdef GEN _e = NULL
        if _have_e:
            _e = (<Gen>e).g
        cdef GEN _ret = nffactorback(_nf, _f, _e)
        return new_gen(_ret)

    def nffactormod(self, nf, Q, pr):
        r'''
        This routine is obsolete, use :literal:`nfmodpr` and :literal:`factormod`.

        Factors the univariate polynomial :math:`Q` modulo the prime ideal :emphasis:`pr` in
        the number field :math:`nf`. The coefficients of :math:`Q` belong to the number
        field (scalar, polmod, polynomial, even column vector) and the main variable
        of :math:`nf` must be of lower priority than that of :math:`Q` (see
        ``priority`` (in the PARI manual)). The prime ideal :emphasis:`pr` is either in
        :literal:`idealprimedec` or (preferred) :literal:`modprinit` format. The coefficients
        of the polynomial factors are lifted to elements of :emphasis:`nf`:

        ::

        ? K = nfinit(y^2+1);
        ? P = idealprimedec(K, 3)[1];
        ? nffactormod(K, x^2 + y*x + 18*y+1, P)
        %3 =
        [x + (2*y + 1) 1]
        
        [x + (2*y + 2) 1]
        ? P = nfmodprinit(K, P); \\ convert to nfmodprinit format
        ? nffactormod(K, x^2 + y*x + 18*y+1)
        %5 =
        [x + (2*y + 1) 1]
        
        [x + (2*y + 2) 1]

        Same result, of course, here about 10\% faster due to the
        precomputation.
        '''
        from warnings import warn
        warn('the PARI/GP function nffactormod is obsolete (2016-09-18)', DeprecationWarning)
        nf = objtogen(nf)
        Q = objtogen(Q)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = nffactormod(_nf, _Q, _pr)
        return new_gen(_ret)

    def nfgaloisapply(self, nf, aut, x):
        r'''
        Let :math:`nf` be a
        number field as output by :literal:`nfinit`, and let :emphasis:`aut` be a Galois
        automorphism of :math:`nf` expressed by its image on the field generator
        (such automorphisms can be found using :literal:`nfgaloisconj`). The function
        computes the action of the automorphism :emphasis:`aut` on the object :math:`x` in the
        number field; :math:`x` can be a number field element, or an ideal (possibly
        extended). Because of possible confusion with elements and ideals, other
        vector or matrix arguments are forbidden.

        ::

        ? nf = nfinit(x^2+1);
        ? L = nfgaloisconj(nf)
        %2 = [-x, x]~
        ? aut = L[1]; /* the non-trivial automorphism */
        ? nfgaloisapply(nf, aut, x)
        %4 = Mod(-x, x^2 + 1)
        ? P = idealprimedec(nf,5); /* prime ideals above 5 */
        ? nfgaloisapply(nf, aut, P[2]) == P[1]
        %6 = 0 \\ !!!!
        ? idealval(nf, nfgaloisapply(nf, aut, P[2]), P[1])
        %7 = 1

        The surprising failure of the equality test (:literal:`\%7`) is
        due to the fact that although the corresponding prime ideals are equal, their
        representations are not. (A prime ideal is specified by a uniformizer, and
        there is no guarantee that applying automorphisms yields the same elements
        as a direct :literal:`idealprimedec` call.)

        The automorphism can also be given as a column vector, representing the
        image of :literal:`Mod(x, nf.pol)` as an algebraic number. This last
        representation is more efficient and should be preferred if a given
        automorphism must be used in many such calls.

        ::

        ? nf = nfinit(x^3 - 37*x^2 + 74*x - 37);
        ? aut = nfgaloisconj(nf)[2]; \\  an automorphism in basistoalg form
        %2 = -31/11*x^2 + 1109/11*x - 925/11
        ? AUT = nfalgtobasis(nf, aut); \\  same in algtobasis form
        %3 = [16, -6, 5]~
        ? v = [1, 2, 3]~; nfgaloisapply(nf, aut, v) == nfgaloisapply(nf, AUT, v)
        %4 = 1 \\  same result...
        ? for (i=1,10^5, nfgaloisapply(nf, aut, v))
        time = 463 ms.
        ? for (i=1,10^5, nfgaloisapply(nf, AUT, v))
        time = 343 ms. \\  but the latter is faster
        '''
        nf = objtogen(nf)
        aut = objtogen(aut)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _aut = (<Gen>aut).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = galoisapply(_nf, _aut, _x)
        return new_gen(_ret)

    def nfgaloisconj(self, nf, long flag=0, d=None, long precision=DEFAULT_BITPREC):
        r'''
        :math:`nf` being a number field as output by :literal:`nfinit`, computes the
        conjugates of a root :math:`r` of the non-constant polynomial :math:`x = nf[1]`
        expressed as polynomials in :math:`r`. This also makes sense when the number field
        is not Galois since some conjugates may lie in the field.
        :math:`nf` can simply be a polynomial.

        If no flags or :math:`flag = 0`, use a combination of flag :math:`4` and :math:`1` and the result
        is always complete. There is no point whatsoever in using the other flags.

        If :math:`flag = 1`, use :literal:`nfroots`: a little slow, but guaranteed to work in
        polynomial time.

        If :math:`flag = 4`, use :literal:`galoisinit`: very fast, but only applies to (most)
        Galois fields. If the field is Galois with weakly super-solvable Galois
        group (see :literal:`galoisinit`), return the complete list of automorphisms, else
        only the identity element. If present, :math:`d` is assumed to be a multiple of the
        least common denominator of the conjugates expressed as polynomial in a root
        of :emphasis:`pol`.

        This routine can only compute :math:`\mathbb{Q}`-automorphisms, but it may be used to get
        :math:`K`-automorphism for any base field :math:`K` as follows:

        ::

        rnfgaloisconj(nfK, R) = \\ K-automorphisms of L = K[X] / (R)
        {
        my(polabs, N,al,S, ala,k, vR);
        R *= Mod(1, nfK.pol); \\ convert coeffs to polmod elts of K
        vR = variable(R);
        al = Mod(variable(nfK.pol),nfK.pol);
        [polabs,ala,k] = rnfequation(nfK, R, 1);
        Rt = if(k==0,R,subst(R,vR,vR-al*k));
        N = nfgaloisconj(polabs) % Rt; \\ Q-automorphisms of L
        S = select(s->subst(Rt, vR, Mod(s,Rt)) == 0, N);
        if (k==0, S, apply(s->subst(s,vR,vR+k*al)-k*al,S));
        }
        K = nfinit(y^2 + 7);
        rnfgaloisconj(K, x^4 - y*x^3 - 3*x^2 + y*x + 1) \\ K-automorphisms of L
        '''
        nf = objtogen(nf)
        cdef bint _have_d = (d is not None)
        if _have_d:
            d = objtogen(d)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _d = NULL
        if _have_d:
            _d = (<Gen>d).g
        precision = nbits2prec(precision)
        cdef GEN _ret = galoisconj0(_nf, flag, _d, precision)
        return new_gen(_ret)

    def nfgrunwaldwang(self, nf, Lpr, Ld, pl, v=None):
        r'''
        Given :emphasis:`nf` a number field in :emphasis:`nf` or :emphasis:`bnf` format,
        a :literal:`t_VEC` :emphasis:`Lpr` of primes of :emphasis:`nf` and a :literal:`t_VEC` :emphasis:`Ld` of
        positive integers of the same length, a :literal:`t_VECSMALL` :emphasis:`pl` of length
        :math:`r_1` the number of real places of :emphasis:`nf`, computes a polynomial with
        coefficients in :emphasis:`nf` defining a cyclic extension of :emphasis:`nf` of
        minimal degree satisfying certain local conditions:

        - at the prime :math:`Lpr[i]`, the extension has local degree a multiple
        of :math:`Ld[i]`;

        - at the :math:`i`-th real place of :emphasis:`nf`, it is complex if :math:`pl[i] = -1`
        (no condition if :math:`pl[i] = 0`).

        The extension has degree the LCM of the local degrees. Currently, the degree
        is restricted to be a prime power for the search, and to be prime for the
        construction because of the :literal:`rnfkummer` restrictions.

        When :emphasis:`nf` is :math:`\mathbb{Q}`, prime integers are accepted instead of :literal:`prid`
        structures. However, their primality is not checked and the behavior is
        undefined if you provide a composite number.

        :strong:`Warning.` If the number field :emphasis:`nf` does not contain the :math:`n`-th
        roots of unity where :math:`n` is the degree of the extension to be computed,
        triggers the computation of the :emphasis:`bnf` of :math:`nf(\zeta_n)`, which may be
        costly.

        ::

        ? nf = nfinit(y^2-5);
        ? pr = idealprimedec(nf,13)[1];
        ? pol = nfgrunwaldwang(nf, [pr], [2], [0,-1], 'x)
        %3 = x^2 + Mod(3/2*y + 13/2, y^2 - 5)
        '''
        nf = objtogen(nf)
        Lpr = objtogen(Lpr)
        Ld = objtogen(Ld)
        pl = objtogen(pl)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _Lpr = (<Gen>Lpr).g
        cdef GEN _Ld = (<Gen>Ld).g
        cdef GEN _pl = (<Gen>pl).g
        cdef GEN _ret = nfgrunwaldwang(_nf, _Lpr, _Ld, _pl, _v)
        return new_gen(_ret)

    def nfhilbert(self, nf, a, b, pr=None):
        r'''
        If :emphasis:`pr` is omitted,
        compute the global quadratic Hilbert symbol :math:`(a,b)` in :math:`nf`, that
        is :math:`1` if :math:`x^2 - a y^2 - b z^2` has a non trivial solution :math:`(x,y,z)` in
        :math:`nf`, and :math:`-1` otherwise. Otherwise compute the local symbol modulo
        the prime ideal :emphasis:`pr`, as output by :literal:`idealprimedec`.
        '''
        nf = objtogen(nf)
        a = objtogen(a)
        b = objtogen(b)
        cdef bint _have_pr = (pr is not None)
        if _have_pr:
            pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _pr = NULL
        if _have_pr:
            _pr = (<Gen>pr).g
        cdef long _ret = nfhilbert0(_nf, _a, _b, _pr)
        clear_stack()
        return _ret

    def nfhnf(self, nf, x, long flag=0):
        r'''
        Given a pseudo-matrix :math:`(A,I)`, finds a
        pseudo-basis :math:`(B,J)` in Hermite normal form of the module it generates.
        If :math:`flag` is non-zero, also return the transformation matrix :math:`U` such that
        :math:`AU = [0\|B]`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = nfhnf0(_nf, _x, flag)
        return new_gen(_ret)

    def nfhnfmod(self, nf, x, detx):
        r'''
        Given a pseudo-matrix :math:`(A,I)`
        and an ideal :emphasis:`detx` which is contained in (read integral multiple of) the
        determinant of :math:`(A,I)`, finds a pseudo-basis in Hermite normal form
        of the module generated by :math:`(A,I)`. This avoids coefficient explosion.
        :emphasis:`detx` can be computed using the function :literal:`nfdetint`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        detx = objtogen(detx)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _detx = (<Gen>detx).g
        cdef GEN _ret = nfhnfmod(_nf, _x, _detx)
        return new_gen(_ret)

    def nfinit(self, pol, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        :emphasis:`pol` being a non-constant,
        preferably monic, irreducible polynomial in :math:`\mathbb{Z}[X]`, initializes a
        :emphasis:`number field` structure (:literal:`nf`) attached to the field :math:`K` defined
        by :emphasis:`pol`. As such, it's a technical object passed as the first argument
        to most :literal:`nf`:emphasis:`xxx` functions, but it contains some information which
        may be directly useful. Access to this information via :emphasis:`member
        functions` is preferred since the specific data organization given below
        may change in the future. Currently, :literal:`nf` is a row vector with 9
        components:

        :math:`nf[1]` contains the polynomial :emphasis:`pol` (:literal:`:emphasis:`nf`.pol`).

        :math:`nf[2]` contains :math:`[r1,r2]` (:literal:`:emphasis:`nf`.sign`, :literal:`:emphasis:`nf`.r1`,
        :literal:`:emphasis:`nf`.r2`), the number of real and complex places of :math:`K`.

        :math:`nf[3]` contains the discriminant :math:`d(K)` (:literal:`:emphasis:`nf`.disc`) of :math:`K`.

        :math:`nf[4]` contains the index of :math:`nf[1]` (:literal:`:emphasis:`nf`.index`),
        i.e. :math:`[\mathbb{Z}_K : \mathbb{Z}[\theta]]`, where :math:`\theta` is any root of :math:`nf[1]`.

        :math:`nf[5]` is a vector containing 7 matrices :math:`M`, :math:`G`, :emphasis:`roundG`, :math:`T`,
        :math:`MD`, :math:`TI`, :math:`MDI` useful for certain computations in the number field :math:`K`.

        :strong:`*` :math:`M` is the :math:`(r1+r2) x n` matrix whose columns represent
        the numerical values of the conjugates of the elements of the integral
        basis.

        :strong:`*` :math:`G` is an :math:`n x n` matrix such that :math:`T2 = ^t G G`,
        where :math:`T2` is the quadratic form :math:`T_2(x) = \sum \|\sigma (x)\|^2`, :math:`\sigma`
        running over the embeddings of :math:`K` into :math:`\mathbb{C}`.

        :strong:`*` :emphasis:`roundG` is a rescaled copy of :math:`G`, rounded to nearest
        integers.

        :strong:`*` :math:`T` is the :math:`n x n` matrix whose coefficients are
        :math:`Tr(\omega_i\omega_j)` where the :math:`\omega_i` are the elements of the
        integral basis. Note also that :math:`\det (T)` is equal to the discriminant of the
        field :math:`K`. Also, when understood as an ideal, the matrix :math:`T^{-1}`
        generates the codifferent ideal.

        :strong:`*` The columns of :math:`MD` (:literal:`:emphasis:`nf`.diff`) express a :math:`\mathbb{Z}`-basis
        of the different of :math:`K` on the integral basis.

        :strong:`*` :math:`TI` is equal to the primitive part of :math:`T^{-1}`, which has integral
        coefficients.

        :strong:`*` Finally, :math:`MDI` is a two-element representation (for faster
        ideal product) of :math:`d(K)` times the codifferent ideal
        (:literal:`:emphasis:`nf`.disc:math:`*`:emphasis:`nf`.codiff`, which is an integral ideal). :math:`MDI`
        is only used in :literal:`idealinv`.

        :math:`nf[6]` is the vector containing the :math:`r1+r2` roots
        (:literal:`:emphasis:`nf`.roots`) of :math:`nf[1]` corresponding to the :math:`r1+r2`
        embeddings of the number field into :math:`\mathbb{C}` (the first :math:`r1` components are real,
        the next :math:`r2` have positive imaginary part).

        :math:`nf[7]` is an integral basis for :math:`\mathbb{Z}_K` (:literal:`:emphasis:`nf`.zk`) expressed
        on the powers of :math:`\theta`. Its first element is guaranteed to be :math:`1`. This
        basis is LLL-reduced with respect to :math:`T_2` (strictly speaking, it is a
        permutation of such a basis, due to the condition that the first element be
        :math:`1`).

        :math:`nf[8]` is the :math:`n x n` integral matrix expressing the power
        basis in terms of the integral basis, and finally

        :math:`nf[9]` is the :math:`n x n^2` matrix giving the multiplication table
        of the integral basis.

        If a non monic polynomial is input, :literal:`nfinit` will transform it into a
        monic one, then reduce it (see :math:`flag = 3`). It is allowed, though not very
        useful given the existence of :literal:`nfnewprec`, to input a :emphasis:`nf` or a
        :emphasis:`bnf` instead of a polynomial. It is also allowed to
        input a :emphasis:`rnf`, in which case an :literal:`nf` structure attached to the
        absolute defining polynomial :literal:`polabs` is returned (:emphasis:`flag` is then ignored).

        ::

        ? nf = nfinit(x^3 - 12); \\ initialize number field Q[X] / (X^3 - 12)
        ? nf.pol \\ defining polynomial
        %2 = x^3 - 12
        ? nf.disc \\ field discriminant
        %3 = -972
        ? nf.index \\ index of power basis order in maximal order
        %4 = 2
        ? nf.zk \\ integer basis, lifted to Q[X]
        %5 = [1, x, 1/2*x^2]
        ? nf.sign \\ signature
        %6 = [1, 1]
        ? factor(abs(nf.disc )) \\ determines ramified primes
        %7 =
        [2 2]
        
        [3 5]
        ? idealfactor(nf, 2)
        %8 =
        [[2, [0, 0, -1]~, 3, 1, [0, 1, 0]~] 3] \\  p_2^3

        :strong:`Huge discriminants, helping nfdisc.`

        In case :emphasis:`pol` has a huge discriminant which is difficult to factor,
        it is hard to compute from scratch the maximal order. The special input
        format :math:`[pol, B]` is also accepted where :emphasis:`pol` is a polynomial as
        above and :math:`B` has one of the following forms

        - an integer basis, as would be computed by :literal:`nfbasis`: a vector of
        polynomials with first element :math:`1`. This is useful if the maximal order is
        known in advance.

        - an argument :literal:`listP` which specifies a list of primes (see
        :literal:`nfbasis`). Instead of the maximal order, :literal:`nfinit` then computes an
        order which is maximal at these particular primes as well as the primes
        contained in the private prime table (see :literal:`addprimes`). The result is
        unconditionaly correct when the discriminant :literal:`nf.disc` factors
        completely over this set of primes. The function :literal:`nfcertify` automates
        this:

        ::

        ? pol = polcompositum(x^5 - 101, polcyclo(7))[1];
        ? nf = nfinit( [pol, 10^3] );
        ? nfcertify(nf)
        %3 = []

        A priori, :literal:`nf.zk` defines an order which is only known
        to be maximal at all primes :math:`<= 10^3` (no prime :math:`<= 10^3` divides
        :literal:`nf.index`). The certification step proves the correctness of the
        computation. Had it failed, that particular :literal:`nf` structure could
        not have been trusted and may have caused routines using it to fail randomly.
        One particular function that remains trustworthy in all cases is
        :literal:`idealprimedec` when applied to a prime included in the above list
        of primes or, more generally, a prime not dividing any entry in
        :literal:`nfcertify` output.

        If :math:`flag = 2`: :emphasis:`pol` is changed into another polynomial :math:`P` defining the same
        number field, which is as simple as can easily be found using the
        :literal:`polredbest` algorithm, and all the subsequent computations are done
        using this new polynomial. In particular, the first component of the result
        is the modified polynomial.

        If :math:`flag = 3`, apply :literal:`polredbest` as in case 2, but outputs
        :math:`[nf,Mod (a,P)]`, where :math:`nf` is as before and
        :math:`Mod (a,P) = Mod (x,pol)` gives the change of
        variables. This is implicit when :emphasis:`pol` is not monic: first a linear change
        of variables is performed, to get a monic polynomial, then :literal:`polredbest`.
        '''
        pol = objtogen(pol)
        sig_on()
        cdef GEN _pol = (<Gen>pol).g
        precision = nbits2prec(precision)
        cdef GEN _ret = nfinit0(_pol, flag, precision)
        return new_gen(_ret)

    def nfisideal(self, nf, x):
        r'''
        Returns 1 if :math:`x` is an ideal in the number field :math:`nf`, 0 otherwise.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = isideal(_nf, _x)
        clear_stack()
        return _ret

    def nfisincl(self, f, g):
        r'''
        Let :math:`f` and :math:`g` define number fields, where :math:`f` and :math:`g` are irreducible
        polynomials in :math:`\mathbb{Q}[X]` and :emphasis:`nf` structures as output by :literal:`nfinit`.
        Tests whether the number field :math:`f` is conjugate to a subfield of the field
        :math:`g`. If they are not, the output is the integer 0. If they are, the output is
        a vector of polynomials, each polynomial :math:`a` representing an embedding
        i.e. being such that :math:`g \| f o a`. If either :math:`f` or :math:`g` is not
        irreducible, the result is undefined.

        ::

        ? T = x^6 + 3*x^4 - 6*x^3 + 3*x^2 + 18*x + 10;
        ? U = x^3 + 3*x^2 + 3*x - 2
        
        ? v = nfisincl(U, T);
        %2 = [24/179*x^5-27/179*x^4+80/179*x^3-234/179*x^2+380/179*x+94/179]
        
        ? subst(U, x, Mod(v[1],T))
        %3 = Mod(0, x^6 + 3*x^4 - 6*x^3 + 3*x^2 + 18*x + 10)
        ? #nfisincl(x^2+1, T) \\ two embeddings
        %4 = 2
        
        \\ same result with nf structures
        ? nfisincl(U, L = nfinit(T)) == v
        %5 = 1
        ? nfisincl(K = nfinit(U), T) == v
        %6 = 1
        ? nfisincl(K, L) == v
        %7 = 1
        
        \\ comparative bench: an nf is a little faster, esp. for the subfield
        ? B = 10^3;
        ? for (i=1, B, nfisincl(U,T))
        time = 712 ms.
        
        ? for (i=1, B, nfisincl(K,T))
        time = 485 ms.
        
        ? for (i=1, B, nfisincl(U,L))
        time = 704 ms.
        
        ? for (i=1, B, nfisincl(K,L))
        time = 465 ms.

        Using an :emphasis:`nf` structure for the potential subfield is
        faster if the structure is already available. On the other hand, the gain in
        :literal:`nfisincl` is usually not sufficient to make it worthwhile to initialize
        only for that purpose.

        ::

        ? for (i=1, B, nfinit(U))
        time = 308 ms.
        '''
        f = objtogen(f)
        g = objtogen(g)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _g = (<Gen>g).g
        cdef GEN _ret = nfisincl(_f, _g)
        return new_gen(_ret)

    def nfisisom(self, f, g):
        r'''
        As :literal:`nfisincl`, but tests for isomorphism. More efficient if
        :math:`f` or :math:`g` is a number field structure.

        ::

        ? f = x^6 + 30*x^5 + 495*x^4 + 1870*x^3 + 16317*x^2 - 22560*x + 59648;
        ? g = x^6 + 42*x^5 + 999*x^4 + 8966*x^3 + 36117*x^2 + 21768*x + 159332;
        ? h = x^6 + 30*x^5 + 351*x^4 + 2240*x^3 + 10311*x^2 + 35466*x + 58321;
        
        ? #nfisisom(f,g) \\ two isomorphisms
        %3 = 2
        ? nfisisom(f,h) \\ not isomorphic
        %4 = 0
        \\ comparative bench
        ? K = nfinit(f); L = nfinit(g); B = 10^3;
        ? for (i=1, B, nfisisom(f,g))
        time = 6,124 ms.
        ? for (i=1, B, nfisisom(K,g))
        time = 3,356 ms.
        ? for (i=1, B, nfisisom(f,L))
        time = 3,204 ms.
        ? for (i=1, B, nfisisom(K,L))
        time = 3,173 ms.

        The function is usually very fast when the fields are non-isomorphic,
        whenever the fields can be distinguished via a simple invariant such as
        degree, signature or discriminant. It may be slower when the fields
        share all invariants, but still faster than computing actual isomorphisms:

        ::

        \\ usually very fast when the answer is 'no':
        ? for (i=1, B, nfisisom(f,h))
        time = 32 ms.
        
        \\ but not always
        ? u = x^6 + 12*x^5 + 6*x^4 - 377*x^3 - 714*x^2 + 5304*x + 15379
        ? v = x^6 + 12*x^5 + 60*x^4 + 166*x^3 + 708*x^2 + 6600*x + 23353
        ? nfisisom(u,v)
        %13 = 0
        ? polsturm(u) == polsturm(v)
        %14 = 1
        ? nfdisc(u) == nfdisc(v)
        %15 = 1
        ? for(i=1,B, nfisisom(u,v))
        time = 1,821 ms.
        ? K = nfinit(u); L = nfinit(v);
        ? for(i=1,B, nfisisom(K,v))
        time = 232 ms.
        '''
        f = objtogen(f)
        g = objtogen(g)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _g = (<Gen>g).g
        cdef GEN _ret = nfisisom(_f, _g)
        return new_gen(_ret)

    def nfislocalpower(self, nf, pr, a, n):
        r'''
        Let :emphasis:`nf` be a :emphasis:`nf` structure attached to a number field :math:`K`,
        let :math:`a \in K` and let :emphasis:`pr` be a :emphasis:`prid` structure attached to a
        maximal ideal :math:`v`. Return :math:`1` if :math:`a` is an :math:`n`-th power in the completed
        local field :math:`K_v`, and :math:`0` otherwise.

        ::

        ? K = nfinit(y^2+1);
        ? P = idealprimedec(K,2)[1]; \\ the ramified prime above 2
        ? nfislocalpower(K,P,-1, 2) \\ -1 is a square
        %3 = 1
        ? nfislocalpower(K,P,-1, 4) \\ ... but not a 4-th power
        %4 = 0
        ? nfislocalpower(K,P,2, 2) \\ 2 is not a square
        %5 = 0
        
        ? Q = idealprimedec(K,5)[1]; \\ a prime above 5
        ? nfislocalpower(K,Q, [0, 32]~, 30) \\ 32*I is locally a 30-th power
        %7 = 1
        '''
        nf = objtogen(nf)
        pr = objtogen(pr)
        a = objtogen(a)
        n = objtogen(n)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _n = (<Gen>n).g
        cdef long _ret = nfislocalpower(_nf, _pr, _a, _n)
        clear_stack()
        return _ret

    def nfkermodpr(self, nf, x, pr):
        r'''
        This function is obsolete, use :literal:`nfmodpr`.

        Kernel of the matrix :math:`a` in :math:`\mathbb{Z}_K/pr`, where :emphasis:`pr` is in
        :strong:`modpr` format (see :literal:`nfmodprinit`).
        '''
        from warnings import warn
        warn('the PARI/GP function nfkermodpr is obsolete (2016-08-09)', DeprecationWarning)
        nf = objtogen(nf)
        x = objtogen(x)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = nfkermodpr(_nf, _x, _pr)
        return new_gen(_ret)

    def nfmodpr(self, nf, x, pr):
        r'''
        Map :math:`x` to a :literal:`t_FFELT` in the residue field modulo :emphasis:`pr`.
        The argument :emphasis:`pr` is either a maximal ideal in :literal:`idealprimedec`
        format or, preferably, a :emphasis:`modpr` structure from :literal:`nfmodprinit`. The
        function :literal:`nfmodprlift` allows to lift back to :math:`\mathbb{Z}_K`.

        Note that the function applies to number field elements and not to
        vector / matrices / polynomials of such. Use :literal:`apply` to convert
        recursive structures.

        ::

        ? K = nfinit(y^3-250);
        ? P = idealprimedec(K, 5)[2];
        ? modP = nfmodprinit(K,P);
        ? K.zk
        %4 = [1, 1/5*y, 1/25*y^2]
        ? apply(t->nfmodpr(K,t,modP), K.zk)
        %5 = [1, y, 2*y + 1]
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = nfmodpr(_nf, _x, _pr)
        return new_gen(_ret)

    def nfmodprinit(self, nf, pr):
        r'''
        Transforms the prime ideal :emphasis:`pr` into :literal:`modpr` format necessary
        for all operations modulo :emphasis:`pr` in the number field :emphasis:`nf`.
        The functions :literal:`nfmodpr` and :literal:`nfmodprlift` allow to project
        to and lift from the residue field.
        '''
        nf = objtogen(nf)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = nfmodprinit(_nf, _pr)
        return new_gen(_ret)

    def nfmodprlift(self, nf, x, pr):
        r'''
        Lift the :literal:`t_FFELT` :math:`x` (from :literal:`nfmodpr`) in the residue field
        modulo :emphasis:`pr` to the ring of integers. Vectors and matrices are also
        supported. For polynomials, use :literal:`apply` and the present function.

        The argument :emphasis:`pr` is either a maximal ideal in :literal:`idealprimedec`
        format or, preferably, a :emphasis:`modpr` structure from :literal:`nfmodprinit`.
        There are no compatibility checks to try and decide whether :math:`x` is attached
        the same residue field as defined by :emphasis:`pr`: the result is undefined
        if not.

        The function :literal:`nfmodpr` allows to reduce to the residue field.

        ::

        ? K = nfinit(y^3-250);
        ? P = idealprimedec(K, 5)[2];
        ? modP = nfmodprinit(K,P);
        ? K.zk
        %4 = [1, 1/5*y, 1/25*y^2]
        ? apply(t->nfmodpr(K,t,modP), K.zk)
        %5 = [1, y, 2*y + 1]
        ? nfmodprlift(K, %, modP)
        %6 = [1, 1/5*y, 2/5*y + 1]
        ? nfeltval(K, %[3] - K.zk[3], P)
        %7 = 1
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = nfmodprlift(_nf, _x, _pr)
        return new_gen(_ret)

    def nfnewprec(self, nf, long precision=DEFAULT_BITPREC):
        r'''
        Transforms the number field :math:`nf`
        into the corresponding data using current (usually larger) precision. This
        function works as expected if :emphasis:`nf` is in fact a :emphasis:`bnf` or a :emphasis:`bnr`
        (update structure to current precision) but may be quite slow: many
        generators of principal ideals have to be computed; note that in this latter
        case, the :emphasis:`bnf` must contain fundamental units.
        '''
        nf = objtogen(nf)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        precision = nbits2prec(precision)
        cdef GEN _ret = nfnewprec(_nf, precision)
        return new_gen(_ret)

    def nfpolsturm(self, nf, T, pl=None):
        r'''
        Given a polynomial :math:`T` with coefficients in the number field :emphasis:`nf`,
        returns the number of real roots of the :math:`s(T)` where :math:`s` runs through
        the real embeddings of the field specified by optional argument :emphasis:`pl`:

        - :emphasis:`pl` omitted: all :math:`r_1` real places;

        - :emphasis:`pl` an integer between :math:`1` and :math:`r_1`: the embedding attached to
        the :math:`i`-th real root of :literal:`nf.pol`, i.e. :literal:`nf.roots:math:`[i]``;

        - :emphasis:`pl` a vector or :literal:`t_VECSMALL`: the embeddings
        attached to the :math:`pl[i]`-th real roots of :literal:`nf.pol`.

        ::

        ? nf = nfinit('y^2 - 2);
        ? nf.sign
        %2 = [2, 0]
        ? nf.roots
        %3 = [-1.414..., 1.414...]
        ? T = x^2 + 'y;
        ? nfpolsturm(nf, T, 1) \\ subst(T,y,sqrt(2)) has two real roots
        %5 = 2
        ? nfpolsturm(nf, T, 2) \\ subst(T,y,-sqrt(2)) has no real root
        %6 = 0
        ? nfpolsturm(nf, T) \\ all embeddings together
        %7 = [2, 0]
        ? nfpolsturm(nf, T, [2,1]) \\ second then first embedding
        %8 = [0, 2]
        ? nfpolsturm(nf, x^3) \\ number of distinct roots !
        %9 = [1, 1]
        ? nfpolsturm(nf, x, 6) \\ there are only 2 real embeddings !
        *** at top-level: nfpolsturm(nf,x,6)
        *** ^-----------------
        *** nfpolsturm: domain error in nfpolsturm: index > 2
        '''
        nf = objtogen(nf)
        T = objtogen(T)
        cdef bint _have_pl = (pl is not None)
        if _have_pl:
            pl = objtogen(pl)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _T = (<Gen>T).g
        cdef GEN _pl = NULL
        if _have_pl:
            _pl = (<Gen>pl).g
        cdef GEN _ret = nfpolsturm(_nf, _T, _pl)
        return new_gen(_ret)

    def nfroots(self, nf=None, x=None):
        r'''
        Roots of the polynomial :math:`x` in the
        number field :math:`nf` given by :literal:`nfinit` without multiplicity (in :math:`\mathbb{Q}`
        if :math:`nf` is omitted). :math:`x` has coefficients in the number field (scalar,
        polmod, polynomial, column vector). The main variable of :math:`nf` must be
        of lower priority than that of :math:`x` (see ``priority`` (in the PARI manual)). However if the
        coefficients of the number field occur explicitly (as polmods) as
        coefficients of :math:`x`, the variable of these polmods :emphasis:`must` be the same as
        the main variable of :math:`t` (see :literal:`nffactor`).

        It is possible to input a defining polynomial for :emphasis:`nf`
        instead, but this is in general less efficient since parts of an :literal:`nf`
        structure will then be computed internally. This is useful in two
        situations: when you do not need the :literal:`nf` elsewhere, or when you cannot
        initialize an :literal:`nf` due to integer factorization difficulties when
        attempting to compute the field discriminant and maximal order.

        :strong:`Caveat.` :literal:`nfinit([T, listP])` allows to compute in polynomial
        time a conditional :emphasis:`nf` structure, which sets :literal:`nf.zk` to an order
        which is not guaranteed to be maximal at all primes. Always either use
        :literal:`nfcertify` first (which may not run in polynomial time) or make sure
        to input :literal:`nf.pol` instead of the conditional :emphasis:`nf`: :literal:`nfroots` is
        able to recover in polynomial time in this case, instead of potentially
        missing a factor.
        '''
        cdef bint _have_nf = (nf is not None)
        if _have_nf:
            nf = objtogen(nf)
        if x is None:
            raise TypeError("missing required argument: 'x'")
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = NULL
        if _have_nf:
            _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = nfroots(_nf, _x)
        return new_gen(_ret)

    def nfrootsof1(self, nf):
        r'''
        Returns a two-component vector :math:`[w,z]` where :math:`w` is the number of roots of
        unity in the number field :emphasis:`nf`, and :math:`z` is a primitive :math:`w`-th root
        of unity.

        ::

        ? K = nfinit(polcyclo(11));
        ? nfrootsof1(K)
        %2 = [22, [0, 0, 0, 0, 0, -1, 0, 0, 0, 0]~]
        ? z = nfbasistoalg(K, %[2]) \\ in algebraic form
        %3 = Mod(-x^5, x^10 + x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1)
        ? [lift(z^11), lift(z^2)] \\ proves that the order of z is 22
        %4 = [-1, -x^9 - x^8 - x^7 - x^6 - x^5 - x^4 - x^3 - x^2 - x - 1]

        This function guesses the number :math:`w` as the gcd of the :math:`\#k(v)^*` for
        unramified :math:`v` above odd primes, then computes the roots in :emphasis:`nf`
        of the :math:`w`-th cyclotomic polynomial: the algorithm is polynomial time with
        respect to the field degree and the bitsize of the multiplication table in
        :emphasis:`nf` (both of them polynomially bounded in terms of the size of the
        discriminant). Fields of degree up to :math:`100` or so should require less than
        one minute.
        '''
        nf = objtogen(nf)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _ret = rootsof1(_nf)
        return new_gen(_ret)

    def nfsnf(self, nf, x, long flag=0):
        r'''
        Given a torsion :math:`\mathbb{Z}_K`-module :math:`x` attached to the square integral
        invertible pseudo-matrix :math:`(A,I,J)`, returns an ideal list
        :math:`D = [d_1,...,d_n]` which is the Smith normal form of :math:`x`. In other
        words, :math:`x` is isomorphic to :math:`\mathbb{Z}_K/d_1\oplus...\oplus\mathbb{Z}_K/d_n` and :math:`d_i`
        divides :math:`d_{i-1}` for :math:`i >= 2`. If :math:`flag` is non-zero return :math:`[D,U,V]`, where
        :math:`UAV` is the identity.

        See ``ZKmodules`` (in the PARI manual) for the definition of integral pseudo-matrix;
        briefly, it is input as a 3-component row vector :math:`[A,I,J]` where
        :math:`I = [b_1,...,b_n]` and :math:`J = [a_1,...,a_n]` are two ideal lists,
        and :math:`A` is a square :math:`n x n` matrix with columns :math:`(A_1,...,A_n)`,
        seen as elements in :math:`K^n` (with canonical basis :math:`(e_1,...,e_n)`).
        This data defines the :math:`\mathbb{Z}_K` module :math:`x` given by

        .. MATH::

        (b_1e_1\oplus...\oplus b_ne_n) / (a_1A_1\oplus...\oplus a_nA_n)
        ,

        The integrality condition is :math:`a_{i,j} \in b_i a_j^{-1}` for all :math:`i,j`. If it
        is not satisfied, then the :math:`d_i` will not be integral. Note that every
        finitely generated torsion module is isomorphic to a module of this form and
        even with :math:`b_i = Z_K` for all :math:`i`.
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = nfsnf0(_nf, _x, flag)
        return new_gen(_ret)

    def nfsolvemodpr(self, nf, a, b, P):
        r'''
        This function is obsolete, use :literal:`nfmodpr`.

        Let :math:`P` be a prime ideal in :strong:`modpr` format (see :literal:`nfmodprinit`),
        let :math:`a` be a matrix, invertible over the residue field, and let :math:`b` be
        a column vector or matrix. This function returns a solution of :math:`a.x =
        b`; the coefficients of :math:`x` are lifted to :emphasis:`nf` elements.

        ::

        ? K = nfinit(y^2+1);
        ? P = idealprimedec(K, 3)[1];
        ? P = nfmodprinit(K, P);
        ? a = [y+1, y; y, 0]; b = [1, y]~
        ? nfsolvemodpr(K, a,b, P)
        %5 = [1, 2]~
        '''
        from warnings import warn
        warn('the PARI/GP function nfsolvemodpr is obsolete (2016-08-09)', DeprecationWarning)
        nf = objtogen(nf)
        a = objtogen(a)
        b = objtogen(b)
        P = objtogen(P)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _b = (<Gen>b).g
        cdef GEN _P = (<Gen>P).g
        cdef GEN _ret = nfsolvemodpr(_nf, _a, _b, _P)
        return new_gen(_ret)

    def nfsplitting(self, P, d=None):
        r'''
        Defining polynomial over :math:`\mathbb{Q}` for the splitting field of :emphasis:`P`,
        that is the smallest field over which :math:`P` is totally split. If :math:`P`
        can also be given by a :literal:`nf` structure, which is more efficient.
        If :math:`d` is given, it must be a multiple of the splitting field degree.
        Note that if :math:`P` is reducible the splitting field degree can be smaller
        than the degree of :math:`P`.

        ::

        ? K = nfinit(x^3-2);
        ? nfsplitting(K)
        %2 = x^6 + 108
        ? nfsplitting(x^8-2)
        %3 = x^16 + 272*x^8 + 64
        ? S = nfsplitting(x^6-8) // reducible
        %4 = x^4+2*x^2+4
        ? lift(nfroots(subst(S,x,a),x^6-8))
        %5 = [-a,a,-1/2*a^3-a,-1/2*a^3,1/2*a^3,1/2*a^3+a]

        Specifying the degree of the splitting field can make the computation faster.

        ::

        ? nfsplitting(x^17-123);
        time = 3,607 ms.
        ? poldegree(%)
        %2 = 272
        ? nfsplitting(x^17-123,272);
        time = 150 ms.
        ? nfsplitting(x^17-123,273);
        *** nfsplitting: Warning: ignoring incorrect degree bound 273
        time = 3,611 ms.

        The complexity of the algorithm is polynomial in the degree :math:`d` of the
        splitting field and the bitsize of :math:`T`; if :math:`d` is large the result will
        likely be unusable, e.g. :literal:`nfinit` will not be an option:

        ::

        ? nfsplitting(x^6-x-1)
        [... degree 720 polynomial deleted ...]
        time = 11,020 ms.
        '''
        P = objtogen(P)
        cdef bint _have_d = (d is not None)
        if _have_d:
            d = objtogen(d)
        sig_on()
        cdef GEN _P = (<Gen>P).g
        cdef GEN _d = NULL
        if _have_d:
            _d = (<Gen>d).g
        cdef GEN _ret = nfsplitting(_P, _d)
        return new_gen(_ret)

    def nfsubfields(self, pol, long d=0):
        r'''
        Finds all subfields of degree
        :math:`d` of the number field defined by the (monic, integral) polynomial
        :emphasis:`pol` (all subfields if :math:`d` is null or omitted). The result is a vector
        of subfields, each being given by :math:`[g,h]`, where :math:`g` is an absolute equation
        and :math:`h` expresses one of the roots of :math:`g` in terms of the root :math:`x` of the
        polynomial defining :math:`nf`. This routine uses J. Klüners's algorithm
        in the general case, and B. Allombert's :literal:`galoissubfields` when :emphasis:`nf`
        is Galois (with weakly supersolvable Galois group).
        '''
        pol = objtogen(pol)
        sig_on()
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _ret = nfsubfields(_pol, d)
        return new_gen(_ret)

    def norm(self, x):
        r'''
        Algebraic norm of :math:`x`, i.e. the product of :math:`x` with
        its conjugate (no square roots are taken), or conjugates for polmods. For
        vectors and matrices, the norm is taken componentwise and hence is not the
        :math:`L^2`-norm (see :literal:`norml2`). Note that the norm of an element of
        :math:`\mathbb{R}` is its square, so as to be compatible with the complex norm.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gnorm(_x)
        return new_gen(_ret)

    def norml2(self, x):
        r'''
        Square of the :math:`L^2`-norm of :math:`x`. More precisely,
        if :math:`x` is a scalar, :math:`norml2 (x)` is defined to be the square
        of the complex modulus of :math:`x` (real :literal:`t_QUAD` s are not supported).
        If :math:`x` is a polynomial, a (row or column) vector or a matrix, :literal:`norml2(:math:`x`)` is
        defined recursively as :math:`\sum_i norml2 (x_i)`, where :math:`(x_i)` run through
        the components of :math:`x`. In particular, this yields the usual :math:`\sum \|x_i\|^2`
        (resp. :math:`\sum \|x_{i,j}\|^2`) if :math:`x` is a polynomial or vector (resp. matrix) with
        complex components.

        ::

        ? norml2( [ 1, 2, 3 ] ) \\ vector
        %1 = 14
        ? norml2( [ 1, 2; 3, 4] ) \\ matrix
        %2 = 30
        ? norml2( 2*I + x )
        %3 = 5
        ? norml2( [ [1,2], [3,4], 5, 6 ] ) \\ recursively defined
        %4 = 91
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gnorml2(_x)
        return new_gen(_ret)

    def normlp(self, x, p=None, long precision=DEFAULT_BITPREC):
        r'''
        :math:`L^p`-norm of :math:`x`; sup norm if :math:`p` is omitted or :literal:`+oo`. More precisely,
        if :math:`x` is a scalar, :literal:`normlp`:math:`(x, p)` is defined to be :literal:`abs`:math:`(x)`.
        If :math:`x` is a polynomial, a (row or column) vector or a matrix:

        - if :math:`p` is omitted or :literal:`+oo`, then :literal:`normlp(:math:`x`)` is defined
        recursively as :math:`\max_i normlp (x_i))`, where :math:`(x_i)` run through the
        components of :math:`x`. In particular, this yields the usual sup norm if :math:`x` is a
        polynomial or vector with complex components.

        - otherwise, :literal:`normlp(:math:`x`, :math:`p`)` is defined recursively as :math:`(\sum_i
        normlp^p(x_i,p))^{1/p}`. In particular, this yields the usual :math:`(\sum
        \|x_i\|^p)^{1/p}` if :math:`x` is a polynomial or vector with complex components.

        ::

        ? v = [1,-2,3]; normlp(v) \\ vector
        %1 = 3
        ? normlp(v, +oo) \\ same, more explicit
        %2 = 3
        ? M = [1,-2;-3,4]; normlp(M) \\ matrix
        %3 = 4
        ? T = (1+I) + I*x^2; normlp(T)
        %4 = 1.4142135623730950488016887242096980786
        ? normlp([[1,2], [3,4], 5, 6]) \\ recursively defined
        %5 = 6
        
        ? normlp(v, 1)
        %6 = 6
        ? normlp(M, 1)
        %7 = 10
        ? normlp(T, 1)
        %8 = 2.4142135623730950488016887242096980786
        '''
        x = objtogen(x)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gnormlp(_x, _p, precision)
        return new_gen(_ret)

    def numbpart(self, n):
        r'''
        Gives the number of unrestricted partitions of
        :math:`n`, usually called :math:`p(n)` in the literature; in other words the number of
        nonnegative integer solutions to :math:`a+2b+3c+.. .= n`. :math:`n` must be of type
        integer and :math:`n < 10^{15}` (with trivial values :math:`p(n) = 0` for :math:`n < 0` and
        :math:`p(0) = 1`). The algorithm uses the Hardy-Ramanujan-Rademacher formula.
        To explicitly enumerate them, see :literal:`partitions`.
        '''
        n = objtogen(n)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = numbpart(_n)
        return new_gen(_ret)

    def numdiv(self, x):
        r'''
        Number of divisors of :math:`\|x\|`. :math:`x` must be of type integer.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = numdiv(_x)
        return new_gen(_ret)

    def numerator(self, f, D=None):
        r'''
        Numerator of :math:`f`. This is defined as :literal:`f * denominator(f,D)`, see
        :literal:`denominator` for details. The optional argument :math:`D` allows to control
        over which ring we compute the denominator:

        - :math:`1`: we only consider the underlying :math:`\mathbb{Q}`-structure and the
        denominator is a (positive) rational integer

        - a simple variable, say :literal:`'x`: all entries as rational functions
        in :math:`K(x)` and the denominator is a polynomial in :math:`x`.

        ::

        ? f = x + 1/y + 1/2;
        ? numerator(f) \\ a t_POL in x
        %2 = x + ((y + 2)/(2*y))
        ? numerator(f, 1) \\ Q-denominator is 2
        %3 = x + ((y + 2)/y)
        ? numerator(f, y) \\ as a rational function in y
        %5 = 2*y*x + (y + 2)
        '''
        f = objtogen(f)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = numerator(_f, _D)
        return new_gen(_ret)

    def numtoperm(self, long n, k):
        r'''
        Generates the :math:`k`-th permutation (as a row vector of length :math:`n`) of the
        numbers :math:`1` to :math:`n`. The number :math:`k` is taken modulo :math:`n!`, i.e. inverse
        function of :literal:`permtonum`. The numbering used is the standard lexicographic
        ordering, starting at :math:`0`.
        '''
        k = objtogen(k)
        sig_on()
        cdef GEN _k = (<Gen>k).g
        cdef GEN _ret = numtoperm(n, _k)
        return new_gen(_ret)

    def omega(self, x):
        r'''
        Number of distinct prime divisors of :math:`\|x\|`. :math:`x` must be of type integer.

        ::

        ? factor(392)
        %1 =
        [2 3]
        
        [7 2]
        
        ? omega(392)
        %2 = 2; \\ without multiplicity
        ? bigomega(392)
        %3 = 5; \\ = 3+2, with multiplicity
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = omega(_x)
        clear_stack()
        return _ret

    def oo(self):
        r'''
        Returns an object meaning :math:`+ oo`, for use in functions such as
        :literal:`intnum`. It can be negated (:literal:`-oo` represents :math:`- oo`), and
        compared to real numbers (:literal:`t_INT`, :literal:`t_FRAC`, :literal:`t_REAL`), with the
        expected meaning: :math:`+ oo` is greater than any real number and :math:`- oo` is
        smaller.
        '''
        sig_on()
        cdef GEN _ret = mkoo()
        return new_gen(_ret)

    def padicappr(self, pol, a):
        r'''
        Vector of :math:`p`-adic roots of the polynomial :emphasis:`pol` congruent to the
        :math:`p`-adic number :math:`a` modulo :math:`p`, and with the same :math:`p`-adic precision as :math:`a`.
        The number :math:`a` can be an ordinary :math:`p`-adic number (type :literal:`t_PADIC`, i.e. an
        element of :math:`\mathbb{Z}_p`) or can be an integral element of a finite
        :emphasis:`unramified` extension :math:`\mathbb{Q}_p[X]/(T)` of :math:`\mathbb{Q}_p`, given as a :literal:`t_POLMOD`
        :literal:`Mod`:math:`(A,T)` at least one of whose coefficients is a :literal:`t_PADIC` and :math:`T`
        irreducible modulo :math:`p`. In this case, the result is the vector of roots
        belonging to the same extension of :math:`\mathbb{Q}_p` as :math:`a`. The polynomial :emphasis:`pol`
        should have exact coefficients; if not, its coefficients are first rounded
        to :math:`\mathbb{Q}` or :math:`\mathbb{Q}[X]/(T)` and this is the polynomial whose roots we consider.
        '''
        pol = objtogen(pol)
        a = objtogen(a)
        sig_on()
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _ret = padicappr(_pol, _a)
        return new_gen(_ret)

    def padicfields(self, p, N, long flag=0):
        r'''
        Returns a vector of polynomials generating all the extensions of degree
        :math:`N` of the field :math:`\mathbb{Q}_p` of :math:`p`-adic rational numbers; :math:`N` is
        allowed to be a 2-component vector :math:`[n,d]`, in which case we return the
        extensions of degree :math:`n` and discriminant :math:`p^d`.

        The list is minimal in the sense that two different polynomials generate
        non-isomorphic extensions; in particular, the number of polynomials is the
        number of classes of non-isomorphic extensions. If :math:`P` is a polynomial in this
        list, :math:`\alpha` is any root of :math:`P` and :math:`K = \mathbb{Q}_p(\alpha)`, then :math:`\alpha`
        is the sum of a uniformizer and a (lift of a) generator of the residue field
        of :math:`K`; in particular, the powers of :math:`\alpha` generate the ring of :math:`p`-adic
        integers of :math:`K`.

        If :math:`flag = 1`, replace each polynomial :math:`P` by a vector :math:`[P, e, f, d, c]`
        where :math:`e` is the ramification index, :math:`f` the residual degree, :math:`d` the
        valuation of the discriminant, and :math:`c` the number of conjugate fields.
        If :math:`flag = 2`, only return the :emphasis:`number` of extensions in a fixed
        algebraic closure (Krasner's formula), which is much faster.
        '''
        p = objtogen(p)
        N = objtogen(N)
        sig_on()
        cdef GEN _p = (<Gen>p).g
        cdef GEN _N = (<Gen>N).g
        cdef GEN _ret = padicfields0(_p, _N, flag)
        return new_gen(_ret)

    def padicprec(self, x, p):
        r'''
        Returns the absolute :math:`p`-adic precision of the object :math:`x`; this is the
        minimum precision of the components of :math:`x`. The result is :literal:`+oo` if :math:`x`
        is an exact object (as a :math:`p`-adic):

        ::

        ? padicprec((1 + O(2^5)) * x + (2 + O(2^4)), 2)
        %1 = 4
        ? padicprec(x + 2, 2)
        %2 = +oo
        ? padicprec(2 + x + O(x^2), 2)
        %3 = +oo

        The function raises an exception if it encounters
        an object incompatible with :math:`p`-adic computations:

        ::

        ? padicprec(O(3), 2)
        *** at top-level: padicprec(O(3),2)
        *** ^-----------------
        *** padicprec: inconsistent moduli in padicprec: 3 != 2
        
        ? padicprec(1.0, 2)
        *** at top-level: padicprec(1.0,2)
        *** ^----------------
        *** padicprec: incorrect type in padicprec (t_REAL).
        '''
        x = objtogen(x)
        p = objtogen(p)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = gppadicprec(_x, _p)
        return new_gen(_ret)

    def parapply(self, f, x):
        r'''
        Parallel evaluation of :literal:`f` on the elements of :literal:`x`.
        The function :literal:`f` must not access global variables or variables
        declared with local(), and must be free of side effects.

        ::

        parapply(factor,[2^256 + 1, 2^193 - 1])

        factors :math:`2^{256} + 1` and :math:`2^{193} - 1` in parallel.

        ::

        {
        my(E = ellinit([1,3]), V = vector(12,i,randomprime(2^200)));
        parapply(p->ellcard(E,p), V)
        }

        computes the order of :math:`E(\mathbb{F}_p)` for :math:`12` random primes of :math:`200` bits.
        '''
        f = objtogen(f)
        x = objtogen(x)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = parapply(_f, _x)
        return new_gen(_ret)

    def pareval(self, x):
        r'''
        Parallel evaluation of the elements of :literal:`x`, where :literal:`x` is a
        vector of closures. The closures must be of arity :math:`0`, must not access
        global variables or variables declared with :literal:`local` and must be
        free of side effects.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = pareval(_x)
        return new_gen(_ret)

    def parselect(self, f, A, long flag=0):
        r'''
        Selects elements of :math:`A` according to the selection function :math:`f`, done in
        parallel. If :emphasis:`flag` is :math:`1`, return the indices of those elements (indirect
        selection) The function :literal:`f` must not access global variables or
        variables declared with local(), and must be free of side effects.
        '''
        f = objtogen(f)
        A = objtogen(A)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _A = (<Gen>A).g
        cdef GEN _ret = parselect(_f, _A, flag)
        return new_gen(_ret)

    def partitions(self, long k, a=None, n=None):
        r'''
        Returns the vector of partitions of the integer :math:`k` as a sum of positive
        integers (parts); for :math:`k < 0`, it returns the empty set :literal:`[]`, and for :math:`k
        = 0` the trivial partition (no parts). A partition is given by a
        :literal:`t_VECSMALL`, where parts are sorted in nondecreasing order:

        ::

        ? partitions(3)
        %1 = [Vecsmall([3]), Vecsmall([1, 2]), Vecsmall([1, 1, 1])]

        correspond to :math:`3`, :math:`1+2` and :math:`1+1+1`. The number
        of (unrestricted) partitions of :math:`k` is given
        by :literal:`numbpart`:

        ::

        ? #partitions(50)
        %1 = 204226
        ? numbpart(50)
        %2 = 204226

        Optional parameters :math:`n` and :math:`a` are as follows:

        - :math:`n = nmax` (resp. :math:`n = [nmin,nmax]`) restricts
        partitions to length less than :math:`nmax` (resp. length between
        :math:`nmin` and :math:`nmax`), where the :emphasis:`length` is the number of nonzero
        entries.

        - :math:`a = amax` (resp. :math:`a = [amin,amax]`) restricts the parts
        to integers less than :math:`amax` (resp. between :math:`amin` and
        :math:`amax`).

        ::

        ? partitions(4, 2) \\ parts bounded by 2
        %1 = [Vecsmall([2, 2]), Vecsmall([1, 1, 2]), Vecsmall([1, 1, 1, 1])]
        ? partitions(4,, 2) \\ at most 2 parts
        %2 = [Vecsmall([4]), Vecsmall([1, 3]), Vecsmall([2, 2])]
        ? partitions(4,[0,3], 2) \\ at most 2 parts
        %3 = [Vecsmall([4]), Vecsmall([1, 3]), Vecsmall([2, 2])]

        By default, parts are positive and we remove zero entries unless
        :math:`amin <= 0`, in which case :math:`nmin` is ignored and we fix :math:`\#X = nmax`:

        ::

        ? partitions(4, [0,3]) \\ parts between 0 and 3
        %1 = [Vecsmall([0, 0, 1, 3]), Vecsmall([0, 0, 2, 2]),\
        Vecsmall([0, 1, 1, 2]), Vecsmall([1, 1, 1, 1])]
        ? partitions(1, [0,3], [2,4]) \\ no partition with 2 to 4 non-zero parts
        %2 = []
        '''
        cdef bint _have_a = (a is not None)
        if _have_a:
            a = objtogen(a)
        cdef bint _have_n = (n is not None)
        if _have_n:
            n = objtogen(n)
        sig_on()
        cdef GEN _a = NULL
        if _have_a:
            _a = (<Gen>a).g
        cdef GEN _n = NULL
        if _have_n:
            _n = (<Gen>n).g
        cdef GEN _ret = partitions(k, _a, _n)
        return new_gen(_ret)

    def permorder(self, x):
        r'''
        Given a permutation :math:`x` on :math:`n` elements, return its order.

        ::

        ? p = Vecsmall([3,1,4,2,5]);
        ? p^2
        %2 = Vecsmall([4,3,2,1,5])
        ? p^4
        %3 = Vecsmall([1,2,3,4,5])
        ? permorder(p)
        %4 = 4
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = permorder(_x)
        clear_stack()
        return _ret

    def permsign(self, x):
        r'''
        Given a permutation :math:`x` on :math:`n` elements, return its signature.

        ::

        ? p = Vecsmall([3,1,4,2,5]);
        ? permsign(p)
        %2 = -1
        ? permsign(p^2)
        %3 = 1
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = permsign(_x)
        clear_stack()
        return _ret

    def permtonum(self, x):
        r'''
        Given a permutation :math:`x` on :math:`n` elements, gives the number :math:`k` such that
        :math:`x = numtoperm(n,k)`, i.e. inverse function of :literal:`numtoperm`.
        The numbering used is the standard lexicographic ordering, starting at :math:`0`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = permtonum(_x)
        return new_gen(_ret)

    def plotbox(self, long w, x2, y2, long filled=0):
        r'''
        Let :math:`(x1,y1)` be the current position of the virtual cursor. Draw in the
        rectwindow :math:`w` the outline of the rectangle which is such that the points
        :math:`(x1,y1)` and :math:`(x2,y2)` are opposite corners. Only the part of the rectangle
        which is in :math:`w` is drawn. The virtual cursor does :emphasis:`not` move.
        If :math:`filled = 1`, fill the box.
        '''
        x2 = objtogen(x2)
        y2 = objtogen(y2)
        sig_on()
        cdef GEN _x2 = (<Gen>x2).g
        cdef GEN _y2 = (<Gen>y2).g
        plotbox(w, _x2, _y2, filled)
        clear_stack()

    def plotclip(self, long w):
        r'''
        `clips' the content of rectwindow :math:`w`, i.e remove all parts of the
        drawing that would not be visible on the screen. Together with
        :literal:`plotcopy` this function enables you to draw on a scratchpad before
        committing the part you're interested in to the final picture.
        '''
        sig_on()
        plotclip(w)
        clear_stack()

    def plotcolor(self, long w, c):
        r'''
        Set default color to :math:`c` in rectwindow :math:`w`. Return [R,G,B] value attached
        to color. Possible values for :math:`c` are

        - a :literal:`t_VEC` or :literal:`t_VECSMALL` :math:`[R,G,B]` giving the color RGB value
        (all 3 values are between 0 and 255), e.g. :literal:`[250,235,215]` or
        equivalently :literal:`[0xfa, 0xeb, 0xd7]` for :literal:`antiquewhite`;

        - a :literal:`t_STR` giving a valid colour name (see the :literal:`rgb.txt`
        file in X11 distributions), e.g. :literal:`"antiquewhite"` or an RGV
        value given by a :literal:`\#` followed by 6 hexadecimal digits, e.g.
        :literal:`"\#faebd7"` for :literal:`antiquewhite`;

        - a :literal:`t_INT`, an index in the :literal:`graphcolormap` default, factory
        setting are

        1 = black, 2 = blue, 3 = violetred, 4 = red, 5 = green, 6 = grey, 7 = gainsborough.

        but this can be extended if needed.

        ::

        ? plotinit(0,100,100);
        ? plotcolor(0, "turquoise")
        %2 = [64, 224, 208]
        ? plotbox(0, 50,50,1);
        ? plotmove(0, 50,50);
        ? plotcolor(0, 2) \\ blue
        %4 = [0, 0, 255]
        ? plotbox(0, 50,50,1);
        ? plotdraw(0);
        '''
        c = objtogen(c)
        sig_on()
        cdef GEN _c = (<Gen>c).g
        cdef GEN _ret = plotcolor(w, _c)
        return new_gen(_ret)

    def plotcopy(self, long sourcew, long destw, dx, dy, long flag=0):
        r'''
        Copy the contents of rectwindow :emphasis:`sourcew` to rectwindow :emphasis:`destw`
        with offset (dx,dy). If flag's bit 1 is set, dx and dy express fractions of
        the size of the current output device, otherwise dx and dy are in pixels. dx
        and dy are relative positions of northwest corners if other bits of flag
        vanish, otherwise of: 2: southwest, 4: southeast, 6: northeast corners
        '''
        dx = objtogen(dx)
        dy = objtogen(dy)
        sig_on()
        cdef GEN _dx = (<Gen>dx).g
        cdef GEN _dy = (<Gen>dy).g
        plotcopy(sourcew, destw, _dx, _dy, flag)
        clear_stack()

    def plotcursor(self, long w):
        r'''
        Give as a 2-component vector the current
        (scaled) position of the virtual cursor corresponding to the rectwindow :math:`w`.
        '''
        sig_on()
        cdef GEN _ret = plotcursor(w)
        return new_gen(_ret)

    def plotdraw(self, w, long flag=0):
        r'''
        Physically draw the rectwindow :math:`w`. More generally,
        :math:`w` can be of the form :math:`[w_1,x_1,y_1,w_2,x_2,y_2,...]` (number of
        components must be divisible by :math:`3`; the windows :math:`w_1`, :math:`w_2`, etc. are
        physically placed with their upper left corner at physical position
        :math:`(x_1,y_1)`, :math:`(x_2,y_2)`,...respectively, and are then drawn together.
        Overlapping regions will thus be drawn twice, and the windows are considered
        transparent. Then display the whole drawing in a window on your screen.
        If :math:`flag != 0`, :math:`x_1`, :math:`y_1` etc. express fractions of the size of the
        current output device
        '''
        w = objtogen(w)
        sig_on()
        cdef GEN _w = (<Gen>w).g
        plotdraw(_w, flag)
        clear_stack()

    def plotexport(self, fmt, list, long flag=0):
        r'''
        Draw list of rectwindows as in :literal:`plotdraw(list,flag)`, returning
        the resulting picture as a character string which can then be written to
        a file. The format :literal:`fmt` is either :literal:`"ps"` (PostScript output)
        or :literal:`"svg"` (Scalable Vector Graphics).

        ::

        ? plotinit(0, 100, 100);
        ? plotbox(0, 50, 50);
        ? plotcolor(0, 2);
        ? plotbox(0, 30, 30);
        ? plotdraw(0); \\ watch result on screen
        ? s = plotexport("svg, 0);
        ? write("graph.svg", s); \\ dump result to file
        '''
        fmt = objtogen(fmt)
        list = objtogen(list)
        sig_on()
        cdef GEN _fmt = (<Gen>fmt).g
        cdef GEN _list = (<Gen>list).g
        cdef GEN _ret = plotexport(_fmt, _list, flag)
        return new_gen(_ret)

    def plothraw(self, X, Y, long flag=0):
        r'''
        Given :math:`X` and :math:`Y` two vectors of equal length, plots (in
        high precision) the points whose :math:`(x,y)`-coordinates are given in
        :math:`X` and :math:`Y`. Automatic positioning and scaling is done, but
        with the same scaling factor on :math:`x` and :math:`y`. If :math:`flag` is 1, join points,
        other non-0 flags toggle display options and should be combinations of bits
        :math:`2^k`, :math:`k >= 3` as in :literal:`ploth`.
        '''
        X = objtogen(X)
        Y = objtogen(Y)
        sig_on()
        cdef GEN _X = (<Gen>X).g
        cdef GEN _Y = (<Gen>Y).g
        cdef GEN _ret = plothraw(_X, _Y, flag)
        return new_gen(_ret)

    def plothrawexport(self, fmt, X, Y, long flag=0):
        r'''
        Given :math:`X` and :math:`Y` two vectors of equal length, plots (in high precision)
        the points whose :math:`(x,y)`-coordinates are given in :math:`X` and :math:`Y`, returning the
        resulting picture as a character string which can then be written to a file.
        The format :literal:`fmt` is either :literal:`"ps"` (PostScript output) or :literal:`"svg"`
        (Scalable Vector Graphics).

        Automatic positioning and scaling is done, but with the same scaling factor
        on :math:`x` and :math:`y`. If :math:`flag` is 1, join points, other non-0 flags toggle display
        options and should be combinations of bits :math:`2^k`, :math:`k >= 3` as in
        :literal:`ploth`.
        '''
        fmt = objtogen(fmt)
        X = objtogen(X)
        Y = objtogen(Y)
        sig_on()
        cdef GEN _fmt = (<Gen>fmt).g
        cdef GEN _X = (<Gen>X).g
        cdef GEN _Y = (<Gen>Y).g
        cdef GEN _ret = plothrawexport(_fmt, _X, _Y, flag)
        return new_gen(_ret)

    def plothsizes(self, long flag=0):
        r'''
        Return data corresponding to the output window
        in the form of a 8-component vector: window width and height, sizes for ticks
        in horizontal and vertical directions (this is intended for the :literal:`gnuplot`
        interface and is currently not significant), width and height of characters,
        width and height of display, if applicable. If display has no sense, e.g.
        for svg plots or postscript plots, then width and height of display are set
        to 0.

        If :math:`flag = 0`, sizes of ticks and characters are in
        pixels, otherwise are fractions of the screen size
        '''
        sig_on()
        cdef GEN _ret = plothsizes(flag)
        return new_gen(_ret)

    def plotinit(self, long w, x=None, y=None, long flag=0):
        r'''
        Initialize the rectwindow :math:`w`,
        destroying any rect objects you may have already drawn in :math:`w`. The virtual
        cursor is set to :math:`(0,0)`. The rectwindow size is set to width :math:`x` and height
        :math:`y`; omitting either :math:`x` or :math:`y` means we use the full size of the device
        in that direction.
        If :math:`flag = 0`, :math:`x` and :math:`y` represent pixel units. Otherwise, :math:`x` and :math:`y`
        are understood as fractions of the size of the current output device (hence
        must be between :math:`0` and :math:`1`) and internally converted to pixels.

        The plotting device imposes an upper bound for :math:`x` and :math:`y`, for instance the
        number of pixels for screen output. These bounds are available through the
        :literal:`plothsizes` function. The following sequence initializes in a portable
        way (i.e independent of the output device) a window of maximal size, accessed
        through coordinates in the :math:`[0,1000] x [0,1000]` range:

        ::

        s = plothsizes();
        plotinit(0, s[1]-1, s[2]-1);
        plotscale(0, 0,1000, 0,1000);
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        cdef bint _have_y = (y is not None)
        if _have_y:
            y = objtogen(y)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _y = NULL
        if _have_y:
            _y = (<Gen>y).g
        plotinit(w, _x, _y, flag)
        clear_stack()

    def plotkill(self, long w):
        r'''
        Erase rectwindow :math:`w` and free the corresponding memory. Note that if you
        want to use the rectwindow :math:`w` again, you have to use :literal:`plotinit` first
        to specify the new size. So it's better in this case to use :literal:`plotinit`
        directly as this throws away any previous work in the given rectwindow.
        '''
        sig_on()
        plotkill(w)
        clear_stack()

    def plotlines(self, long w, X, Y, long flag=0):
        r'''
        Draw on the rectwindow :math:`w`
        the polygon such that the (x,y)-coordinates of the vertices are in the
        vectors of equal length :math:`X` and :math:`Y`. For simplicity, the whole
        polygon is drawn, not only the part of the polygon which is inside the
        rectwindow. If :math:`flag` is non-zero, close the polygon. In any case, the
        virtual cursor does not move.

        :math:`X` and :math:`Y` are allowed to be scalars (in this case, both have to).
        There, a single segment will be drawn, between the virtual cursor current
        position and the point :math:`(X,Y)`. And only the part thereof which
        actually lies within the boundary of :math:`w`. Then :emphasis:`move` the virtual cursor
        to :math:`(X,Y)`, even if it is outside the window. If you want to draw a
        line from :math:`(x1,y1)` to :math:`(x2,y2)` where :math:`(x1,y1)` is not necessarily the
        position of the virtual cursor, use :literal:`plotmove(w,x1,y1)` before using this
        function.
        '''
        X = objtogen(X)
        Y = objtogen(Y)
        sig_on()
        cdef GEN _X = (<Gen>X).g
        cdef GEN _Y = (<Gen>Y).g
        plotlines(w, _X, _Y, flag)
        clear_stack()

    def plotlinetype(self, long w, long type):
        r'''
        This function is obsolete and currently a no-op.

        Change the type of lines subsequently plotted in rectwindow :math:`w`.
        :emphasis:`type` :math:`-2` corresponds to frames, :math:`-1` to axes, larger values may
        correspond to something else. :math:`w = -1` changes highlevel plotting.
        '''
        from warnings import warn
        warn('the PARI/GP function plotlinetype is obsolete (2007-05-11)', DeprecationWarning)
        sig_on()
        plotlinetype(w, type)
        clear_stack()

    def plotmove(self, long w, x, y):
        r'''
        Move the virtual cursor of the rectwindow :math:`w` to position :math:`(x,y)`.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        plotmove(w, _x, _y)
        clear_stack()

    def plotpoints(self, long w, X, Y):
        r'''
        Draw on the rectwindow :math:`w` the
        points whose :math:`(x,y)`-coordinates are in the vectors of equal length :math:`X` and
        :math:`Y` and which are inside :math:`w`. The virtual cursor does :emphasis:`not` move. This
        is basically the same function as :literal:`plothraw`, but either with no scaling
        factor or with a scale chosen using the function :literal:`plotscale`.

        As was the case with the :literal:`plotlines` function, :math:`X` and :math:`Y` are allowed to
        be (simultaneously) scalar. In this case, draw the single point :math:`(X,Y)` on
        the rectwindow :math:`w` (if it is actually inside :math:`w`), and in any case
        :emphasis:`move` the virtual cursor to position :math:`(x,y)`.

        If you draw few points in the rectwindow, they will be hard to see; in
        this case, you can use filled boxes instead. Compare:

        ::

        ? plotinit(0, 100,100); plotpoints(0, 50,50);
        ? plotdraw(0)
        ? plotinit(1, 100,100); plotmove(1,48,48); plotrbox(1, 4,4, 1);
        ? plotdraw(1)
        '''
        X = objtogen(X)
        Y = objtogen(Y)
        sig_on()
        cdef GEN _X = (<Gen>X).g
        cdef GEN _Y = (<Gen>Y).g
        plotpoints(w, _X, _Y)
        clear_stack()

    def plotpointsize(self, long w, size):
        r'''
        This function is obsolete. It is currently a no-op.

        Changes the "size" of following points in rectwindow :math:`w`. If :math:`w = -1`,
        change it in all rectwindows.
        '''
        from warnings import warn
        warn('the PARI/GP function plotpointsize is obsolete (2007-05-11)', DeprecationWarning)
        size = objtogen(size)
        sig_on()
        cdef GEN _size = (<Gen>size).g
        plotpointsize(w, _size)
        clear_stack()

    def plotpointtype(self, long w, long type):
        r'''
        This function is obsolete and currently a no-op.

        change the type of points subsequently plotted in rectwindow :math:`w`.
        :math:`type = -1` corresponds to a dot, larger values may correspond to
        something else. :math:`w = -1` changes highlevel plotting.
        '''
        from warnings import warn
        warn('the PARI/GP function plotpointtype is obsolete (2007-05-11)', DeprecationWarning)
        sig_on()
        plotpointtype(w, type)
        clear_stack()

    def plotrbox(self, long w, dx, dy, long filled=0):
        r'''
        Draw in the rectwindow :math:`w` the outline of the rectangle which is such
        that the points :math:`(x1,y1)` and :math:`(x1+dx,y1+dy)` are opposite corners, where
        :math:`(x1,y1)` is the current position of the cursor. Only the part of the
        rectangle which is in :math:`w` is drawn. The virtual cursor does :emphasis:`not` move.
        If :math:`filled = 1`, fill the box.
        '''
        dx = objtogen(dx)
        dy = objtogen(dy)
        sig_on()
        cdef GEN _dx = (<Gen>dx).g
        cdef GEN _dy = (<Gen>dy).g
        plotrbox(w, _dx, _dy, filled)
        clear_stack()

    def plotrecthraw(self, long w, data, long flags=0):
        r'''
        Plot graph(s) for
        :emphasis:`data` in rectwindow :math:`w`. :math:`flag` has the same significance here as in
        :literal:`ploth`, though recursive plot is no more significant.

        :emphasis:`data` is a vector of vectors, each corresponding to a list a coordinates.
        If parametric plot is set, there must be an even number of vectors, each
        successive pair corresponding to a curve. Otherwise, the first one contains
        the :math:`x` coordinates, and the other ones contain the :math:`y`-coordinates
        of curves to plot.
        '''
        data = objtogen(data)
        sig_on()
        cdef GEN _data = (<Gen>data).g
        cdef GEN _ret = plotrecthraw(w, _data, flags)
        return new_gen(_ret)

    def plotrline(self, long w, dx, dy):
        r'''
        Draw in the rectwindow :math:`w` the part of the segment
        :math:`(x1,y1)-(x1+dx,y1+dy)` which is inside :math:`w`, where :math:`(x1,y1)` is the current
        position of the virtual cursor, and move the virtual cursor to
        :math:`(x1+dx,y1+dy)` (even if it is outside the window).
        '''
        dx = objtogen(dx)
        dy = objtogen(dy)
        sig_on()
        cdef GEN _dx = (<Gen>dx).g
        cdef GEN _dy = (<Gen>dy).g
        plotrline(w, _dx, _dy)
        clear_stack()

    def plotrmove(self, long w, dx, dy):
        r'''
        Move the virtual cursor of the rectwindow :math:`w` to position
        :math:`(x1+dx,y1+dy)`, where :math:`(x1,y1)` is the initial position of the cursor
        (i.e. to position :math:`(dx,dy)` relative to the initial cursor).
        '''
        dx = objtogen(dx)
        dy = objtogen(dy)
        sig_on()
        cdef GEN _dx = (<Gen>dx).g
        cdef GEN _dy = (<Gen>dy).g
        plotrmove(w, _dx, _dy)
        clear_stack()

    def plotrpoint(self, long w, dx, dy):
        r'''
        Draw the point :math:`(x1+dx,y1+dy)` on the rectwindow :math:`w` (if it is inside
        :math:`w`), where :math:`(x1,y1)` is the current position of the cursor, and in any case
        move the virtual cursor to position :math:`(x1+dx,y1+dy)`.

        If you draw few points in the rectwindow, they will be hard to see; in
        this case, you can use filled boxes instead. Compare:

        ::

        ? plotinit(0, 100,100); plotrpoint(0, 50,50); plotrpoint(0, 10,10);
        ? plotdraw(0)
        
        ? thickpoint(w,x,y)= plotmove(w,x-2,y-2); plotrbox(w,4,4,1);
        ? plotinit(1, 100,100); thickpoint(1, 50,50); thickpoint(1, 60,60);
        ? plotdraw(1)
        '''
        dx = objtogen(dx)
        dy = objtogen(dy)
        sig_on()
        cdef GEN _dx = (<Gen>dx).g
        cdef GEN _dy = (<Gen>dy).g
        plotrpoint(w, _dx, _dy)
        clear_stack()

    def plotscale(self, long w, x1, x2, y1, y2):
        r'''
        Scale the local coordinates of the rectwindow :math:`w` so that :math:`x` goes from
        :math:`x1` to :math:`x2` and :math:`y` goes from :math:`y1` to :math:`y2` (:math:`x2 < x1` and :math:`y2 < y1` being
        allowed). Initially, after the initialization of the rectwindow :math:`w` using
        the function :literal:`plotinit`, the default scaling is the graphic pixel count,
        and in particular the :math:`y` axis is oriented downwards since the origin is at
        the upper left. The function :literal:`plotscale` allows to change all these
        defaults and should be used whenever functions are graphed.
        '''
        x1 = objtogen(x1)
        x2 = objtogen(x2)
        y1 = objtogen(y1)
        y2 = objtogen(y2)
        sig_on()
        cdef GEN _x1 = (<Gen>x1).g
        cdef GEN _x2 = (<Gen>x2).g
        cdef GEN _y1 = (<Gen>y1).g
        cdef GEN _y2 = (<Gen>y2).g
        plotscale(w, _x1, _x2, _y1, _y2)
        clear_stack()

    def plotstring(self, long w, x, long flags=0):
        r'''
        Draw on the rectwindow :math:`w` the String :math:`x` (see ``strings`` (in the PARI manual)), at
        the current position of the cursor.

        :emphasis:`flag` is used for justification: bits 1 and 2 regulate horizontal alignment:
        left if 0, right if 2, center if 1. Bits 4 and 8 regulate vertical
        alignment: bottom if 0, top if 8, v-center if 4. Can insert additional small
        gap between point and string: horizontal if bit 16 is set, vertical if bit
        32 is set (see the tutorial for an example).
        '''
        x = to_bytes(x)
        cdef char* _x = <bytes>x
        sig_on()
        plotstring(w, _x, flags)
        clear_stack()

    def polchebyshev(self, long n, long flag=1, a=None):
        r'''
        Returns the :math:`n-th`
        Chebyshev polynomial of the first kind :math:`T_n` (:math:`flag = 1`) or the second
        kind :math:`U_n` (:math:`flag = 2`), evaluated at :math:`a` (:literal:`'x` by default). Both series of
        polynomials satisfy the 3-term relation

        .. MATH::

        P_{n+1} = 2xP_n - P_{n-1},

        and are determined by the initial conditions :math:`U_0 = T_0 = 1`, :math:`T_1 = x`,
        :math:`U_1 = 2x`. In fact :math:`T_n' = n U_{n-1}` and, for all complex numbers :math:`z`, we
        have :math:`T_n(\cos z) = \cos (nz)` and :math:`U_{n-1}(\cos z) = \sin (nz)/\sin z`.
        If :math:`n >= 0`, then these polynomials have degree :math:`n`. For :math:`n < 0`,
        :math:`T_n` is equal to :math:`T_{-n}` and :math:`U_n` is equal to :math:`-U_{-2-n}`.
        In particular, :math:`U_{-1} = 0`.
        '''
        cdef bint _have_a = (a is not None)
        if _have_a:
            a = objtogen(a)
        sig_on()
        cdef GEN _a = NULL
        if _have_a:
            _a = (<Gen>a).g
        cdef GEN _ret = polchebyshev_eval(n, flag, _a)
        return new_gen(_ret)

    def polclass(self, D, long inv=0, x=None):
        r'''
        Return a polynomial in :math:`\mathbb{Z}[x]` generating the Hilbert class field for the
        imaginary quadratic discriminant :math:`D`. If :math:`inv` is 0 (the default),
        use the modular :math:`j`-function and return the classical Hilbert polynomial,
        otherwise use a class invariant. The following invariants correspond to
        the different values of :math:`inv`, where :math:`f` denotes Weber's function
        :literal:`weber`, and :math:`w_{p,q}` the double eta quotient given by
        :math:`w_{p,q} = (\eta (x/p) \eta (x/q) )/(\eta (x) \eta (x/{pq}) )`

        The invariants :math:`w_{p,q}` are not allowed unless they satisfy the following
        technical conditions ensuring they do generate the Hilbert class
        field and not a strict subfield:

        - if :math:`p != q`, we need them both non-inert, prime to the conductor of
        :math:`\mathbb{Z}[\sqrt{D}]`. Let :math:`P, Q` be prime ideals above :math:`p` and :math:`q`; if both are
        unramified, we further require that :math:`P^{± 1} Q^{± 1}` be all distinct in
        the class group of :math:`\mathbb{Z}[\sqrt{D}]`; if both are ramified, we require that :math:`PQ
        != 1` in the class group.

        - if :math:`p = q`, we want it split and prime to the conductor and
        the prime ideal above it must have order :math:`!= 1, 2, 4` in the class group.

        Invariants are allowed under the additional conditions on :math:`D`
        listed below.

        - 0 : :math:`j`

        - 1 : :math:`f`, :math:`D = 1 mod 8` and :math:`D = 1,2 mod 3`;

        - 2 : :math:`f^2`, :math:`D = 1 mod 8` and :math:`D = 1,2 mod 3`;

        - 3 : :math:`f^3`, :math:`D = 1 mod 8`;

        - 4 : :math:`f^4`, :math:`D = 1 mod 8` and :math:`D = 1,2 mod 3`;

        - 5 : :math:`\gamma_2 = j^{1/3}`, :math:`D = 1,2 mod 3`;

        - 6 : :math:`w_{2,3}`, :math:`D = 1 mod 8` and :math:`D = 1,2 mod 3`;

        - 8 : :math:`f^8`, :math:`D = 1 mod 8` and :math:`D = 1,2 mod 3`;

        - 9 : :math:`w_{3,3}`, :math:`D = 1 mod 2` and :math:`D = 1,2 mod 3`;

        - 10: :math:`w_{2,5}`, :math:`D != 60 mod 80` and :math:`D = 1,2 mod 3`;

        - 14: :math:`w_{2,7}`, :math:`D = 1 mod 8`;

        - 15: :math:`w_{3,5}`, :math:`D = 1,2 mod 3`;

        - 21: :math:`w_{3,7}`, :math:`D = 1 mod 2` and :math:`21` does not divide :math:`D`

        - 23: :math:`w_{2,3}^2`, :math:`D = 1,2 mod 3`;

        - 24: :math:`w_{2,5}^2`, :math:`D = 1,2 mod 3`;

        - 26: :math:`w_{2,13}`, :math:`D != 156 mod 208`;

        - 27: :math:`w_{2,7}^2`, :math:`D != 28 mod 112`;

        - 28: :math:`w_{3,3}^2`, :math:`D = 1,2 mod 3`;

        - 35: :math:`w_{5,7}`, :math:`D = 1,2 mod 3`;

        - 39: :math:`w_{3,13}`, :math:`D = 1 mod 2` and :math:`D = 1,2 mod 3`;

        The algorithm for computing the polynomial does not use the floating point
        approach, which would evaluate a precise modular function in a precise
        complex argument. Instead, it relies on a faster Chinese remainder based
        approach modulo small primes, in which the class invariant is only defined
        algebraically by the modular polynomial relating the modular function to :math:`j`.
        So in fact, any of the several roots of the modular polynomial may actually
        be the class invariant, and more precise assertions cannot be made.

        For instance, while :literal:`polclass(D)` returns the minimal polynomial of
        :math:`j(\tau)` with :math:`\tau` (any) quadratic integer for the discriminant :math:`D`,
        the polynomial returned by :literal:`polclass(D, 5)` can be the minimal polynomial
        of any of :math:`\gamma_2 (\tau)`, :math:`\zeta_3 \gamma_2 (\tau)` or
        :math:`\zeta_3^2 \gamma_2 (\tau)`, the three roots of the modular polynomial
        :math:`j = \gamma_2^3`, in which :math:`j` has been specialised to :math:`j (\tau)`.

        The modular polynomial is given by
        :math:`j = ((f^{24}-16)^3 )/(f^{24})` for Weber's function :math:`f`.

        For the double eta quotients of level :math:`N = p q`, all functions are covered
        such that the modular curve :math:`X_0^+ (N)`, the function field of which is
        generated by the functions invariant under :math:`\Gamma^0 (N)` and the
        Fricke-Atkin-Lehner involution, is of genus :math:`0` with function field
        generated by (a power of) the double eta quotient :math:`w`.
        This ensures that the full Hilbert class field (and not a proper subfield)
        is generated by class invariants from these double eta quotients.
        Then the modular polynomial is of degree :math:`2` in :math:`j`, and
        of degree :math:`\psi (N) = (p+1)(q+1)` in :math:`w`.

        ::

        ? polclass(-163)
        %1 = x + 262537412640768000
        ? polclass(-51, , 'z)
        %2 = z^2 + 5541101568*z + 6262062317568
        ? polclass(-151,1)
        x^7 - x^6 + x^5 + 3*x^3 - x^2 + 3*x + 1
        '''
        D = objtogen(D)
        cdef long _x = -1
        if x is not None:
            _x = get_var(x)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        cdef GEN _ret = polclass(_D, inv, _x)
        return new_gen(_ret)

    def polcoef(self, x, long n, v=None):
        r'''
        Coefficient of degree :math:`n` of the polynomial :math:`x`, with respect to the
        main variable if :math:`v` is omitted, with respect to :math:`v` otherwise. If :math:`n`
        is greater than the degree, the result is zero.

        Naturally applies to scalars (polynomial of degree :math:`0`), as well as to
        rational functions whose denominator is a monomial. It also applies to power
        series: if :math:`n` is less than the valuation, the result is zero. If it is
        greater than the largest significant degree, then an error message is issued.
        '''
        x = objtogen(x)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = polcoef(_x, n, _v)
        return new_gen(_ret)

    def polcoeff(self, x, long n, v=None):
        r'''
        Deprecated alias for polcoef.
        '''
        from warnings import warn
        warn('the PARI/GP function polcoeff is obsolete (2018-05-14)', DeprecationWarning)
        x = objtogen(x)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = polcoeff0(_x, n, _v)
        return new_gen(_ret)

    def polcompositum(self, P, Q, long flag=0):
        r'''
        :math:`P` and :math:`Q`
        being squarefree polynomials in :math:`\mathbb{Z}[X]` in the same variable, outputs
        the simple factors of the étale :math:`\mathbb{Q}`-algebra :math:`A = \mathbb{Q} (X, Y) / (P(X), Q(Y))`.
        The factors are given by a list of polynomials :math:`R` in :math:`\mathbb{Z}[X]`, attached to
        the number field :math:`\mathbb{Q} (X)/ (R)`, and sorted by increasing degree (with respect
        to lexicographic ordering for factors of equal degrees). Returns an error if
        one of the polynomials is not squarefree.

        Note that it is more efficient to reduce to the case where :math:`P` and :math:`Q` are
        irreducible first. The routine will not perform this for you, since it may be
        expensive, and the inputs are irreducible in most applications anyway. In
        this case, there will be a single factor :math:`R` if and only if the number
        fields defined by :math:`P` and :math:`Q` are linearly disjoint (their intersection is
        :math:`\mathbb{Q}`).

        Assuming :math:`P` is irreducible (of smaller degree than :math:`Q` for efficiency), it
        is in general much faster to proceed as follows

        ::

        nf = nfinit(P); L = nffactor(nf, Q)[,1];
        vector(#L, i, rnfequation(nf, L[i]))

        to obtain the same result. If you are only interested in the degrees of the
        simple factors, the :literal:`rnfequation` instruction can be replaced by a
        trivial :literal:`poldegree(P) * poldegree(L[i])`.

        The binary digits of :math:`flag` mean

        1: outputs a vector of 4-component vectors :math:`[R,a,b,k]`, where :math:`R`
        ranges through the list of all possible compositums as above, and :math:`a`
        (resp. :math:`b`) expresses the root of :math:`P` (resp. :math:`Q`) as an element of
        :math:`\mathbb{Q} (X)/(R)`. Finally, :math:`k` is a small integer such that :math:`b + ka = X` modulo
        :math:`R`.

        2: assume that :math:`P` and :math:`Q` define number fields which are linearly disjoint:
        both polynomials are irreducible and the corresponding number fields
        have no common subfield besides :math:`\mathbb{Q}`. This allows to save a costly
        factorization over :math:`\mathbb{Q}`. In this case return the single simple factor
        instead of a vector with one element.

        A compositum is often defined by a complicated polynomial, which it is
        advisable to reduce before further work. Here is an example involving
        the field :math:`\mathbb{Q} (\zeta_5, 5^{1/5})`:

        ::

        ? L = polcompositum(x^5 - 5, polcyclo(5), 1); \\ list of [R,a,b,k]
        ? [R, a] = L[1]; \\ pick the single factor, extract R,a (ignore b,k)
        ? R \\ defines the compositum
        %3 = x^20 + 5*x^19 + 15*x^18 + 35*x^17 + 70*x^16 + 141*x^15 + 260*x^14\
        + 355*x^13 + 95*x^12 - 1460*x^11 - 3279*x^10 - 3660*x^9 - 2005*x^8 \
        + 705*x^7 + 9210*x^6 + 13506*x^5 + 7145*x^4 - 2740*x^3 + 1040*x^2 \
        - 320*x + 256
        ? a^5 - 5 \\ a fifth root of 5
        %4 = 0
        ? [T, X] = polredbest(R, 1);
        ? T \\ simpler defining polynomial for Q[x]/(R)
        %6 = x^20 + 25*x^10 + 5
        ? X \\  root of R in Q[y]/(T(y))
        %7 = Mod(-1/11*x^15 - 1/11*x^14 + 1/22*x^10 - 47/22*x^5 - 29/11*x^4 + 7/22,\
        x^20 + 25*x^10 + 5)
        ? a = subst(a.pol, 'x, X) \\ a in the new coordinates
        %8 = Mod(1/11*x^14 + 29/11*x^4, x^20 + 25*x^10 + 5)
        ? a^5 - 5
        %9 = 0

        In the above example, :math:`x^5-5` and the :math:`5`-th cyclotomic
        polynomial are irreducible over :math:`\mathbb{Q}`; they have coprime degrees so
        define linearly disjoint extensions and we could have started by

        ::

        ? [R,a] = polcompositum(x^5 - 5, polcyclo(5), 3); \\ [R,a,b,k]
        '''
        P = objtogen(P)
        Q = objtogen(Q)
        sig_on()
        cdef GEN _P = (<Gen>P).g
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _ret = polcompositum0(_P, _Q, flag)
        return new_gen(_ret)

    def polcyclo(self, long n, a=None):
        r'''
        :math:`n`-th cyclotomic polynomial, evaluated at :math:`a` (:literal:`'x` by default). The
        integer :math:`n` must be positive.

        Algorithm used: reduce to the case where :math:`n` is squarefree; to compute the
        cyclotomic polynomial, use :math:`\Phi_{np}(x) = \Phi_n(x^p)/\Phi (x)`; to compute
        it evaluated, use :math:`\Phi_n(x) = \prod_{d \| n} (x^d-1)^{\mu (n/d)}`. In the
        evaluated case, the algorithm assumes that :math:`a^d - 1` is either :math:`0` or
        invertible, for all :math:`d \| n`. If this is not the case (the base ring has
        zero divisors), use :literal:`subst(polcyclo(n),x,a)`.
        '''
        cdef bint _have_a = (a is not None)
        if _have_a:
            a = objtogen(a)
        sig_on()
        cdef GEN _a = NULL
        if _have_a:
            _a = (<Gen>a).g
        cdef GEN _ret = polcyclo_eval(n, _a)
        return new_gen(_ret)

    def polcyclofactors(self, f):
        r'''
        Returns a vector of polynomials, whose product is the product of
        distinct cyclotomic polynomials dividing :math:`f`.

        ::

        ? f = x^10+5*x^8-x^7+8*x^6-4*x^5+8*x^4-3*x^3+7*x^2+3;
        ? v = polcyclofactors(f)
        %2 = [x^2 + 1, x^2 + x + 1, x^4 - x^3 + x^2 - x + 1]
        ? apply(poliscycloprod, v)
        %3 = [1, 1, 1]
        ? apply(poliscyclo, v)
        %4 = [4, 3, 10]

        In general, the polynomials are products of cyclotomic
        polynomials and not themselves irreducible:

        ::

        ? g = x^8+2*x^7+6*x^6+9*x^5+12*x^4+11*x^3+10*x^2+6*x+3;
        ? polcyclofactors(g)
        %2 = [x^6 + 2*x^5 + 3*x^4 + 3*x^3 + 3*x^2 + 2*x + 1]
        ? factor(%[1])
        %3 =
        [ x^2 + x + 1 1]
        
        [x^4 + x^3 + x^2 + x + 1 1]
        '''
        f = objtogen(f)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _ret = polcyclofactors(_f)
        return new_gen(_ret)

    def poldegree(self, x, v=None):
        r'''
        Degree of the polynomial :math:`x` in the main variable if :math:`v` is omitted, in
        the variable :math:`v` otherwise.

        The degree of :math:`0` is :literal:`-oo`. The degree of a non-zero scalar is :math:`0`.
        Finally, when :math:`x` is a non-zero polynomial or rational function, returns the
        ordinary degree of :math:`x`. Raise an error otherwise.
        '''
        x = objtogen(x)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gppoldegree(_x, _v)
        return new_gen(_ret)

    def poldisc(self, pol, v=None):
        r'''
        Discriminant of the polynomial
        :emphasis:`pol` in the main variable if :math:`v` is omitted, in :math:`v` otherwise. Uses a
        modular algorithm over :math:`\mathbb{Z}` or :math:`\mathbb{Q}`, and the subresultant algorithm
        otherwise.

        ::

        ? T = x^4 + 2*x+1;
        ? poldisc(T)
        %2 = -176
        ? poldisc(T^2)
        %3 = 0

        For convenience, the function also applies to types :literal:`t_QUAD` and
        :literal:`t_QFI`/:literal:`t_QFR`:

        ::

        ? z = 3*quadgen(8) + 4;
        ? poldisc(z)
        %2 = 8
        ? q = Qfb(1,2,3);
        ? poldisc(q)
        %4 = -8
        '''
        pol = objtogen(pol)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _ret = poldisc0(_pol, _v)
        return new_gen(_ret)

    def poldiscfactors(self, T, long flag=0):
        r'''
        Given a polynomial :math:`T` with integer coefficients, return
        :math:`[D, faD]` where :math:`D` is the discriminant of :math:`T` and
        :emphasis:`faD` is a cheap partial factorization of :math:`\|D\|`: entries in its first
        column are coprime and not perfect powers but need not be primes.
        The factors are obtained by a combination of trial division, testing for
        perfect powers, factorizations in coprimes, and computing Euclidean
        remainder sequences for :math:`(T,T')` modulo composite factors :math:`d` of :math:`D`
        (which is likely to produce :math:`0`-divisors in :math:`\mathbb{Z}/d\mathbb{Z}`).
        If :emphasis:`flag` is :math:`1`, finish the factorization using :literal:`factorint`.

        ::

        ? T = x^3 - 6021021*x^2 + 12072210077769*x - 8092423140177664432;
        ? [D,faD] = poldiscfactors(T); print(faD); D
        [3, 3; 7, 2; 373, 2; 500009, 2; 24639061, 2]
        %2 = -27937108625866859018515540967767467
        
        ? T = x^3 + 9*x^2 + 27*x - 125014250689643346789780229390526092263790263725;
        ? [D,faD] = poldiscfactors(T); print(faD)
        [2, 6; 3, 3; 125007125141751093502187, 4]
        ? [D,faD] = poldiscfactors(T, 1); print(faD)
        [2, 6; 3, 3; 500009, 12; 1000003, 4]
        '''
        T = objtogen(T)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = poldiscfactors(_T, flag)
        return new_gen(_ret)

    def poldiscreduced(self, f):
        r'''
        Reduced discriminant vector of the
        (integral, monic) polynomial :math:`f`. This is the vector of elementary divisors
        of :math:`\mathbb{Z}[\alpha]/f'(\alpha)\mathbb{Z}[\alpha]`, where :math:`\alpha` is a root of the
        polynomial :math:`f`. The components of the result are all positive, and their
        product is equal to the absolute value of the discriminant of :math:`f`.
        '''
        f = objtogen(f)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _ret = reduceddiscsmith(_f)
        return new_gen(_ret)

    def polgalois(self, T, long precision=DEFAULT_BITPREC):
        r'''
        Galois group of the non-constant
        polynomial :math:`T\in\mathbb{Q}[X]`. In the present version :strong:`2.11.4`, :math:`T` must be irreducible
        and the degree :math:`d` of :math:`T` must be less than or equal to 7. If the
        :literal:`galdata` package has been installed, degrees 8, 9, 10 and 11 are also
        implemented. By definition, if :math:`K = \mathbb{Q}[x]/(T)`, this computes the action of
        the Galois group of the Galois closure of :math:`K` on the :math:`d` distinct roots of
        :math:`T`, up to conjugacy (corresponding to different root orderings).

        The output is a 4-component vector :math:`[n,s,k,name]` with the
        following meaning: :math:`n` is the cardinality of the group, :math:`s` is its signature
        (:math:`s = 1` if the group is a subgroup of the alternating group :math:`A_d`, :math:`s = -1`
        otherwise) and name is a character string containing name of the transitive
        group according to the GAP 4 transitive groups library by Alexander Hulpke.

        :math:`k` is more arbitrary and the choice made up to version 2.2.3 of PARI is rather
        unfortunate: for :math:`d > 7`, :math:`k` is the numbering of the group among all
        transitive subgroups of :math:`S_d`, as given in "The transitive groups of degree up
        to eleven", G. Butler and J. McKay, :emphasis:`Communications in Algebra`, vol. 11,
        1983,
        pp. 863--911 (group :math:`k` is denoted :math:`T_k` there). And for :math:`d <= 7`, it was ad
        hoc, so as to ensure that a given triple would denote a unique group.
        Specifically, for polynomials of degree :math:`d <= 7`, the groups are coded as
        follows, using standard notations

        In degree 1: :math:`S_1 = [1,1,1]`.

        In degree 2: :math:`S_2 = [2,-1,1]`.

        In degree 3: :math:`A_3 = C_3 = [3,1,1]`, :math:`S_3 = [6,-1,1]`.

        In degree 4: :math:`C_4 = [4,-1,1]`, :math:`V_4 = [4,1,1]`, :math:`D_4 = [8,-1,1]`, :math:`A_4 = [12,1,1]`,
        :math:`S_4 = [24,-1,1]`.

        In degree 5: :math:`C_5 = [5,1,1]`, :math:`D_5 = [10,1,1]`, :math:`M_{20} = [20,-1,1]`,
        :math:`A_5 = [60,1,1]`, :math:`S_5 = [120,-1,1]`.

        In degree 6: :math:`C_6 = [6,-1,1]`, :math:`S_3 = [6,-1,2]`, :math:`D_6 = [12,-1,1]`, :math:`A_4 = [12,1,1]`,
        :math:`G_{18} = [18,-1,1]`, :math:`S_4^ -= [24,-1,1]`, :math:`A_4 x C_2 = [24,-1,2]`,
        :math:`S_4^ += [24,1,1]`, :math:`G_{36}^ -= [36,-1,1]`, :math:`G_{36}^ += [36,1,1]`,
        :math:`S_4 x C_2 = [48,-1,1]`, :math:`A_5 = PSL_2(5) = [60,1,1]`, :math:`G_{72} = [72,-1,1]`,
        :math:`S_5 = PGL_2(5) = [120,-1,1]`, :math:`A_6 = [360,1,1]`, :math:`S_6 = [720,-1,1]`.

        In degree 7: :math:`C_7 = [7,1,1]`, :math:`D_7 = [14,-1,1]`, :math:`M_{21} = [21,1,1]`,
        :math:`M_{42} = [42,-1,1]`, :math:`PSL_2(7) = PSL_3(2) = [168,1,1]`, :math:`A_7 = [2520,1,1]`,
        :math:`S_7 = [5040,-1,1]`.

        This is deprecated and obsolete, but for reasons of backward compatibility,
        we cannot change this behavior yet. So you can use the default
        :literal:`new_galois_format` to switch to a consistent naming scheme, namely :math:`k` is
        always the standard numbering of the group among all transitive subgroups of
        :math:`S_n`. If this default is in effect, the above groups will be coded as:

        In degree 1: :math:`S_1 = [1,1,1]`.

        In degree 2: :math:`S_2 = [2,-1,1]`.

        In degree 3: :math:`A_3 = C_3 = [3,1,1]`, :math:`S_3 = [6,-1,2]`.

        In degree 4: :math:`C_4 = [4,-1,1]`, :math:`V_4 = [4,1,2]`, :math:`D_4 = [8,-1,3]`, :math:`A_4 = [12,1,4]`,
        :math:`S_4 = [24,-1,5]`.

        In degree 5: :math:`C_5 = [5,1,1]`, :math:`D_5 = [10,1,2]`, :math:`M_{20} = [20,-1,3]`,
        :math:`A_5 = [60,1,4]`, :math:`S_5 = [120,-1,5]`.

        In degree 6: :math:`C_6 = [6,-1,1]`, :math:`S_3 = [6,-1,2]`, :math:`D_6 = [12,-1,3]`, :math:`A_4 = [12,1,4]`,
        :math:`G_{18} = [18,-1,5]`, :math:`A_4 x C_2 = [24,-1,6]`, :math:`S_4^ += [24,1,7]`,
        :math:`S_4^ -= [24,-1,8]`, :math:`G_{36}^ -= [36,-1,9]`, :math:`G_{36}^ += [36,1,10]`,
        :math:`S_4 x C_2 = [48,-1,11]`, :math:`A_5 = PSL_2(5) = [60,1,12]`, :math:`G_{72} = [72,-1,13]`,
        :math:`S_5 = PGL_2(5) = [120,-1,14]`, :math:`A_6 = [360,1,15]`, :math:`S_6 = [720,-1,16]`.

        In degree 7: :math:`C_7 = [7,1,1]`, :math:`D_7 = [14,-1,2]`, :math:`M_{21} = [21,1,3]`,
        :math:`M_{42} = [42,-1,4]`, :math:`PSL_2(7) = PSL_3(2) = [168,1,5]`, :math:`A_7 = [2520,1,6]`,
        :math:`S_7 = [5040,-1,7]`.

        :strong:`Warning.` The method used is that of resolvent polynomials and is
        sensitive to the current precision. The precision is updated internally but,
        in very rare cases, a wrong result may be returned if the initial precision
        was not sufficient.
        '''
        T = objtogen(T)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        precision = nbits2prec(precision)
        cdef GEN _ret = polgalois(_T, precision)
        return new_gen(_ret)

    def polgraeffe(self, f):
        r'''
        Returns the Graeffe transform :math:`g` of :math:`f`, such that :math:`g(x^2) = f(x)
        f(-x)`.
        '''
        f = objtogen(f)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _ret = polgraeffe(_f)
        return new_gen(_ret)

    def polhensellift(self, A, B, p, long e):
        r'''
        Given a prime :math:`p`, an integral polynomial :math:`A` whose leading coefficient
        is a :math:`p`-unit, a vector :math:`B` of integral polynomials that are monic and
        pairwise relatively prime modulo :math:`p`, and whose product is congruent to
        :math:`A/lc(A)` modulo :math:`p`, lift the elements of :math:`B` to polynomials whose
        product is congruent to :math:`A` modulo :math:`p^e`.

        More generally, if :math:`T` is an integral polynomial irreducible mod :math:`p`, and
        :math:`B` is a factorization of :math:`A` over the finite field :math:`\mathbb{F}_p[t]/(T)`, you can
        lift it to :math:`\mathbb{Z}_p[t]/(T, p^e)` by replacing the :math:`p` argument with :math:`[p,T]`:

        ::

        ? { T = t^3 - 2; p = 7; A = x^2 + t + 1;
        B = [x + (3*t^2 + t + 1), x + (4*t^2 + 6*t + 6)];
        r = polhensellift(A, B, [p, T], 6) }
        %1 = [x + (20191*t^2 + 50604*t + 75783), x + (97458*t^2 + 67045*t + 41866)]
        ? liftall( r[1] * r[2] * Mod(Mod(1,p^6),T) )
        %2 = x^2 + (t + 1)
        '''
        A = objtogen(A)
        B = objtogen(B)
        p = objtogen(p)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _B = (<Gen>B).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = polhensellift(_A, _B, _p, e)
        return new_gen(_ret)

    def polhermite(self, long n, a=None):
        r'''
        :math:`n-th` Hermite polynomial :math:`H_n` evaluated at :math:`a`
        (:literal:`'x` by default), i.e.

        .. MATH::

        H_n(x) = (-1)^n e^{x^2} (d^n)/(dx^n)e^{-x^2}.
        '''
        cdef bint _have_a = (a is not None)
        if _have_a:
            a = objtogen(a)
        sig_on()
        cdef GEN _a = NULL
        if _have_a:
            _a = (<Gen>a).g
        cdef GEN _ret = polhermite_eval(n, _a)
        return new_gen(_ret)

    def polinterpolate(self, X, Y=None, t=None, e=None):
        r'''
        Given the data vectors
        :math:`X` and :math:`Y` of the same length :math:`n` (:math:`X` containing the :math:`x`-coordinates,
        and :math:`Y` the corresponding :math:`y`-coordinates), this function finds the
        interpolating polynomial :math:`P` of minimal degree passing through these
        points and evaluates it at :math:`t`. If :math:`Y` is omitted, the polynomial :math:`P`
        interpolates the :math:`(i,X[i])`. If present, :math:`e` will contain an error estimate
        on the returned value.
        '''
        X = objtogen(X)
        cdef bint _have_Y = (Y is not None)
        if _have_Y:
            Y = objtogen(Y)
        cdef bint _have_t = (t is not None)
        if _have_t:
            t = objtogen(t)
        cdef bint _have_e = (e is not None)
        if _have_e:
            raise NotImplementedError("optional argument e not available")
        sig_on()
        cdef GEN _X = (<Gen>X).g
        cdef GEN _Y = NULL
        if _have_Y:
            _Y = (<Gen>Y).g
        cdef GEN _t = NULL
        if _have_t:
            _t = (<Gen>t).g
        cdef GEN * _e = NULL
        cdef GEN _ret = polint(_X, _Y, _t, _e)
        return new_gen(_ret)

    def poliscyclo(self, f):
        r'''
        Returns 0 if :math:`f` is not a cyclotomic polynomial, and :math:`n > 0` if :math:`f =
        \Phi_n`, the :math:`n`-th cyclotomic polynomial.

        ::

        ? poliscyclo(x^4-x^2+1)
        %1 = 12
        ? polcyclo(12)
        %2 = x^4 - x^2 + 1
        ? poliscyclo(x^4-x^2-1)
        %3 = 0
        '''
        f = objtogen(f)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef long _ret = poliscyclo(_f)
        clear_stack()
        return _ret

    def poliscycloprod(self, f):
        r'''
        Returns 1 if :math:`f` is a product of cyclotomic polynomial, and :math:`0`
        otherwise.

        ::

        ? f = x^6+x^5-x^3+x+1;
        ? poliscycloprod(f)
        %2 = 1
        ? factor(f)
        %3 =
        [ x^2 + x + 1 1]
        
        [x^4 - x^2 + 1 1]
        ? [ poliscyclo(T) | T <- %[,1] ]
        %4 = [3, 12]
        ? polcyclo(3) * polcyclo(12)
        %5 = x^6 + x^5 - x^3 + x + 1
        '''
        f = objtogen(f)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef long _ret = poliscycloprod(_f)
        clear_stack()
        return _ret

    def polisirreducible(self, pol):
        r'''
        :emphasis:`pol` being a polynomial (univariate in the present version :strong:`2.11.4`),
        returns 1 if :emphasis:`pol` is non-constant and irreducible, 0 otherwise.
        Irreducibility is checked over the smallest base field over which :emphasis:`pol`
        seems to be defined.
        '''
        pol = objtogen(pol)
        sig_on()
        cdef GEN _pol = (<Gen>pol).g
        cdef long _ret = isirreducible(_pol)
        clear_stack()
        return _ret

    def pollead(self, x, v=None):
        r'''
        Leading coefficient of the polynomial or power series :math:`x`. This is
        computed with respect to the main variable of :math:`x` if :math:`v` is omitted, with
        respect to the variable :math:`v` otherwise.
        '''
        x = objtogen(x)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = pollead(_x, _v)
        return new_gen(_ret)

    def pollegendre(self, long n, a=None):
        r'''
        :math:`n-th` Legendre polynomial evaluated at :math:`a` (:literal:`'x` by
        default).
        '''
        cdef bint _have_a = (a is not None)
        if _have_a:
            a = objtogen(a)
        sig_on()
        cdef GEN _a = NULL
        if _have_a:
            _a = (<Gen>a).g
        cdef GEN _ret = pollegendre_eval(n, _a)
        return new_gen(_ret)

    def polmodular(self, long L, long inv=0, x=None, y=None, long derivs=0):
        r'''
        Return the modular polynomial of prime level :math:`L` in variables :math:`x` and :math:`y`
        for the modular function specified by :literal:`inv`. If :literal:`inv` is 0 (the
        default), use the modular :math:`j` function, if :literal:`inv` is 1 use the
        Weber-:math:`f` function, and if :literal:`inv` is 5 use :math:`\gamma_2 =
        \sqrt[3]{j}`.
        See :literal:`polclass` for the full list of invariants.
        If :math:`x` is given as :literal:`Mod(j, p)` or an element :math:`j` of
        a finite field (as a :literal:`t_FFELT`), then return the modular polynomial of
        level :math:`L` evaluated at :math:`j`. If :math:`j` is from a finite field and
        :literal:`derivs` is non-zero, then return a triple where the
        last two elements are the first and second derivatives of the modular
        polynomial evaluated at :math:`j`.

        ::

        ? polmodular(3)
        %1 = x^4 + (-y^3 + 2232*y^2 - 1069956*y + 36864000)*x^3 + ...
        ? polmodular(7, 1, , 'J)
        %2 = x^8 - J^7*x^7 + 7*J^4*x^4 - 8*J*x + J^8
        ? polmodular(7, 5, 7*ffgen(19)^0, 'j)
        %3 = j^8 + 4*j^7 + 4*j^6 + 8*j^5 + j^4 + 12*j^2 + 18*j + 18
        ? polmodular(7, 5, Mod(7,19), 'j)
        %4 = Mod(1, 19)*j^8 + Mod(4, 19)*j^7 + Mod(4, 19)*j^6 + ...
        
        ? u = ffgen(5)^0; T = polmodular(3,0,,'j)*u;
        ? polmodular(3, 0, u,'j,1)
        %6 = [j^4 + 3*j^2 + 4*j + 1, 3*j^2 + 2*j + 4, 3*j^3 + 4*j^2 + 4*j + 2]
        ? subst(T,x,u)
        %7 = j^4 + 3*j^2 + 4*j + 1
        ? subst(T',x,u)
        %8 = 3*j^2 + 2*j + 4
        ? subst(T'',x,u)
        %9 = 3*j^3 + 4*j^2 + 4*j + 2
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        cdef long _y = -1
        if y is not None:
            _y = get_var(y)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _ret = polmodular(L, inv, _x, _y, derivs)
        return new_gen(_ret)

    def polrecip(self, pol):
        r'''
        Reciprocal polynomial of :emphasis:`pol`, i.e. the coefficients are in
        reverse order. :emphasis:`pol` must be a polynomial.
        '''
        pol = objtogen(pol)
        sig_on()
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _ret = polrecip(_pol)
        return new_gen(_ret)

    def polred(self, T, long flag=0, _arg3=None):
        r'''
        This function is :emphasis:`deprecated`, use :literal:`polredbest` instead.
        Finds polynomials with reasonably small coefficients defining subfields of
        the number field defined by :math:`T`. One of the polynomials always defines :math:`\mathbb{Q}`
        (hence has degree :math:`1`), and another always defines the same number field
        as :math:`T` if :math:`T` is irreducible.

        All :math:`T` accepted by :literal:`nfinit` are also allowed here;
        in particular, the format :literal:`[T, listP]` is recommended, e.g. with
        :math:`listP = 10^5` or a vector containing all ramified primes. Otherwise,
        the maximal order of :math:`\mathbb{Q}[x]/(T)` must be computed.

        The following binary digits of :math:`flag` are significant:

        1: Possibly use a suborder of the maximal order. The
        primes dividing the index of the order chosen are larger than
        :literal:`primelimit` or divide integers stored in the :literal:`addprimes` table.
        This flag is :emphasis:`deprecated`, the :literal:`[T, listP]` format is more
        flexible.

        2: gives also elements. The result is a two-column matrix, the first column
        giving primitive elements defining these subfields, the second giving the
        corresponding minimal polynomials.

        ::

        ? M = polred(x^4 + 8, 2)
        %1 =
        [ 1 x - 1]
        
        [ 1/2*x^2 + 1 x^2 - 2*x + 3]
        
        [-1/2*x^2 + 1 x^2 - 2*x + 3]
        
        [ 1/2*x^2 x^2 + 2]
        
        [ 1/4*x^3 x^4 + 2]
        ? minpoly(Mod(M[2,1], x^4+8))
        %2 = x^2 + 2
        '''
        from warnings import warn
        warn('the PARI/GP function polred is obsolete (2013-03-27)', DeprecationWarning)
        if _arg3 is not None:
            from warnings import warn
            warn('argument 3 of the PARI/GP function polred is undocumented and deprecated', DeprecationWarning)
        T = objtogen(T)
        cdef bint _have__arg3 = (_arg3 is not None)
        if _have__arg3:
            _arg3 = objtogen(_arg3)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN __arg3 = NULL
        if _have__arg3:
            __arg3 = (<Gen>_arg3).g
        cdef GEN _ret = polred0(_T, flag, __arg3)
        return new_gen(_ret)

    def polredabs(self, T, long flag=0):
        r'''
        Returns a canonical defining polynomial :math:`P` for the number field
        :math:`\mathbb{Q}[X]/(T)` defined by :math:`T`, such that the sum of the squares of the modulus
        of the roots (i.e. the :math:`T_2`-norm) is minimal. Different :math:`T` defining
        isomorphic number fields will yield the same :math:`P`. All :math:`T` accepted by
        :literal:`nfinit` are also allowed here, e.g. non-monic polynomials, or pairs
        :literal:`[T, listP]` specifying that a non-maximal order may be used. For
        convenience, any number field structure (:emphasis:`nf`, :emphasis:`bnf`,...) can also
        be used instead of :math:`T`.

        ::

        ? polredabs(x^2 + 16)
        %1 = x^2 + 1
        ? K = bnfinit(x^2 + 16); polredabs(K)
        %2 = x^2 + 1

        :strong:`Warning 1.` Using a :literal:`t_POL` :math:`T` requires computing
        and fully factoring the discriminant :math:`d_K` of the maximal order which may be
        very hard. You can use the format :literal:`[T, listP]`, where :literal:`listP`
        encodes a list of known coprime divisors of :math:`\mathrm{disc} (T)` (see :literal:`??nfbasis`),
        to help the routine, thereby replacing this part of the algorithm by a
        polynomial time computation But this may only compute a suborder of the
        maximal order, when the divisors are not squarefree or do not include all
        primes dividing :math:`d_K`. The routine attempts to certify the result
        independently of this order computation as per :literal:`nfcertify`: we try to
        prove that the computed order is maximal. If the certification fails,
        the routine then fully factors the integers returned by :literal:`nfcertify`.
        You can use :literal:`polredbest` or :literal:`polredabs(,16)` to avoid this
        factorization step; in both cases, the result is no longer canonical.

        :strong:`Warning 2.` Apart from the factorization of the discriminant of
        :math:`T`, this routine runs in polynomial time for a :emphasis:`fixed` degree.
        But the complexity is exponential in the degree: this routine
        may be exceedingly slow when the number field has many subfields, hence a
        lot of elements of small :math:`T_2`-norm. If you do not need a canonical
        polynomial, the function :literal:`polredbest` is in general much faster (it runs
        in polynomial time), and tends to return polynomials with smaller
        discriminants.

        The binary digits of :math:`flag` mean

        1: outputs a two-component row vector :math:`[P,a]`, where :math:`P` is the default
        output and :literal:`Mod(a, P)` is a root of the original :math:`T`.

        4: gives :emphasis:`all` polynomials of minimal :math:`T_2` norm; of the two polynomials
        :math:`P(x)` and :math:`± P(-x)`, only one is given.

        16: Possibly use a suborder of the maximal order, :emphasis:`without` attempting to
        certify the result as in Warning 1: we always return a polynomial and never
        :math:`0`. The result is a priori not canonical.

        ::

        ? T = x^16 - 136*x^14 + 6476*x^12 - 141912*x^10 + 1513334*x^8 \
        - 7453176*x^6 + 13950764*x^4 - 5596840*x^2 + 46225
        ? T1 = polredabs(T); T2 = polredbest(T);
        ? [ norml2(polroots(T1)), norml2(polroots(T2)) ]
        %3 = [88.0000000, 120.000000]
        ? [ sizedigit(poldisc(T1)), sizedigit(poldisc(T2)) ]
        %4 = [75, 67]

        The precise definition of the output of :literal:`polredabs` is as follows.

        - Consider the finite list of characteristic polynomials of primitive
        elements of :math:`K` that are in :math:`\mathbb{Z}_K` and minimal for the :math:`T_2` norm;
        now remove from the list the polynomials whose discriminant do not have
        minimal absolute value. Note that this condition is restricted to the
        original list of polynomials with minimal :math:`T_2` norm and does not imply that
        the defining polynomial for the field with smallest discriminant belongs to
        the list !

        - To a polynomial :math:`P(x) = x^n +...+ a_n \in \mathbb{R}[x]` we attach
        the sequence :math:`S(P)` given by :math:`\|a_1\|, a_1,..., \|a_n\|, a_n`.
        Order the polynomials :math:`P` by the lexicographic order on the coefficient
        vectors :math:`S(P)`. Then the output of :literal:`polredabs` is the smallest
        polynomial in the above list for that order. In other words, the monic
        polynomial which is lexicographically smallest with respect to the absolute
        values of coefficients, favouring negative coefficients to break ties, i.e.
        choosing :math:`x^3-2` rather than :math:`x^3+2`.
        '''
        T = objtogen(T)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = polredabs0(_T, flag)
        return new_gen(_ret)

    def polredbest(self, T, long flag=0):
        r'''
        Finds a polynomial with reasonably
        small coefficients defining the same number field as :math:`T`.
        All :math:`T` accepted by :literal:`nfinit` are also allowed here (e.g. non-monic
        polynomials, :literal:`nf`, :literal:`bnf`, :literal:`[T,Z_K_basis]`). Contrary to
        :literal:`polredabs`, this routine runs in polynomial time, but it offers no
        guarantee as to the minimality of its result.

        This routine computes an LLL-reduced basis for an order in :math:`\mathbb{Q}[X]/(T)`, then
        examines small linear combinations of the basis vectors, computing their
        characteristic polynomials. It returns the :emphasis:`separable` polynomial :math:`P` of
        smallest discriminant, the one with lexicographically smallest
        :literal:`abs(Vec(P))` in case of ties. This is a good candidate for subsequent
        number field computations since it guarantees that the denominators of
        algebraic integers, when expressed in the power basis, are reasonably small.
        With no claim of minimality, though.

        It can happen that iterating this functions yields better and better
        polynomials, until it stabilizes:

        ::

        ? \p5
        ? P = X^12+8*X^8-50*X^6+16*X^4-3069*X^2+625;
        ? poldisc(P)*1.
        %2 = 1.2622 E55
        ? P = polredbest(P);
        ? poldisc(P)*1.
        %4 = 2.9012 E51
        ? P = polredbest(P);
        ? poldisc(P)*1.
        %6 = 8.8704 E44

        In this example, the initial polynomial :math:`P` is the one
        returned by :literal:`polredabs`, and the last one is stable.

        If :math:`flag = 1`: outputs a two-component row vector :math:`[P,a]`, where :math:`P` is the
        default output and :literal:`Mod(a, P)` is a root of the original :math:`T`.

        ::

        ? [P,a] = polredbest(x^4 + 8, 1)
        %1 = [x^4 + 2, Mod(x^3, x^4 + 2)]
        ? charpoly(a)
        %2 = x^4 + 8

        In particular, the map :math:`\mathbb{Q}[x]/(T) \to \mathbb{Q}[x]/(P)`,
        :math:`x:--->Mod(a,P)` defines an isomorphism of number fields, which can
        be computed as

        ::

        subst(lift(Q), 'x, a)

        if :math:`Q` is a :literal:`t_POLMOD` modulo :math:`T`; :literal:`b = modreverse(a)`
        returns a :literal:`t_POLMOD` giving the inverse of the above map (which should be
        useless since :math:`\mathbb{Q}[x]/(P)` is a priori a better representation for the number
        field and its elements).
        '''
        T = objtogen(T)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = polredbest(_T, flag)
        return new_gen(_ret)

    def polredord(self, x):
        r'''
        This function is obsolete, use polredbest.
        '''
        from warnings import warn
        warn('the PARI/GP function polredord is obsolete (2008-07-20)', DeprecationWarning)
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = polredord(_x)
        return new_gen(_ret)

    def polresultant(self, x, y, v=None, long flag=0):
        r'''
        Resultant of the two
        polynomials :math:`x` and :math:`y` with exact entries, with respect to the main
        variables of :math:`x` and :math:`y` if :math:`v` is omitted, with respect to the variable :math:`v`
        otherwise. The algorithm assumes the base ring is a domain. If you also need
        the :math:`u` and :math:`v` such that :math:`x*u + y*v = Res(x,y)`, use the
        :literal:`polresultantext` function.

        If :math:`flag = 0` (default), uses the algorithm best suited to the inputs,
        either the subresultant algorithm (Lazard/Ducos variant, generic case),
        a modular algorithm (inputs in :math:`\mathbb{Q}[X]`) or Sylvester's matrix (inexact
        inputs).

        If :math:`flag = 1`, uses the determinant of Sylvester's matrix instead; this should
        always be slower than the default.

        If :math:`x` or :math:`y` are multivariate with a huge :emphasis:`polynomial` content, it
        is advisable to remove it before calling this function. Compare:

        ::

        ? a = polcyclo(7) * ((t+1)/(t+2))^100;
        ? b = polcyclo(11)* ((t+2)/(t+3))^100);
        ? polresultant(a,b);
        time = 3,833 ms.
        ? ca = content(a); cb = content(b); \
        polresultant(a/ca,b/cb)*ca^poldegree(b)*cb*poldegree(a); \\ instantaneous

        The function only removes rational denominators and does
        not compute automatically the content because it is generically small and
        potentially :emphasis:`very` expensive (e.g. in multivariate contexts).
        The choice is yours, depending on your application.
        '''
        x = objtogen(x)
        y = objtogen(y)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = polresultant0(_x, _y, _v, flag)
        return new_gen(_ret)

    def polresultantext(self, A, B, v=None):
        r'''
        Finds polynomials :math:`U` and :math:`V` such that :math:`A*U + B*V = R`, where :math:`R` is
        the resultant of :math:`U` and :math:`V` with respect to the main variables of :math:`A` and
        :math:`B` if :math:`v` is omitted, and with respect to :math:`v` otherwise. Returns the row
        vector :math:`[U,V,R]`. The algorithm used (subresultant) assumes that the base
        ring is a domain.

        ::

        ? A = x*y; B = (x+y)^2;
        ? [U,V,R] = polresultantext(A, B)
        %2 = [-y*x - 2*y^2, y^2, y^4]
        ? A*U + B*V
        %3 = y^4
        ? [U,V,R] = polresultantext(A, B, y)
        %4 = [-2*x^2 - y*x, x^2, x^4]
        ? A*U+B*V
        %5 = x^4
        '''
        A = objtogen(A)
        B = objtogen(B)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        cdef GEN _B = (<Gen>B).g
        cdef GEN _ret = polresultantext0(_A, _B, _v)
        return new_gen(_ret)

    def polroots(self, T, long precision=DEFAULT_BITPREC):
        r'''
        Complex roots of the polynomial
        :math:`T`, given as a column vector where each root is repeated according to
        its multiplicity. The precision is given as for transcendental functions: in
        GP it is kept in the variable :literal:`realprecision` and is transparent to the
        user, but it must be explicitly given as a second argument in library mode.

        The algorithm used is a modification of Schönhage's
        root-finding algorithm, due to and originally implemented by Gourdon.
        It is guaranteed to converge; if furthermore :math:`T` has rational coefficients,
        roots are guaranteed to the required relative accuracy.
        '''
        T = objtogen(T)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        precision = nbits2prec(precision)
        cdef GEN _ret = roots(_T, precision)
        return new_gen(_ret)

    def polrootsbound(self, T, tau=None):
        r'''
        Return a sharp upper bound :math:`B` for the modulus of
        the largest complex root of the polynomial :math:`T` with complex coefficients
        with relative error :math:`\tau`. More precisely, we have :math:`\|z\| <= B` for all roots
        and there exist one root such that :math:`\|z_0\| >= B \exp (-2\tau)`. Much faster
        than either polroots or polrootsreal.

        ::

        ? T=poltchebi(500);
        ? vecmax(abs(polroots(T)))
        time = 5,706 ms.
        %2 = 0.99999506520185816611184481744870013191
        ? vecmax(abs(polrootsreal(T)))
        time = 1,972 ms.
        %3 = 0.99999506520185816611184481744870013191
        ? polrootsbound(T)
        time = 217 ms.
        %4 = 1.0098792554165905155
        ? polrootsbound(T, log(2)/2) \\ allow a factor 2, much faster
        time = 51 ms.
        %5 = 1.4065759938190154354
        ? polrootsbound(T, 1e-4)
        time = 504 ms.
        %6 = 1.0000920717983847741
        ? polrootsbound(T, 1e-6)
        time = 810 ms.
        %7 = 0.9999960628901692905
        ? polrootsbound(T, 1e-10)
        time = 1,351 ms.
        %8 = 0.9999950652993869760
        '''
        T = objtogen(T)
        cdef bint _have_tau = (tau is not None)
        if _have_tau:
            tau = objtogen(tau)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN _tau = NULL
        if _have_tau:
            _tau = (<Gen>tau).g
        cdef GEN _ret = polrootsbound(_T, _tau)
        return new_gen(_ret)

    def polrootsff(self, x, p=None, a=None):
        r'''
        Obsolete, kept for backward compatibility: use factormod.
        '''
        from warnings import warn
        warn('the PARI/GP function polrootsff is obsolete (2018-03-11)', DeprecationWarning)
        x = objtogen(x)
        cdef bint _have_p = (p is not None)
        if _have_p:
            p = objtogen(p)
        cdef bint _have_a = (a is not None)
        if _have_a:
            a = objtogen(a)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _p = NULL
        if _have_p:
            _p = (<Gen>p).g
        cdef GEN _a = NULL
        if _have_a:
            _a = (<Gen>a).g
        cdef GEN _ret = polrootsff(_x, _p, _a)
        return new_gen(_ret)

    def polrootsmod(self, f, D=None):
        r'''
        Vector of roots of the polynomial :math:`f` over the finite field defined
        by the domain :math:`D` as follows:

        - :math:`D = p` a prime: factor over :math:`\mathbb{F}_p`;

        - :math:`D = [T,p]` for a prime :math:`p` and :math:`T` an irreducible polynomial over
        :math:`\mathbb{F}_p`: factor over :math:`\mathbb{F}_p[x]/(T)`;

        - :math:`D` a :literal:`t_FFELT`: factor over the attached field;

        - :math:`D` omitted: factor over the field of definition of :math:`f`, which
        must be a finite field.

        Multiple roots are :emphasis:`not` repeated.

        ::

        ? polrootsmod(x^2-1,2)
        %1 = [Mod(1, 2)]~
        ? polrootsmod(x^2+1,3)
        %2 = []~
        ? polrootsmod(x^2+1, [3,y^2+1])
        %3 = [Mod(Mod(1, 3)*y, Mod(1, 3)*y^2 + Mod(1, 3)),
        Mod(Mod(2, 3)*y, Mod(1, 3)*y^2 + Mod(1, 3))]~
        ? polrootsmod(x^2 + Mod(1,3))
        %4 = []~
        ? liftall( polrootsmod(x^2 + Mod(Mod(1,3),y^2+1)) )
        %5 = [y, 2*y]~
        ? t = ffgen(y^2+Mod(1,3)); polrootsmod(x^2 + t^0)
        %6 = [y, 2*y]~
        '''
        f = objtogen(f)
        cdef bint _have_D = (D is not None)
        if _have_D:
            D = objtogen(D)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _D = NULL
        if _have_D:
            _D = (<Gen>D).g
        cdef GEN _ret = polrootsmod(_f, _D)
        return new_gen(_ret)

    def polrootspadic(self, x, p, long r):
        r'''
        Vector of :math:`p`-adic roots of the polynomial :emphasis:`pol`, given to
        :math:`p`-adic precision :math:`r`; the integer :math:`p` is assumed to be a prime.
        Multiple roots are
        :emphasis:`not` repeated. Note that this is not the same as the roots in
        :math:`\mathbb{Z}/p^r\mathbb{Z}`, rather it gives approximations in :math:`\mathbb{Z}/p^r\mathbb{Z}` of the true roots
        living in :math:`\mathbb{Q}_p`.

        ::

        ? polrootspadic(x^3 - x^2 + 64, 2, 5)
        %1 = [2^3 + O(2^5), 2^3 + 2^4 + O(2^5), 1 + O(2^5)]~

        If :emphasis:`pol` has inexact :literal:`t_PADIC` coefficients, this is not always
        well-defined; in this case, the polynomial is first made integral by dividing
        out the :math:`p`-adic content, then lifted
        to :math:`\mathbb{Z}` using :literal:`truncate` coefficientwise. Hence the roots given are
        approximations of the roots of an exact polynomial which is :math:`p`-adically
        close to the input. To avoid pitfalls, we advise to only factor polynomials
        with exact rational coefficients.
        '''
        x = objtogen(x)
        p = objtogen(p)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = rootpadic(_x, _p, r)
        return new_gen(_ret)

    def polrootsreal(self, T, ab=None, long precision=DEFAULT_BITPREC):
        r'''
        Real roots of the polynomial :math:`T` with real coefficients, multiple
        roots being included according to their multiplicity. If the polynomial
        does not have rational coefficients, it is first rescaled and rounded.
        The roots are given to a relative accuracy of :literal:`realprecision`.
        If argument :emphasis:`ab` is
        present, it must be a vector :math:`[a,b]` with two components (of type
        :literal:`t_INT`, :literal:`t_FRAC` or :literal:`t_INFINITY`) and we restrict to roots belonging
        to that closed interval.

        ::

        ? \p9
        ? polrootsreal(x^2-2)
        %1 = [-1.41421356, 1.41421356]~
        ? polrootsreal(x^2-2, [1,+oo])
        %2 = [1.41421356]~
        ? polrootsreal(x^2-2, [2,3])
        %3 = []~
        ? polrootsreal((x-1)*(x-2), [2,3])
        %4 = [2.00000000]~

        The algorithm used is a modification of Uspensky's method (relying on
        Descartes's rule of sign), following Rouillier and Zimmerman's article
        "Efficient isolation of a polynomial real roots"
        (:literal:`http://hal.inria.fr/inria-00072518/`). Barring bugs, it is guaranteed
        to converge and to give the roots to the required accuracy.

        :strong:`Remark.` If the polynomial :math:`T` is of the
        form :math:`Q(x^h)` for some :math:`h >= 2` and :emphasis:`ab` is omitted, the routine will
        apply the algorithm to :math:`Q` (restricting to non-negative roots when :math:`h` is
        even), then take :math:`h`-th roots. On the other hand, if you want to specify
        :emphasis:`ab`, you should apply the routine to :math:`Q` yourself and a suitable
        interval :math:`[a',b']` using approximate :math:`h`-th roots adapted to your problem:
        the function will not perform this change of variables if :emphasis:`ab` is present.
        '''
        T = objtogen(T)
        cdef bint _have_ab = (ab is not None)
        if _have_ab:
            ab = objtogen(ab)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ab = NULL
        if _have_ab:
            _ab = (<Gen>ab).g
        precision = nbits2prec(precision)
        cdef GEN _ret = realroots(_T, _ab, precision)
        return new_gen(_ret)

    def polsturm(self, T, ab=None, _arg3=None):
        r'''
        Number of distinct real roots of the real polynomial :emphasis:`T`. If
        the argument :emphasis:`ab` is present, it must be a vector :math:`[a,b]` with
        two real components (of type :literal:`t_INT`, :literal:`t_REAL`, :literal:`t_FRAC`
        or :literal:`t_INFINITY`) and we count roots belonging to that closed interval.

        If possible, you should stick to exact inputs, that is avoid :literal:`t_REAL` s in
        :math:`T` and the bounds :math:`a,b`: the result is then guaranteed and we use a fast
        algorithm (Uspensky's method, relying on Descartes's rule of sign, see
        :literal:`polrootsreal`). Otherwise, the polynomial is rescaled and rounded first
        and the result may be wrong due to that initial error. If only :math:`a` or :math:`b` is
        inexact, on the other hand, the interval is first thickened using rational
        endpoints and the result remains guaranteed unless there exist a root
        :emphasis:`very` close to a non-rational endpoint (which may be missed or unduly
        included).

        ::

        ? T = (x-1)*(x-2)*(x-3);
        ? polsturm(T)
        %2 = 3
        ? polsturm(T, [-oo,2])
        %3 = 2
        ? polsturm(T, [1/2,+oo])
        %4 = 3
        ? polsturm(T, [1, Pi]) \\ Pi inexact: not recommended !
        %5 = 3
        ? polsturm(T*1., [0, 4]) \\ T*1. inexact: not recommended !
        %6 = 3
        ? polsturm(T^2, [0, 4]) \\ not squarefree: roots are not repeated!
        %7 = 3
        '''
        if _arg3 is not None:
            from warnings import warn
            warn('argument 3 of the PARI/GP function polsturm is undocumented and deprecated', DeprecationWarning)
        T = objtogen(T)
        cdef bint _have_ab = (ab is not None)
        if _have_ab:
            ab = objtogen(ab)
        cdef bint _have__arg3 = (_arg3 is not None)
        if _have__arg3:
            _arg3 = objtogen(_arg3)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ab = NULL
        if _have_ab:
            _ab = (<Gen>ab).g
        cdef GEN __arg3 = NULL
        if _have__arg3:
            __arg3 = (<Gen>_arg3).g
        cdef long _ret = sturmpart(_T, _ab, __arg3)
        clear_stack()
        return _ret

    def polsubcyclo(self, long n, long d, v=None):
        r'''
        Gives polynomials (in variable :math:`v`) defining the sub-Abelian extensions
        of degree :math:`d` of the cyclotomic field :math:`\mathbb{Q} (\zeta_n)`, where :math:`d \| \phi (n)`.

        If there is exactly one such extension the output is a polynomial, else it is
        a vector of polynomials, possibly empty. To get a vector in all cases,
        use :literal:`concat([], polsubcyclo(n,d))`.

        The function :literal:`galoissubcyclo` allows to specify exactly which
        sub-Abelian extension should be computed.
        '''
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _ret = polsubcyclo(n, d, _v)
        return new_gen(_ret)

    def polsylvestermatrix(self, x, y):
        r'''
        Forms the Sylvester matrix
        corresponding to the two polynomials :math:`x` and :math:`y`, where the coefficients of
        the polynomials are put in the columns of the matrix (which is the natural
        direction for solving equations afterwards). The use of this matrix can be
        essential when dealing with polynomials with inexact entries, since
        polynomial Euclidean division doesn't make much sense in this case.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = sylvestermatrix(_x, _y)
        return new_gen(_ret)

    def polsym(self, x, long n):
        r'''
        Creates the column vector of the symmetric powers of the roots of the
        polynomial :math:`x` up to power :math:`n`, using Newton's formula.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = polsym(_x, n)
        return new_gen(_ret)

    def poltchebi(self, long n, v=None):
        r'''
        Deprecated alias for :literal:`polchebyshev`
        '''
        from warnings import warn
        warn('the PARI/GP function poltchebi is obsolete (2013-04-03)', DeprecationWarning)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _ret = polchebyshev1(n, _v)
        return new_gen(_ret)

    def poltschirnhaus(self, x):
        r'''
        Applies a random Tschirnhausen
        transformation to the polynomial :math:`x`, which is assumed to be non-constant
        and separable, so as to obtain a new equation for the étale algebra
        defined by :math:`x`. This is for instance useful when computing resolvents,
        hence is used by the :literal:`polgalois` function.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = tschirnhaus(_x)
        return new_gen(_ret)

    def polylog(self, long m, x, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        One of the different polylogarithms, depending on :emphasis:`flag`:

        If :math:`flag = 0` or is omitted: :math:`m-th` polylogarithm of :math:`x`, i.e. analytic
        continuation of the power series :math:`Li_m(x) = \sum_{n >= 1}x^n/n^m`
        (:math:`x < 1`). Uses the functional equation linking the values at :math:`x` and :math:`1/x`
        to restrict to the case :math:`\|x\| <= 1`, then the power series when
        :math:`\|x\|^2 <= 1/2`, and the power series expansion in :math:`\log (x)` otherwise.

        Using :math:`flag`, computes a modified :math:`m-th` polylogarithm of :math:`x`.
        We use Zagier's notations; let :math:`\Re_m` denote :math:`\Re` or :math:`\Im` depending
        on whether :math:`m` is odd or even:

        If :math:`flag = 1`: compute :math:`~ D_m(x)`, defined for :math:`\|x\| <= 1` by

        .. MATH::

        \Re_m(\sum_{k = 0}^{m-1} ((-\log\|x\|)^k)/(k!)Li_{m-k}(x)
        +((-\log\|x\|)^{m-1})/(m!)\log\|1-x\|).

        If :math:`flag = 2`: compute :math:`D_m(x)`, defined for :math:`\|x\| <= 1` by

        .. MATH::

        \Re_m(\sum_{k = 0}^{m-1}((-\log\|x\|)^k)/(k!)Li_{m-k}(x)
        -(1)/(2)((-\log\|x\|)^m)/(m!)).

        If :math:`flag = 3`: compute :math:`P_m(x)`, defined for :math:`\|x\| <= 1` by

        .. MATH::

        \Re_m(\sum_{k = 0}^{m-1}(2^kB_k)/(k!)(\log\|x\|)^kLi_{m-k}(x)
        -(2^{m-1}B_m)/(m!)(\log\|x\|)^m).

        These three functions satisfy the functional equation
        :math:`f_m(1/x) = (-1)^{m-1}f_m(x)`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = polylog0(m, _x, flag, precision)
        return new_gen(_ret)

    def polzagier(self, long n, long m):
        r'''
        Creates Zagier's polynomial :math:`P_n^{(m)}` used in
        the functions :literal:`sumalt` and :literal:`sumpos` (with :math:`flag = 1`), see
        "Convergence acceleration of alternating series", Cohen et al.,
        :emphasis:`Experiment. Math.`, vol. 9, 2000, pp. 3--12.

        If :math:`m < 0` or :math:`m >= n`, :math:`P_n^{(m)} = 0`.
        We have
        :math:`P_n := P_n^{(0)}` is :math:`T_n(2x-1)`, where :math:`T_n` is the Legendre polynomial of
        the second kind. For :math:`n > m > 0`, :math:`P_n^{(m)}` is the :math:`m`-th difference with
        step :math:`2` of the sequence :math:`n^{m+1}P_n`; in this case, it satisfies

        .. MATH::

        2 P_n^{(m)}(sin^2 t) = (d^{m+1})/(dt^{m+1})(\sin (2t)^m \sin (2(n-m)t)).
        '''
        sig_on()
        cdef GEN _ret = polzag(n, m)
        return new_gen(_ret)

    def powers(self, x, long n, x0=None):
        r'''
        For non-negative :math:`n`, return the vector with :math:`n+1` components
        :math:`[1,x,...,x^n]` if :literal:`x0` is omitted, and :math:`[x_0, x_0*x, ..., x_0*x^n]`
        otherwise.

        ::

        ? powers(Mod(3,17), 4)
        %1 = [Mod(1, 17), Mod(3, 17), Mod(9, 17), Mod(10, 17), Mod(13, 17)]
        ? powers(Mat([1,2;3,4]), 3)
        %2 = [[1, 0; 0, 1], [1, 2; 3, 4], [7, 10; 15, 22], [37, 54; 81, 118]]
        ? powers(3, 5, 2)
        %3 = [2, 6, 18, 54, 162, 486]

        When :math:`n < 0`, the function returns the empty vector :literal:`[]`.
        '''
        x = objtogen(x)
        cdef bint _have_x0 = (x0 is not None)
        if _have_x0:
            x0 = objtogen(x0)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _x0 = NULL
        if _have_x0:
            _x0 = (<Gen>x0).g
        cdef GEN _ret = gpowers0(_x, n, _x0)
        return new_gen(_ret)

    def precision(self, x, long n=0):
        r'''
        The function behaves differently according to whether :math:`n` is
        present and positive or not. If :math:`n` is missing, the function returns the
        floating point precision in decimal digits of the PARI object :math:`x`. If :math:`x`
        has no floating point component, the function returns :literal:`+oo`.

        ::

        ? precision(exp(1e-100))
        %1 = 154 \\ 154 significant decimal digits
        ? precision(2 + x)
        %2 = +oo \\ exact object
        ? precision(0.5 + O(x))
        %3 = 38 \\ floating point accuracy, NOT series precision
        ? precision( [ exp(1e-100), 0.5 ] )
        %4 = 38 \\ minimal accuracy among components

        If :math:`n` is present, the function creates a new object equal to :math:`x` with a new
        floating point precision :math:`n`: :math:`n` is the number of desired significant
        :emphasis:`decimal` digits. If :math:`n` is smaller than the precision of a :literal:`t_REAL`
        component of :math:`x`, it is truncated, otherwise it is extended with zeros.
        For non-floating point types, no change.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = precision0(_x, n)
        return new_gen(_ret)

    def precprime(self, x):
        r'''
        Finds the largest pseudoprime (see
        :literal:`ispseudoprime`) less than or equal to :math:`x`. :math:`x` can be of any real type.
        Returns 0 if :math:`x <= 1`. Note that if :math:`x` is a prime, this function returns :math:`x`
        and not the largest prime strictly smaller than :math:`x`. To rigorously prove that
        the result is prime, use :literal:`isprime`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = precprime(_x)
        return new_gen(_ret)

    def prime(self, long n):
        r'''
        The :math:`n-th` prime number

        ::

        ? prime(10^9)
        %1 = 22801763489

        Uses checkpointing and a naive :math:`O(n)` algorithm. Will need
        about 30 minutes for :math:`n` up to :math:`10^{11}`; make sure to start gp with
        :literal:`primelimit` at least :math:`\sqrt{p_n}`, e.g. the value
        :math:`\sqrt{n\log (n\log n)}` is guaranteed to be sufficient.
        '''
        sig_on()
        cdef GEN _ret = prime(n)
        return new_gen(_ret)

    def primecert(self, N, long flag=0):
        r'''
        If N is a prime, return a PARI Primality Certificate for the prime :math:`N`,
        as described below. Otherwise, return 0. A Primality Certificate
        :math:`c` can be checked using :literal:`primecertisvalid`:math:`(c)`.

        If :math:`flag = 0` (default), return an ECPP certificate (Atkin-Morain)

        A PARI ECPP Primality Certificate for the prime :math:`N` is either a prime
        integer :math:`N < 2^{64}` or a vector :literal:`C` of length :math:`\ell` whose :math:`i`th
        component :literal:`C[i]` is a vector of length :math:`5` containing :math:`N_i`, :math:`t_i`,
        :math:`s_i`, :math:`a_i`, :math:`P_i` (in that order) where :math:`N_1 = N`. It is said to be valid
        if for each :math:`i = 1,..., \ell`, all of the following conditions are
        satisfied

        - :math:`N_i` is a positive integer

        - :math:`t_i` is an integer such that :math:`t_i < 4N_i^2`

        - :math:`s_i` is a positive integer which divides :math:`m_i` where
        :math:`m_i = N_i + 1 - t_i`

        - If we set :math:`q_i = (m_i)/(s_i)`, then

        :strong:`*` :math:`q_i > (N_i^{1/4}+1)^2`

        :strong:`*` :math:`q_i = N_{i+1}` if :math:`1 <= i < l`

        :strong:`*` :math:`q_\ell <= 2^{64}` is prime

        - :math:`a_i` is an integer

        :strong:`*` :literal:`P[i]` is a vector of length :math:`2` representing the affine
        point :math:`P_i = (x_i, y_i)` on the elliptic curve :math:`E: y^2 = x^3 + a_ix + b_i`
        modulo :math:`N_i` where :math:`b_i = y_i^2 - x_i^3 - a_ix_i` satisfying the following:

        :strong:`*` :math:`m_i P_i = oo`

        :strong:`*` :math:`s_i P_i != oo`

        :strong:`Theorem.` If :math:`N` is an integer and there exist positive integers
        :math:`m, q` and a point :math:`P` on the elliptic curve :math:`E: y^2 = x^3 + ax + b` defined
        modulo :math:`N` such that :math:`q > (N^{1/4} + 1)^2`, :math:`q` is a prime divisor of :math:`m`,
        :math:`mP = oo` and :math:`(m)/(q)P != oo`, then :math:`N` is prime.

        Using the above theorem, the data in the vector :literal:`C` can be used to
        certify the primality of :math:`N` assuming :math:`q_\ell` is prime.

        ::

        ? primecert(10^35 + 69)
        %1 = [[100000000000000000000000000000000069, 5468679110354
        52074, 2963504668391148, 0, [60737979324046450274283740674
        208692, 24368673584839493121227731392450025]], [3374383076
        4501150277, -11610830419, 734208843, 0, [26740412374402652
        72 4, 6367191119818901665]], [45959444779, 299597, 2331, 0
        , [18022351516, 9326882 51]]]
        ? primecert(nextprime(2^64))
        %2 = [[18446744073709551629, -8423788454, 160388, 1, [1059
        8342506117936052, 2225259013356795550]]]
        ? primecert(6)
        %3 = 0
        ? primecert(41)
        %4 = 41

        If :math:`flag = 1` (very slow), return an :math:`N-1` certificate (Pocklington Lehmer)

        A PARI :math:`N-1` Primality Certificate for the prime :math:`N` is either a prime
        integer :math:`N < 2^{64}` or a pair :math:`[N, C]`, where :math:`C` is a vector with :math:`\ell`
        elements which are either a single integer :math:`p_i < 2^{64}` or a
        triple :math:`[p_i,a_i,C_i]` with :math:`p_i > 2^{64}` satisfying the following
        properties:

        - :math:`p_i` is a prime divisor of :math:`N - 1`;

        - :math:`a_i` is an integer such that :math:`a_i^{N-1} = 1 (mod N)` and
        :math:`a_i^{(N-1)/p_i} - 1` is coprime with :math:`N`;

        - :math:`C_i` is an :math:`N-1` Primality Certificate for :math:`p_i`

        - The product :math:`F` of the :math:`p_i^{v_{p_i}(N-1)}` is strictly larger than
        :math:`N^{1/3}`. Provided that all :math:`p_i` are indeed primes, this implies that any
        divisor of :math:`N` is congruent to :math:`1` modulo :math:`F`.

        - The Billhart, Lehmer, Selfridge criterion is satisfied: when we write
        :math:`N = 1 + c_1 F + c_2 F^2` in base :math:`F` the polynomial :math:`1 + c_1 X + c_2 X^2`
        is irreducible over :math:`\mathbb{Z}`, i.e. :math:`c_1^2 - 4c_2` is not a square. This
        implies that :math:`N` is prime.

        This algorithm requires factoring partially :math:`p-1` for various prime integers
        :math:`p` with an unfactored parted :math:`<= p^{2/3}` and this may be exceedingly
        slow compared to the default.

        The algorithm fails if one of the pseudo-prime factors is not prime, which is
        exceedingly unlikely and well worth a bug report. Note that if you monitor
        the algorithm at a high enough debug level, you may see warnings about
        untested integers being declared primes. This is normal: we ask for partial
        factorizations (sufficient to prove primality if the unfactored part is not
        too large), and :literal:`factor` warns us that the cofactor hasn't been tested.
        It may or may not be tested later, and may or may not be prime. This does
        not affect the validity of the whole Primality Certificate.
        '''
        N = objtogen(N)
        sig_on()
        cdef GEN _N = (<Gen>N).g
        cdef GEN _ret = primecert(_N, flag)
        return new_gen(_ret)

    def primecertexport(self, cert, long format=0):
        r'''
        Returns a string suitable for print/write to display a primality certificate
        from :literal:`primecert`, the format of which depends on the value of :literal:`format`:

        - 0 (default): Human-readable format.

        - 1: Primo format 4.

        - 2: MAGMA format.

        Currently, only ECPP Primality Certificates are supported.

        ::

        ? cert = primecert(10^35+69);
        ? s = primecertexport(cert); \\ Human-readable
        ? print(s)
        [1]
        N = 100000000000000000000000000000000069
        t = 546867911035452074
        s = 2963504668391148
        a4 = 0
        D = -3
        m = 99999999999999999453132088964547996
        q = 33743830764501150277
        E = [0, 1]
        P = [21567861682493263464353543707814204,
        49167839501923147849639425291163552]
        [2]
        N = 33743830764501150277
        t = -11610830419
        s = 734208843
        a4 = 0
        D = -3
        m = 33743830776111980697
        q = 45959444779
        E = [0, 25895956964997806805]
        P = [29257172487394218479, 3678591960085668324]
        
        \\ Primo format
        ? s = primecertexport(cert,1); write("cert.out", s);
        
        \\ Magma format, write to file
        ? s = primecertexport(cert,2); write("cert.m", s);
        
        ? cert = primecert(10^35+69, 1); \\ N-1 certificate
        *** at top-level: primecertexport(cert)
        *** ^---------------------
        *** primecertexport: sorry, N-1 certificate is not yet implemented.
        '''
        cert = objtogen(cert)
        sig_on()
        cdef GEN _cert = (<Gen>cert).g
        cdef GEN _ret = primecertexport(_cert, format)
        return new_gen(_ret)

    def primecertisvalid(self, cert):
        r'''
        Verifies if cert is a valid PARI ECPP Primality certificate, as described
        in :literal:`??primecert`.

        ::

        ? cert = primecert(10^35 + 69)
        %1 = [[100000000000000000000000000000000069, 5468679110354
        52074, 2963504668391148, 0, [60737979324046450274283740674
        208692, 24368673584839493121227731392450025]], [3374383076
        4501150277, -11610830419, 734208843, 0, [26740412374402652
        72 4, 6367191119818901665]], [45959444779, 299597, 2331, 0
        , [18022351516, 9326882 51]]]
        ? primecertisvalid(cert)
        %2 = 1
        
        ? cert[1][1]++; \\ random perturbation
        ? primecertisvalid(cert)
        %4 = 0 \\ no longer valid
        ? primecertisvalid(primecert(6))
        %5 = 0
        '''
        cert = objtogen(cert)
        sig_on()
        cdef GEN _cert = (<Gen>cert).g
        cdef long _ret = primecertisvalid(_cert)
        clear_stack()
        return _ret

    def primepi(self, x):
        r'''
        The prime counting function. Returns the number of
        primes :math:`p`, :math:`p <= x`.

        ::

        ? primepi(10)
        %1 = 4;
        ? primes(5)
        %2 = [2, 3, 5, 7, 11]
        ? primepi(10^11)
        %3 = 4118054813

        Uses checkpointing and a naive :math:`O(x)` algorithm;
        make sure to start gp with :literal:`primelimit` at least :math:`\sqrt{x}`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = primepi(_x)
        return new_gen(_ret)

    def primes(self, n):
        r'''
        Creates a row vector whose components are the first :math:`n` prime numbers.
        (Returns the empty vector for :math:`n <= 0`.) A :literal:`t_VEC` :math:`n = [a,b]` is also
        allowed, in which case the primes in :math:`[a,b]` are returned

        ::

        ? primes(10) \\ the first 10 primes
        %1 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
        ? primes([0,29]) \\ the primes up to 29
        %2 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
        ? primes([15,30])
        %3 = [17, 19, 23, 29]
        '''
        n = objtogen(n)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = primes0(_n)
        return new_gen(_ret)

    def prodeulerrat(self, F, s=None, long a=2, long precision=DEFAULT_BITPREC):
        r'''
        :math:`\prod_{p >= a, p prime}F(p^s)`, where :math:`F` is a rational function.

        ::

        ? prodeulerrat(1+1/q^3,1)
        %1 = 1.1815649490102569125693997341604542605
        ? zeta(3)/zeta(6)
        %2 = 1.1815649490102569125693997341604542606
        '''
        F = objtogen(F)
        cdef bint _have_s = (s is not None)
        if _have_s:
            s = objtogen(s)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _s = NULL
        if _have_s:
            _s = (<Gen>s).g
        precision = nbits2prec(precision)
        cdef GEN _ret = prodeulerrat(_F, _s, a, precision)
        return new_gen(_ret)

    def prodnumrat(self, F, long a, long precision=DEFAULT_BITPREC):
        r'''
        :math:`\prod_{n >= a}F(n)`, where :math:`F-1` is a rational function of degree less
        than or equal to :math:`-2`.

        ::

        ? prodnumrat(1+1/x^2,1)
        %1 = 3.6760779103749777206956974920282606665
        '''
        F = objtogen(F)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        precision = nbits2prec(precision)
        cdef GEN _ret = prodnumrat(_F, a, precision)
        return new_gen(_ret)

    def psdraw(self, list, long flag=0):
        r'''
        This function is obsolete, use plotexport and write the result to file.
        '''
        from warnings import warn
        warn('the PARI/GP function psdraw is obsolete (2018-02-01)', DeprecationWarning)
        list = objtogen(list)
        sig_on()
        cdef GEN _list = (<Gen>list).g
        psdraw(_list, flag)
        clear_stack()

    def psi(self, x, long precision=DEFAULT_BITPREC):
        r'''
        The :math:`\psi`-function of :math:`x`, i.e. the logarithmic derivative
        :math:`\Gamma'(x)/\Gamma (x)`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gpsi(_x, precision)
        return new_gen(_ret)

    def psplothraw(self, listx, listy, long flag=0):
        r'''
        This function is obsolete, use plothrawexport and write the result to file.
        '''
        from warnings import warn
        warn('the PARI/GP function psplothraw is obsolete (2018-02-01)', DeprecationWarning)
        listx = objtogen(listx)
        listy = objtogen(listy)
        sig_on()
        cdef GEN _listx = (<Gen>listx).g
        cdef GEN _listy = (<Gen>listy).g
        cdef GEN _ret = psplothraw(_listx, _listy, flag)
        return new_gen(_ret)

    def qfauto(self, G, fl=None):
        r'''
        :math:`G` being a square and symmetric matrix with integer entries representing a
        positive definite quadratic form, outputs the automorphism group of the
        associate lattice.
        Since this requires computing the minimal vectors, the computations can
        become very lengthy as the dimension grows. :math:`G` can also be given by an
        :literal:`qfisominit` structure.
        See :literal:`qfisominit` for the meaning of :emphasis:`fl`.

        The output is a two-components vector :math:`[o,g]` where :math:`o` is the group order
        and :math:`g` is the list of generators (as a vector). For each generator :math:`H`,
        the equality :math:`G = {^t}H G H` holds.

        The interface of this function is experimental and will likely change in the
        future.

        This function implements an algorithm of Plesken and Souvignier, following
        Souvignier's implementation.
        '''
        G = objtogen(G)
        cdef bint _have_fl = (fl is not None)
        if _have_fl:
            fl = objtogen(fl)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _fl = NULL
        if _have_fl:
            _fl = (<Gen>fl).g
        cdef GEN _ret = qfauto0(_G, _fl)
        return new_gen(_ret)

    def qfautoexport(self, qfa, long flag=0):
        r'''
        :emphasis:`qfa` being an automorphism group as output by
        :literal:`qfauto`, export the underlying matrix group as a string suitable
        for (no flags or :math:`flag = 0`) GAP or (:math:`flag = 1`) Magma. The following example
        computes the size of the matrix group using GAP:

        ::

        ? G = qfauto([2,1;1,2])
        %1 = [12, [[-1, 0; 0, -1], [0, -1; 1, 1], [1, 1; 0, -1]]]
        ? s = qfautoexport(G)
        %2 = "Group([[-1, 0], [0, -1]], [[0, -1], [1, 1]], [[1, 1], [0, -1]])"
        ? extern("echo \"Order("s");\" | gap -q")
        %3 = 12
        '''
        qfa = objtogen(qfa)
        sig_on()
        cdef GEN _qfa = (<Gen>qfa).g
        cdef GEN _ret = qfautoexport(_qfa, flag)
        return new_gen(_ret)

    def qfbclassno(self, D, long flag=0):
        r'''
        Ordinary class number of the quadratic order of discriminant :math:`D`, for
        "small" values of :math:`D`.

        - if :math:`D > 0` or :math:`flag = 1`, use a :math:`O(\|D\|^{1/2})`
        algorithm (compute :math:`L(1,\chi_D)` with the approximate functional equation).
        This is slower than :literal:`quadclassunit` as soon as :math:`\|D\| ~ 10^2` or
        so and is not meant to be used for large :math:`D`.

        - if :math:`D < 0` and :math:`flag = 0` (or omitted), use a :math:`O(\|D\|^{1/4})`
        algorithm (Shanks's baby-step/giant-step method). It should
        be faster than :literal:`quadclassunit` for small values of :math:`D`, say
        :math:`\|D\| < 10^{18}`.

        :strong:`Important warning.` In the latter case, this function only
        implements part of Shanks's method (which allows to speed it up
        considerably). It gives unconditionnally correct results for
        :math:`\|D\| < 2.10^{10}`, but may give incorrect results for larger values
        if the class
        group has many cyclic factors. We thus recommend to double-check results
        using the function :literal:`quadclassunit`, which is about 2 to 3 times slower in
        the range :math:`\|D\| \in [10^{10}, 10^{18}]`, assuming GRH. We currently have no
        counter-examples but they should exist: we would appreciate a bug report if
        you find one.

        :strong:`Warning.` Contrary to what its name implies, this routine does not
        compute the number of classes of binary primitive forms of discriminant :math:`D`,
        which is equal to the :emphasis:`narrow` class number. The two notions are the same
        when :math:`D < 0` or the fundamental unit :math:`\varepsilon` has negative norm; when :math:`D
        > 0` and :math:`N\varepsilon > 0`, the number of classes of forms is twice the
        ordinary class number. This is a problem which we cannot fix for backward
        compatibility reasons. Use the following routine if you are only interested
        in the number of classes of forms:

        ::

        QFBclassno(D) =
        qfbclassno(D) * if (D < 0 || norm(quadunit(D)) < 0, 1, 2)

        Here are a few examples:

        ::

        ? qfbclassno(400000028) \\ D > 0: slow
        time = 3,140 ms.
        %1 = 1
        ? quadclassunit(400000028).no
        time = 20 ms. \\{ much faster, assume GRH}
        %2 = 1
        ? qfbclassno(-400000028) \\ D < 0: fast enough
        time = 0 ms.
        %3 = 7253
        ? quadclassunit(-400000028).no
        time = 0 ms.
        %4 = 7253

        See also :literal:`qfbhclassno`.
        '''
        D = objtogen(D)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        cdef GEN _ret = qfbclassno0(_D, flag)
        return new_gen(_ret)

    def qfbcompraw(self, x, y):
        r'''
        composition of the binary quadratic forms :math:`x` and :math:`y`, without
        reduction of the result. This is useful e.g. to compute a generating
        element of an ideal. The result is undefined if :math:`x` and :math:`y` do not have the
        same discriminant.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = qfbcompraw(_x, _y)
        return new_gen(_ret)

    def qfbhclassno(self, x):
        r'''
        Hurwitz class number of :math:`x`, when
        :math:`x` is non-negative and congruent to 0 or 3 modulo 4, and :math:`0` for other
        values. For :math:`x > 5.10^5`, we assume the GRH, and use :literal:`quadclassunit`
        with default parameters.

        ::

        ? qfbhclassno(1) \\ not 0 or 3 mod 4
        %1 = 0
        ? qfbhclassno(3)
        %2 = 1/3
        ? qfbhclassno(4)
        %3 = 1/2
        ? qfbhclassno(23)
        %4 = 3
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = hclassno(_x)
        return new_gen(_ret)

    def qfbil(self, x, y, q=None):
        r'''
        This function is obsolete, use :literal:`qfeval`.
        '''
        from warnings import warn
        warn('the PARI/GP function qfbil is obsolete (2016-08-08)', DeprecationWarning)
        x = objtogen(x)
        y = objtogen(y)
        cdef bint _have_q = (q is not None)
        if _have_q:
            q = objtogen(q)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _q = NULL
        if _have_q:
            _q = (<Gen>q).g
        cdef GEN _ret = qfbil(_x, _y, _q)
        return new_gen(_ret)

    def qfbnucomp(self, x, y, L):
        r'''
        composition of the primitive positive
        definite binary quadratic forms :math:`x` and :math:`y` (type :literal:`t_QFI`) using the NUCOMP
        and NUDUPL algorithms of Shanks, à la Atkin. :math:`L` is any positive
        constant, but for optimal speed, one should take :math:`L = \|D/4\|^{1/4}`, i.e.
        :literal:`sqrtnint(abs(D) >> 2,4)`, where :math:`D` is the common discriminant of :math:`x` and
        :math:`y`. When :math:`x` and :math:`y` do not have the same discriminant, the result is
        undefined.

        The current implementation is slower than the generic routine for small :math:`D`,
        and becomes faster when :math:`D` has about :math:`45` bits.
        '''
        x = objtogen(x)
        y = objtogen(y)
        L = objtogen(L)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _L = (<Gen>L).g
        cdef GEN _ret = nucomp(_x, _y, _L)
        return new_gen(_ret)

    def qfbnupow(self, x, n, L=None):
        r'''
        :math:`n`-th power of the primitive positive definite
        binary quadratic form :math:`x` using Shanks's NUCOMP and NUDUPL algorithms;
        if set, :math:`L` should be equal to :literal:`sqrtnint(abs(D) >> 2,4)`, where :math:`D < 0` is
        the discriminant of :math:`x`.

        The current implementation is slower than the generic routine for small
        discriminant :math:`D`, and becomes faster for :math:`D ~ 2^{45}`.
        '''
        x = objtogen(x)
        n = objtogen(n)
        cdef bint _have_L = (L is not None)
        if _have_L:
            L = objtogen(L)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _n = (<Gen>n).g
        cdef GEN _L = NULL
        if _have_L:
            _L = (<Gen>L).g
        cdef GEN _ret = nupow(_x, _n, _L)
        return new_gen(_ret)

    def qfbpowraw(self, x, long n):
        r'''
        :math:`n`-th power of the binary quadratic form
        :math:`x`, computed without doing any reduction (i.e. using :literal:`qfbcompraw`).
        Here :math:`n` must be non-negative and :math:`n < 2^{31}`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = qfbpowraw(_x, n)
        return new_gen(_ret)

    def qfbprimeform(self, x, p, long precision=DEFAULT_BITPREC):
        r'''
        Prime binary quadratic form of discriminant
        :math:`x` whose first coefficient is :math:`p`, where :math:`\|p\|` is a prime number.
        By abuse of notation,
        :math:`p = ± 1` is also valid and returns the unit form. Returns an
        error if :math:`x` is not a quadratic residue mod :math:`p`, or if :math:`x < 0` and :math:`p < 0`.
        (Negative definite :literal:`t_QFI` are not implemented.) In the case where :math:`x > 0`,
        the "distance" component of the form is set equal to zero according to the
        current precision.
        '''
        x = objtogen(x)
        p = objtogen(p)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _p = (<Gen>p).g
        precision = nbits2prec(precision)
        cdef GEN _ret = primeform(_x, _p, precision)
        return new_gen(_ret)

    def qfbred(self, x, long flag=0, d=None, isd=None, sd=None):
        r'''
        Reduces the binary quadratic form :math:`x` (updating Shanks's distance function
        if :math:`x` is indefinite). The binary digits of :math:`flag` are toggles meaning

        1: perform a single reduction step

        2: don't update Shanks's distance

        The arguments :math:`d`, :emphasis:`isd`, :emphasis:`sd`, if present, supply the values of the
        discriminant, :math:`floor{\sqrt{d}}`, and :math:`\sqrt{d}` respectively
        (no checking is done of these facts). If :math:`d < 0` these values are useless,
        and all references to Shanks's distance are irrelevant.
        '''
        x = objtogen(x)
        cdef bint _have_d = (d is not None)
        if _have_d:
            d = objtogen(d)
        cdef bint _have_isd = (isd is not None)
        if _have_isd:
            isd = objtogen(isd)
        cdef bint _have_sd = (sd is not None)
        if _have_sd:
            sd = objtogen(sd)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _d = NULL
        if _have_d:
            _d = (<Gen>d).g
        cdef GEN _isd = NULL
        if _have_isd:
            _isd = (<Gen>isd).g
        cdef GEN _sd = NULL
        if _have_sd:
            _sd = (<Gen>sd).g
        cdef GEN _ret = qfbred0(_x, flag, _d, _isd, _sd)
        return new_gen(_ret)

    def qfbredsl2(self, x, data=None):
        r'''
        Reduction of the (real or imaginary) binary quadratic form :math:`x`, return
        :math:`[y,g]` where :math:`y` is reduced and :math:`g` in :math:`SL(2,\mathbb{Z})` is such that
        :math:`g.x = y`; :emphasis:`data`, if
        present, must be equal to :math:`[D, sqrtint (D)]`, where :math:`D > 0` is the
        discriminant of :math:`x`. In case :math:`x` is a :literal:`t_QFR`, the distance component is
        unaffected.
        '''
        x = objtogen(x)
        cdef bint _have_data = (data is not None)
        if _have_data:
            data = objtogen(data)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _data = NULL
        if _have_data:
            _data = (<Gen>data).g
        cdef GEN _ret = qfbredsl2(_x, _data)
        return new_gen(_ret)

    def qfbsolve(self, Q, p):
        r'''
        Solve the equation :math:`Q(x,y) = p` over the integers,
        where :math:`Q` is a binary quadratic form and :math:`p` a prime number.

        Return :math:`[x,y]` as a two-components vector, or zero if there is no solution.
        Note that this function returns only one solution and not all the solutions.

        Let :math:`D = \mathrm{disc} Q`. The algorithm used runs in probabilistic polynomial time
        in :math:`p` (through the computation of a square root of :math:`D` modulo :math:`p`); it is
        polynomial time in :math:`D` if :math:`Q` is imaginary, but exponential time if :math:`Q` is
        real (through the computation of a full cycle of reduced forms). In the
        latter case, note that :literal:`bnfisprincipal` provides a solution in heuristic
        subexponential time in :math:`D` assuming the GRH.
        '''
        Q = objtogen(Q)
        p = objtogen(p)
        sig_on()
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = qfbsolve(_Q, _p)
        return new_gen(_ret)

    def qfeval(self, q=None, x=None, y=None):
        r'''
        Evaluate the quadratic form :math:`q` (given by a symmetric matrix)
        at the vector :math:`x`; if :math:`y` is present, evaluate the polar form at :math:`(x,y)`;
        if :math:`q` omitted, use the standard Euclidean scalar product, corresponding to
        the identity matrix.

        Roughly equivalent to :literal:`x~ * q * y`, but a little faster and
        more convenient (does not distinguish between column and row vectors):

        ::

        ? x = [1,2,3]~; y = [-1,3,1]~; q = [1,2,3;2,2,-1;3,-1,9];
        ? qfeval(q,x,y)
        %2 = 23
        ? for(i=1,10^6, qfeval(q,x,y))
        time = 661ms
        ? for(i=1,10^6, x~*q*y)
        time = 697ms

        The speedup is noticeable for the quadratic form,
        compared to :literal:`x~ * q * x`, since we save almost half the
        operations:

        ::

        ? for(i=1,10^6, qfeval(q,x))
        time = 487ms

        The special case :math:`q = Id` is handled faster if we
        omit :math:`q` altogether:

        ::

        ? qfeval(,x,y)
        %6 = 8
        ? q = matid(#x);
        ? for(i=1,10^6, qfeval(q,x,y))
        time = 529 ms.
        ? for(i=1,10^6, qfeval(,x,y))
        time = 228 ms.
        ? for(i=1,10^6, x~*y)
        time = 274 ms.

        We also allow :literal:`t_MAT` s of compatible dimensions for :math:`x`,
        and return :literal:`x~ * q * x` in this case as well:

        ::

        ? M = [1,2,3;4,5,6;7,8,9]; qfeval(,M) \\ Gram matrix
        %5 =
        [66 78 90]
        
        [78 93 108]
        
        [90 108 126]
        
        ? q = [1,2,3;2,2,-1;3,-1,9];
        ? for(i=1,10^6, qfeval(q,M))
        time = 2,008 ms.
        ? for(i=1,10^6, M~*q*M)
        time = 2,368 ms.
        
        ? for(i=1,10^6, qfeval(,M))
        time = 1,053 ms.
        ? for(i=1,10^6, M~*M)
        time = 1,171 ms.

        If :math:`q` is a :literal:`t_QFI` or :literal:`t_QFR`, it is implicitly converted to the
        attached symmetric :literal:`t_MAT`. This is done more
        efficiently than by direct conversion, since we avoid introducing a
        denominator :math:`2` and rational arithmetic:

        ::

        ? q = Qfb(2,3,4); x = [2,3];
        ? qfeval(q, x)
        %2 = 62
        ? Q = Mat(q)
        %3 =
        [ 2 3/2]
        
        [3/2 4]
        ? qfeval(Q, x)
        %4 = 62
        ? for (i=1, 10^6, qfeval(q,x))
        time = 758 ms.
        ? for (i=1, 10^6, qfeval(Q,x))
        time = 1,110 ms.

        Finally, when :math:`x` is a :literal:`t_MAT` with :emphasis:`integral` coefficients, we allow
        a :literal:`t_QFI` or :literal:`t_QFR` for :math:`q` and return the binary
        quadratic form :math:`q o M`. Again, the conversion to :literal:`t_MAT` is less
        efficient in this case:

        ::

        ? q = Qfb(2,3,4); Q = Mat(q); x = [1,2;3,4];
        ? qfeval(q, x)
        %2 = Qfb(47, 134, 96)
        ? qfeval(Q,x)
        %3 =
        [47 67]
        
        [67 96]
        ? for (i=1, 10^6, qfeval(q,x))
        time = 701 ms.
        ? for (i=1, 10^6, qfeval(Q,x))
        time = 1,639 ms.
        '''
        cdef bint _have_q = (q is not None)
        if _have_q:
            q = objtogen(q)
        if x is None:
            raise TypeError("missing required argument: 'x'")
        x = objtogen(x)
        cdef bint _have_y = (y is not None)
        if _have_y:
            y = objtogen(y)
        sig_on()
        cdef GEN _q = NULL
        if _have_q:
            _q = (<Gen>q).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = NULL
        if _have_y:
            _y = (<Gen>y).g
        cdef GEN _ret = qfeval0(_q, _x, _y)
        return new_gen(_ret)

    def qfgaussred(self, q):
        r'''
        decomposition into squares of the
        quadratic form represented by the symmetric matrix :math:`q`. The result is a
        matrix whose diagonal entries are the coefficients of the squares, and the
        off-diagonal entries on each line represent the bilinear forms. More
        precisely, if :math:`(a_{ij})` denotes the output, one has

        .. MATH::

        q(x) = \sum_i a_{ii} (x_i + \sum_{j != i} a_{ij} x_j)^2

        ::

        ? qfgaussred([0,1;1,0])
        %1 =
        [1/2 1]
        
        [-1 -1/2]

        This means that :math:`2xy = (1/2)(x+y)^2 - (1/2)(x-y)^2`.
        Singular matrices are supported, in which case some diagonal coefficients
        will vanish:

        ::

        ? qfgaussred([1,1;1,1])
        %1 =
        [1 1]
        
        [1 0]

        This means that :math:`x^2 + 2xy + y^2 = (x+y)^2`.
        '''
        q = objtogen(q)
        sig_on()
        cdef GEN _q = (<Gen>q).g
        cdef GEN _ret = qfgaussred(_q)
        return new_gen(_ret)

    def qfisom(self, G, H, fl=None, grp=None):
        r'''
        :math:`G`, :math:`H` being square and symmetric matrices with integer entries representing
        positive definite quadratic forms, return an invertible matrix :math:`S` such that
        :math:`G = {^t}S H S`. This defines a isomorphism between the corresponding lattices.
        Since this requires computing the minimal vectors, the computations can
        become very lengthy as the dimension grows.
        See :literal:`qfisominit` for the meaning of :emphasis:`fl`.
        If :emphasis:`grp` is given it must be the automorphism group of :math:`H`. It will be used
        to speed up the computation.

        :math:`G` can also be given by an :literal:`qfisominit` structure which is preferable if
        several forms :math:`H` need to be compared to :math:`G`.

        This function implements an algorithm of Plesken and Souvignier, following
        Souvignier's implementation.
        '''
        G = objtogen(G)
        H = objtogen(H)
        cdef bint _have_fl = (fl is not None)
        if _have_fl:
            fl = objtogen(fl)
        cdef bint _have_grp = (grp is not None)
        if _have_grp:
            grp = objtogen(grp)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _H = (<Gen>H).g
        cdef GEN _fl = NULL
        if _have_fl:
            _fl = (<Gen>fl).g
        cdef GEN _grp = NULL
        if _have_grp:
            _grp = (<Gen>grp).g
        cdef GEN _ret = qfisom0(_G, _H, _fl, _grp)
        return new_gen(_ret)

    def qfisominit(self, G, fl=None, m=None):
        r'''
        :math:`G` being a square and symmetric matrix with integer entries representing a
        positive definite quadratic form, return an :literal:`isom` structure allowing to
        compute isomorphisms between :math:`G` and other quadratic forms faster.

        The interface of this function is experimental and will likely change in future
        release.

        If present, the optional parameter :emphasis:`fl` must be a :literal:`t_VEC` with two
        components. It allows to specify the invariants used, which can make the
        computation faster or slower. The components are

        - :literal:`fl[1]` Depth of scalar product combination to use.

        - :literal:`fl[2]` Maximum level of Bacher polynomials to use.

        If present, :math:`m` must be the set of vectors of norm up to the maximal of the
        diagonal entry of :math:`G`, either as a matrix or as given by :literal:`qfminim`.
        Otherwise this function computes the minimal vectors so it become very
        lengthy as the dimension of :math:`G` grows.
        '''
        G = objtogen(G)
        cdef bint _have_fl = (fl is not None)
        if _have_fl:
            fl = objtogen(fl)
        cdef bint _have_m = (m is not None)
        if _have_m:
            m = objtogen(m)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _fl = NULL
        if _have_fl:
            _fl = (<Gen>fl).g
        cdef GEN _m = NULL
        if _have_m:
            _m = (<Gen>m).g
        cdef GEN _ret = qfisominit0(_G, _fl, _m)
        return new_gen(_ret)

    def qfjacobi(self, A, long precision=DEFAULT_BITPREC):
        r'''
        Apply Jacobi's eigenvalue algorithm to the real symmetric matrix :math:`A`.
        This returns :math:`[L, V]`, where

        - :math:`L` is the vector of (real) eigenvalues of :math:`A`, sorted in increasing
        order,

        - :math:`V` is the corresponding orthogonal matrix of eigenvectors of :math:`A`.

        ::

        ? \p19
        ? A = [1,2;2,1]; mateigen(A)
        %1 =
        [-1 1]
        
        [ 1 1]
        ? [L, H] = qfjacobi(A);
        ? L
        %3 = [-1.000000000000000000, 3.000000000000000000]~
        ? H
        %4 =
        [ 0.7071067811865475245 0.7071067811865475244]
        
        [-0.7071067811865475244 0.7071067811865475245]
        ? norml2( (A-L[1])*H[,1] ) \\ approximate eigenvector
        %5 = 9.403954806578300064 E-38
        ? norml2(H*H~ - 1)
        %6 = 2.350988701644575016 E-38 \\ close to orthogonal
        '''
        A = objtogen(A)
        sig_on()
        cdef GEN _A = (<Gen>A).g
        precision = nbits2prec(precision)
        cdef GEN _ret = jacobi(_A, precision)
        return new_gen(_ret)

    def qflll(self, x, long flag=0):
        r'''
        LLL algorithm applied to the
        :emphasis:`columns` of the matrix :math:`x`. The columns of :math:`x` may be linearly
        dependent. The result is a unimodular transformation matrix :math:`T` such that :math:`x
        .T` is an LLL-reduced basis of the lattice generated by the column
        vectors of :math:`x`. Note that if :math:`x` is not of maximal rank :math:`T` will not be
        square. The LLL parameters are :math:`(0.51,0.99)`, meaning that the Gram-Schmidt
        coefficients for the final basis satisfy :math:`\|\mu_{i,j}\| <= 0.51`, and the
        Lovász's constant is :math:`0.99`.

        If :math:`flag = 0` (default), assume that :math:`x` has either exact (integral or
        rational) or real floating point entries. The matrix is rescaled, converted
        to integers and the behavior is then as in :math:`flag = 1`.

        If :math:`flag = 1`, assume that :math:`x` is integral. Computations involving Gram-Schmidt
        vectors are approximate, with precision varying as needed (Lehmer's trick,
        as generalized by Schnorr). Adapted from Nguyen and Stehlé's algorithm
        and Stehlé's code (:literal:`fplll-1.3`).

        If :math:`flag = 2`, :math:`x` should be an integer matrix whose columns are linearly
        independent. Returns a partially reduced basis for :math:`x`, using an unpublished
        algorithm by Peter Montgomery: a basis is said to be :emphasis:`partially reduced`
        if :math:`\|v_i ± v_j\| >= \|v_i\|` for any two distinct basis vectors :math:`v_i,
        v_j`.

        This is faster than :math:`flag = 1`, esp. when one row is huge compared
        to the other rows (knapsack-style), and should quickly produce relatively
        short vectors. The resulting basis is :emphasis:`not` LLL-reduced in general.
        If LLL reduction is eventually desired, avoid this partial reduction:
        applying LLL to the partially reduced matrix is significantly :emphasis:`slower`
        than starting from a knapsack-type lattice.

        If :math:`flag = 4`, as :math:`flag = 1`, returning a vector :math:`[K, T]` of matrices: the
        columns of :math:`K` represent a basis of the integer kernel of :math:`x`
        (not LLL-reduced in general) and :math:`T` is the transformation
        matrix such that :math:`x.T` is an LLL-reduced :math:`\mathbb{Z}`-basis of the image
        of the matrix :math:`x`.

        If :math:`flag = 5`, case as case :math:`4`, but :math:`x` may have polynomial coefficients.

        If :math:`flag = 8`, same as case :math:`0`, but :math:`x` may have polynomial coefficients.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = qflll0(_x, flag)
        return new_gen(_ret)

    def qflllgram(self, G, long flag=0):
        r'''
        Same as :literal:`qflll`, except that the
        matrix :math:`G = x~ * x` is the Gram matrix of some lattice vectors :math:`x`,
        and not the coordinates of the vectors themselves. In particular, :math:`G` must
        now be a square symmetric real matrix, corresponding to a positive
        quadratic form (not necessarily definite: :math:`x` needs not have maximal rank).
        The result is a unimodular
        transformation matrix :math:`T` such that :math:`x.T` is an LLL-reduced basis of
        the lattice generated by the column vectors of :math:`x`. See :literal:`qflll` for
        further details about the LLL implementation.

        If :math:`flag = 0` (default), assume that :math:`G` has either exact (integral or
        rational) or real floating point entries. The matrix is rescaled, converted
        to integers and the behavior is then as in :math:`flag = 1`.

        If :math:`flag = 1`, assume that :math:`G` is integral. Computations involving Gram-Schmidt
        vectors are approximate, with precision varying as needed (Lehmer's trick,
        as generalized by Schnorr). Adapted from Nguyen and Stehlé's algorithm
        and Stehlé's code (:literal:`fplll-1.3`).

        :math:`flag = 4`: :math:`G` has integer entries, gives the kernel and reduced image of :math:`x`.

        :math:`flag = 5`: same as :math:`4`, but :math:`G` may have polynomial coefficients.
        '''
        G = objtogen(G)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _ret = qflllgram0(_G, flag)
        return new_gen(_ret)

    def qfminim(self, x, b=None, m=None, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        :math:`x` being a square and symmetric matrix representing a positive definite
        quadratic form, this function deals with the vectors of :math:`x` whose norm is
        less than or equal to :math:`b`, enumerated using the Fincke-Pohst algorithm,
        storing at most :math:`m` vectors (no limit if :math:`m` is omitted). The function
        searches for the minimal non-zero vectors if :math:`b` is omitted. The behavior is
        undefined if :math:`x` is not positive definite (a "precision too low" error is
        most likely, although more precise error messages are possible). The precise
        behavior depends on :math:`flag`.

        If :math:`flag = 0` (default), returns at most :math:`2m` vectors. The result is a
        three-component vector, the first component being the number of vectors
        enumerated (which may be larger than :math:`2m`), the second being the maximum
        norm found, and the last vector
        is a matrix whose columns are found vectors, only one being given for each
        pair :math:`± v` (at most :math:`m` such pairs, unless :math:`m` was omitted). The vectors
        are returned in no particular order.

        If :math:`flag = 1`, ignores :math:`m` and returns :math:`[N,v]`, where :math:`v` is a non-zero vector
        of length :math:`N <= b`, or :math:`[]` if no non-zero vector has length :math:`<= b`.
        If no explicit :math:`b` is provided, return a vector of smallish norm
        (smallest vector in an LLL-reduced basis).

        In these two cases, :math:`x` must have :emphasis:`integral` entries. The
        implementation uses low precision floating point computations for maximal
        speed, which gives incorrect result when :math:`x` has large entries. (The
        condition is checked in the code and the routine raises an error if
        large rounding errors occur.) A more robust, but much slower,
        implementation is chosen if the following flag is used:

        If :math:`flag = 2`, :math:`x` can have non integral real entries. In this case, if :math:`b`
        is omitted, the "minimal" vectors only have approximately the same norm.
        If :math:`b` is omitted, :math:`m` is an upper bound for the number of vectors that
        will be stored and returned, but all minimal vectors are nevertheless
        enumerated. If :math:`m` is omitted, all vectors found are stored and returned;
        note that this may be a huge vector!

        ::

        ? x = matid(2);
        ? qfminim(x) \\ 4 minimal vectors of norm 1: ±[0,1], ±[1,0]
        %2 = [4, 1, [0, 1; 1, 0]]
        ? { x =
        [4, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 1, 0,-1, 0, 0, 0,-2;
        2, 4,-2,-2, 0,-2, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0,-1, 0, 1,-1,-1;
        0,-2, 4, 0,-2, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1, 0, 0, 1,-1,-1, 0, 0;
        0,-2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 1,-1, 0, 1,-1, 1, 0;
        0, 0,-2, 0, 4, 0, 0, 0, 1,-1, 0, 0, 1, 0, 0, 0,-2, 0, 0,-1, 1, 1, 0, 0;
        -2, -2,0, 0, 0, 4,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,-1, 1, 1;
        0, 0, 0, 0, 0,-2, 4,-2, 0, 0, 0, 0, 0, 1, 0, 0, 0,-1, 0, 0, 0, 1,-1, 0;
        0, 0, 0, 0, 0, 0,-2, 4, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0,-1,-1,-1, 0, 1, 0;
        0, 0, 0, 0, 1,-1, 0, 0, 4, 0,-2, 0, 1, 1, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0;
        0, 0, 0, 0,-1, 0, 0, 0, 0, 4, 0, 0, 1, 1,-1, 1, 0, 0, 0, 1, 0, 0, 1, 0;
        0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 4,-2, 0,-1, 0, 0, 0,-1, 0,-1, 0, 0, 0, 0;
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 4,-1, 1, 0, 0,-1, 1, 0, 1, 1, 1,-1, 0;
        1, 0,-1, 1, 1, 0, 0,-1, 1, 1, 0,-1, 4, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1,-1;
        -1,-1, 1,-1, 0, 0, 1, 0, 1, 1,-1, 1, 0, 4, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1;
        0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 1, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0;
        0, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1, 1, 0, 4, 0, 0, 0, 0, 1, 1, 0, 0;
        0, 0, 1, 0,-2, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 4, 1, 1, 1, 0, 0, 1, 1;
        1, 0, 0, 1, 0, 0,-1, 0, 1, 0,-1, 1, 1, 0, 0, 0, 1, 4, 0, 1, 1, 0, 1, 0;
        0, 0, 0,-1, 0, 1, 0,-1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 4, 0, 1, 1, 0, 1;
        -1, -1,1, 0,-1, 1, 0,-1, 0, 1,-1, 1, 0, 1, 0, 0, 1, 1, 0, 4, 0, 0, 1, 1;
        0, 0,-1, 1, 1, 0, 0,-1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 4, 1, 0, 1;
        0, 1,-1,-1, 1,-1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 4, 0, 1;
        0,-1, 0, 1, 0, 1,-1, 1, 0, 1, 0,-1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 4, 1;
        -2,-1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 4]; }
        ? qfminim(x,,0) \\ the Leech lattice has 196560 minimal vectors of norm 4
        time = 648 ms.
        %4 = [196560, 4, [;]]
        ? qfminim(x,,0,2); \\ safe algorithm. Slower and unnecessary here.
        time = 18,161 ms.
        %5 = [196560, 4.000061035156250000, [;]]

        In the last example, we store 0 vectors to limit memory use. All minimal
        vectors are nevertheless enumerated. Provided :literal:`parisize` is about 50MB,
        :literal:`qfminim(x)` succeeds in 2.5 seconds.
        '''
        x = objtogen(x)
        cdef bint _have_b = (b is not None)
        if _have_b:
            b = objtogen(b)
        cdef bint _have_m = (m is not None)
        if _have_m:
            m = objtogen(m)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _b = NULL
        if _have_b:
            _b = (<Gen>b).g
        cdef GEN _m = NULL
        if _have_m:
            _m = (<Gen>m).g
        precision = nbits2prec(precision)
        cdef GEN _ret = qfminim0(_x, _b, _m, flag, precision)
        return new_gen(_ret)

    def qfnorm(self, x, q=None):
        r'''
        This function is obsolete, use :literal:`qfeval`.
        '''
        from warnings import warn
        warn('the PARI/GP function qfnorm is obsolete (2016-08-08)', DeprecationWarning)
        x = objtogen(x)
        cdef bint _have_q = (q is not None)
        if _have_q:
            q = objtogen(q)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _q = NULL
        if _have_q:
            _q = (<Gen>q).g
        cdef GEN _ret = qfnorm(_x, _q)
        return new_gen(_ret)

    def qforbits(self, G, V):
        r'''
        Return the orbits of :math:`V` under the action of the group
        of linear transformation generated by the set :math:`G`.
        It is assumed that :math:`G` contains minus identity, and only one vector
        in :math:`{v, -v}` should be given.
        If :math:`G` does not stabilize :math:`V`, the function return :math:`0`.

        In the example below, we compute representatives and lengths of the orbits of
        the vectors of norm :math:`<= 3` under the automorphisms of the lattice :math:`A_1^6`.

        ::

        ? Q=matid(6); G=qfauto(Q); V=qfminim(Q,3);
        ? apply(x->[x[1],#x],qforbits(G,V))
        %2 = [[[0,0,0,0,0,1]~,6],[[0,0,0,0,1,-1]~,30],[[0,0,0,1,-1,-1]~,80]]
        '''
        G = objtogen(G)
        V = objtogen(V)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _V = (<Gen>V).g
        cdef GEN _ret = qforbits(_G, _V)
        return new_gen(_ret)

    def qfparam(self, G, sol, long flag=0):
        r'''
        Coefficients of binary quadratic forms that parametrize the
        solutions of the ternary quadratic form :math:`G`, using the particular
        solution :emphasis:`sol`.
        :emphasis:`flag` is optional and can be 1, 2, or 3, in which case the :emphasis:`flag`-th form is
        reduced. The default is :emphasis:`flag` = 0 (no reduction).

        ::

        ? G = [1,0,0;0,1,0;0,0,-34];
        ? M = qfparam(G, qfsolve(G))
        %2 =
        [ 3 -10 -3]
        
        [-5 -6 5]
        
        [ 1 0 1]

        Indeed, the solutions can be parametrized as

        .. MATH::

        (3x^2 - 10xy - 3y^2)^2 + (-5x^2 - 6xy + 5y^2)^2 -34(x^2 + y^2)^2 = 0.

        ::

        ? v = y^2 * M*[1,x/y,(x/y)^2]~
        %3 = [3*x^2 - 10*y*x - 3*y^2, -5*x^2 - 6*y*x + 5*y^2, -x^2 - y^2]~
        ? v~*G*v
        %4 = 0
        '''
        G = objtogen(G)
        sol = objtogen(sol)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _sol = (<Gen>sol).g
        cdef GEN _ret = qfparam(_G, _sol, flag)
        return new_gen(_ret)

    def qfperfection(self, G):
        r'''
        :math:`G` being a square and symmetric matrix with
        integer entries representing a positive definite quadratic form, outputs the
        perfection rank of the form. That is, gives the rank of the family of the :math:`s`
        symmetric matrices :math:`v_iv_i^t`, where :math:`s` is half the number of minimal
        vectors and the :math:`v_i` (:math:`1 <= i <= s`) are the minimal vectors.

        Since this requires computing the minimal vectors, the computations can
        become very lengthy as the dimension of :math:`x` grows.
        '''
        G = objtogen(G)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _ret = perf(_G)
        return new_gen(_ret)

    def qfrep(self, q, B, long flag=0):
        r'''
        :math:`q` being a square and symmetric matrix with integer entries representing a
        positive definite quadratic form, count the vectors representing successive
        integers.

        - If :math:`flag = 0`, count all vectors. Outputs the vector whose :math:`i`-th
        entry, :math:`1 <= i <= B` is half the number of vectors :math:`v` such that :math:`q(v) = i`.

        - If :math:`flag = 1`, count vectors of even norm. Outputs the vector
        whose :math:`i`-th entry, :math:`1 <= i <= B` is half the number of vectors such
        that :math:`q(v) = 2i`.

        ::

        ? q = [2, 1; 1, 3];
        ? qfrep(q, 5)
        %2 = Vecsmall([0, 1, 2, 0, 0]) \\ 1 vector of norm 2, 2 of norm 3, etc.
        ? qfrep(q, 5, 1)
        %3 = Vecsmall([1, 0, 0, 1, 0]) \\ 1 vector of norm 2, 0 of norm 4, etc.

        This routine uses a naive algorithm based on :literal:`qfminim`, and
        will fail if any entry becomes larger than :math:`2^{31}` (or :math:`2^{63}`).
        '''
        q = objtogen(q)
        B = objtogen(B)
        sig_on()
        cdef GEN _q = (<Gen>q).g
        cdef GEN _B = (<Gen>B).g
        cdef GEN _ret = qfrep0(_q, _B, flag)
        return new_gen(_ret)

    def qfsign(self, x):
        r'''
        Returns :math:`[p,m]` the signature of the quadratic form represented by the
        symmetric matrix :math:`x`. Namely, :math:`p` (resp. :math:`m`) is the number of positive
        (resp. negative) eigenvalues of :math:`x`. The result is computed using Gaussian
        reduction.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = qfsign(_x)
        return new_gen(_ret)

    def qfsolve(self, G):
        r'''
        Given a square symmetric matrix :math:`G` of dimension :math:`n >= 1`, solve over
        :math:`\mathbb{Q}` the quadratic equation :math:`X^tGX = 0`. The matrix :math:`G` must have rational
        coefficients. The solution might be a single non-zero vector (vectorv) or a
        matrix (whose columns generate a totally isotropic subspace).

        If no solution exists, returns an integer, that can be a prime :math:`p` such that
        there is no local solution at :math:`p`, or :math:`-1` if there is no real solution,
        or :math:`-2` if :math:`n = 2` and :math:`-\det G` is positive but not a square (which implies
        there is a real solution, but no local solution at some :math:`p` dividing :math:`\det G`).

        ::

        ? G = [1,0,0;0,1,0;0,0,-34];
        ? qfsolve(G)
        %1 = [-3, -5, 1]~
        ? qfsolve([1,0; 0,2])
        %2 = -1 \\ no real solution
        ? qfsolve([1,0,0;0,3,0; 0,0,-2])
        %3 = 3 \\ no solution in Q_3
        ? qfsolve([1,0; 0,-2])
        %4 = -2 \\ no solution, n = 2
        '''
        G = objtogen(G)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _ret = qfsolve(_G)
        return new_gen(_ret)

    def quadclassunit(self, D, long flag=0, tech=None, long precision=DEFAULT_BITPREC):
        r'''
        Buchmann-McCurley's sub-exponential algorithm for computing the
        class group of a quadratic order of discriminant :math:`D`.

        This function should be used instead of :literal:`qfbclassno` or :literal:`quadregula`
        when :math:`D < -10^{25}`, :math:`D > 10^{10}`, or when the :emphasis:`structure` is wanted. It
        is a special case of :literal:`bnfinit`, which is slower, but more robust.

        The result is a vector :math:`v` whose components should be accessed using member
        functions:

        - :literal:`:math:`v`.no`: the class number

        - :literal:`:math:`v`.cyc`: a vector giving the structure of the class group as a
        product of cyclic groups;

        - :literal:`:math:`v`.gen`: a vector giving generators of those cyclic groups (as
        binary quadratic forms).

        - :literal:`:math:`v`.reg`: the regulator, computed to an accuracy which is the
        maximum of an internal accuracy determined by the program and the current
        default (note that once the regulator is known to a small accuracy it is
        trivial to compute it to very high accuracy, see the tutorial).

        The :math:`flag` is obsolete and should be left alone. In older versions,
        it supposedly computed the narrow class group when :math:`D > 0`, but this did not
        work at all; use the general function :literal:`bnfnarrow`.

        Optional parameter :emphasis:`tech` is a row vector of the form :math:`[c_1, c_2]`,
        where :math:`c_1 <= c_2` are non-negative real numbers which control the execution
        time and the stack size, see ``GRHbnf`` (in the PARI manual). The parameter is used as a
        threshold to balance the relation finding phase against the final linear
        algebra. Increasing the default :math:`c_1` means that relations are easier
        to find, but more relations are needed and the linear algebra will be
        harder. The default value for :math:`c_1` is :math:`0` and means that it is taken equal
        to :math:`c_2`. The parameter :math:`c_2` is mostly obsolete and should not be changed,
        but we still document it for completeness: we compute a tentative class
        group by generators and relations using a factorbase of prime ideals
        :math:`<= c_1 (\log \|D\|)^2`, then prove that ideals of norm
        :math:`<= c_2 (\log \|D\|)^2` do
        not generate a larger group. By default an optimal :math:`c_2` is chosen, so that
        the result is provably correct under the GRH --- a famous result of Bach
        states that :math:`c_2 = 6` is fine, but it is possible to improve on this
        algorithmically. You may provide a smaller :math:`c_2`, it will be ignored
        (we use the provably correct
        one); you may provide a larger :math:`c_2` than the default value, which results
        in longer computing times for equally correct outputs (under GRH).
        '''
        D = objtogen(D)
        cdef bint _have_tech = (tech is not None)
        if _have_tech:
            tech = objtogen(tech)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        cdef GEN _tech = NULL
        if _have_tech:
            _tech = (<Gen>tech).g
        precision = nbits2prec(precision)
        cdef GEN _ret = quadclassunit0(_D, flag, _tech, precision)
        return new_gen(_ret)

    def quaddisc(self, x):
        r'''
        Discriminant of the étale algebra :math:`\mathbb{Q} (\sqrt{x})`, where :math:`x\in\mathbb{Q}^*`.
        This is the same as :literal:`coredisc`:math:`(d)` where :math:`d` is the integer square-free
        part of :math:`x`, so x = :math:`d f^2` with :math:`f\in \mathbb{Q}^*` and :math:`d\in\mathbb{Z}`.
        This returns :math:`0` for :math:`x = 0`, :math:`1` for :math:`x` square and the discriminant of the
        quadratic field :math:`\mathbb{Q} (\sqrt{x})` otherwise.

        ::

        ? quaddisc(7)
        %1 = 28
        ? quaddisc(-7)
        %2 = -7
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = quaddisc(_x)
        return new_gen(_ret)

    def quadgen(self, D, v=None):
        r'''
        Creates the quadratic number :math:`\omega = (a+\sqrt{D})/2` where
        :math:`a = 0` if :math:`D = 0 mod 4`,
        :math:`a = 1` if :math:`D = 1 mod 4`, so that :math:`(1,\omega)` is an integral basis for the
        quadratic order of discriminant :math:`D`. :math:`D` must be an integer congruent to 0 or
        1 modulo 4, which is not a square.
        If :emphasis:`v` is given, the variable name is used to display :math:`g` else 'w' is used.

        ::

        ? w = quadgen(5, 'w); w^2 - w - 1
        %1 = 0
        ? w = quadgen(0, 'w)
        *** at top-level: w=quadgen(0)
        *** ^----------
        *** quadgen: domain error in quadpoly: issquare(disc) = 1
        '''
        D = objtogen(D)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        cdef GEN _ret = quadgen0(_D, _v)
        return new_gen(_ret)

    def quadhilbert(self, D, long precision=DEFAULT_BITPREC):
        r'''
        Relative equation defining the
        Hilbert class field of the quadratic field of discriminant :math:`D`.

        If :math:`D < 0`, uses complex multiplication (Schertz's variant).

        If :math:`D > 0` Stark units are used and (in rare cases) a
        vector of extensions may be returned whose compositum is the requested class
        field. See :literal:`bnrstark` for details.
        '''
        D = objtogen(D)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        precision = nbits2prec(precision)
        cdef GEN _ret = quadhilbert(_D, precision)
        return new_gen(_ret)

    def quadpoly(self, D, v=None):
        r'''
        Creates the "canonical" quadratic
        polynomial (in the variable :math:`v`) corresponding to the discriminant :math:`D`,
        i.e. the minimal polynomial of :math:`quadgen (D)`. :math:`D` must be an integer
        congruent to 0 or 1 modulo 4, which is not a square.

        ::

        ? quadpoly(5,'y)
        %1 = y^2 - y - 1
        ? quadpoly(0,'y)
        *** at top-level: quadpoly(0,'y)
        *** ^--------------
        *** quadpoly: domain error in quadpoly: issquare(disc) = 1
        '''
        D = objtogen(D)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        cdef GEN _ret = quadpoly0(_D, _v)
        return new_gen(_ret)

    def quadray(self, D, f, long precision=DEFAULT_BITPREC):
        r'''
        Relative equation for the ray
        class field of conductor :math:`f` for the quadratic field of discriminant :math:`D`
        using analytic methods. A :literal:`bnf` for :math:`x^2 - D` is also accepted in place
        of :math:`D`.

        For :math:`D < 0`, uses the :math:`\sigma` function and Schertz's method.

        For :math:`D > 0`, uses Stark's conjecture, and a vector of relative equations may be
        returned. See :literal:`bnrstark` for more details.
        '''
        D = objtogen(D)
        f = objtogen(f)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        cdef GEN _f = (<Gen>f).g
        precision = nbits2prec(precision)
        cdef GEN _ret = quadray(_D, _f, precision)
        return new_gen(_ret)

    def quadregulator(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Regulator of the quadratic field of positive discriminant :math:`x`. Returns
        an error if :math:`x` is not a discriminant (fundamental or not) or if :math:`x` is a
        square. See also :literal:`quadclassunit` if :math:`x` is large.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = quadregulator(_x, precision)
        return new_gen(_ret)

    def quadunit(self, D, v=None):
        r'''
        Fundamental unit :math:`u` of the
        real quadratic field :math:`\mathbb{Q} (\sqrt D)` where :math:`D` is the positive discriminant
        of the field. If :math:`D` is not a fundamental discriminant, this probably gives
        the fundamental unit of the corresponding order. :math:`D` must be an integer
        congruent to 0 or 1 modulo 4, which is not a square; the result is a
        quadratic number (see ``quadgen`` (in the PARI manual)).
        If :emphasis:`v` is given, the variable name is used to display :math:`u`
        else 'w' is used.
        '''
        D = objtogen(D)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        cdef GEN _ret = quadunit0(_D, _v)
        return new_gen(_ret)

    def ramanujantau(self, n):
        r'''
        Compute the value of Ramanujan's tau function at an individual :math:`n`,
        assuming the truth of the GRH (to compute quickly class numbers of imaginary
        quadratic fields using :literal:`quadclassunit`).
        Algorithm in :math:`~{O}(n^{1/2})` using :math:`O(\log n)` space. If all values up
        to :math:`N` are required, then

        .. MATH::

        \sum \tau (n)q^n = q \prod_{n >= 1} (1-q^n)^{24}

        will produce them in time :math:`~{O}(N)`, against :math:`~{O}(N^{3/2})` for
        individual calls to :literal:`ramanujantau`; of course the space complexity then
        becomes :math:`~{O}(N)`.

        ::

        ? tauvec(N) = Vec(q*eta(q + O(q^N))^24);
        ? N = 10^4; v = tauvec(N);
        time = 26 ms.
        ? ramanujantau(N)
        %3 = -482606811957501440000
        ? w = vector(N, n, ramanujantau(n)); \\ much slower !
        time = 13,190 ms.
        ? v == w
        %4 = 1
        '''
        n = objtogen(n)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = ramanujantau(_n)
        return new_gen(_ret)

    def random(self, N=None):
        r'''
        Returns a random element in various natural sets depending on the
        argument :math:`N`.

        - :literal:`t_INT`: returns an integer
        uniformly distributed between :math:`0` and :math:`N-1`. Omitting the argument
        is equivalent to :literal:`random(2^31)`.

        - :literal:`t_REAL`: returns a real number in :math:`[0,1[` with the same accuracy as
        :math:`N` (whose mantissa has the same number of significant words).

        - :literal:`t_INTMOD`: returns a random intmod for the same modulus.

        - :literal:`t_FFELT`: returns a random element in the same finite field.

        - :literal:`t_VEC` of length :math:`2`, :math:`N = [a,b]`: returns an integer uniformly
        distributed between :math:`a` and :math:`b`.

        - :literal:`t_VEC` generated by :literal:`ellinit` over a finite field :math:`k`
        (coefficients are :literal:`t_INTMOD` s modulo a prime or :literal:`t_FFELT` s): returns a
        "random" :math:`k`-rational :emphasis:`affine` point on the curve. More precisely
        if the curve has a single point (at infinity!) we return it; otherwise
        we return an affine point by drawing an abscissa uniformly at
        random until :literal:`ellordinate` succeeds. Note that this is definitely not a
        uniform distribution over :math:`E(k)`, but it should be good enough for
        applications.

        - :literal:`t_POL` return a random polynomial of degree at most the degree of :math:`N`.
        The coefficients are drawn by applying :literal:`random` to the leading
        coefficient of :math:`N`.

        ::

        ? random(10)
        %1 = 9
        ? random(Mod(0,7))
        %2 = Mod(1, 7)
        ? a = ffgen(ffinit(3,7), 'a); random(a)
        %3 = a^6 + 2*a^5 + a^4 + a^3 + a^2 + 2*a
        ? E = ellinit([3,7]*Mod(1,109)); random(E)
        %4 = [Mod(103, 109), Mod(10, 109)]
        ? E = ellinit([1,7]*a^0); random(E)
        %5 = [a^6 + a^5 + 2*a^4 + 2*a^2, 2*a^6 + 2*a^4 + 2*a^3 + a^2 + 2*a]
        ? random(Mod(1,7)*x^4)
        %6 = Mod(5, 7)*x^4 + Mod(6, 7)*x^3 + Mod(2, 7)*x^2 + Mod(2, 7)*x + Mod(5, 7)
        

        These variants all depend on a single internal generator, and are
        independent from your operating system's random number generators.
        A random seed may be obtained via :literal:`getrand`, and reset
        using :literal:`setrand`: from a given seed, and given sequence of :literal:`random` s,
        the exact same values will be generated. The same seed is used at each
        startup, reseed the generator yourself if this is a problem. Note that
        internal functions also call the random number generator; adding such a
        function call in the middle of your code will change the numbers produced.

        :strong:`Technical note.`
        Up to
        version 2.4 included, the internal generator produced pseudo-random numbers
        by means of linear congruences, which were not well distributed in arithmetic
        progressions. We now
        use Brent's XORGEN algorithm, based on Feedback Shift Registers, see
        :literal:`http://wwwmaths.anu.edu.au/~brent/random.html`. The generator has period
        :math:`2^{4096}-1`, passes the Crush battery of statistical tests of L'Ecuyer and
        Simard, but is not suitable for cryptographic purposes: one can reconstruct
        the state vector from a small sample of consecutive values, thus predicting
        the entire sequence.
        '''
        cdef bint _have_N = (N is not None)
        if _have_N:
            N = objtogen(N)
        sig_on()
        cdef GEN _N = NULL
        if _have_N:
            _N = (<Gen>N).g
        cdef GEN _ret = genrand(_N)
        return new_gen(_ret)

    def randomprime(self, N=None):
        r'''
        Returns a strong pseudo prime (see :literal:`ispseudoprime`) in :math:`[2,N-1]`.
        A :literal:`t_VEC` :math:`N = [a,b]` is also allowed, with :math:`a <= b` in which case a
        pseudo prime :math:`a <= p <= b` is returned; if no prime exists in the
        interval, the function will run into an infinite loop. If the upper bound
        is less than :math:`2^{64}` the pseudo prime returned is a proven prime.
        '''
        cdef bint _have_N = (N is not None)
        if _have_N:
            N = objtogen(N)
        sig_on()
        cdef GEN _N = NULL
        if _have_N:
            _N = (<Gen>N).g
        cdef GEN _ret = randomprime(_N)
        return new_gen(_ret)

    def read(self, filename=None):
        r'''
        Reads in the file
        :emphasis:`filename` (subject to string expansion). If :emphasis:`filename` is
        omitted, re-reads the last file that was fed into :literal:`gp`. The return
        value is the result of the last expression evaluated.

        If a GP :literal:`binary file` is read using this command (see
        ``writebin`` (in the PARI manual)), the file is loaded and the last object in the file
        is returned.

        In case the file you read in contains an :literal:`allocatemem` statement (to be
        generally avoided), you should leave :literal:`read` instructions by themselves,
        and not part of larger instruction sequences.

        :strong:`Variants.` :literal:`readvec` allows to read a whole file at once;
        :literal:`fileopen` followed by either :literal:`fileread` (evaluated lines) or
        :literal:`filereadstr` (lines as non-evaluated strings) allows to read a file
        one line at a time.
        '''
        cdef char* _filename
        if filename is None:
            _filename = ""
        else:
            filename = to_bytes(filename)
            _filename = <bytes>filename
        sig_on()
        cdef GEN _ret = gp_read_file(_filename)
        return new_gen(_ret)

    def readstr(self, filename=None):
        r'''
        Reads in the file :emphasis:`filename` and return a vector of GP strings,
        each component containing one line from the file. If :emphasis:`filename` is
        omitted, re-reads the last file that was fed into :literal:`gp`.
        '''
        cdef char* _filename
        if filename is None:
            _filename = ""
        else:
            filename = to_bytes(filename)
            _filename = <bytes>filename
        sig_on()
        cdef GEN _ret = readstr(_filename)
        return new_gen(_ret)

    def readvec(self, filename=None):
        r'''
        Reads in the file
        :emphasis:`filename` (subject to string expansion). If :emphasis:`filename` is
        omitted, re-reads the last file that was fed into :literal:`gp`. The return
        value is a vector whose components are the evaluation of all sequences
        of instructions contained in the file. For instance, if :emphasis:`file` contains

        ::

        1
        2
        3

        then we will get:

        ::

        ? \r a
        %1 = 1
        %2 = 2
        %3 = 3
        ? read(a)
        %4 = 3
        ? readvec(a)
        %5 = [1, 2, 3]

        In general a sequence is just a single line, but as usual braces and
        :literal:`\\` may be used to enter multiline sequences.
        '''
        cdef char* _filename
        if filename is None:
            _filename = ""
        else:
            filename = to_bytes(filename)
            _filename = <bytes>filename
        sig_on()
        cdef GEN _ret = gp_readvec_file(_filename)
        return new_gen(_ret)

    def real(self, x):
        r'''
        Real part of :math:`x`. In the case where :math:`x` is a quadratic number, this is the
        coefficient of :math:`1` in the "canonical" integral basis :math:`(1,\omega)`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = greal(_x)
        return new_gen(_ret)

    def removeprimes(self, x=None):
        r'''
        Removes the primes listed in :math:`x` from
        the prime number table. In particular :literal:`removeprimes(addprimes())` empties
        the extra prime table. :math:`x` can also be a single integer. List the current
        extra primes if :math:`x` is omitted.
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _ret = removeprimes(_x)
        return new_gen(_ret)

    def rnfalgtobasis(self, rnf, x):
        r'''
        Expresses :math:`x` on the relative
        integral basis. Here, :math:`rnf` is a relative number field extension :math:`L/K`
        as output by :literal:`rnfinit`, and :math:`x` an element of :math:`L` in absolute form, i.e.
        expressed as a polynomial or polmod with polmod coefficients, :emphasis:`not` on
        the relative integral basis.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfalgtobasis(_rnf, _x)
        return new_gen(_ret)

    def rnfbasis(self, bnf, M):
        r'''
        Let :math:`K` the field represented by
        :emphasis:`bnf`, as output by :literal:`bnfinit`. :math:`M` is a projective :math:`\mathbb{Z}_K`-module
        of rank :math:`n` (:math:`M\otimes K` is an :math:`n`-dimensional :math:`K`-vector space), given by a
        pseudo-basis of size :math:`n`. The routine returns either a true :math:`\mathbb{Z}_K`-basis of
        :math:`M` (of size :math:`n`) if it exists, or an :math:`n+1`-element generating set of :math:`M` if
        not.

        It is allowed to use a monic irreducible polynomial :math:`P` in :math:`K[X]` instead of
        :math:`M`, in which case, :math:`M` is defined as the ring of integers of :math:`K[X]/(P)`,
        viewed as a :math:`\mathbb{Z}_K`-module.
        '''
        bnf = objtogen(bnf)
        M = objtogen(M)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = rnfbasis(_bnf, _M)
        return new_gen(_ret)

    def rnfbasistoalg(self, rnf, x):
        r'''
        Computes the representation of :math:`x`
        as a polmod with polmods coefficients. Here, :math:`rnf` is a relative number
        field extension :math:`L/K` as output by :literal:`rnfinit`, and :math:`x` an element of
        :math:`L` expressed on the relative integral basis.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfbasistoalg(_rnf, _x)
        return new_gen(_ret)

    def rnfcharpoly(self, nf, T, a, var=None):
        r'''
        Characteristic polynomial of
        :math:`a` over :math:`nf`, where :math:`a` belongs to the algebra defined by :math:`T` over
        :math:`nf`, i.e. :math:`nf[X]/(T)`. Returns a polynomial in variable :math:`v`
        (:math:`x` by default).

        ::

        ? nf = nfinit(y^2+1);
        ? rnfcharpoly(nf, x^2+y*x+1, x+y)
        %2 = x^2 + Mod(-y, y^2 + 1)*x + 1
        '''
        nf = objtogen(nf)
        T = objtogen(T)
        a = objtogen(a)
        cdef long _var = -1
        if var is not None:
            _var = get_var(var)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _T = (<Gen>T).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _ret = rnfcharpoly(_nf, _T, _a, _var)
        return new_gen(_ret)

    def rnfconductor(self, bnf, T):
        r'''
        Given a :emphasis:`bnf` structure attached to a number field :math:`K`, as produced
        by :literal:`bnfinit`, and :math:`T` a monic irreducible polynomial in :math:`K[x]`
        defining an Abelian extension :math:`L = K[x]/(T)`, computes the class field
        theory conductor of this Abelian extension. The result is a 3-component vector
        :math:`[conductor,bnr,subgroup]`, where :emphasis:`conductor` is
        the conductor of the extension given as a 2-component row vector
        :math:`[f_0,f_ oo ]`, :emphasis:`bnr` is the attached :literal:`bnr` structure
        and :emphasis:`subgroup` is a matrix in HNF defining the subgroup of the ray class
        group on the ray class group generators :literal:`bnr.gen`.

        :strong:`Huge discriminants, helping rnfdisc.` the format :math:`[T,B]` is
        also accepted instead of :math:`T` and computes the conductor of the extension
        provided it factors completely over prime divisors of rational primes :math:`p < B`,
        see :literal:`??rnfinit`: the valuation of :math:`f_0` is then correct at all prime
        ideals :math:`p` above a rational prime :math:`p < B` but may be incorrect at other
        primes.
        '''
        bnf = objtogen(bnf)
        T = objtogen(T)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = rnfconductor(_bnf, _T)
        return new_gen(_ret)

    def rnfdedekind(self, nf, pol, pr=None, long flag=0):
        r'''
        Given a number field :math:`K` coded by :math:`nf` and a monic
        polynomial :math:`P\in \mathbb{Z}_K[X]`, irreducible over :math:`K` and thus defining a relative
        extension :math:`L` of :math:`K`, applies Dedekind's criterion to the order
        :math:`\mathbb{Z}_K[X]/(P)`, at the prime ideal :emphasis:`pr`. It is possible to set :emphasis:`pr`
        to a vector of prime ideals (test maximality at all primes in the vector),
        or to omit altogether, in which case maximality at :emphasis:`all` primes is tested;
        in this situation :emphasis:`flag` is automatically set to :math:`1`.

        The default historic behavior (:emphasis:`flag` is 0 or omitted and :emphasis:`pr` is a
        single prime ideal) is not so useful since
        :literal:`rnfpseudobasis` gives more information and is generally not that
        much slower. It returns a 3-component vector :math:`[max, basis, v]`:

        - :emphasis:`basis` is a pseudo-basis of an enlarged order :math:`O` produced by
        Dedekind's criterion, containing the original order :math:`\mathbb{Z}_K[X]/(P)`
        with index a power of :emphasis:`pr`. Possibly equal to the original order.

        - :emphasis:`max` is a flag equal to 1 if the enlarged order :math:`O`
        could be proven to be :emphasis:`pr`-maximal and to 0 otherwise; it may still be
        maximal in the latter case if :emphasis:`pr` is ramified in :math:`L`,

        - :math:`v` is the valuation at :emphasis:`pr` of the order discriminant.

        If :emphasis:`flag` is non-zero, on the other hand, we just return :math:`1` if the order
        :math:`\mathbb{Z}_K[X]/(P)` is :emphasis:`pr`-maximal (resp. maximal at all relevant primes, as
        described above), and :math:`0` if not. This is much faster than the default,
        since the enlarged order is not computed.

        ::

        ? nf = nfinit(y^2-3); P = x^3 - 2*y;
        ? pr3 = idealprimedec(nf,3)[1];
        ? rnfdedekind(nf, P, pr3)
        %3 = [1, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]], 8]
        ? rnfdedekind(nf, P, pr3, 1)
        %4 = 1

        In this example, :literal:`pr3` is the ramified ideal above :math:`3`,
        and the order generated by the cube roots of :math:`y` is already
        :literal:`pr3`-maximal. The order-discriminant has valuation :math:`8`. On the other
        hand, the order is not maximal at the prime above 2:

        ::

        ? pr2 = idealprimedec(nf,2)[1];
        ? rnfdedekind(nf, P, pr2, 1)
        %6 = 0
        ? rnfdedekind(nf, P, pr2)
        %7 = [0, [[2, 0, 0; 0, 1, 0; 0, 0, 1], [[1, 0; 0, 1], [1, 0; 0, 1],
        [1, 1/2; 0, 1/2]]], 2]

        The enlarged order is not proven to be :literal:`pr2`-maximal yet. In fact, it
        is; it is in fact the maximal order:

        ::

        ? B = rnfpseudobasis(nf, P)
        %8 = [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, [1, 1/2; 0, 1/2]],
        [162, 0; 0, 162], -1]
        ? idealval(nf,B[3], pr2)
        %9 = 2

        It is possible to use this routine with non-monic
        :math:`P = \sum_{i <= n} a_i X^i \in \mathbb{Z}_K[X]` if :math:`flag = 1`;
        in this case, we test maximality of Dedekind's order generated by

        .. MATH::

        1, a_n \alpha, a_n\alpha^2 + a_{n-1}\alpha,...,
        a_n\alpha^{n-1} + a_{n-1}\alpha^{n-2} +...+ a_1\alpha.

        The routine will fail if :math:`P` is :math:`0` on the projective line over the residue
        field :math:`\mathbb{Z}_K/pr` (FIXME).
        '''
        nf = objtogen(nf)
        pol = objtogen(pol)
        cdef bint _have_pr = (pr is not None)
        if _have_pr:
            pr = objtogen(pr)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _pr = NULL
        if _have_pr:
            _pr = (<Gen>pr).g
        cdef GEN _ret = rnfdedekind(_nf, _pol, _pr, flag)
        return new_gen(_ret)

    def rnfdet(self, nf, M):
        r'''
        Given a pseudo-matrix :math:`M` over the maximal
        order of :math:`nf`, computes its determinant.
        '''
        nf = objtogen(nf)
        M = objtogen(M)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _M = (<Gen>M).g
        cdef GEN _ret = rnfdet(_nf, _M)
        return new_gen(_ret)

    def rnfdisc(self, nf, T):
        r'''
        Given an :emphasis:`nf` structure attached to a number field :math:`K`, as output
        by :literal:`nfinit`, and a monic irreducible polynomial :math:`T\in K[x]` defining a
        relative extension :math:`L = K[x]/(T)`, compute the relative discriminant of :math:`L`.
        This is a vector :math:`[D,d]`, where :math:`D` is the relative ideal discriminant and
        :math:`d` is the relative discriminant considered as an element of :math:`K^*/{K^*}^2`.
        The main variable of :math:`nf` :emphasis:`must` be of lower priority than that of
        :math:`T`, see ``priority`` (in the PARI manual).

        :strong:`Huge discriminants, helping rnfdisc.` the format :math:`[T,B]` is
        also accepted instead of :math:`T` and computes an order which is maximal at all
        :math:`p < B`, see :literal:`??rnfinit`: the valuation of :math:`D` is then correct at all
        prime ideals :math:`p` above a rational prime :math:`p < B` but may be incorrect
        at other primes.
        '''
        nf = objtogen(nf)
        T = objtogen(T)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = rnfdiscf(_nf, _T)
        return new_gen(_ret)

    def rnfeltabstorel(self, rnf, x):
        r'''
        Let :math:`rnf` be a relative
        number field extension :math:`L/K` as output by :literal:`rnfinit` and let :math:`x` be an
        element of :math:`L` expressed as a polynomial modulo the absolute equation
        :literal:`:emphasis:`rnf`.pol`, or in terms of the absolute :math:`\mathbb{Z}`-basis for :math:`\mathbb{Z}_L`
        if :emphasis:`rnf` contains one (as in :literal:`rnfinit(nf,pol,1)`, or after
        a call to :literal:`nfinit(rnf)`).
        Computes :math:`x` as an element of the relative extension
        :math:`L/K` as a polmod with polmod coefficients.

        ::

        ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y);
        ? L.polabs
        %2 = x^4 + 1
        ? rnfeltabstorel(L, Mod(x, L.polabs))
        %3 = Mod(x, x^2 + Mod(-y, y^2 + 1))
        ? rnfeltabstorel(L, 1/3)
        %4 = 1/3
        ? rnfeltabstorel(L, Mod(x, x^2-y))
        %5 = Mod(x, x^2 + Mod(-y, y^2 + 1))
        
        ? rnfeltabstorel(L, [0,0,0,1]~) \\ Z_L not initialized yet
        *** at top-level: rnfeltabstorel(L,[0,
        *** ^--------------------
        *** rnfeltabstorel: incorrect type in rnfeltabstorel, apply nfinit(rnf).
        ? nfinit(L); \\ initialize now
        ? rnfeltabstorel(L, [0,0,0,1]~)
        %6 = Mod(Mod(y, y^2 + 1)*x, x^2 + Mod(-y, y^2 + 1))
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfeltabstorel(_rnf, _x)
        return new_gen(_ret)

    def rnfeltdown(self, rnf, x, long flag=0):
        r'''
        :math:`rnf` being a relative number
        field extension :math:`L/K` as output by :literal:`rnfinit` and :math:`x` being an element of
        :math:`L` expressed as a polynomial or polmod with polmod coefficients (or as a
        :literal:`t_COL` on :literal:`nfinit(rnf).zk`), computes
        :math:`x` as an element of :math:`K` as a :literal:`t_POLMOD` if :math:`flag = 0` and as a :literal:`t_COL`
        otherwise. If :math:`x` is not in :math:`K`, a domain error occurs.

        ::

        ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y);
        ? L.pol
        %2 = x^4 + 1
        ? rnfeltdown(L, Mod(x^2, L.pol))
        %3 = Mod(y, y^2 + 1)
        ? rnfeltdown(L, Mod(x^2, L.pol), 1)
        %4 = [0, 1]~
        ? rnfeltdown(L, Mod(y, x^2-y))
        %5 = Mod(y, y^2 + 1)
        ? rnfeltdown(L, Mod(y,K.pol))
        %6 = Mod(y, y^2 + 1)
        ? rnfeltdown(L, Mod(x, L.pol))
        *** at top-level: rnfeltdown(L,Mod(x,x
        *** ^--------------------
        *** rnfeltdown: domain error in rnfeltdown: element not in the base field
        ? rnfeltdown(L, Mod(y, x^2-y), 1) \\ as a t_COL
        %7 = [0, 1]~
        ? rnfeltdown(L, [0,1,0,0]~) \\ not allowed without absolute nf struct
        *** rnfeltdown: incorrect type in rnfeltdown (t_COL).
        ? nfinit(L); \\ add absolute nf structure to L
        ? rnfeltdown(L, [0,1,0,0]~) \\ now OK
        %8 = Mod(y, y^2 + 1)

        If we had started with
        :literal:`L = rnfinit(K, x^2-y, 1)`, then the final would have worked directly.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfeltdown0(_rnf, _x, flag)
        return new_gen(_ret)

    def rnfeltnorm(self, rnf, x):
        r'''
        :math:`rnf` being a relative number field extension :math:`L/K` as output by
        :literal:`rnfinit` and :math:`x` being an element of :math:`L`, returns the relative norm
        :math:`N_{L/K}(x)` as an element of :math:`K`.

        ::

        ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y);
        ? rnfeltnorm(L, Mod(x, L.pol))
        %2 = Mod(x, x^2 + Mod(-y, y^2 + 1))
        ? rnfeltnorm(L, 2)
        %3 = 4
        ? rnfeltnorm(L, Mod(x, x^2-y))
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfeltnorm(_rnf, _x)
        return new_gen(_ret)

    def rnfeltreltoabs(self, rnf, x):
        r'''
        :math:`rnf` being a relative
        number field extension :math:`L/K` as output by :literal:`rnfinit` and :math:`x` being an
        element of :math:`L` expressed as a polynomial or polmod with polmod
        coefficients, computes :math:`x` as an element of the absolute extension :math:`L/\mathbb{Q}` as
        a polynomial modulo the absolute equation :literal:`:emphasis:`rnf`.pol`.

        ::

        ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y);
        ? L.pol
        %2 = x^4 + 1
        ? rnfeltreltoabs(L, Mod(x, L.pol))
        %3 = Mod(x, x^4 + 1)
        ? rnfeltreltoabs(L, Mod(y, x^2-y))
        %4 = Mod(x^2, x^4 + 1)
        ? rnfeltreltoabs(L, Mod(y,K.pol))
        %5 = Mod(x^2, x^4 + 1)
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfeltreltoabs(_rnf, _x)
        return new_gen(_ret)

    def rnfelttrace(self, rnf, x):
        r'''
        :math:`rnf` being a relative number field extension :math:`L/K` as output by
        :literal:`rnfinit` and :math:`x` being an element of :math:`L`, returns the relative trace
        :math:`Tr_{L/K}(x)` as an element of :math:`K`.

        ::

        ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y);
        ? rnfelttrace(L, Mod(x, L.pol))
        %2 = 0
        ? rnfelttrace(L, 2)
        %3 = 4
        ? rnfelttrace(L, Mod(x, x^2-y))
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfelttrace(_rnf, _x)
        return new_gen(_ret)

    def rnfeltup(self, rnf, x, long flag=0):
        r'''
        :math:`rnf` being a relative number field extension :math:`L/K` as output by
        :literal:`rnfinit` and :math:`x` being an element of :math:`K`, computes :math:`x` as an element of
        the absolute extension :math:`L/\mathbb{Q}`. As a :literal:`t_POLMOD` modulo :literal:`:emphasis:`rnf`.pol`
        if :math:`flag = 0` and as a :literal:`t_COL` on the absolute field integer basis if
        :math:`flag = 1`.

        ::

        ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y);
        ? L.pol
        %2 = x^4 + 1
        ? rnfeltup(L, Mod(y, K.pol))
        %3 = Mod(x^2, x^4 + 1)
        ? rnfeltup(L, y)
        %4 = Mod(x^2, x^4 + 1)
        ? rnfeltup(L, [1,2]~) \\ in terms of K.zk
        %5 = Mod(2*x^2 + 1, x^4 + 1)
        ? rnfeltup(L, y, 1) \\ in terms of nfinit(L).zk
        %6 = [0, 1, 0, 0]~
        ? rnfeltup(L, [1,2]~, 1)
        %7 = [1, 2, 0, 0]~
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfeltup0(_rnf, _x, flag)
        return new_gen(_ret)

    def rnfequation(self, nf, pol, long flag=0):
        r'''
        Given a number field
        :math:`nf` as output by :literal:`nfinit` (or simply a polynomial) and a
        polynomial :emphasis:`pol` with coefficients in :math:`nf` defining a relative
        extension :math:`L` of :math:`nf`, computes an absolute equation of :math:`L` over
        :math:`\mathbb{Q}`.

        The main variable of :math:`nf` :emphasis:`must` be of lower priority than that
        of :emphasis:`pol` (see ``priority`` (in the PARI manual)). Note that for efficiency, this does
        not check whether the relative equation is irreducible over :math:`nf`, but
        only if it is squarefree. If it is reducible but squarefree, the result will
        be the absolute equation of the étale algebra defined by :emphasis:`pol`. If
        :emphasis:`pol` is not squarefree, raise an :literal:`e_DOMAIN` exception.

        ::

        ? rnfequation(y^2+1, x^2 - y)
        %1 = x^4 + 1
        ? T = y^3-2; rnfequation(nfinit(T), (x^3-2)/(x-Mod(y,T)))
        %2 = x^6 + 108 \\ Galois closure of Q(2^(1/3))

        If :math:`flag` is non-zero, outputs a 3-component row vector :math:`[z,a,k]`, where

        - :math:`z` is the absolute equation of :math:`L` over :math:`\mathbb{Q}`, as in the default
        behavior,

        - :math:`a` expresses as a :literal:`t_POLMOD` modulo :math:`z` a root :math:`\alpha` of the
        polynomial defining the base field :math:`nf`,

        - :math:`k` is a small integer such that :math:`\theta = \beta+k\alpha`
        is a root of :math:`z`, where :math:`\beta` is a root of :math:`pol`. It is guaranteed
        that :math:`k = 0` whenever :math:`\mathbb{Q} (\beta) = L`.

        ::

        ? T = y^3-2; pol = x^2 +x*y + y^2;
        ? [z,a,k] = rnfequation(T, pol, 1);
        ? z
        %3 = x^6 + 108
        ? subst(T, y, a)
        %4 = 0
        ? alpha= Mod(y, T);
        ? beta = Mod(x*Mod(1,T), pol);
        ? subst(z, x, beta + k*alpha)
        %7 = 0
        '''
        nf = objtogen(nf)
        pol = objtogen(pol)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _ret = rnfequation0(_nf, _pol, flag)
        return new_gen(_ret)

    def rnfhnfbasis(self, bnf, x):
        r'''
        Given :math:`bnf` as output by
        :literal:`bnfinit`, and either a polynomial :math:`x` with coefficients in :math:`bnf`
        defining a relative extension :math:`L` of :math:`bnf`, or a pseudo-basis :math:`x` of
        such an extension, gives either a true :math:`bnf`-basis of :math:`L` in upper
        triangular Hermite normal form, if it exists, and returns :math:`0` otherwise.
        '''
        bnf = objtogen(bnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfhnfbasis(_bnf, _x)
        return new_gen(_ret)

    def rnfidealabstorel(self, rnf, x):
        r'''
        Let :math:`rnf` be a relative
        number field extension :math:`L/K` as output by :literal:`rnfinit` and let :math:`x` be an
        ideal of the absolute extension :math:`L/\mathbb{Q}`. Returns the relative pseudo-matrix in
        HNF giving the ideal :math:`x` considered as an ideal of the relative extension
        :math:`L/K`, i.e. as a :math:`\mathbb{Z}_K`-module.

        Let :literal:`Labs` be an (absolute) :literal:`nf` structure attached to :math:`L`,
        obtained via :literal:`Labs = nfinit(rnf))`. Then :literal:`rnf` "knows" about
        :literal:`Labs` and :math:`x` may be given in any format
        attached to :literal:`Labs`, e.g. a prime ideal or an ideal in HNF wrt.
        :literal:`Labs.zk`:

        ::

        ? K = nfinit(y^2+1); rnf = rnfinit(K, x^2-y); Labs = nfinit(rnf);
        ? m = idealhnf(Labs, 17, x^3+2); \\ some ideal in HNF wrt. Labs.zk
        ? B = rnfidealabstorel(rnf, m)
        %3 = [[1, 8; 0, 1], [[17, 4; 0, 1], 1]] \\ pseudo-basis for m as Z_K-module
        ? A = rnfidealreltoabs(rnf, B)
        %4 = [17, x^2 + 4, x + 8, x^3 + 8*x^2] \\ Z-basis for m in Q[x]/(rnf.polabs)
        ? mathnf(matalgtobasis(Labs, A)) == m
        %5 = 1

        If on the other hand, we do not have a :literal:`Labs` at hand,
        because it would be too expensive to compute, but we nevertheless have
        a :math:`\mathbb{Z}`-basis for :math:`x`, then we can use the function with this basis as
        argument. The entries of :math:`x` may be given either modulo :literal:`rnf.polabs`
        (absolute form, possibly lifted) or modulo :literal:`rnf.pol` (relative form as
        :literal:`t_POLMOD` s):

        ::

        ? K = nfinit(y^2+1); rnf = rnfinit(K, x^2-y);
        ? rnfidealabstorel(rnf, [17, x^2 + 4, x + 8, x^3 + 8*x^2])
        %2 = [[1, 8; 0, 1], [[17, 4; 0, 1], 1]]
        ? rnfidealabstorel(rnf, Mod([17, y + 4, x + 8, y*x + 8*y], x^2-y))
        %3 = [[1, 8; 0, 1], [[17, 4; 0, 1], 1]]
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfidealabstorel(_rnf, _x)
        return new_gen(_ret)

    def rnfidealdown(self, rnf, x):
        r'''
        Let :math:`rnf` be a relative number
        field extension :math:`L/K` as output by :literal:`rnfinit`, and :math:`x` an ideal of
        :math:`L`, given either in relative form or by a :math:`\mathbb{Z}`-basis of elements of :math:`L`
        (see ``rnfidealabstorel`` (in the PARI manual)). This function returns the ideal of :math:`K`
        below :math:`x`, i.e. the intersection of :math:`x` with :math:`K`.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfidealdown(_rnf, _x)
        return new_gen(_ret)

    def rnfidealfactor(self, rnf, x):
        r'''
        Factor into prime ideal powers the
        ideal :math:`x` in the attached absolute number field :math:`L = nfinit (rnf)`.
        The output format is similar to the :literal:`factor` function, and the prime
        ideals are represented in the form output by the :literal:`idealprimedec`
        function for :math:`L`.

        ::

        ? rnf = rnfinit(nfinit(y^2+1), x^2-y+1);
        ? rnfidealfactor(rnf, y+1) \\ P_2^2
        %2 =
        [[2, [0,0,1,0]~, 4, 1, [0,0,0,2;0,0,-2,0;-1,-1,0,0;1,-1,0,0]] 2]
        
        ? rnfidealfactor(rnf, x) \\ P_2
        %3 =
        [[2, [0,0,1,0]~, 4, 1, [0,0,0,2;0,0,-2,0;-1,-1,0,0;1,-1,0,0]] 1]
        
        ? L = nfinit(rnf);
        ? id = idealhnf(L, idealhnf(L, 25, (x+1)^2));
        ? idealfactor(L, id) == rnfidealfactor(rnf, id)
        %6 = 1

        Note that ideals of the base field :math:`K` must be explicitly
        lifted to :math:`L` via :literal:`rnfidealup` before they can be factored.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfidealfactor(_rnf, _x)
        return new_gen(_ret)

    def rnfidealhnf(self, rnf, x):
        r'''
        :math:`rnf` being a relative number
        field extension :math:`L/K` as output by :literal:`rnfinit` and :math:`x` being a relative
        ideal (which can be, as in the absolute case, of many different types,
        including of course elements), computes the HNF pseudo-matrix attached to
        :math:`x`, viewed as a :math:`\mathbb{Z}_K`-module.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfidealhnf(_rnf, _x)
        return new_gen(_ret)

    def rnfidealmul(self, rnf, x, y):
        r'''
        :math:`rnf` being a relative number
        field extension :math:`L/K` as output by :literal:`rnfinit` and :math:`x` and :math:`y` being ideals
        of the relative extension :math:`L/K` given by pseudo-matrices, outputs the ideal
        product, again as a relative ideal.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = rnfidealmul(_rnf, _x, _y)
        return new_gen(_ret)

    def rnfidealnormabs(self, rnf, x):
        r'''
        Let :math:`rnf` be a relative
        number field extension :math:`L/K` as output by :literal:`rnfinit` and let :math:`x` be a
        relative ideal (which can be, as in the absolute case, of many different
        types, including of course elements). This function computes the norm of the
        :math:`x` considered as an ideal of the absolute extension :math:`L/\mathbb{Q}`. This is
        identical to

        ::

        idealnorm(rnf, rnfidealnormrel(rnf,x))

        but faster.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfidealnormabs(_rnf, _x)
        return new_gen(_ret)

    def rnfidealnormrel(self, rnf, x):
        r'''
        Let :math:`rnf` be a relative
        number field extension :math:`L/K` as output by :literal:`rnfinit` and let :math:`x` be a
        relative ideal (which can be, as in the absolute case, of many different
        types, including of course elements). This function computes the relative
        norm of :math:`x` as an ideal of :math:`K` in HNF.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfidealnormrel(_rnf, _x)
        return new_gen(_ret)

    def rnfidealprimedec(self, rnf, pr):
        r'''
        Let :emphasis:`rnf` be a relative number
        field extension :math:`L/K` as output by :literal:`rnfinit`, and :emphasis:`pr` a maximal
        ideal of :math:`K` (:emphasis:`prid`), this function completes the :emphasis:`rnf`
        with a :emphasis:`nf` structure attached to :math:`L` (see ``rnfinit`` (in the PARI manual))
        and returns the prime ideal decomposition of :emphasis:`pr` in :math:`L/K`.

        ::

        ? K = nfinit(y^2+1); rnf = rnfinit(K, x^3+y+1);
        ? P = idealprimedec(K, 2)[1];
        ? S = rnfidealprimedec(rnf, P);
        ? #S
        %4 = 1

        The argument :emphasis:`pr` is also allowed to be a prime number :math:`p`, in which
        case the function returns a pair of vectors :literal:`[SK,SL]`, where :literal:`SK` contains
        the primes of :math:`K` above :math:`p` and :literal:`SL`:math:`[i]` is the vector of primes of :math:`L`
        above :literal:`SK`:math:`[i]`.

        ::

        ? [SK,SL] = rnfidealprimedec(rnf, 5);
        ? [#SK, vector(#SL,i,#SL[i])]
        %6 = [2, [2, 2]]
        '''
        rnf = objtogen(rnf)
        pr = objtogen(pr)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _pr = (<Gen>pr).g
        cdef GEN _ret = rnfidealprimedec(_rnf, _pr)
        return new_gen(_ret)

    def rnfidealreltoabs(self, rnf, x, long flag=0):
        r'''
        Let :math:`rnf` be a relative
        number field extension :math:`L/K` as output by :literal:`rnfinit` and let :math:`x` be a
        relative ideal, given as a :math:`\mathbb{Z}_K`-module by a pseudo matrix :math:`[A,I]`.
        This function returns the ideal :math:`x` as an absolute ideal of :math:`L/\mathbb{Q}`.
        If :math:`flag = 0`, the result is given by a vector of :literal:`t_POLMOD` s modulo
        :literal:`rnf.pol` forming a :math:`\mathbb{Z}`-basis; if :math:`flag = 1`, it is given in HNF in terms
        of the fixed :math:`\mathbb{Z}`-basis for :math:`\mathbb{Z}_L`, see ``rnfinit`` (in the PARI manual).

        ::

        ? K = nfinit(y^2+1); rnf = rnfinit(K, x^2-y);
        ? P = idealprimedec(K,2)[1];
        ? P = rnfidealup(rnf, P)
        %3 = [2, x^2 + 1, 2*x, x^3 + x]
        ? Prel = rnfidealhnf(rnf, P)
        %4 = [[1, 0; 0, 1], [[2, 1; 0, 1], [2, 1; 0, 1]]]
        ? rnfidealreltoabs(rnf,Prel)
        %5 = [2, x^2 + 1, 2*x, x^3 + x]
        ? rnfidealreltoabs(rnf,Prel,1)
        %6 =
        [2 1 0 0]
        
        [0 1 0 0]
        
        [0 0 2 1]
        
        [0 0 0 1]

        The reason why we do not return by default (:math:`flag = 0`) the customary HNF in
        terms of a fixed :math:`\mathbb{Z}`-basis for :math:`\mathbb{Z}_L` is precisely because
        a :emphasis:`rnf` does not contain such a basis by default. Completing the
        structure so that it contains a :emphasis:`nf` structure for :math:`L` is polynomial
        time but costly when the absolute degree is large, thus it is not done by
        default. Note that setting :math:`flag = 1` will complete the :emphasis:`rnf`.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfidealreltoabs0(_rnf, _x, flag)
        return new_gen(_ret)

    def rnfidealtwoelt(self, rnf, x):
        r'''
        :math:`rnf` being a relative
        number field extension :math:`L/K` as output by :literal:`rnfinit` and :math:`x` being an
        ideal of the relative extension :math:`L/K` given by a pseudo-matrix, gives a
        vector of two generators of :math:`x` over :math:`\mathbb{Z}_L` expressed as polmods with polmod
        coefficients.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfidealtwoelement(_rnf, _x)
        return new_gen(_ret)

    def rnfidealup(self, rnf, x, long flag=0):
        r'''
        Let :math:`rnf` be a relative number
        field extension :math:`L/K` as output by :literal:`rnfinit` and let :math:`x` be an ideal of
        :math:`K`. This function returns the ideal :math:`x\mathbb{Z}_L` as an absolute ideal of :math:`L/\mathbb{Q}`,
        in the form of a :math:`\mathbb{Z}`-basis. If :math:`flag = 0`, the result is given by a vector of
        polynomials (modulo :literal:`rnf.pol`); if :math:`flag = 1`, it is given in HNF in terms
        of the fixed :math:`\mathbb{Z}`-basis for :math:`\mathbb{Z}_L`, see ``rnfinit`` (in the PARI manual).

        ::

        ? K = nfinit(y^2+1); rnf = rnfinit(K, x^2-y);
        ? P = idealprimedec(K,2)[1];
        ? rnfidealup(rnf, P)
        %3 = [2, x^2 + 1, 2*x, x^3 + x]
        ? rnfidealup(rnf, P,1)
        %4 =
        [2 1 0 0]
        
        [0 1 0 0]
        
        [0 0 2 1]
        
        [0 0 0 1]

        The reason why we do not return by default (:math:`flag = 0`) the customary HNF in
        terms of a fixed :math:`\mathbb{Z}`-basis for :math:`\mathbb{Z}_L` is precisely because
        a :emphasis:`rnf` does not contain such a basis by default. Completing the
        structure so that it contains a :emphasis:`nf` structure for :math:`L` is polynomial
        time but costly when the absolute degree is large, thus it is not done by
        default. Note that setting :math:`flag = 1` will complete the :emphasis:`rnf`.
        '''
        rnf = objtogen(rnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfidealup0(_rnf, _x, flag)
        return new_gen(_ret)

    def rnfinit(self, nf, T, long flag=0):
        r'''
        Given an :emphasis:`nf` structure attached to a number field :math:`K`, as output by
        :literal:`nfinit`, and a monic irreducible polynomial :math:`T` in :math:`K[x]` defining a
        relative extension :math:`L = K[x]/(T)`, this computes data to work in :math:`L/K`
        The main variable of :math:`T` must be of higher priority
        (see ``priority`` (in the PARI manual)) than that of :math:`nf`, and the coefficients of
        :math:`T` must be in :math:`K`.

        The result is a row vector, whose components are technical.
        We let :math:`m = [K:\mathbb{Q}]` the degree of the base field, :math:`n = [L:K]` the relative
        degree, :math:`r_1` and :math:`r_2` the number of real and complex places of :math:`K`. Access
        to this information via :emphasis:`member functions` is preferred since the
        specific data organization specified below will change in the future.

        If :math:`flag = 1`, add an :emphasis:`nf` structure attached to :math:`L` to :emphasis:`rnf`.
        This is likely to be very expensive if the absolute degree :math:`mn` is large,
        but fixes an integer basis for :math:`\mathbb{Z}_L` as a :math:`\mathbb{Z}`-module and allows to input
        and output elements of :math:`L` in absolute form: as :literal:`t_COL` for elements,
        as :literal:`t_MAT` in HNF for ideals, as :literal:`prid` for prime ideals. Without such
        a call, elements of :math:`L` are represented as :literal:`t_POLMOD`, etc.
        Note that a subsequent :literal:`nfinit`:math:`(rnf)` will also explicitly
        add such a component, and so will the following functions :literal:`rnfidealmul`,
        :literal:`rnfidealtwoelt`, :literal:`rnfidealprimedec`, :literal:`rnfidealup` (with flag 1)
        and :literal:`rnfidealreltoabs` (with flag 1). The absolute :emphasis:`nf` structure
        attached to :math:`L` can be recovered using :literal:`nfinit(rnf)`.

        :math:`rnf[1]`(:literal:`rnf.pol`) contains the relative polynomial :math:`T`.

        :math:`rnf[2]` contains the integer basis :math:`[A,d]` of :math:`K`, as
        (integral) elements of :math:`L/\mathbb{Q}`. More precisely, :math:`A` is a vector of
        polynomial with integer coefficients, :math:`d` is a denominator, and the integer
        basis is given by :math:`A/d`.

        :math:`rnf[3]` (:literal:`rnf.disc`) is a two-component row vector
        :math:`[d (L/K),s]` where :math:`d (L/K)` is the relative ideal discriminant
        of :math:`L/K` and :math:`s` is the discriminant of :math:`L/K` viewed as an element of
        :math:`K^*/(K^*)^2`, in other words it is the output of :literal:`rnfdisc`.

        :math:`rnf[4]`(:literal:`rnf.index`) is the ideal index :math:`f`, i.e. such
        that :math:`d(T)\mathbb{Z}_K = f^2d (L/K)`.

        :math:`rnf[5]` is currently unused.

        :math:`rnf[6]` is currently unused.

        :math:`rnf[7]` (:literal:`rnf.zk`) is the pseudo-basis :math:`(A,I)` for the maximal
        order :math:`\mathbb{Z}_L` as a :math:`\mathbb{Z}_K`-module: :math:`A` is the relative integral pseudo basis
        expressed as polynomials (in the variable of :math:`T`) with polmod coefficients
        in :math:`nf`, and the second component :math:`I` is the ideal list of the
        pseudobasis in HNF.

        :math:`rnf[8]` is the inverse matrix of the integral basis matrix, with
        coefficients polmods in :math:`nf`.

        :math:`rnf[9]` is currently unused.

        :math:`rnf[10]` (:literal:`rnf.nf`) is :math:`nf`.

        :math:`rnf[11]` is an extension of :literal:`rnfequation(K, T, 1)`. Namely, a
        vector :math:`[P, a, k, K.pol, T]` describing the :emphasis:`absolute`
        extension :math:`L/\mathbb{Q}`: :math:`P` is an absolute equation, more conveniently obtained
        as :literal:`rnf.polabs`; :math:`a` expresses the generator :math:`\alpha = y mod K.pol`
        of the number field :math:`K` as an element of :math:`L`, i.e. a polynomial modulo the
        absolute equation :math:`P`;

        :math:`k` is a small integer such that, if :math:`\beta` is an abstract root of :math:`T`
        and :math:`\alpha` the generator of :math:`K` given above, then :math:`P(\beta + k\alpha) = 0`.
        It is guaranteed that :math:`k = 0` if :math:`\mathbb{Q} (\beta) = L`.

        :strong:`Caveat.` Be careful if :math:`k != 0` when dealing simultaneously with
        absolute and relative quantities since :math:`L = \mathbb{Q} (\beta + k\alpha) =
        K(\alpha)`, and the generator chosen for the absolute extension is not the
        same as for the relative one. If this happens, one can of course go on
        working, but we advise to change the relative polynomial so that its root
        becomes :math:`\beta + k \alpha`. Typical GP instructions would be

        ::

        [P,a,k] = rnfequation(K, T, 1);
        if (k, T = subst(T, x, x - k*Mod(y, K.pol)));
        L = rnfinit(K, T);

        :math:`rnf[12]` is by default unused and set equal to 0. This field is used
        to store further information about the field as it becomes available (which
        is rarely needed, hence would be too expensive to compute during the initial
        :literal:`rnfinit` call).

        :strong:`Huge discriminants, helping rnfdisc.` When :math:`T` has a
        discriminant which is difficult to factor, it is hard to compute
        :math:`\mathbb{Z}_L`. As in :literal:`nfinit`, the special input format :math:`[T,B]`
        is also accepted, where :math:`T` is a polynomial as above and :math:`B` is
        an integer. Instead of :math:`\mathbb{Z}_L`, this produces an order which is maximal
        at all primes less than :math:`B`. The result is actually a complete and correct
        :emphasis:`rnf` structure if all prime divisors of the relative ideal
        discriminant divide a rational prime less than :math:`B`. In general, the order
        may not be maximal at primes :math:`p \| p` for :math:`p >= B` such that
        :math:`p^2` divides the relative ideal discriminant.
        '''
        nf = objtogen(nf)
        T = objtogen(T)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = rnfinit0(_nf, _T, flag)
        return new_gen(_ret)

    def rnfisabelian(self, nf, T):
        r'''
        :math:`T` being a relative polynomial with coefficients
        in :emphasis:`nf`, return 1 if it defines an abelian extension, and 0 otherwise.

        ::

        ? K = nfinit(y^2 + 23);
        ? rnfisabelian(K, x^3 - 3*x - y)
        %2 = 1
        '''
        nf = objtogen(nf)
        T = objtogen(T)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _T = (<Gen>T).g
        cdef long _ret = rnfisabelian(_nf, _T)
        clear_stack()
        return _ret

    def rnfisfree(self, bnf, x):
        r'''
        Given :math:`bnf` as output by
        :literal:`bnfinit`, and either a polynomial :math:`x` with coefficients in :math:`bnf`
        defining a relative extension :math:`L` of :math:`bnf`, or a pseudo-basis :math:`x` of
        such an extension, returns true (1) if :math:`L/bnf` is free, false (0) if
        not.
        '''
        bnf = objtogen(bnf)
        x = objtogen(x)
        sig_on()
        cdef GEN _bnf = (<Gen>bnf).g
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = rnfisfree(_bnf, _x)
        clear_stack()
        return _ret

    def rnfislocalcyclo(self, rnf):
        r'''
        Let :emphasis:`rnf` be a relative number field extension :math:`L/K` as output
        by :literal:`rnfinit` whose degree :math:`[L:K]` is a power of a prime :math:`\ell`.
        Return :math:`1` if the :math:`\ell`-extension is locally cyclotomic (locally contained in
        the cyclotomic :math:`\mathbb{Z}_\ell`-extension of :math:`K_v` at all places :math:`v \| \ell`), and
        :math:`0` if not.

        ::

        ? K = nfinit(y^2 + y + 1);
        ? L = rnfinit(K, x^3 - y); /* = K(zeta_9), globally cyclotomic */
        ? rnfislocalcyclo(L)
        %3 = 1
        \\ we expect 3-adic continuity by Krasner's lemma
        ? vector(5, i, rnfislocalcyclo(rnfinit(K, x^3 - y + 3^i)))
        %5 = [0, 1, 1, 1, 1]
        '''
        rnf = objtogen(rnf)
        sig_on()
        cdef GEN _rnf = (<Gen>rnf).g
        cdef long _ret = rnfislocalcyclo(_rnf)
        clear_stack()
        return _ret

    def rnfisnorm(self, T, a, long flag=0):
        r'''
        Similar to
        :literal:`bnfisnorm` but in the relative case. :math:`T` is as output by
        :literal:`rnfisnorminit` applied to the extension :math:`L/K`. This tries to decide
        whether the element :math:`a` in :math:`K` is the norm of some :math:`x` in the extension
        :math:`L/K`.

        The output is a vector :math:`[x,q]`, where :math:`a = \mathrm{Norm} (x)*q`. The
        algorithm looks for a solution :math:`x` which is an :math:`S`-integer, with :math:`S` a list
        of places of :math:`K` containing at least the ramified primes, the generators of
        the class group of :math:`L`, as well as those primes dividing :math:`a`. If :math:`L/K` is
        Galois, then this is enough; otherwise, :math:`flag` is used to add more primes to
        :math:`S`: all the places above the primes :math:`p <= flag` (resp. :math:`p\|flag`) if :math:`flag > 0`
        (resp. :math:`flag < 0`).

        The answer is guaranteed (i.e. :math:`a` is a norm iff :math:`q = 1`) if the field is
        Galois, or, under GRH, if :math:`S` contains all primes less than
        :math:`12\log^2\|\mathrm{disc} (M)\|`, where :math:`M` is the normal
        closure of :math:`L/K`.

        If :literal:`rnfisnorminit` has determined (or was told) that :math:`L/K` is
        Galois, and :math:`flag != 0`, a Warning is issued (so that you can set
        :math:`flag = 1` to check whether :math:`L/K` is known to be Galois, according to :math:`T`).
        Example:

        ::

        bnf = bnfinit(y^3 + y^2 - 2*y - 1);
        p = x^2 + Mod(y^2 + 2*y + 1, bnf.pol);
        T = rnfisnorminit(bnf, p);
        rnfisnorm(T, 17)

        checks whether :math:`17` is a norm in the Galois extension :math:`\mathbb{Q} (\beta) /
        \mathbb{Q} (\alpha)`, where :math:`\alpha^3 + \alpha^2 - 2\alpha - 1 = 0` and :math:`\beta^2 +
        \alpha^2 + 2\alpha + 1 = 0` (it is).
        '''
        T = objtogen(T)
        a = objtogen(a)
        sig_on()
        cdef GEN _T = (<Gen>T).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _ret = rnfisnorm(_T, _a, flag)
        return new_gen(_ret)

    def rnfisnorminit(self, pol, polrel, long flag=2):
        r'''
        Let :math:`K` be defined by a root of :emphasis:`pol`, and :math:`L/K` the extension defined
        by the polynomial :emphasis:`polrel`. As usual, :emphasis:`pol` can in fact be an :emphasis:`nf`,
        or :emphasis:`bnf`, etc; if :emphasis:`pol` has degree :math:`1` (the base field is :math:`\mathbb{Q}`),
        polrel is also allowed to be an :emphasis:`nf`, etc. Computes technical data needed
        by :literal:`rnfisnorm` to solve norm equations :math:`Nx = a`, for :math:`x` in :math:`L`, and :math:`a`
        in :math:`K`.

        If :math:`flag = 0`, do not care whether :math:`L/K` is Galois or not.

        If :math:`flag = 1`, :math:`L/K` is assumed to be Galois (unchecked), which speeds up
        :literal:`rnfisnorm`.

        If :math:`flag = 2`, let the routine determine whether :math:`L/K` is Galois.
        '''
        pol = objtogen(pol)
        polrel = objtogen(polrel)
        sig_on()
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _polrel = (<Gen>polrel).g
        cdef GEN _ret = rnfisnorminit(_pol, _polrel, flag)
        return new_gen(_ret)

    def rnfkummer(self, bnr, subgp=None, long d=0, long precision=DEFAULT_BITPREC):
        r'''
        :emphasis:`bnr`
        being as output by :literal:`bnrinit`, finds a relative equation for the
        class field corresponding to the module in :emphasis:`bnr` and the given
        congruence subgroup (the full ray class field if :emphasis:`subgp` is omitted).
        If :math:`d` is positive, outputs the list of all relative equations of
        degree :math:`d` contained in the ray class field defined by :emphasis:`bnr`, with
        the :emphasis:`same` conductor as :math:`(bnr, subgp)`.

        :strong:`Warning.` This routine only works for subgroups of prime index. It
        uses Kummer theory, adjoining necessary roots of unity (it needs to compute a
        tough :literal:`bnfinit` here), and finds a generator via Hecke's characterization
        of ramification in Kummer extensions of prime degree. If your extension does
        not have prime degree, for the time being, you have to split it by hand as a
        tower / compositum of such extensions.
        '''
        bnr = objtogen(bnr)
        cdef bint _have_subgp = (subgp is not None)
        if _have_subgp:
            subgp = objtogen(subgp)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _subgp = NULL
        if _have_subgp:
            _subgp = (<Gen>subgp).g
        precision = nbits2prec(precision)
        cdef GEN _ret = rnfkummer(_bnr, _subgp, d, precision)
        return new_gen(_ret)

    def rnflllgram(self, nf, pol, order, long precision=DEFAULT_BITPREC):
        r'''
        Given a polynomial
        :emphasis:`pol` with coefficients in :emphasis:`nf` defining a relative extension :math:`L` and
        a suborder :emphasis:`order` of :math:`L` (of maximal rank), as output by
        :literal:`rnfpseudobasis`:math:`(nf,pol)` or similar, gives
        :math:`[[neworder],U]`, where :emphasis:`neworder` is a reduced order and :math:`U` is
        the unimodular transformation matrix.
        '''
        nf = objtogen(nf)
        pol = objtogen(pol)
        order = objtogen(order)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _order = (<Gen>order).g
        precision = nbits2prec(precision)
        cdef GEN _ret = rnflllgram(_nf, _pol, _order, precision)
        return new_gen(_ret)

    def rnfnormgroup(self, bnr, pol):
        r'''
        :emphasis:`bnr` being a big ray
        class field as output by :literal:`bnrinit` and :emphasis:`pol` a relative polynomial
        defining an Abelian extension, computes the norm group (alias Artin
        or Takagi group) corresponding to the Abelian extension of
        :math:`bnf =`:literal:`bnr.bnf`
        defined by :emphasis:`pol`, where the module corresponding to :emphasis:`bnr` is assumed
        to be a multiple of the conductor (i.e. :emphasis:`pol` defines a subextension of
        bnr). The result is the HNF defining the norm group on the given generators
        of :literal:`bnr.gen`. Note that neither the fact that :emphasis:`pol` defines an
        Abelian extension nor the fact that the module is a multiple of the conductor
        is checked. The result is undefined if the assumption is not correct,
        but the function will return the empty matrix :literal:`[;]` if it detects a
        problem; it may also not detect the problem and return a wrong result.
        '''
        bnr = objtogen(bnr)
        pol = objtogen(pol)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _ret = rnfnormgroup(_bnr, _pol)
        return new_gen(_ret)

    def rnfpolred(self, nf, pol, long precision=DEFAULT_BITPREC):
        r'''
        This function is obsolete: use :literal:`rnfpolredbest` instead.
        Relative version of :literal:`polred`. Given a monic polynomial :emphasis:`pol` with
        coefficients in :math:`nf`, finds a list of relative polynomials defining some
        subfields, hopefully simpler and containing the original field. In the present
        version :strong:`2.11.4`, this is slower and less efficient than :literal:`rnfpolredbest`.

        :strong:`Remark.` this function is based on an incomplete reduction
        theory of lattices over number fields, implemented by :literal:`rnflllgram`, which
        deserves to be improved.
        '''
        from warnings import warn
        warn('the PARI/GP function rnfpolred is obsolete (2013-12-28)', DeprecationWarning)
        nf = objtogen(nf)
        pol = objtogen(pol)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pol = (<Gen>pol).g
        precision = nbits2prec(precision)
        cdef GEN _ret = rnfpolred(_nf, _pol, precision)
        return new_gen(_ret)

    def rnfpolredabs(self, nf, pol, long flag=0):
        r'''
        Relative version of :literal:`polredabs`. Given an irreducible monic polynomial
        :emphasis:`pol` with coefficients in :math:`nf`, finds a canonical relative
        polynomial defining the same field, hopefully with small coefficients.
        Note that the equation is only canonical for a fixed :emphasis:`nf`, using a
        different defining polynomial in the :emphasis:`nf` structure will produce a
        different relative equation.

        The binary digits of :math:`flag` correspond to :math:`1`: add information to convert
        elements to the new representation, :math:`2`: absolute polynomial, instead of
        relative, :math:`16`: possibly use a suborder of the maximal order. More precisely:

        0: default, return :math:`P`

        1: returns :math:`[P,a]` where :math:`P` is the default output and :math:`a`,
        a :literal:`t_POLMOD` modulo :math:`P`, is a root of :emphasis:`pol`.

        2: returns :emphasis:`Pabs`, an absolute, instead of a relative, polynomial.
        This polynomial is canonical and does not depend on the :emphasis:`nf` structure.
        Same as but faster than

        ::

        polredabs(rnfequation(nf, pol))

        3: returns :math:`[Pabs,a,b]`, where :emphasis:`Pabs` is an absolute polynomial
        as above, :math:`a`, :math:`b` are :literal:`t_POLMOD` modulo :emphasis:`Pabs`, roots of :literal:`nf.pol`
        and :emphasis:`pol` respectively.

        16: possibly use a suborder of the maximal order. This is slower than the
        default when the relative discriminant is smooth, and much faster otherwise.
        In this case the result is no longer canonical; see ``polredabs`` (in the PARI manual).

        :strong:`Warning.` The complexity of :literal:`rnfpolredabs`
        is exponential in the absolute degree. The function :literal:`rnfpolredbest` runs
        in polynomial time, and tends to return polynomials with smaller
        discriminants.
        '''
        nf = objtogen(nf)
        pol = objtogen(pol)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _ret = rnfpolredabs(_nf, _pol, flag)
        return new_gen(_ret)

    def rnfpolredbest(self, nf, pol, long flag=0):
        r'''
        Relative version of :literal:`polredbest`. Given a monic polynomial :emphasis:`pol`
        with coefficients in :math:`nf`, finds a simpler relative polynomial :math:`P`
        defining the same field. As opposed to :literal:`rnfpolredabs` this function does
        not return a :emphasis:`smallest` (canonical) polynomial with respect to some
        measure, but it does run in polynomial time.

        The binary digits of :math:`flag` correspond to :math:`1`: add information to convert
        elements to the new representation, :math:`2`: absolute polynomial, instead of
        relative. More precisely:

        0: default, return :math:`P`

        1: returns :math:`[P,a]` where :math:`P` is the default output and :math:`a`,
        a :literal:`t_POLMOD` modulo :math:`P`, is a root of :emphasis:`pol`.

        2: returns :emphasis:`Pabs`, an absolute, instead of a relative, polynomial.
        Same as but faster than

        ::

        rnfequation(nf, rnfpolredbest(nf,pol))

        3: returns :math:`[Pabs,a,b]`, where :emphasis:`Pabs` is an absolute polynomial
        as above, :math:`a`, :math:`b` are :literal:`t_POLMOD` modulo :emphasis:`Pabs`, roots of :literal:`nf.pol`
        and :emphasis:`pol` respectively.

        ::

        ? K = nfinit(y^3-2); pol = x^2 +x*y + y^2;
        ? [P, a] = rnfpolredbest(K,pol,1);
        ? P
        %3 = x^2 - x + Mod(y - 1, y^3 - 2)
        ? a
        %4 = Mod(Mod(2*y^2+3*y+4,y^3-2)*x + Mod(-y^2-2*y-2,y^3-2),
        x^2 - x + Mod(y-1,y^3-2))
        ? subst(K.pol,y,a)
        %5 = 0
        ? [Pabs, a, b] = rnfpolredbest(K,pol,3);
        ? Pabs
        %7 = x^6 - 3*x^5 + 5*x^3 - 3*x + 1
        ? a
        %8 = Mod(-x^2+x+1, x^6-3*x^5+5*x^3-3*x+1)
        ? b
        %9 = Mod(2*x^5-5*x^4-3*x^3+10*x^2+5*x-5, x^6-3*x^5+5*x^3-3*x+1)
        ? subst(K.pol,y,a)
        %10 = 0
        ? substvec(pol,[x,y],[a,b])
        %11 = 0
        '''
        nf = objtogen(nf)
        pol = objtogen(pol)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _pol = (<Gen>pol).g
        cdef GEN _ret = rnfpolredbest(_nf, _pol, flag)
        return new_gen(_ret)

    def rnfpseudobasis(self, nf, T):
        r'''
        Given an :emphasis:`nf` structure attached to a number field :math:`K`, as output by
        :literal:`nfinit`, and a monic irreducible polynomial :math:`T` in :math:`K[x]` defining a
        relative extension :math:`L = K[x]/(T)`, computes the relative discriminant of :math:`L`
        and a pseudo-basis :math:`(A,J)` for the maximal order :math:`\mathbb{Z}_L` viewed as a
        :math:`\mathbb{Z}_K`-module. This is output as a vector :math:`[A,J,D,d]`, where :math:`D` is the
        relative ideal discriminant and :math:`d` is the relative discriminant considered
        as an element of :math:`K^*/{K^*}^2`.

        ::

        ? K = nfinit(y^2+1);
        ? [A,J,D,d] = rnfpseudobasis(K, x^2+y);
        ? A
        %3 =
        [1 0]
        
        [0 1]
        
        ? J
        %4 = [1, 1]
        ? D
        %5 = [0, -4]~
        ? d
        %6 = [0, -1]~

        :strong:`Huge discriminants, helping rnfdisc.` the format :math:`[T,B]` is
        also accepted instead of :math:`T` and produce an order which is maximal at all
        primes :math:`p < B`, see :literal:`??rnfinit`.

        ::

        ? p = 585403248812100232206609398101;
        ? q = 711171340236468512951957953369;
        ? T = x^2 + 3*(p*q)^2;
        ? [A,J,D,d] = V = rnfpseudobasis(K, T); D
        time = 22,178 ms.
        %10 =
        [3 0]
        
        [0 3]
        ? [A,J,D,d] = W = rnfpseudobasis(K, [T,100]); D
        time = 5 ms.
        %11 =
        [3 0]
        
        [0 3]
        ? V == W
        %12 = 1

        In this example, the results are identical since :math:`D \cap \mathbb{Z}`
        factors over primes less than :math:`100`. Had it not been the case, the
        order would have been guaranteed maximal at primes :math:`p \| p` for :math:`p
        <= 100` only (and might not have been maximal at any maximal ideal
        :math:`p` such that :math:`p^2` dividing :math:`D`.
        '''
        nf = objtogen(nf)
        T = objtogen(T)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _T = (<Gen>T).g
        cdef GEN _ret = rnfpseudobasis(_nf, _T)
        return new_gen(_ret)

    def rnfsteinitz(self, nf, x):
        r'''
        Given a number field :math:`nf` as
        output by :literal:`nfinit` and either a polynomial :math:`x` with coefficients in
        :math:`nf` defining a relative extension :math:`L` of :math:`nf`, or a pseudo-basis
        :math:`x` of such an extension as output for example by :literal:`rnfpseudobasis`,
        computes another pseudo-basis :math:`(A,I)` (not in HNF in general) such that all
        the ideals of :math:`I` except perhaps the last one are equal to the ring of
        integers of :math:`nf`, and outputs the four-component row vector :math:`[A,I,D,d]`
        as in :literal:`rnfpseudobasis`. The name of this function comes from the fact
        that the ideal class of the last ideal of :math:`I`, which is well defined, is the
        Steinitz class of the :math:`\mathbb{Z}_K`-module :math:`\mathbb{Z}_L` (its image in :math:`SK_0(\mathbb{Z}_K)`).
        '''
        nf = objtogen(nf)
        x = objtogen(x)
        sig_on()
        cdef GEN _nf = (<Gen>nf).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = rnfsteinitz(_nf, _x)
        return new_gen(_ret)

    def round(self, x, e=None):
        r'''
        If :math:`x` is in :math:`\mathbb{R}`, rounds :math:`x` to the nearest integer (rounding to
        :math:`+ oo` in case of ties), then and sets :math:`e` to the number of error bits,
        that is the binary exponent of the difference between the original and the
        rounded value (the "fractional part"). If the exponent of :math:`x` is too large
        compared to its precision (i.e. :math:`e > 0`), the result is undefined and an error
        occurs if :math:`e` was not given.

        :strong:`Important remark.` Contrary to the other truncation functions,
        this function operates on every coefficient at every level of a PARI object.
        For example

        .. MATH::

        truncate((2.4*X^2-1.7)/(X)) = 2.4*X,

        whereas

        .. MATH::

        round((2.4*X^2-1.7)/(X)) = (2*X^2-2)/(X).

        An important use of :literal:`round` is to get exact results after an approximate
        computation, when theory tells you that the coefficients must be integers.
        '''
        x = objtogen(x)
        cdef bint _have_e = (e is not None)
        if _have_e:
            raise NotImplementedError("optional argument e not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _e = NULL
        cdef GEN _ret = round0(_x, _e)
        return new_gen(_ret)

    def select(self, f, A, long flag=0):
        r'''
        We first describe the default behavior, when :math:`flag` is 0 or omitted.
        Given a vector or list :literal:`A` and a :literal:`t_CLOSURE` :literal:`f`, :literal:`select`
        returns the elements :math:`x` of :literal:`A` such that :math:`f(x)` is non-zero. In other
        words, :literal:`f` is seen as a selection function returning a boolean value.

        ::

        ? select(x->isprime(x), vector(50,i,i^2+1))
        %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601]
        ? select(x->(x<100), %)
        %2 = [2, 5, 17, 37]

        returns the primes of the form :math:`i^2+1` for some :math:`i <= 50`,
        then the elements less than 100 in the preceding result. The :literal:`select`
        function also applies to a matrix :literal:`A`, seen as a vector of columns, i.e. it
        selects columns instead of entries, and returns the matrix whose columns are
        the selected ones.

        :strong:`Remark.` For :math:`v` a :literal:`t_VEC`, :literal:`t_COL`, :literal:`t_LIST` or :literal:`t_MAT`,
        the alternative set-notations

        ::

        [g(x) | x <- v, f(x)]
        [x | x <- v, f(x)]
        [g(x) | x <- v]

        are available as shortcuts for

        ::

        apply(g, select(f, Vec(v)))
        select(f, Vec(v))
        apply(g, Vec(v))

        respectively:

        ::

        ? [ x | x <- vector(50,i,i^2+1), isprime(x) ]
        %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601]

        If :math:`flag = 1`, this function returns instead the :emphasis:`indices` of
        the selected elements, and not the elements themselves (indirect selection):

        ::

        ? V = vector(50,i,i^2+1);
        ? select(x->isprime(x), V, 1)
        %2 = Vecsmall([1, 2, 4, 6, 10, 14, 16, 20, 24, 26, 36, 40])
        ? vecextract(V, %)
        %3 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601]

        The following function lists the elements in :math:`(\mathbb{Z}/N\mathbb{Z})^*`:

        ::

        ? invertibles(N) = select(x->gcd(x,N) == 1, [1..N])

        Finally

        ::

        ? select(x->x, M)

        selects the non-0 entries in :literal:`M`. If the latter is a
        :literal:`t_MAT`, we extract the matrix of non-0 columns. Note that :emphasis:`removing`
        entries instead of selecting them just involves replacing the selection
        function :literal:`f` with its negation:

        ::

        ? select(x->!isprime(x), vector(50,i,i^2+1))
        '''
        f = objtogen(f)
        A = objtogen(A)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _A = (<Gen>A).g
        cdef GEN _ret = select0(_f, _A, flag)
        return new_gen(_ret)

    def self(self):
        r'''
        Return the calling function or closure as a :literal:`t_CLOSURE` object.
        This is useful for defining anonymous recursive functions.

        ::

        ? (n->if(n==0,1,n*self()(n-1)))(5)
        %1 = 120
        '''
        sig_on()
        cdef GEN _ret = pari_self()
        _ret = gcopy(_ret)
        return new_gen(_ret)

    def seralgdep(self, s, long p, long r):
        r'''
        finds a linear relation between powers :math:`(1,s,
        ..., s^p)` of the series :math:`s`, with polynomial coefficients of degree
        :math:`<= r`. In case no relation is found, return :math:`0`.

        ::

        ? s = 1 + 10*y - 46*y^2 + 460*y^3 - 5658*y^4 + 77740*y^5 + O(y^6);
        ? seralgdep(s, 2, 2)
        %2 = -x^2 + (8*y^2 + 20*y + 1)
        ? subst(%, x, s)
        %3 = O(y^6)
        ? seralgdep(s, 1, 3)
        %4 = (-77*y^2 - 20*y - 1)*x + (310*y^3 + 231*y^2 + 30*y + 1)
        ? seralgdep(s, 1, 2)
        %5 = 0

        The series main variable must not be :math:`x`, so as to be able
        to express the result as a polynomial in :math:`x`.
        '''
        s = objtogen(s)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        cdef GEN _ret = seralgdep(_s, p, r)
        return new_gen(_ret)

    def serchop(self, s, long n=0):
        r'''
        Remove all terms of degree strictly less than :math:`n` in series :math:`s`. When
        the series contains no terms of degree :math:`< n`, return :math:`O(x^n)`.

        ::

        ? s = 1/x + x + 2*x^2 + O(x^3);
        ? serchop(s)
        %2 = x + 2*x^3 + O(x^3)
        ? serchop(s, 2)
        %3 = 2*x^2 + O(x^3)
        ? serchop(s, 100)
        %4 = O(x^100)
        '''
        s = objtogen(s)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        cdef GEN _ret = serchop(_s, n)
        return new_gen(_ret)

    def serconvol(self, x, y):
        r'''
        Convolution (or Hadamard product) of the
        two power series :math:`x` and :math:`y`; in other words if :math:`x = \sum a_k*X^k` and :math:`y = \sum
        b_k*X^k` then :math:`serconvol (x,y) = \sum a_k*b_k*X^k`.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = convol(_x, _y)
        return new_gen(_ret)

    def serlaplace(self, x):
        r'''
        :math:`x` must be a power series with non-negative
        exponents or a polynomial. If :math:`x = \sum (a_k/k!)*X^k` then the result is :math:`\sum
        a_k*X^k`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = laplace(_x)
        return new_gen(_ret)

    def serprec(self, x, v):
        r'''
        Returns the absolute precision of :math:`x` with respect to power series
        in the variable :math:`v`; this is the
        minimum precision of the components of :math:`x`. The result is :literal:`+oo` if :math:`x`
        is an exact object (as a series in :math:`v`):

        ::

        ? serprec(x + O(y^2), y)
        %1 = 2
        ? serprec(x + 2, x)
        %2 = +oo
        ? serprec(2 + x + O(x^2), y)
        %3 = +oo
        '''
        x = objtogen(x)
        cdef long _v = get_var(v)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gpserprec(_x, _v)
        return new_gen(_ret)

    def serreverse(self, s):
        r'''
        Reverse power series of :math:`s`, i.e. the series :math:`t` such that :math:`t(s) = x`;
        :math:`s` must be a power series whose valuation is exactly equal to one.

        ::

        ? \ps 8
        ? t = serreverse(tan(x))
        %2 = x - 1/3*x^3 + 1/5*x^5 - 1/7*x^7 + O(x^8)
        ? tan(t)
        %3 = x + O(x^8)
        '''
        s = objtogen(s)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        cdef GEN _ret = serreverse(_s)
        return new_gen(_ret)

    def setbinop(self, f, X, Y=None):
        r'''
        The set whose elements are the f(x,y), where x,y run through X,Y.
        respectively. If :math:`Y` is omitted, assume that :math:`X = Y` and that :math:`f` is symmetric:
        :math:`f(x,y) = f(y,x)` for all :math:`x,y` in :math:`X`.

        ::

        ? X = [1,2,3]; Y = [2,3,4];
        ? setbinop((x,y)->x+y, X,Y) \\ set X + Y
        %2 = [3, 4, 5, 6, 7]
        ? setbinop((x,y)->x-y, X,Y) \\ set X - Y
        %3 = [-3, -2, -1, 0, 1]
        ? setbinop((x,y)->x+y, X) \\ set 2X = X + X
        %2 = [2, 3, 4, 5, 6]
        '''
        f = objtogen(f)
        X = objtogen(X)
        cdef bint _have_Y = (Y is not None)
        if _have_Y:
            Y = objtogen(Y)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _X = (<Gen>X).g
        cdef GEN _Y = NULL
        if _have_Y:
            _Y = (<Gen>Y).g
        cdef GEN _ret = setbinop(_f, _X, _Y)
        return new_gen(_ret)

    def setintersect(self, x, y):
        r'''
        Intersection of the two sets :math:`x` and :math:`y` (see :literal:`setisset`).
        If :math:`x` or :math:`y` is not a set, the result is undefined.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = setintersect(_x, _y)
        return new_gen(_ret)

    def setisset(self, x):
        r'''
        Returns true (1) if :math:`x` is a set, false (0) if
        not. In PARI, a set is a row vector whose entries are strictly
        increasing with respect to a (somewhat arbitrary) universal comparison
        function. To convert any object into a set (this is most useful for
        vectors, of course), use the function :literal:`Set`.

        ::

        ? a = [3, 1, 1, 2];
        ? setisset(a)
        %2 = 0
        ? Set(a)
        %3 = [1, 2, 3]
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = setisset(_x)
        clear_stack()
        return _ret

    def setminus(self, x, y):
        r'''
        Difference of the two sets :math:`x` and :math:`y` (see :literal:`setisset`),
        i.e. set of elements of :math:`x` which do not belong to :math:`y`.
        If :math:`x` or :math:`y` is not a set, the result is undefined.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = setminus(_x, _y)
        return new_gen(_ret)

    def setrand(self, n):
        r'''
        Reseeds the random number generator using the seed :math:`n`. No value is
        returned. The seed is a small positive integer :math:`0 < n < 2^{64}` used to
        generate deterministically a suitable state array. All gp session start
        by an implicit :literal:`setrand(1)`, so resetting the seed to this value allows
        to replay all computations since the session start. Alternatively,
        running a randomized computation starting by :literal:`setrand` (:math:`n`)
        twice with the same :math:`n` will generate the exact same output.

        In the other direction, including a call to :literal:`setrand(getwalltime())`
        from your gprc will cause GP to produce different streams of random numbers
        in each session. (Unix users may want to use :literal:`/dev/urandom` instead
        of :literal:`getwalltime`.)

        For debugging purposes, one can also record a particular random state
        using :literal:`getrand` (the value is encoded as a huge integer) and feed it to
        :literal:`setrand`:

        ::

        ? state = getrand(); \\ record seed
        ...
        ? setrand(state); \\ we can now replay the exact same computations
        '''
        n = objtogen(n)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        setrand(_n)
        clear_stack()

    def setsearch(self, S, x, long flag=0):
        r'''
        Determines whether :math:`x` belongs to the set :math:`S` (see :literal:`setisset`).

        We first describe the default behavior, when :math:`flag` is zero or omitted. If :math:`x`
        belongs to the set :math:`S`, returns the index :math:`j` such that :math:`S[j] = x`, otherwise
        returns 0.

        ::

        ? T = [7,2,3,5]; S = Set(T);
        ? setsearch(S, 2)
        %2 = 1
        ? setsearch(S, 4) \\ not found
        %3 = 0
        ? setsearch(T, 7) \\ search in a randomly sorted vector
        %4 = 0 \\ WRONG !

        If :math:`S` is not a set, we also allow sorted lists with
        respect to the :literal:`cmp` sorting function, without repeated entries,
        as per :literal:`listsort`:math:`(L,1)`; otherwise the result is undefined.

        ::

        ? L = List([1,4,2,3,2]); setsearch(L, 4)
        %1 = 0 \\ WRONG !
        ? listsort(L, 1); L \\ sort L first
        %2 = List([1, 2, 3, 4])
        ? setsearch(L, 4)
        %3 = 4 \\ now correct

        If :math:`flag` is non-zero, this function returns the index :math:`j` where :math:`x` should be
        inserted, and :math:`0` if it already belongs to :math:`S`. This is meant to be used for
        dynamically growing (sorted) lists, in conjunction with :literal:`listinsert`.

        ::

        ? L = List([1,5,2,3,2]); listsort(L,1); L
        %1 = List([1,2,3,5])
        ? j = setsearch(L, 4, 1) \\ 4 should have been inserted at index j
        %2 = 4
        ? listinsert(L, 4, j); L
        %3 = List([1, 2, 3, 4, 5])
        '''
        S = objtogen(S)
        x = objtogen(x)
        sig_on()
        cdef GEN _S = (<Gen>S).g
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = setsearch(_S, _x, flag)
        clear_stack()
        return _ret

    def setunion(self, x, y):
        r'''
        Union of the two sets :math:`x` and :math:`y` (see :literal:`setisset`).
        If :math:`x` or :math:`y` is not a set, the result is undefined.
        '''
        x = objtogen(x)
        y = objtogen(y)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _ret = setunion(_x, _y)
        return new_gen(_ret)

    def shift(self, x, long n):
        r'''
        Shifts :math:`x` componentwise left by :math:`n` bits if :math:`n >= 0` and right by :math:`\|n\|`
        bits if :math:`n < 0`. May be abbreviated as :math:`x` :literal:` << ` :math:`n` or :math:`x` :literal:` >> ` :math:`(-n)`.
        A left shift by :math:`n` corresponds to multiplication by :math:`2^n`. A right shift of an
        integer :math:`x` by :math:`\|n\|` corresponds to a Euclidean division of :math:`x` by :math:`2^{\|n\|}`
        with a remainder of the same sign as :math:`x`, hence is not the same (in general) as
        :math:`x \ 2^n`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gshift(_x, n)
        return new_gen(_ret)

    def shiftmul(self, x, long n):
        r'''
        Multiplies :math:`x` by :math:`2^n`. The difference with
        :literal:`shift` is that when :math:`n < 0`, ordinary division takes place, hence for
        example if :math:`x` is an integer the result may be a fraction, while for shifts
        Euclidean division takes place when :math:`n < 0` hence if :math:`x` is an integer the result
        is still an integer.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gmul2n(_x, n)
        return new_gen(_ret)

    def sigma(self, x, long k=1):
        r'''
        Sum of the :math:`k-th` powers of the positive divisors of :math:`\|x\|`. :math:`x`
        and :math:`k` must be of type integer.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = sumdivk(_x, k)
        return new_gen(_ret)

    def sign(self, x):
        r'''
        sign (:math:`0`, :math:`1` or :math:`-1`) of :math:`x`, which must be of
        type integer, real or fraction; :literal:`t_QUAD` with positive discriminants and
        :literal:`t_INFINITY` are also supported.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef int _ret = gsigne(_x)
        clear_stack()
        return _ret

    def simplify(self, x):
        r'''
        This function simplifies :math:`x` as much as it can. Specifically, a complex or
        quadratic number whose imaginary part is the integer 0 (i.e. not :literal:`Mod(0,2)`
        or :literal:`0.E-28`) is converted to its real part, and a polynomial of degree :math:`0`
        is converted to its constant term. Simplifications occur recursively.

        This function is especially useful before using arithmetic functions,
        which expect integer arguments:

        ::

        ? x = 2 + y - y
        %1 = 2
        ? isprime(x)
        *** at top-level: isprime(x)
        *** ^----------
        *** isprime: not an integer argument in an arithmetic function
        ? type(x)
        %2 = "t_POL"
        ? type(simplify(x))
        %3 = "t_INT"

        Note that GP results are simplified as above before they are stored in the
        history. (Unless you disable automatic simplification with :literal:`\\backslash y`, that is.)
        In particular

        ::

        ? type(%1)
        %4 = "t_INT"
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = simplify(_x)
        return new_gen(_ret)

    def sin(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Sine of :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gsin(_x, precision)
        return new_gen(_ret)

    def sinc(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Cardinal sine of :math:`x`, i.e. :math:`\sin (x)/x` if :math:`x != 0`, :math:`1` otherwise.
        Note that this function also allows to compute

        .. MATH::

        (1-\cos (x)) / x^2 = sinc (x/2)^2 / 2

        accurately near :math:`x = 0`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gsinc(_x, precision)
        return new_gen(_ret)

    def sinh(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Hyperbolic sine of :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gsinh(_x, precision)
        return new_gen(_ret)

    def sizebyte(self, x):
        r'''
        Outputs the total number of bytes occupied by the tree representing the
        PARI object :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = gsizebyte(_x)
        clear_stack()
        return _ret

    def sizedigit(self, x):
        r'''
        This function is DEPRECATED, essentially meaningless, and provided for
        backwards compatibility only. Don't use it!

        outputs a quick upper bound for the number of decimal digits of (the
        components of) :math:`x`, off by at most :math:`1`. More precisely, for a positive
        integer :math:`x`, it computes (approximately) the ceiling of

        .. MATH::

        floor (1 + \log_2 x) \log_{10}2,

        To count the number of decimal digits of a positive integer :math:`x`, use
        :literal:`\#digits(x)`. To estimate (recursively) the size of :math:`x`, use
        :literal:`normlp(x)`.
        '''
        from warnings import warn
        warn('the PARI/GP function sizedigit is obsolete (2015-01-13)', DeprecationWarning)
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef long _ret = sizedigit(_x)
        clear_stack()
        return _ret

    def sqr(self, x):
        r'''
        Square of :math:`x`. This operation is not completely
        straightforward, i.e. identical to :math:`x * x`, since it can usually be
        computed more efficiently (roughly one-half of the elementary
        multiplications can be saved). Also, squaring a :math:`2`-adic number increases
        its precision. For example,

        ::

        ? (1 + O(2^4))^2
        %1 = 1 + O(2^5)
        ? (1 + O(2^4)) * (1 + O(2^4))
        %2 = 1 + O(2^4)

        Note that this function is also called whenever one multiplies two objects
        which are known to be :emphasis:`identical`, e.g. they are the value of the same
        variable, or we are computing a power.

        ::

        ? x = (1 + O(2^4)); x * x
        %3 = 1 + O(2^5)
        ? (1 + O(2^4))^4
        %4 = 1 + O(2^6)

        (note the difference between :literal:`\%2` and :literal:`\%3` above).
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gsqr(_x)
        return new_gen(_ret)

    def sqrt(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of the square root of :math:`x`, defined as :math:`\sqrt{x} =
        \exp (\log x / 2)`. In particular, we have
        :math:`Arg(sqrt(x))\in ]-\pi/2, \pi/2]`, and if :math:`x\in \mathbb{R}` and :math:`x < 0`,
        then the result is complex with positive imaginary part.

        Intmod a prime :math:`p`, :literal:`t_PADIC` and :literal:`t_FFELT` are allowed as arguments. In
        the first 2 cases (:literal:`t_INTMOD`, :literal:`t_PADIC`), the square root (if it
        exists) which is returned is the one whose first :math:`p`-adic digit is in the
        interval :math:`[0,p/2]`. For other arguments, the result is undefined.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gsqrt(_x, precision)
        return new_gen(_ret)

    def sqrtint(self, x):
        r'''
        Returns the integer square root of :math:`x`, i.e. the largest integer :math:`y`
        such that :math:`y^2 <= x`, where :math:`x` a non-negative integer.

        ::

        ? N = 120938191237; sqrtint(N)
        %1 = 347761
        ? sqrt(N)
        %2 = 347761.68741970412747602130964414095216
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = sqrtint(_x)
        return new_gen(_ret)

    def sqrtn(self, x, n, z=None, long precision=DEFAULT_BITPREC):
        r'''
        Principal branch of the :math:`n`th root of :math:`x`,
        i.e. such that :math:`Arg(sqrtn(x))\in ]-\pi/n, \pi/n]`. Intmod
        a prime and :math:`p`-adics are allowed as arguments.

        If :math:`z` is present, it is set to a suitable root of unity allowing to
        recover all the other roots. If it was not possible, z is
        set to zero. In the case this argument is present and no :math:`n`th root exist,
        :math:`0` is returned instead of raising an error.

        ::

        ? sqrtn(Mod(2,7), 2)
        %1 = Mod(3, 7)
        ? sqrtn(Mod(2,7), 2, &z); z
        %2 = Mod(6, 7)
        ? sqrtn(Mod(2,7), 3)
        *** at top-level: sqrtn(Mod(2,7),3)
        *** ^-----------------
        *** sqrtn: nth-root does not exist in gsqrtn.
        ? sqrtn(Mod(2,7), 3, &z)
        %2 = 0
        ? z
        %3 = 0

        The following script computes all roots in all possible cases:

        ::

        sqrtnall(x,n)=
        { my(V,r,z,r2);
        r = sqrtn(x,n, &z);
        if (!z, error("Impossible case in sqrtn"));
        if (type(x) == "t_INTMOD" || type(x)=="t_PADIC",
        r2 = r*z; n = 1;
        while (r2!=r, r2*=z;n++));
        V = vector(n); V[1] = r;
        for(i=2, n, V[i] = V[i-1]*z);
        V
        }
        addhelp(sqrtnall,"sqrtnall(x,n):compute the vector of nth-roots of x");
        '''
        x = objtogen(x)
        n = objtogen(n)
        cdef bint _have_z = (z is not None)
        if _have_z:
            raise NotImplementedError("optional argument z not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _n = (<Gen>n).g
        cdef GEN * _z = NULL
        precision = nbits2prec(precision)
        cdef GEN _ret = gsqrtn(_x, _n, _z, precision)
        return new_gen(_ret)

    def sqrtnint(self, x, long n):
        r'''
        Returns the integer :math:`n`-th root of :math:`x`, i.e. the largest integer :math:`y` such
        that :math:`y^n <= x`, where :math:`x` is a non-negative integer.

        ::

        ? N = 120938191237; sqrtnint(N, 5)
        %1 = 164
        ? N^(1/5)
        %2 = 164.63140849829660842958614676939677391

        The special case :math:`n = 2` is :literal:`sqrtint`
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = sqrtnint(_x, n)
        return new_gen(_ret)

    def stirling(self, long n, long k, long flag=1):
        r'''
        Stirling number of the first kind :math:`s(n,k)` (:math:`flag = 1`, default) or
        of the second kind :math:`S(n,k)` (:emphasis:`flag` = 2), where :math:`n`, :math:`k` are non-negative
        integers. The former is :math:`(-1)^{n-k}` times the
        number of permutations of :math:`n` symbols with exactly :math:`k` cycles; the latter is
        the number of ways of partitioning a set of :math:`n` elements into :math:`k` non-empty
        subsets. Note that if all :math:`s(n,k)` are needed, it is much faster to compute

        .. MATH::

        \sum_k s(n,k) x^k = x(x-1)...(x-n+1).

        Similarly, if a large number of :math:`S(n,k)` are needed for the same :math:`k`,
        one should use

        .. MATH::

        \sum_n S(n,k) x^n = (x^k)/((1-x)...(1-kx)).

        (Should be implemented using a divide and conquer product.) Here are
        simple variants for :math:`n` fixed:

        ::

        /* list of s(n,k), k = 1..n */
        vecstirling(n) = Vec( factorback(vector(n-1,i,1-i*'x)) )
        
        /* list of S(n,k), k = 1..n */
        vecstirling2(n) =
        { my(Q = x^(n-1), t);
        vector(n, i, t = divrem(Q, x-i); Q=t[1]; simplify(t[2]));
        }
        
        /* Bell numbers, B_n = B[n+1] = sum(k = 0, n, S(n,k)), n = 0..N */
        vecbell(N)=
        { my (B = vector(N+1));
        B[1] = B[2] = 1;
        for (n = 2, N,
        my (C = binomial(n-1));
        B[n+1] = sum(k = 1, n, C[k]*B[k]);
        ); B;
        }
        '''
        sig_on()
        cdef GEN _ret = stirling(n, k, flag)
        return new_gen(_ret)

    def subgrouplist(self, bnr, bound=None, long flag=0):
        r'''
        :emphasis:`bnr` being as output by :literal:`bnrinit` or a list of cyclic components
        of a finite Abelian group :math:`G`, outputs the list of subgroups of :math:`G`. Subgroups
        are given as HNF left divisors of the SNF matrix corresponding to :math:`G`.

        If :math:`flag = 0` (default) and :emphasis:`bnr` is as output by :literal:`bnrinit`, gives
        only the subgroups whose modulus is the conductor. Otherwise, the modulus is
        not taken into account.

        If :emphasis:`bound` is present, and is a positive integer, restrict the output to
        subgroups of index less than :emphasis:`bound`. If :emphasis:`bound` is a vector
        containing a single positive integer :math:`B`, then only subgroups of index
        exactly equal to :math:`B` are computed. For instance

        ::

        ? subgrouplist([6,2])
        %1 = [[6, 0; 0, 2], [2, 0; 0, 2], [6, 3; 0, 1], [2, 1; 0, 1], [3, 0; 0, 2],
        [1, 0; 0, 2], [6, 0; 0, 1], [2, 0; 0, 1], [3, 0; 0, 1], [1, 0; 0, 1]]
        ? subgrouplist([6,2],3) \\ index less than 3
        %2 = [[2, 1; 0, 1], [1, 0; 0, 2], [2, 0; 0, 1], [3, 0; 0, 1], [1, 0; 0, 1]]
        ? subgrouplist([6,2],[3]) \\ index 3
        %3 = [[3, 0; 0, 1]]
        ? bnr = bnrinit(bnfinit(x), [120,[1]], 1);
        ? L = subgrouplist(bnr, [8]);

        In the last example, :math:`L` corresponds to the 24 subfields of
        :math:`\mathbb{Q} (\zeta_{120})`, of degree :math:`8` and conductor :math:`120 oo` (by setting :emphasis:`flag`,
        we see there are a total of :math:`43` subgroups of degree :math:`8`).

        ::

        ? vector(#L, i, galoissubcyclo(bnr, L[i]))

        will produce their equations. (For a general base field, you would
        have to rely on :literal:`bnrstark`, or :literal:`rnfkummer`.)
        '''
        bnr = objtogen(bnr)
        cdef bint _have_bound = (bound is not None)
        if _have_bound:
            bound = objtogen(bound)
        sig_on()
        cdef GEN _bnr = (<Gen>bnr).g
        cdef GEN _bound = NULL
        if _have_bound:
            _bound = (<Gen>bound).g
        cdef GEN _ret = subgrouplist0(_bnr, _bound, flag)
        return new_gen(_ret)

    def subst(self, x, y, z):
        r'''
        Replace the simple variable :math:`y` by the argument :math:`z` in the "polynomial"
        expression :math:`x`. Every type is allowed for :math:`x`, but if it is not a genuine
        polynomial (or power series, or rational function), the substitution will be
        done as if the scalar components were polynomials of degree zero. In
        particular, beware that:

        ::

        ? subst(1, x, [1,2; 3,4])
        %1 =
        [1 0]
        
        [0 1]
        
        ? subst(1, x, Mat([0,1]))
        *** at top-level: subst(1,x,Mat([0,1])
        *** ^--------------------
        *** subst: forbidden substitution by a non square matrix.

        If :math:`x` is a power series, :math:`z` must be either a polynomial, a power
        series, or a rational function. Finally, if :math:`x` is a vector,
        matrix or list, the substitution is applied to each individual entry.

        Use the function :literal:`substvec` to replace several variables at once,
        or the function :literal:`substpol` to replace a polynomial expression.
        '''
        x = objtogen(x)
        cdef long _y = get_var(y)
        z = objtogen(z)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _z = (<Gen>z).g
        cdef GEN _ret = gsubst(_x, _y, _z)
        return new_gen(_ret)

    def substpol(self, x, y, z):
        r'''
        Replace the "variable" :math:`y` by the argument :math:`z` in the "polynomial"
        expression :math:`x`. Every type is allowed for :math:`x`, but the same behavior
        as :literal:`subst` above apply.

        The difference with :literal:`subst` is that :math:`y` is allowed to be any polynomial
        here. The substitution is done moding out all components of :math:`x`
        (recursively) by :math:`y - t`, where :math:`t` is a new free variable of lowest
        priority. Then substituting :math:`t` by :math:`z` in the resulting expression. For
        instance

        ::

        ? substpol(x^4 + x^2 + 1, x^2, y)
        %1 = y^2 + y + 1
        ? substpol(x^4 + x^2 + 1, x^3, y)
        %2 = x^2 + y*x + 1
        ? substpol(x^4 + x^2 + 1, (x+1)^2, y)
        %3 = (-4*y - 6)*x + (y^2 + 3*y - 3)
        '''
        x = objtogen(x)
        y = objtogen(y)
        z = objtogen(z)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _z = (<Gen>z).g
        cdef GEN _ret = gsubstpol(_x, _y, _z)
        return new_gen(_ret)

    def substvec(self, x, v, w):
        r'''
        :math:`v` being a vector of monomials of degree 1 (variables),
        :math:`w` a vector of expressions of the same length, replace in the expression
        :math:`x` all occurrences of :math:`v_i` by :math:`w_i`. The substitutions are done
        simultaneously; more precisely, the :math:`v_i` are first replaced by new
        variables in :math:`x`, then these are replaced by the :math:`w_i`:

        ::

        ? substvec([x,y], [x,y], [y,x])
        %1 = [y, x]
        ? substvec([x,y], [x,y], [y,x+y])
        %2 = [y, x + y] \\ not [y, 2*y]
        '''
        x = objtogen(x)
        v = objtogen(v)
        w = objtogen(w)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _v = (<Gen>v).g
        cdef GEN _w = (<Gen>w).g
        cdef GEN _ret = gsubstvec(_x, _v, _w)
        return new_gen(_ret)

    def sumdedekind(self, h, k):
        r'''
        Returns the Dedekind sum attached to the integers :math:`h` and :math:`k`,
        corresponding to a fast implementation of

        ::

        s(h,k) = sum(n = 1, k-1, (n/k)*(frac(h*n/k) - 1/2))
        '''
        h = objtogen(h)
        k = objtogen(k)
        sig_on()
        cdef GEN _h = (<Gen>h).g
        cdef GEN _k = (<Gen>k).g
        cdef GEN _ret = sumdedekind(_h, _k)
        return new_gen(_ret)

    def sumdigits(self, n, B=None):
        r'''
        Sum of digits in the integer :math:`\|n\|`, when written in base :math:`B > 1`.

        ::

        ? sumdigits(123456789)
        %1 = 45
        ? sumdigits(123456789, 2)
        %1 = 16

        Note that the sum of bits in :math:`n` is also returned by
        :literal:`hammingweight`. This function is much faster than
        :literal:`vecsum(digits(n,B))` when :math:`B` is :math:`10` or a power of :math:`2`, and only
        slightly faster in other cases.
        '''
        n = objtogen(n)
        cdef bint _have_B = (B is not None)
        if _have_B:
            B = objtogen(B)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        cdef GEN _B = NULL
        if _have_B:
            _B = (<Gen>B).g
        cdef GEN _ret = sumdigits0(_n, _B)
        return new_gen(_ret)

    def sumeulerrat(self, F, s=None, long a=2, long precision=DEFAULT_BITPREC):
        r'''
        :math:`\sum_{p >= a, p prime}F(p^s)`, where :math:`F` is a rational function.

        ::

        ? sumeulerrat(1/q)
        %1 = 0.45224742004106549850654336483224793418
        '''
        F = objtogen(F)
        cdef bint _have_s = (s is not None)
        if _have_s:
            s = objtogen(s)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _s = NULL
        if _have_s:
            _s = (<Gen>s).g
        precision = nbits2prec(precision)
        cdef GEN _ret = sumeulerrat(_F, _s, a, precision)
        return new_gen(_ret)

    def sumformal(self, f, v=None):
        r'''
        formal sum of the polynomial expression :math:`f` with respect to the
        main variable if :math:`v` is omitted, with respect to the variable :math:`v` otherwise;
        it is assumed that the base ring has characteristic zero. In other words,
        considering :math:`f` as a polynomial function in the variable :math:`v`,
        returns :math:`F`, a polynomial in :math:`v` vanishing at :math:`0`, such that :math:`F(b) - F(a)
        = sum_{v = a+1}^b f(v)`:

        ::

        ? sumformal(n) \\ 1 + ... + n
        %1 = 1/2*n^2 + 1/2*n
        ? f(n) = n^3+n^2+1;
        ? F = sumformal(f(n)) \\ f(1) + ... + f(n)
        %3 = 1/4*n^4 + 5/6*n^3 + 3/4*n^2 + 7/6*n
        ? sum(n = 1, 2000, f(n)) == subst(F, n, 2000)
        %4 = 1
        ? sum(n = 1001, 2000, f(n)) == subst(F, n, 2000) - subst(F, n, 1000)
        %5 = 1
        ? sumformal(x^2 + x*y + y^2, y)
        %6 = y*x^2 + (1/2*y^2 + 1/2*y)*x + (1/3*y^3 + 1/2*y^2 + 1/6*y)
        ? x^2 * y + x * sumformal(y) + sumformal(y^2) == %
        %7 = 1
        '''
        f = objtogen(f)
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _f = (<Gen>f).g
        cdef GEN _ret = sumformal(_f, _v)
        return new_gen(_ret)

    def sumnumapinit(self, asymp=None, long precision=DEFAULT_BITPREC):
        r'''
        Initialize tables for Abel-Plana summation of a series :math:`\sum f(n)`,
        where :math:`f` is holomorphic in a right half-plane.
        If given, :literal:`asymp` is of the form :math:`[+oo, \alpha]`,
        as in :literal:`intnum` and indicates the decrease rate at infinity of functions
        to be summed. A positive
        :math:`\alpha > 0` encodes an exponential decrease of type :math:`\exp (-\alpha n)` and
        a negative :math:`-2 < \alpha < -1` encodes a slow polynomial decrease of type
        :math:`n^{\alpha}`.

        ::

        ? \p200
        ? sumnumap(n=1, n^-2);
        time = 163 ms.
        ? tab = sumnumapinit();
        time = 160 ms.
        ? sumnum(n=1, n^-2, tab); \\ faster
        time = 7 ms.
        
        ? tab = sumnumapinit([+oo, log(2)]); \\ decrease like 2^-n
        time = 164 ms.
        ? sumnumap(n=1, 2^-n, tab) - 1
        time = 36 ms.
        %5 = 3.0127431466707723218 E-282
        
        ? tab = sumnumapinit([+oo, -4/3]); \\ decrease like n^(-4/3)
        time = 166 ms.
        ? sumnumap(n=1, n^(-4/3), tab);
        time = 181 ms.
        '''
        cdef bint _have_asymp = (asymp is not None)
        if _have_asymp:
            asymp = objtogen(asymp)
        sig_on()
        cdef GEN _asymp = NULL
        if _have_asymp:
            _asymp = (<Gen>asymp).g
        precision = nbits2prec(precision)
        cdef GEN _ret = sumnumapinit(_asymp, precision)
        return new_gen(_ret)

    def sumnuminit(self, asymp=None, long precision=DEFAULT_BITPREC):
        r'''
        Initialize tables for Euler-MacLaurin delta summation of a series with
        positive terms. If given, :literal:`asymp` is of the form :math:`[+oo, \alpha]`,
        as in :literal:`intnum` and indicates the decrease rate at infinity of functions
        to be summed. A positive
        :math:`\alpha > 0` encodes an exponential decrease of type :math:`\exp (-\alpha n)` and
        a negative :math:`-2 < \alpha < -1` encodes a slow polynomial decrease of type
        :math:`n^{\alpha}`.

        ::

        ? \p200
        ? sumnum(n=1, n^-2);
        time = 200 ms.
        ? tab = sumnuminit();
        time = 188 ms.
        ? sumnum(n=1, n^-2, tab); \\ faster
        time = 8 ms.
        
        ? tab = sumnuminit([+oo, log(2)]); \\ decrease like 2^-n
        time = 200 ms.
        ? sumnum(n=1, 2^-n, tab)
        time = 44 ms.
        
        ? tab = sumnuminit([+oo, -4/3]); \\ decrease like n^(-4/3)
        time = 200 ms.
        ? sumnum(n=1, n^(-4/3), tab);
        time = 221 ms.
        '''
        cdef bint _have_asymp = (asymp is not None)
        if _have_asymp:
            asymp = objtogen(asymp)
        sig_on()
        cdef GEN _asymp = NULL
        if _have_asymp:
            _asymp = (<Gen>asymp).g
        precision = nbits2prec(precision)
        cdef GEN _ret = sumnuminit(_asymp, precision)
        return new_gen(_ret)

    def sumnumlagrangeinit(self, asymp=None, c1=None, long precision=DEFAULT_BITPREC):
        r'''
        Initialize tables for Lagrange summation of a series. By
        default, assume that the remainder :math:`R(n) = \sum_{m >= n} f(m)`
        has an asymptotic expansion

        .. MATH::

        R(n) = \sum_{m >= n} f(n) ~ \sum_{i >= 1} a_i / n^i

        at infinity. The argument :literal:`asymp` allows to specify different
        expansions:

        - a real number :math:`\beta` means
        

        .. MATH::

        R(n) = n^{-\beta} \sum_{i >= 1} a_i / n^i

        - a :literal:`t_CLOSURE` :math:`g` means
        

        .. MATH::

        R(n) = g(n) \sum_{i >= 1} a_i / n^i

        (The preceding case corresponds to :math:`g(n) = n^{-\beta}`.)

        - a pair :math:`[\alpha,\beta]` where :math:`\beta` is as above and
        :math:`\alpha\in {2, 1, 1/2, 1/3, 1/4}`. We let :math:`R_2(n) = R(n) - f(n)/2`
        and :math:`R_\alpha (n) = R(n)` for :math:`\alpha != 2`. Then
        

        .. MATH::

        R_\alpha (n) = g(n) \sum_{i >= 1} a_i / n^{i\alpha}

        Note that the initialization times increase considerable for the :math:`\alpha`
        is this list (:math:`1/4` being the slowest).

        The constant :math:`c1` is technical and computed by the program, but can be set
        by the user: the number of interpolation steps will be chosen close to
        :math:`c1.B`, where :math:`B` is the bit accuracy.

        ::

        ? \p2000
        ? sumnumlagrange(n=1, n^-2);
        time = 173 ms.
        ? tab = sumnumlagrangeinit();
        time = 172 ms.
        ? sumnumlagrange(n=1, n^-2, tab);
        time = 4 ms.
        
        ? \p115
        ? sumnumlagrange(n=1, n^(-4/3)) - zeta(4/3);
        %1 = -0.1093[...] \\ junk: expansion in n^(1/3)
        time = 84 ms.
        ? tab = sumnumlagrangeinit([1/3,0]); \\ alpha = 1/3
        time = 336 ms.
        ? sumnumlagrange(n=1, n^(-4/3), tab) - zeta(4/3)
        time = 84 ms.
        %3 = 1.0151767349262596893 E-115 \\ now OK
        
        ? tab = sumnumlagrangeinit(1/3); \\ alpha = 1, beta = 1/3: much faster
        time = 3ms
        ? sumnumlagrange(n=1, n^(-4/3), tab) - zeta(4/3) \\ ... but wrong
        %5 = -0.273825[...] \\ junk !
        ? tab = sumnumlagrangeinit(-2/3); \\ alpha = 1, beta = -2/3
        time = 3ms
        ? sumnumlagrange(n=1, n^(-4/3), tab) - zeta(4/3)
        %6 = 2.030353469852519379 E-115 \\ now OK

        in The final example with :math:`\zeta (4/3)`, the remainder
        :math:`R_1(n)` is of the form :math:`n^{-1/3} \sum_{i >= 0} a_i / n^i`, i.e.
        :math:`n^{2/3} \sum_{i >= 1} a_i / n^i`. The explains the wrong result
        for :math:`\beta = 1/3` and the correction with :math:`\beta = -2/3`.
        '''
        cdef bint _have_asymp = (asymp is not None)
        if _have_asymp:
            asymp = objtogen(asymp)
        cdef bint _have_c1 = (c1 is not None)
        if _have_c1:
            c1 = objtogen(c1)
        sig_on()
        cdef GEN _asymp = NULL
        if _have_asymp:
            _asymp = (<Gen>asymp).g
        cdef GEN _c1 = NULL
        if _have_c1:
            _c1 = (<Gen>c1).g
        precision = nbits2prec(precision)
        cdef GEN _ret = sumnumlagrangeinit(_asymp, _c1, precision)
        return new_gen(_ret)

    def sumnummonieninit(self, asymp=None, w=None, n0=None, long precision=DEFAULT_BITPREC):
        r'''
        Initialize tables for Monien summation of a series :math:`\sum_{n >= n_0}
        f(n)` where :math:`f(1/z)` has a complex analytic continuation in a (complex)
        neighbourhood of the segment :math:`[0,1]`.

        By default, assume that :math:`f(n) = O(n^{-2})` and has a non-zero asymptotic
        expansion

        .. MATH::

        f(n) = \sum_{i >= 2} a_i / n^i

        at infinity. Note that the sum starts at :math:`i = 2`! The argument :literal:`asymp`
        allows to specify different expansions:

        - a real number :math:`\beta > 0` means
        

        .. MATH::

        f(n) = \sum_{i >= 1} a_i / n^{i + \beta}

        (Now the summation starts at :math:`1`.)

        - a vector :math:`[\alpha,\beta]` of reals, where we must have :math:`\alpha > 0`
        and :math:`\alpha + \beta > 1` to ensure convergence, means that
        

        .. MATH::

        f(n) = \sum_{i >= 1} a_i / n^{\alpha i + \beta}

        Note that :math:`asymp = [1, \beta]` is equivalent to
        :math:`asymp = \beta`.

        ::

        ? \p57
        ? s = sumnum(n = 1, sin(1/sqrt(n)) / n); \\ reference point
        
        ? \p38
        ? sumnummonien(n = 1, sin(1/sqrt(n)) / n) - s
        %2 = -0.001[...] \\ completely wrong
        
        ? t = sumnummonieninit(1/2); \\ f(n) = sum_i 1 / n^(i+1/2)
        ? sumnummonien(n = 1, sin(1/sqrt(n)) / n, t) - s
        %3 = 0.E-37 \\ now correct

        (As a matter of fact, in the above summation, the
        result given by :literal:`sumnum` at :literal:`\\p38` is slighly incorrect,
        so we had to increase the accuracy to :literal:`\\p57`.)

        The argument :math:`w` is used to sum expressions of the form

        .. MATH::

        \sum_{n >= n_0} f(n) w(n),

        for varying :math:`f` :emphasis:`as above`, and fixed weight function :math:`w`, where we
        further assume that the auxiliary sums

        .. MATH::

        g_w(m) = \sum_{n >= n_0} w(n) / n^{\alpha m + \beta}

        converge for all :math:`m >= 1`. Note that for non-negative integers :math:`k`,
        and weight :math:`w(n) = (\log n)^k`, the function :math:`g_w(m) = \zeta^{(k)}(\alpha m +
        \beta)` has a simple expression; for general weights, :math:`g_w` is
        computed using :literal:`sumnum`. The following variants are available

        - an integer :math:`k >= 0`, to code :math:`w(n) = (\log n)^k`;

        - a :literal:`t_CLOSURE` computing the values :math:`w(n)`, where we
        assume that :math:`w(n) = O(n^\epsilon)` for all :math:`\epsilon > 0`;

        - a vector :math:`[w, fast]`, where :math:`w` is a closure as above
        and :literal:`fast` is a scalar;
        we assume that :math:`w(n) = O(n^{fast+\epsilon})`; note that
        :math:`w = [w, 0]` is equivalent to :math:`w = w`. Note that if
        :math:`w` decreases exponentially, :literal:`suminf` should be used instead.

        The subsequent calls to :literal:`sumnummonien` :emphasis:`must` use the same value
        of :math:`n_0` as was used here.

        ::

        ? \p300
        ? sumnummonien(n = 1, n^-2*log(n)) + zeta'(2)
        time = 328 ms.
        %1 = -1.323[...]E-6 \\ completely wrong, f does not satisfy hypotheses !
        ? tab = sumnummonieninit(, 1); \\ codes w(n) = log(n)
        time = 3,993 ms.
        ? sumnummonien(n = 1, n^-2, tab) + zeta'(2)
        time = 41 ms.
        %3 = -5.562684646268003458 E-309 \\ now perfect
        
        ? tab = sumnummonieninit(, n->log(n)); \\ generic, slower
        time = 9,808 ms.
        ? sumnummonien(n = 1, n^-2, tab) + zeta'(2)
        time = 40 ms.
        %5 = -5.562684646268003458 E-309 \\ identical result
        '''
        cdef bint _have_asymp = (asymp is not None)
        if _have_asymp:
            asymp = objtogen(asymp)
        cdef bint _have_w = (w is not None)
        if _have_w:
            w = objtogen(w)
        cdef bint _have_n0 = (n0 is not None)
        if _have_n0:
            n0 = objtogen(n0)
        sig_on()
        cdef GEN _asymp = NULL
        if _have_asymp:
            _asymp = (<Gen>asymp).g
        cdef GEN _w = NULL
        if _have_w:
            _w = (<Gen>w).g
        cdef GEN _n0 = NULL
        if _have_n0:
            _n0 = (<Gen>n0).g
        precision = nbits2prec(precision)
        cdef GEN _ret = sumnummonieninit(_asymp, _w, _n0, precision)
        return new_gen(_ret)

    def sumnumrat(self, F, a, long precision=DEFAULT_BITPREC):
        r'''
        :math:`\sum_{n >= a}F(n)`, where :math:`F` is a rational function of degree less
        than or equal to :math:`-2` and where poles of :math:`F` at integers :math:`>= a` are
        omitted from the summation. The argument :math:`a` must be a :literal:`t_INT`
        or :literal:`-oo`.

        ::

        ? sumnumrat(1/(x^2+1)^2,0)
        %1 = 1.3068369754229086939178621382829073480
        ? sumnumrat(1/x^2, -oo) \\ value at x=0 is discarded
        %2 = 3.2898681336964528729448303332920503784
        ? 2*zeta(2)
        %3 = 3.2898681336964528729448303332920503784

        When :math:`\deg F = -1`, we define

        .. MATH::

        \sum_{- oo }^{ oo } F(n) := \sum_{n >= 0} (F(n) + F(-1-n)):

        ::

        ? sumnumrat(1/x, -oo)
        %4 = 0.E-38
        '''
        F = objtogen(F)
        a = objtogen(a)
        sig_on()
        cdef GEN _F = (<Gen>F).g
        cdef GEN _a = (<Gen>a).g
        precision = nbits2prec(precision)
        cdef GEN _ret = sumnumrat(_F, _a, precision)
        return new_gen(_ret)

    def system(self, str):
        r'''
        :emphasis:`str` is a string representing a system command. This command is
        executed, its output written to the standard output (this won't get into your
        logfile), and control returns to the PARI system. This simply calls the C
        :literal:`system` command.
        '''
        str = to_bytes(str)
        cdef char* _str = <bytes>str
        sig_on()
        gpsystem(_str)
        clear_stack()

    def tan(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Tangent of :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gtan(_x, precision)
        return new_gen(_ret)

    def tanh(self, x, long precision=DEFAULT_BITPREC):
        r'''
        Hyperbolic tangent of :math:`x`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gtanh(_x, precision)
        return new_gen(_ret)

    def taylor(self, x, t, long serprec=-1):
        r'''
        Taylor expansion around :math:`0` of :math:`x` with respect to
        the simple variable :math:`t`. :math:`x` can be of any reasonable type, for example a
        rational function. Contrary to :literal:`Ser`, which takes the valuation into
        account, this function adds :math:`O(t^d)` to all components of :math:`x`.

        ::

        ? taylor(x/(1+y), y, 5)
        %1 = (y^4 - y^3 + y^2 - y + 1)*x + O(y^5)
        ? Ser(x/(1+y), y, 5)
        *** at top-level: Ser(x/(1+y),y,5)
        *** ^----------------
        *** Ser: main variable must have higher priority in gtoser.
        '''
        x = objtogen(x)
        cdef long _t = get_var(t)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        if serprec < 0:
            serprec = precdl  # Global PARI series precision
        cdef GEN _ret = tayl(_x, _t, serprec)
        return new_gen(_ret)

    def teichmuller(self, x, tab=None):
        r'''
        Teichmüller character of the :math:`p`-adic number :math:`x`, i.e. the unique
        :math:`(p-1)`-th root of unity congruent to :math:`x / p^{v_p(x)}` modulo :math:`p`.
        If :math:`x` is of the form :math:`[p,n]`, for a prime :math:`p` and integer :math:`n`,
        return the lifts to :math:`\mathbb{Z}` of the images of :math:`i + O(p^n)` for
        :math:`i = 1,..., p-1`, i.e. all roots of :math:`1` ordered by residue class modulo
        :math:`p`. Such a vector can be fed back to :literal:`teichmuller`, as the
        optional argument :literal:`tab`, to speed up later computations.

        ::

        ? z = teichmuller(2 + O(101^5))
        %1 = 2 + 83*101 + 18*101^2 + 69*101^3 + 62*101^4 + O(101^5)
        ? z^100
        %2 = 1 + O(101^5)
        ? T = teichmuller([101, 5]);
        ? teichmuller(2 + O(101^5), T)
        %4 = 2 + 83*101 + 18*101^2 + 69*101^3 + 62*101^4 + O(101^5)

        As a rule of thumb, if more than

        .. MATH::

        p / 2(\log_2(p) + hammingweight (p))

        values of :literal:`teichmuller` are to be computed, then it is worthwile to
        initialize:

        ::

        ? p = 101; n = 100; T = teichmuller([p,n]); \\ instantaneous
        ? for(i=1,10^3, vector(p-1, i, teichmuller(i+O(p^n), T)))
        time = 60 ms.
        ? for(i=1,10^3, vector(p-1, i, teichmuller(i+O(p^n))))
        time = 1,293 ms.
        ? 1 + 2*(log(p)/log(2) + hammingweight(p))
        %8 = 22.316[...]

        Here the precompuation induces a speedup by a factor
        :math:`1293/ 60 ~ 21.5`.

        :strong:`Caveat.`
        If the accuracy of :literal:`tab` (the argument :math:`n` above) is lower than the
        precision of :math:`x`, the :emphasis:`former` is used, i.e. the cached value is not
        refined to higher accuracy. It the accuracy of :literal:`tab` is larger, then
        the precision of :math:`x` is used:

        ::

        ? Tlow = teichmuller([101, 2]); \\ lower accuracy !
        ? teichmuller(2 + O(101^5), Tlow)
        %10 = 2 + 83*101 + O(101^5) \\ no longer a root of 1
        
        ? Thigh = teichmuller([101, 10]); \\ higher accuracy
        ? teichmuller(2 + O(101^5), Thigh)
        %12 = 2 + 83*101 + 18*101^2 + 69*101^3 + 62*101^4 + O(101^5)
        '''
        x = objtogen(x)
        cdef bint _have_tab = (tab is not None)
        if _have_tab:
            tab = objtogen(tab)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _tab = NULL
        if _have_tab:
            _tab = (<Gen>tab).g
        cdef GEN _ret = teichmuller(_x, _tab)
        return new_gen(_ret)

    def theta(self, q, z, long precision=DEFAULT_BITPREC):
        r'''
        Jacobi sine theta-function

        .. MATH::

        \theta_1(z, q) = 2q^{1/4} \sum_{n >= 0} (-1)^n q^{n(n+1)} \sin ((2n+1)z).
        '''
        q = objtogen(q)
        z = objtogen(z)
        sig_on()
        cdef GEN _q = (<Gen>q).g
        cdef GEN _z = (<Gen>z).g
        precision = nbits2prec(precision)
        cdef GEN _ret = theta(_q, _z, precision)
        return new_gen(_ret)

    def thetanullk(self, q, long k, long precision=DEFAULT_BITPREC):
        r'''
        :math:`k`-th derivative at :math:`z = 0` of :math:`theta (q,z)`.
        '''
        q = objtogen(q)
        sig_on()
        cdef GEN _q = (<Gen>q).g
        precision = nbits2prec(precision)
        cdef GEN _ret = thetanullk(_q, k, precision)
        return new_gen(_ret)

    def thue(self, tnf, a, sol=None):
        r'''
        Returns all solutions of the equation
        :math:`P(x,y) = a` in integers :math:`x` and :math:`y`, where :emphasis:`tnf` was created with
        :math:`thueinit (P)`. If present, :emphasis:`sol` must contain the solutions of
        :math:`\mathrm{Norm} (x) = a` modulo units of positive norm in the number field
        defined by :math:`P` (as computed by :literal:`bnfisintnorm`). If there are infinitely
        many solutions, an error is issued.

        It is allowed to input directly the polynomial :math:`P` instead of a :emphasis:`tnf`,
        in which case, the function first performs :literal:`thueinit(P,0)`. This is
        very wasteful if more than one value of :math:`a` is required.

        If :emphasis:`tnf` was computed without assuming GRH (flag :math:`1` in :literal:`thueinit`),
        then the result is unconditional. Otherwise, it depends in principle of the
        truth of the GRH, but may still be unconditionally correct in some
        favorable cases. The result is conditional on the GRH if
        :math:`a != ± 1` and :math:`P` has a single irreducible rational factor, whose
        attached tentative class number :math:`h` and regulator :math:`R` (as computed
        assuming the GRH) satisfy

        - :math:`h > 1`,

        - :math:`R/0.2 > 1.5`.

        Here's how to solve the Thue equation :math:`x^{13} - 5y^{13} = - 4`:

        ::

        ? tnf = thueinit(x^13 - 5);
        ? thue(tnf, -4)
        %1 = [[1, 1]]

        In this case, one checks that :literal:`bnfinit(x^13 -5).no`
        is :math:`1`. Hence, the only solution is :math:`(x,y) = (1,1)` and the result is
        unconditional. On the other hand:

        ::

        ? P = x^3-2*x^2+3*x-17; tnf = thueinit(P);
        ? thue(tnf, -15)
        %2 = [[1, 1]] \\ a priori conditional on the GRH.
        ? K = bnfinit(P); K.no
        %3 = 3
        ? K.reg
        %4 = 2.8682185139262873674706034475498755834

        This time the result is conditional. All results computed using this
        particular :emphasis:`tnf` are likewise conditional, :emphasis:`except` for a right-hand
        side of :math:`± 1`.
        The above result is in fact correct, so we did not just disprove the GRH:

        ::

        ? tnf = thueinit(x^3-2*x^2+3*x-17, 1 /*unconditional*/);
        ? thue(tnf, -15)
        %4 = [[1, 1]]

        Note that reducible or non-monic polynomials are allowed:

        ::

        ? tnf = thueinit((2*x+1)^5 * (4*x^3-2*x^2+3*x-17), 1);
        ? thue(tnf, 128)
        %2 = [[-1, 0], [1, 0]]

        Reducible polynomials are in fact much easier to handle.

        :strong:`Note.` When :math:`P` is irreducible without a real root, the default
        strategy is to use brute force enumeration in time :math:`\|a\|^{1/\deg P}` and
        avoid computing a touch :emphasis:`bnf` attached to :math:`P`, see :literal:`thueinit`.
        Besides reusing a quantity you might need for other purposes, the
        default argument :emphasis:`sol` can also be used to use a different strategy
        and prove that there are no solutions; of course you need to compute a
        :emphasis:`bnf` on you own to obtain :emphasis:`sol`. If there :emphasis:`are` solutions
        this won't help unless :math:`P` is quadratic, since the enumeration will be
        performed in any case.
        '''
        tnf = objtogen(tnf)
        a = objtogen(a)
        cdef bint _have_sol = (sol is not None)
        if _have_sol:
            sol = objtogen(sol)
        sig_on()
        cdef GEN _tnf = (<Gen>tnf).g
        cdef GEN _a = (<Gen>a).g
        cdef GEN _sol = NULL
        if _have_sol:
            _sol = (<Gen>sol).g
        cdef GEN _ret = thue(_tnf, _a, _sol)
        return new_gen(_ret)

    def thueinit(self, P, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        Initializes the :emphasis:`tnf` corresponding to :math:`P`, a non-constant
        univariate polynomial with integer coefficients.
        The result is meant to be used in conjunction with :literal:`thue` to solve Thue
        equations :math:`P(X / Y)Y^{\deg P} = a`, where :math:`a` is an integer. Accordingly,
        :math:`P` must either have at least two distinct irreducible factors over :math:`\mathbb{Q}`,
        or have one irreducible factor :math:`T` with degree :math:`> 2` or two conjugate
        complex roots: under these (necessary and sufficient) conditions, the
        equation has finitely many integer solutions.

        ::

        ? S = thueinit(t^2+1);
        ? thue(S, 5)
        %2 = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]]
        ? S = thueinit(t+1);
        *** at top-level: thueinit(t+1)
        *** ^-------------
        *** thueinit: domain error in thueinit: P = t + 1

        The hardest case is when :math:`\deg P > 2` and :math:`P` is irreducible
        with at least one real root. The routine then uses Bilu-Hanrot's algorithm.

        If :math:`flag` is non-zero, certify results unconditionally. Otherwise, assume
        GRH, this being much faster of course. In the latter case, the result
        may still be unconditionally correct, see :literal:`thue`. For instance in most
        cases where :math:`P` is reducible (not a pure power of an irreducible), :emphasis:`or`
        conditional computed class groups are trivial :emphasis:`or` the right hand side
        is :math:`±1`, then results are unconditional.

        :strong:`Note.` The general philosophy is to disprove the existence of large
        solutions then to enumerate bounded solutions naively. The implementation
        will overflow when there exist huge solutions and the equation has degree
        :math:`> 2` (the quadratic imaginary case is special, since we can stick to
        :literal:`bnfisintnorm`, there are no fundamental units):

        ::

        ? thue(t^3+2, 10^30)
        *** at top-level: L=thue(t^3+2,10^30)
        *** ^-----------------
        *** thue: overflow in thue (SmallSols): y <= 80665203789619036028928.
        ? thue(x^2+2, 10^30) \\ quadratic case much easier
        %1 = [[-1000000000000000, 0], [1000000000000000, 0]]

        :strong:`Note.` It is sometimes possible to circumvent the above, and in any
        case obtain an important speed-up, if you can write :math:`P = Q(x^d)` for some :math:`d >
        1` and :math:`Q` still satisfying the :literal:`thueinit` hypotheses. You can then solve
        the equation attached to :math:`Q` then eliminate all solutions :math:`(x,y)` such that
        either :math:`x` or :math:`y` is not a :math:`d`-th power.

        ::

        ? thue(x^4+1, 10^40); \\ stopped after 10 hours
        ? filter(L,d) =
        my(x,y); [[x,y] | v<-L, ispower(v[1],d,&x)&&ispower(v[2],d,&y)];
        ? L = thue(x^2+1, 10^40);
        ? filter(L, 2)
        %4 = [[0, 10000000000], [10000000000, 0]]

        The last 2 commands use less than 20ms.

        :strong:`Note.` When :math:`P` is irreducible without a real root, the equation
        can be solved unconditionnally in time :math:`\|a\|^{1/\deg P}`. When this
        latter quantity is huge and the equation has no solutions, this fact
        may still be ascertained via arithmetic conditions but this now implies
        solving norm equations, computing a :emphasis:`bnf` and possibly assuming the GRH.
        When there is no real root, the code does not compute a :emphasis:`bnf`
        (with certification if :math:`flag = 1`) if it expects this to be an "easy"
        computation (because the result would only be used for huge values of :math:`a`).
        See :literal:`thue` for a way to compute an expensive :emphasis:`bnf` on your own and
        still get a result where this default cheap strategy fails.
        '''
        P = objtogen(P)
        sig_on()
        cdef GEN _P = (<Gen>P).g
        precision = nbits2prec(precision)
        cdef GEN _ret = thueinit(_P, flag, precision)
        return new_gen(_ret)

    def trace(self, x):
        r'''
        This applies to quite general :math:`x`. If :math:`x` is not a
        matrix, it is equal to the sum of :math:`x` and its conjugate, except for polmods
        where it is the trace as an algebraic number.

        For :math:`x` a square matrix, it is the ordinary trace. If :math:`x` is a
        non-square matrix (but not a vector), an error occurs.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = gtrace(_x)
        return new_gen(_ret)

    def truncate(self, x, e=None):
        r'''
        Truncates :math:`x` and sets :math:`e` to the number of
        error bits. When :math:`x` is in :math:`\mathbb{R}`, this means that the part after the decimal
        point is chopped away, :math:`e` is the binary exponent of the difference between
        the original and the truncated value (the "fractional part"). If the
        exponent of :math:`x` is too large compared to its precision (i.e. :math:`e > 0`), the
        result is undefined and an error occurs if :math:`e` was not given. The function
        applies componentwise on vector / matrices; :math:`e` is then the maximal number of
        error bits. If :math:`x` is a rational function, the result is the "integer part"
        (Euclidean quotient of numerator by denominator) and :math:`e` is not set.

        Note a very special use of :literal:`truncate`: when applied to a power series, it
        transforms it into a polynomial or a rational function with denominator
        a power of :math:`X`, by chopping away the :math:`O(X^k)`. Similarly, when applied to
        a :math:`p`-adic number, it transforms it into an integer or a rational number
        by chopping away the :math:`O(p^k)`.
        '''
        x = objtogen(x)
        cdef bint _have_e = (e is not None)
        if _have_e:
            raise NotImplementedError("optional argument e not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _e = NULL
        cdef GEN _ret = trunc0(_x, _e)
        return new_gen(_ret)

    def type(self, x):
        r'''
        This is useful only under :literal:`gp`. Returns the internal type name of
        the PARI object :math:`x` as a string. Check out existing type names with the
        metacommand :literal:`\\t`. For example :literal:`type(1)` will return ":literal:`t_INT`".
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = type0(_x)
        return new_gen(_ret)

    def valuation(self, x, p):
        r'''
        Computes the highest
        exponent of :math:`p` dividing :math:`x`. If :math:`p` is of type integer, :math:`x` must be an
        integer, an intmod whose modulus is divisible by :math:`p`, a fraction, a
        :math:`q`-adic number with :math:`q = p`, or a polynomial or power series in which case the
        valuation is the minimum of the valuation of the coefficients.

        If :math:`p` is of type polynomial, :math:`x` must be of type polynomial or rational
        function, and also a power series if :math:`x` is a monomial. Finally, the
        valuation of a vector, complex or quadratic number is the minimum of the
        component valuations.

        If :math:`x = 0`, the result is :literal:`+oo` if :math:`x` is an exact object. If :math:`x` is a
        :math:`p`-adic numbers or power series, the result is the exponent of the zero.
        Any other type combinations gives an error.
        '''
        x = objtogen(x)
        p = objtogen(p)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _p = (<Gen>p).g
        cdef GEN _ret = gpvaluation(_x, _p)
        return new_gen(_ret)

    def varhigher(self, name, v=None):
        r'''
        Return a variable :emphasis:`name` whose priority is higher
        than the priority of :math:`v` (of all existing variables if :math:`v` is omitted).
        This is a counterpart to :literal:`varlower`.

        ::

        ? Pol([x,x], t)
        *** at top-level: Pol([x,x],t)
        *** ^------------
        *** Pol: incorrect priority in gtopoly: variable x <= t
        ? t = varhigher("t", x);
        ? Pol([x,x], t)
        %3 = x*t + x

        This routine is useful since new GP variables directly
        created by the interpreter always have lower priority than existing
        GP variables. When some basic objects already exist in a variable
        that is incompatible with some function requirement, you can now
        create a new variable with a suitable priority instead of changing variables
        in existing objects:

        ::

        ? K = nfinit(x^2+1);
        ? rnfequation(K,y^2-2)
        *** at top-level: rnfequation(K,y^2-2)
        *** ^--------------------
        *** rnfequation: incorrect priority in rnfequation: variable y >= x
        ? y = varhigher("y", x);
        ? rnfequation(K, y^2-2)
        %3 = y^4 - 2*y^2 + 9

        :strong:`Caution 1.`
        The :emphasis:`name` is an arbitrary character string, only used for display
        purposes and need not be related to the GP variable holding the result, nor
        to be a valid variable name. In particular the :emphasis:`name` can
        not be used to retrieve the variable, it is not even present in the parser's
        hash tables.

        ::

        ? x = varhigher("#");
        ? x^2
        %2 = #^2

        :strong:`Caution 2.` There are a limited number of variables and if no
        existing variable with the given display name has the requested
        priority, the call to :literal:`varhigher` uses up one such slot. Do not create
        new variables in this way unless it's absolutely necessary,
        reuse existing names instead and choose sensible priority requirements:
        if you only need a variable with higher priority than :math:`x`, state so
        rather than creating a new variable with highest priority.

        ::

        \\ quickly use up all variables
        ? n = 0; while(1,varhigher("tmp"); n++)
        *** at top-level: n=0;while(1,varhigher("tmp");n++)
        *** ^-------------------
        *** varhigher: no more variables available.
        *** Break loop: type 'break' to go back to GP prompt
        break> n
        65510
        \\ infinite loop: here we reuse the same 'tmp'
        ? n = 0; while(1,varhigher("tmp", x); n++)
        '''
        name = to_bytes(name)
        cdef char* _name = <bytes>name
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _ret = varhigher(_name, _v)
        return new_gen(_ret)

    def variable(self, x=None):
        r'''
        Gives the main variable of the object :math:`x` (the variable with the highest
        priority used in :math:`x`), and :math:`p` if :math:`x` is a :math:`p`-adic number. Return :math:`0` if
        :math:`x` has no variable attached to it.

        ::

        ? variable(x^2 + y)
        %1 = x
        ? variable(1 + O(5^2))
        %2 = 5
        ? variable([x,y,z,t])
        %3 = x
        ? variable(1)
        %4 = 0

        The construction

        ::

        if (!variable(x),...)

        can be used to test whether a variable is attached to :math:`x`.

        If :math:`x` is omitted, returns the list of user variables known to the
        interpreter, by order of decreasing priority. (Highest priority is initially
        :math:`x`, which come first until :literal:`varhigher` is used.) If :literal:`varhigher`
        or :literal:`varlower` are used, it is quite possible to end up with different
        variables (with different priorities) printed in the same way: they
        will then appear multiple times in the output:

        ::

        ? varhigher("y");
        ? varlower("y");
        ? variable()
        %4 = [y, x, y]

        Using :literal:`v = variable()` then :literal:`v[1]`, :literal:`v[2]`,
        etc. allows to recover and use existing variables.
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _ret = gpolvar(_x)
        return new_gen(_ret)

    def variables(self, x=None):
        r'''
        Returns the list of all variables occurring in object :math:`x` (all user
        variables known to the interpreter if :math:`x` is omitted), sorted by
        decreasing priority.

        ::

        ? variables([x^2 + y*z + O(t), a+x])
        %1 = [x, y, z, t, a]

        The construction

        ::

        if (!variables(x),...)

        can be used to test whether a variable is attached to :math:`x`.

        If :literal:`varhigher` or :literal:`varlower` are used, it is quite possible to end up
        with different variables (with different priorities) printed in the same
        way: they will then appear multiple times in the output:

        ::

        ? y1 = varhigher("y");
        ? y2 = varlower("y");
        ? variables(y*y1*y2)
        %4 = [y, y, y]
        '''
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        cdef GEN _ret = variables_vec(_x)
        return new_gen(_ret)

    def varlower(self, name, v=None):
        r'''
        Return a variable :emphasis:`name` whose priority is lower
        than the priority of :math:`v` (of all existing variables if :math:`v` is omitted).
        This is a counterpart to :literal:`varhigher`.

        New GP variables directly created by the interpreter always
        have lower priority than existing GP variables, but it is not easy
        to check whether an identifier is currently unused, so that the
        corresponding variable has the expected priority when it's created!
        Thus, depending on the session history, the same command may fail or succeed:

        ::

        ? t; z; \\ now t > z
        ? rnfequation(t^2+1,z^2-t)
        *** at top-level: rnfequation(t^2+1,z^
        *** ^--------------------
        *** rnfequation: incorrect priority in rnfequation: variable t >= t

        Restart and retry:

        ::

        ? z; t; \\ now z > t
        ? rnfequation(t^2+1,z^2-t)
        %2 = z^4 + 1

        It is quite annoying for package authors, when trying to
        define a base ring, to notice that the package may fail for some users
        depending on their session history. The safe way to do this is as follows:

        ::

        ? z; t; \\ In new session: now z > t
        ...
        ? t = varlower("t", 'z);
        ? rnfequation(t^2+1,z^2-2)
        %2 = z^4 - 2*z^2 + 9
        ? variable()
        %3 = [x, y, z, t]

        ::

        ? t; z; \\ In new session: now t > z
        ...
        ? t = varlower("t", 'z); \\ create a new variable, still printed "t"
        ? rnfequation(t^2+1,z^2-2)
        %2 = z^4 - 2*z^2 + 9
        ? variable()
        %3 = [x, y, t, z, t]

        Now both constructions succeed. Note that in the
        first case, :literal:`varlower` is essentially a no-op, the existing variable :math:`t`
        has correct priority. While in the second case, two different variables are
        displayed as :literal:`t`, one with higher priority than :math:`z` (created in the first
        line) and another one with lower priority (created by :literal:`varlower`).

        :strong:`Caution 1.`
        The :emphasis:`name` is an arbitrary character string, only used for display
        purposes and need not be related to the GP variable holding the result, nor
        to be a valid variable name. In particular the :emphasis:`name` can
        not be used to retrieve the variable, it is not even present in the parser's
        hash tables.

        ::

        ? x = varlower("#");
        ? x^2
        %2 = #^2

        :strong:`Caution 2.` There are a limited number of variables and if no
        existing variable with the given display name has the requested
        priority, the call to :literal:`varlower` uses up one such slot. Do not create
        new variables in this way unless it's absolutely necessary,
        reuse existing names instead and choose sensible priority requirements:
        if you only need a variable with higher priority than :math:`x`, state so
        rather than creating a new variable with highest priority.

        ::

        \\ quickly use up all variables
        ? n = 0; while(1,varlower("x"); n++)
        *** at top-level: n=0;while(1,varlower("x");n++)
        *** ^-------------------
        *** varlower: no more variables available.
        *** Break loop: type 'break' to go back to GP prompt
        break> n
        65510
        \\ infinite loop: here we reuse the same 'tmp'
        ? n = 0; while(1,varlower("tmp", x); n++)
        '''
        name = to_bytes(name)
        cdef char* _name = <bytes>name
        cdef long _v = -1
        if v is not None:
            _v = get_var(v)
        sig_on()
        cdef GEN _ret = varlower(_name, _v)
        return new_gen(_ret)

    def vecextract(self, x, y, z=None):
        r'''
        Extraction of components of the vector or matrix :math:`x` according to :math:`y`.
        In case :math:`x` is a matrix, its components are the :emphasis:`columns` of :math:`x`. The
        parameter :math:`y` is a component specifier, which is either an integer, a string
        describing a range, or a vector.

        If :math:`y` is an integer, it is considered as a mask: the binary bits of :math:`y` are
        read from right to left, but correspond to taking the components from left to
        right. For example, if :math:`y = 13 = (1101)_2` then the components 1,3 and 4 are
        extracted.

        If :math:`y` is a vector (:literal:`t_VEC`, :literal:`t_COL` or :literal:`t_VECSMALL`), which must have
        integer entries, these entries correspond to the component numbers to be
        extracted, in the order specified.

        If :math:`y` is a string, it can be

        - a single (non-zero) index giving a component number (a negative
        index means we start counting from the end).

        - a range of the form :literal:`":math:`a`..:math:`b`"`, where :math:`a` and :math:`b` are
        indexes as above. Any of :math:`a` and :math:`b` can be omitted; in this case, we take
        as default values :math:`a = 1` and :math:`b = -1`, i.e. the first and last components
        respectively. We then extract all components in the interval :math:`[a,b]`, in
        reverse order if :math:`b < a`.

        In addition, if the first character in the string is :literal:`^`, the
        complement of the given set of indices is taken.

        If :math:`z` is not omitted, :math:`x` must be a matrix. :math:`y` is then the :emphasis:`row`
        specifier, and :math:`z` the :emphasis:`column` specifier, where the component specifier
        is as explained above.

        ::

        ? v = [a, b, c, d, e];
        ? vecextract(v, 5) \\ mask
        %1 = [a, c]
        ? vecextract(v, [4, 2, 1]) \\ component list
        %2 = [d, b, a]
        ? vecextract(v, "2..4") \\ interval
        %3 = [b, c, d]
        ? vecextract(v, "-1..-3") \\ interval + reverse order
        %4 = [e, d, c]
        ? vecextract(v, "^2") \\ complement
        %5 = [a, c, d, e]
        ? vecextract(matid(3), "2..", "..")
        %6 =
        [0 1 0]
        
        [0 0 1]

        The range notations :literal:`v[i..j]` and :literal:`v[^i]` (for :literal:`t_VEC` or
        :literal:`t_COL`) and :literal:`M[i..j, k..l]` and friends (for :literal:`t_MAT`) implement a
        subset of the above, in a simpler and :emphasis:`faster` way, hence should be
        preferred in most common situations. The following features are not
        implemented in the range notation:

        - reverse order,

        - omitting either :math:`a` or :math:`b` in :literal:`:math:`a`..:math:`b``.
        '''
        x = objtogen(x)
        y = objtogen(y)
        cdef bint _have_z = (z is not None)
        if _have_z:
            z = objtogen(z)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _y = (<Gen>y).g
        cdef GEN _z = NULL
        if _have_z:
            _z = (<Gen>z).g
        cdef GEN _ret = extract0(_x, _y, _z)
        return new_gen(_ret)

    def vecmax(self, x, v=None):
        r'''
        If :math:`x` is a vector or a matrix, returns the largest entry of :math:`x`,
        otherwise returns a copy of :math:`x`. Error if :math:`x` is empty.

        If :math:`v` is given, set it to the index of a largest entry (indirect maximum),
        when :math:`x` is a vector. If :math:`x` is a matrix, set :math:`v` to coordinates :math:`[i,j]`
        such that :math:`x[i,j]` is a largest entry. This flag is ignored if :math:`x` is not a
        vector or matrix.

        ::

        ? vecmax([10, 20, -30, 40])
        %1 = 40
        ? vecmax([10, 20, -30, 40], &v); v
        %2 = 4
        ? vecmax([10, 20; -30, 40], &v); v
        %3 = [2, 2]
        '''
        x = objtogen(x)
        cdef bint _have_v = (v is not None)
        if _have_v:
            raise NotImplementedError("optional argument v not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _v = NULL
        cdef GEN _ret = vecmax0(_x, _v)
        return new_gen(_ret)

    def vecmin(self, x, v=None):
        r'''
        If :math:`x` is a vector or a matrix, returns the smallest entry of :math:`x`,
        otherwise returns a copy of :math:`x`. Error if :math:`x` is empty.

        If :math:`v` is given, set it to the index of a smallest entry (indirect minimum),
        when :math:`x` is a vector. If :math:`x` is a matrix, set :math:`v` to coordinates :math:`[i,j]` such
        that :math:`x[i,j]` is a smallest entry. This is ignored if :math:`x` is not a vector or
        matrix.

        ::

        ? vecmin([10, 20, -30, 40])
        %1 = -30
        ? vecmin([10, 20, -30, 40], &v); v
        %2 = 3
        ? vecmin([10, 20; -30, 40], &v); v
        %3 = [2, 1]
        '''
        x = objtogen(x)
        cdef bint _have_v = (v is not None)
        if _have_v:
            raise NotImplementedError("optional argument v not available")
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN * _v = NULL
        cdef GEN _ret = vecmin0(_x, _v)
        return new_gen(_ret)

    def vecprod(self, v):
        r'''
        Return the product of the components of the vector :math:`v`. Return :math:`1` on an
        empty vector.

        ::

        ? vecprod([1,2,3])
        %1 = 6
        ? vecprod([])
        %2 = 1
        '''
        v = objtogen(v)
        sig_on()
        cdef GEN _v = (<Gen>v).g
        cdef GEN _ret = vecprod(_v)
        return new_gen(_ret)

    def vecsearch(self, v, x, cmpf=None):
        r'''
        Determines whether :math:`x` belongs to the sorted vector or list :math:`v`: return
        the (positive) index where :math:`x` was found, or :math:`0` if it does not belong to
        :math:`v`.

        If the comparison function cmpf is omitted, we assume that :math:`v` is sorted in
        increasing order, according to the standard comparison function :literal:`lex`,
        thereby restricting the possible types for :math:`x` and the elements of :math:`v`
        (integers, fractions, reals, and vectors of such). We also transparently
        allow a :literal:`t_VECSMALL` :math:`x` in this case, for the natural ordering of the
        integers.

        If :literal:`cmpf` is present, it is understood as a comparison function and we
        assume that :math:`v` is sorted according to it, see :literal:`vecsort` for how to
        encode comparison functions.

        ::

        ? v = [1,3,4,5,7];
        ? vecsearch(v, 3)
        %2 = 2
        ? vecsearch(v, 6)
        %3 = 0 \\ not in the list
        ? vecsearch([7,6,5], 5) \\ unsorted vector: result undefined
        %4 = 0

        Note that if we are sorting with respect to a key
        which is expensive to compute (e.g. a discriminant), one should rather
        precompute all keys, sort that vector and search in the vector of keys,
        rather than searching in the original vector with respect to a comparison
        function.

        By abuse of notation, :math:`x` is also allowed to be a matrix, seen as a vector
        of its columns; again by abuse of notation, a :literal:`t_VEC` is considered
        as part of the matrix, if its transpose is one of the matrix columns.

        ::

        ? v = vecsort([3,0,2; 1,0,2]) \\ sort matrix columns according to lex order
        %1 =
        [0 2 3]
        
        [0 2 1]
        ? vecsearch(v, [3,1]~)
        %2 = 3
        ? vecsearch(v, [3,1]) \\ can search for x or x~
        %3 = 3
        ? vecsearch(v, [1,2])
        %4 = 0 \\ not in the list
        '''
        v = objtogen(v)
        x = objtogen(x)
        cdef bint _have_cmpf = (cmpf is not None)
        if _have_cmpf:
            cmpf = objtogen(cmpf)
        sig_on()
        cdef GEN _v = (<Gen>v).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _cmpf = NULL
        if _have_cmpf:
            _cmpf = (<Gen>cmpf).g
        cdef long _ret = vecsearch(_v, _x, _cmpf)
        clear_stack()
        return _ret

    def vecsort(self, x, cmpf=None, long flag=0):
        r'''
        Sorts the vector :math:`x` in ascending order, using a mergesort method.
        :math:`x` must be a list, vector or matrix (seen as a vector of its columns).
        Note that mergesort is stable, hence the initial ordering of "equal"
        entries (with respect to the sorting criterion) is not changed.

        If :literal:`cmpf` is omitted, we use the standard comparison function
        :literal:`lex`, thereby restricting the possible types for the elements of :math:`x`
        (integers, fractions or reals and vectors of those). We also transparently
        allow a :literal:`t_VECSMALL` :math:`x` in this case, for the standard ordering on the
        integers.

        If :literal:`cmpf` is present, it is understood as a comparison function and we
        sort according to it. The following possibilities exist:

        - an integer :math:`k`: sort according to the value of the :math:`k`-th
        subcomponents of the components of :math:`x`.

        - a vector: sort lexicographically according to the components listed in
        the vector. For example, if :math:`cmpf = [2,1,3]`, sort with respect to
        the second component, and when these are equal, with respect to the first,
        and when these are equal, with respect to the third.

        - a comparison function: :literal:`t_CLOSURE` with two arguments :math:`x` and :math:`y`,
        and returning a real number which is :math:`< 0`, :math:`> 0` or :math:`= 0` if :math:`x < y`, :math:`x > y` or
        :math:`x = y` respectively.

        - a key: :literal:`t_CLOSURE` with one argument :math:`x` and returning
        the value :math:`f(x)` with respect to which we sort.

        ::

        ? vecsort([3,0,2; 1,0,2]) \\ sort columns according to lex order
        %1 =
        [0 2 3]
        
        [0 2 1]
        ? vecsort(v, (x,y)->y-x) \\ reverse sort
        ? vecsort(v, (x,y)->abs(x)-abs(y)) \\ sort by increasing absolute value
        ? vecsort(v, abs) \\ sort by increasing absolute value, using key
        ? cmpf(x,y) = my(dx = poldisc(x), dy = poldisc(y)); abs(dx) - abs(dy);
        ? v = [x^2+1, x^3-2, x^4+5*x+1] vecsort(v, cmpf) \\ comparison function
        ? vecsort(v, x->abs(poldisc(x))) \\ key

        The :literal:`abs` and :literal:`cmpf` examples show how to use a named function
        instead of an anonymous function. It is preferable to use a :emphasis:`key`
        whenever possible rather than include it in the comparison function as above
        since the key is evaluated :math:`O(n)` times instead of :math:`O(n\log n)`,
        where :math:`n` is the number of entries.

        A direct approach is also possible and equivalent to using a sorting key:

        ::

        ? T = [abs(poldisc(x)) | x<-v];
        ? perm = vecsort(T,,1); \\ indirect sort
        ? vecextract(v, perm)

        This also provides the vector :math:`T` of all keys, which is
        interesting for instance in later :literal:`vecsearch` calls: it is more
        efficient to sort :math:`T` (:literal:`T = vecextract(T, perm)`) then search for a key
        in :math:`T` rather than to search in :math:`v` using a comparison function or a key.
        Note also that :literal:`mapisdefined` is often easier to use and faster than
        :literal:`vecsearch`.

        The binary digits of :emphasis:`flag` mean:

        - 1: indirect sorting of the vector :math:`x`, i.e. if :math:`x` is an
        :math:`n`-component vector, returns a permutation of :math:`[1,2,...,n]` which
        applied to the components of :math:`x` sorts :math:`x` in increasing order.
        For example, :literal:`vecextract(x, vecsort(x,,1))` is equivalent to
        :literal:`vecsort(x)`.

        - 4: use descending instead of ascending order.

        - 8: remove "duplicate" entries with respect to the sorting function
        (keep the first occurring entry). For example:

        ::

        ? vecsort([Pi,Mod(1,2),z], (x,y)->0, 8) \\ make everything compare equal
        %1 = [3.141592653589793238462643383]
        ? vecsort([[2,3],[0,1],[0,3]], 2, 8)
        %2 = [[0, 1], [2, 3]]
        '''
        x = objtogen(x)
        cdef bint _have_cmpf = (cmpf is not None)
        if _have_cmpf:
            cmpf = objtogen(cmpf)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _cmpf = NULL
        if _have_cmpf:
            _cmpf = (<Gen>cmpf).g
        cdef GEN _ret = vecsort0(_x, _cmpf, flag)
        return new_gen(_ret)

    def vecsum(self, v):
        r'''
        Return the sum of the components of the vector :math:`v`. Return :math:`0` on an
        empty vector.

        ::

        ? vecsum([1,2,3])
        %1 = 6
        ? vecsum([])
        %2 = 0
        '''
        v = objtogen(v)
        sig_on()
        cdef GEN _v = (<Gen>v).g
        cdef GEN _ret = vecsum(_v)
        return new_gen(_ret)

    def version(self):
        r'''
        Returns the current version number as a :literal:`t_VEC` with three integer
        components (major version number, minor version number and patchlevel);
        if your sources were obtained through our version control system, this will
        be followed by further more precise arguments, including
        e.g. a :literal:`git` :emphasis:`commit hash`.

        This function is present in all versions of PARI following releases 2.3.4
        (stable) and 2.4.3 (testing).

        Unless you are working with multiple development versions, you probably only
        care about the 3 first numeric components. In any case, the :literal:`lex` function
        offers a clever way to check against a particular version number, since it will
        compare each successive vector entry, numerically or as strings, and will not
        mind if the vectors it compares have different lengths:

        ::

        if (lex(version(), [2,3,5]) >= 0,
        \\ code to be executed if we are running 2.3.5 or more recent.
        ,
        \\ compatibility code
        );

        On a number of different machines, :literal:`version()` could return either of

        ::

        %1 = [2, 3, 4] \\ released version, stable branch
        %1 = [2, 4, 3] \\ released version, testing branch
        %1 = [2, 6, 1, 15174, ""505ab9b"] \\ development

        In particular, if you are only working with released versions, the first
        line of the gp introductory message can be emulated by

        ::

        [M,m,p] = version();
        printf("GP/PARI CALCULATOR Version %s.%s.%s", M,m,p);

        If you :emphasis:`are` working with many development versions of
        PARI/GP, the 4th and/or 5th components can be profitably included in the
        name of your logfiles, for instance.

        :strong:`Technical note.` For development versions obtained via :literal:`git`,
        the 4th and 5th components are liable to change eventually, but we document
        their current meaning for completeness. The 4th component counts the number
        of reachable commits in the branch (analogous to :literal:`svn`'s revision
        number), and the 5th is the :literal:`git` commit hash. In particular, :literal:`lex`
        comparison still orders correctly development versions with respect to each
        others or to released versions (provided we stay within a given branch,
        e.g. :literal:`master`)!
        '''
        sig_on()
        cdef GEN _ret = pari_version()
        return new_gen(_ret)

    def weber(self, x, long flag=0, long precision=DEFAULT_BITPREC):
        r'''
        One of Weber's three :math:`f` functions.
        If :math:`flag = 0`, returns

        .. MATH::

        f(x) = \exp (-i\pi/24).\eta ((x+1)/2)/\eta (x) {such that}
        j = (f^{24}-16)^3/f^{24},

        where :math:`j` is the elliptic :math:`j`-invariant (see the function :literal:`ellj`).
        If :math:`flag = 1`, returns

        .. MATH::

        f_1(x) = \eta (x/2)/\eta (x) {such that}
        j = (f_1^{24}+16)^3/f_1^{24}.

        Finally, if :math:`flag = 2`, returns

        .. MATH::

        f_2(x) = \sqrt{2}\eta (2x)/\eta (x) {such that}
        j = (f_2^{24}+16)^3/f_2^{24}.

        Note the identities :math:`f^8 = f_1^8+f_2^8` and :math:`ff_1f_2 = \sqrt2`.
        '''
        x = objtogen(x)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        precision = nbits2prec(precision)
        cdef GEN _ret = weber0(_x, flag, precision)
        return new_gen(_ret)

    def writebin(self, filename, x=None):
        r'''
        Writes (appends) to
        :emphasis:`filename` the object :math:`x` in binary format. This format is not human
        readable, but contains the exact internal structure of :math:`x`, and is much
        faster to save/load than a string expression, as would be produced by
        :literal:`write`. The binary file format includes a magic number, so that such a
        file can be recognized and correctly input by the regular :literal:`read` or :literal:`\\r`
        function. If saved objects refer to polynomial variables that are not
        defined in the new session, they will be displayed as :literal:`t:math:`n`` for some
        integer :math:`n` (the attached variable number).
        Installed functions and history objects can not be saved via this function.

        If :math:`x` is omitted, saves all user variables from the session, together with
        their names. Reading such a "named object" back in a :literal:`gp` session will set
        the corresponding user variable to the saved value. E.g after

        ::

        x = 1; writebin("log")

        reading :literal:`log` into a clean session will set :literal:`x` to :math:`1`.
        The relative variables priorities (see ``priority`` (in the PARI manual)) of new variables
        set in this way remain the same (preset variables retain their former
        priority, but are set to the new value). In particular, reading such a
        session log into a clean session will restore all variables exactly as they
        were in the original one.

        Just as a regular input file, a binary file can be compressed
        using :literal:`gzip`, provided the file name has the standard :literal:`.gz`
        extension.

        In the present implementation, the binary files are architecture dependent
        and compatibility with future versions of :literal:`gp` is not guaranteed. Hence
        binary files should not be used for long term storage (also, they are
        larger and harder to compress than text files).
        '''
        filename = to_bytes(filename)
        cdef char* _filename = <bytes>filename
        cdef bint _have_x = (x is not None)
        if _have_x:
            x = objtogen(x)
        sig_on()
        cdef GEN _x = NULL
        if _have_x:
            _x = (<Gen>x).g
        gpwritebin(_filename, _x)
        clear_stack()

    def zeta(self, s, long precision=DEFAULT_BITPREC):
        r'''
        For :math:`s != 1` a complex number, Riemann's zeta
        function :math:`\zeta (s) = \sum_{n >= 1}n^{-s}`,
        computed using the Euler-Maclaurin summation formula, except
        when :math:`s` is of type integer, in which case it is computed using
        Bernoulli numbers for :math:`s <= 0` or :math:`s > 0` and
        even, and using modular forms for :math:`s > 0` and odd. Power series
        are also allowed:

        ::

        ? zeta(2) - Pi^2/6
        %1 = 0.E-38
        ? zeta(1+x+O(x^3))
        %2 = 1.0000000000000000000000000000000000000*x^-1 + \
        0.57721566490153286060651209008240243104 + O(x)

        For :math:`s != 1` a :math:`p`-adic number, Kubota-Leopoldt zeta function at :math:`s`, that
        is the unique continuous :math:`p`-adic function on the :math:`p`-adic integers
        that interpolates the values of :math:`(1 - p^{-k}) \zeta (k)` at negative
        integers :math:`k` such that :math:`k = 1 (mod p-1)` (resp. :math:`k` is odd) if
        :math:`p` is odd (resp. :math:`p = 2`). Power series are not allowed in this case.

        ::

        ? zeta(-3+O(5^10))
        %1 = 4*5^-1 + 4 + 3*5 + 4*5^3 + 4*5^5 + 4*5^7 + O(5^9)))))
        ? (1-5^3) * zeta(-3)
        %2 = -1.0333333333333333333333333333333333333
        ? bestappr(%)
        %3 = -31/30
        ? zeta(-3+O(5^10)) - (-31/30)
        %4 = O(5^9)
        '''
        s = objtogen(s)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        precision = nbits2prec(precision)
        cdef GEN _ret = gzeta(_s, precision)
        return new_gen(_ret)

    def zetahurwitz(self, s, x, long der=0, long precision=DEFAULT_BITPREC):
        r'''
        Hurwitz zeta function :math:`\zeta (s,x) = \sum_{n >= 0}(n+x)^{-s}` and
        analytically continued, with :math:`s != 1` and :math:`x` not a negative or zero
        integer. Note that :math:`\zeta (s,1) = \zeta (s)`. :math:`s` can also be a polynomial,
        rational function, or power series. If :literal:`der` is positive, compute the
        :literal:`der`'th derivative with respect to :math:`s`. Note that the derivative
        with respect to :math:`x` is simply :math:`-s\zeta (s+1,x)`.

        ::

        ? zetahurwitz(Pi,Pi)
        %1 = 0.056155444497585099925180502385781494484
        ? zetahurwitz(2,1) - zeta(2)
        %2 = -2.350988701644575016 E-38
        ? zetahurwitz(Pi,3) - (zeta(Pi)-1-1/2^Pi)
        %3 = -2.2040519077917890774 E-39
        ? zetahurwitz(-7/2,1) - zeta(-7/2)
        %4 = -2.295887403949780289 E-41
        ? zetahurwitz(-2.3,Pi+I*log(2))
        %5 = -5.1928369229555125820137832704455696057\
        - 6.1349660138824147237884128986232049582*I
        ? zetahurwitz(-1+x^2+O(x^3),1)
        %6 = -0.083333333333333333333333333333333333333\
        - 0.16542114370045092921391966024278064276*x^2 + O(x^3)
        ? zetahurwitz(1+x+O(x^4),2)
        %7 = 1.0000000000000000000000000000000000000*x^-1\
        - 0.42278433509846713939348790991759756896\
        + 0.072815845483676724860586375874901319138*x + O(x^2)
        ? zetahurwitz(2,1,2) \\ zeta''(2)
        %8 = 1.9892802342989010234208586874215163815
        '''
        s = objtogen(s)
        x = objtogen(x)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        cdef GEN _x = (<Gen>x).g
        cdef GEN _ret = zetahurwitz(_s, _x, der, precision)
        return new_gen(_ret)

    def zetamult(self, s, T=None, long precision=DEFAULT_BITPREC):
        r'''
        For :math:`s` a vector of positive integers such that :math:`s[1] >= 2`,
        returns the multiple zeta value (MZV)

        .. MATH::

        \zeta (s_1,..., s_k) = \sum_{n_1 > ... > n_k > 0} n_1^{-s_1}...n_k^{-s_k}.

        ::

        ? zetamult([2,1]) - zeta(3) \\ Euler's identity
        %1 = 0.E-38

        If the bit precision is :math:`B`, this function runs in time :math:`~{O}(k B^2)`.

        If :math:`T` is provided, it must be the output of :literal:`zetamultinit`:math:`(w)` for
        some :math:`w >= s_1 +...+ s_k` and will provide a small speed up,
        usually about 10\%.

        ::

        ? T = zetamultinit(20); s = [2,1,1,1,1,1,1,1,1];
        ? for(i=1,10^3, zetamult(s))
        time = 373 ms.
        ? for(i=1,10^3, zetamult(s, T)) \\ faster
        time = 279 ms.
        ? zetamult(vector(10,i,2), T)
        %4 = 1.7165384749821433018378232207719985786 E-10
        ? zetamult(vector(11,i,2), T) \\ overshoot
        *** at top-level: zetamult(vector(11,i
        *** ^--------------------
        *** zetamult: domain error in zetamult: weight > 20

        In addition to the above format (:literal:`avec`), the function
        also accepts an internal binary format :literal:`evec` (each :math:`s_i` is replaced
        by :math:`s_i` bits, all of them 0 but the last one), and an :literal:`index` format
        (if :math:`e` is the positive integer attached the :literal:`evec` vector of
        bits, the index is the integer :math:`e + 2^{k-2}`). The function
        :literal:`zetamultconvert` allows to pass from one format to the other; the
        function :literal:`zetamultall` computes simultaneously all MZVs of weight
        :math:`\sum_{i <= k} s_i` up to :math:`n`.
        '''
        s = objtogen(s)
        cdef bint _have_T = (T is not None)
        if _have_T:
            T = objtogen(T)
        sig_on()
        cdef GEN _s = (<Gen>s).g
        cdef GEN _T = NULL
        if _have_T:
            _T = (<Gen>T).g
        precision = nbits2prec(precision)
        cdef GEN _ret = zetamult0(_s, _T, precision)
        return new_gen(_ret)

    def zetamultall(self, long n, long precision=DEFAULT_BITPREC):
        r'''
        List of all multiple zeta values for weight :math:`s_1 +...+ s_k` up to :math:`n`.
        The function returns a vector with :math:`2^{n-1}-1` components whose :math:`i`-th entry
        is the MZV of :literal:`index` :math:`i` (see :literal:`zetamult`).

        ::

        ? z = zetamultall(5);
        ? z[10]
        %2 = 0.22881039760335375976874614894168879193
        ? zetamultconvert(10) \\ convert index 10 to avec
        %3 = Vecsmall([3, 2])
        ? zetamult(%)
        %4 = 0.22881039760335375976874614894168879193
        ? zetamult(10)
        %5 = 0.22881039760335375976874614894168879193

        If the bit precision is :math:`B`, this function runs in time
        :math:`O(2^n n B^2)` for an output of size :math:`O(2^n B)`.
        '''
        sig_on()
        precision = nbits2prec(precision)
        cdef GEN _ret = zetamultall(n, precision)
        return new_gen(_ret)

    def zetamultconvert(self, a, long fl=1):
        r'''
        :literal:`a` being either an :literal:`evec`, :literal:`avec`, or index :literal:`m`,
        converts into :literal:`evec` (:literal:`fl = 0`), :literal:`avec` (:literal:`fl = 1`, default), or
        index :literal:`m` (:literal:`fl = 2`); see :literal:`zetamult` for explanations.

        ::

        ? zetamultconvert(10)
        %1 = Vecsmall([3, 2])
        ? zetamultconvert(13)
        %2 = Vecsmall([2, 2, 1])
        ? zetamultconvert(10, 0)
        %3 = Vecsmall([0, 0, 1, 0, 1])
        ? zetamultconvert(13, 0)
        %4 = Vecsmall([0, 1, 0, 1, 1])

        The last two lines imply that :math:`[3,2]` and :math:`[2,2,1]`
        are dual (reverse order of bits and swap :math:`0` and :math:`1` in :literal:`evec` form).
        Hence they have the same zeta value:

        ::

        ? zetamult([3,2])
        %5 = 0.22881039760335375976874614894168879193
        ? zetamult([2,2,1])
        %6 = 0.22881039760335375976874614894168879193
        '''
        a = objtogen(a)
        sig_on()
        cdef GEN _a = (<Gen>a).g
        cdef GEN _ret = zetamultconvert(_a, fl)
        return new_gen(_ret)

    def zetamultinit(self, long maxw, long precision=DEFAULT_BITPREC):
        r'''
        Initialize data (depending on the precision) used to compute
        multiple zeta values at
        integral points :math:`s = [s_1,...,s_k]` for any :math:`s_1 +...+ s_k \leq
        maxw`. The corresponding data is inexpensive to compute or store
        and provides a small speedup (usually about 10\%) when multiple values are to
        be computed at a given accuracy.

        ::

        ? for(i = 1, 2^12-1, zetamult(i))
        time = 1,413 ms
        ? T = zetamultinit(13); \\ instantaneous
        ? for(i = 1, 2^12-1, zetamult(i, T)) \\ used cached data
        time = 1,315 ms
        ? zetamultall(12); \\ much faster !
        time = 27 ms
        
        ? T=zetamultinit(102); sizebyte(T) \\ small even for huge weights
        time = 5 ms.
        %5 = 1440504
        ? for(i = 1, 2^5, zetamult(2^100+i))
        time = 633 ms.
        ? for(i = 1, 2^5, zetamult(2^100+i, T))
        time = 550 ms.

        For small weights, :literal:`zetamultall` will be much more efficient; but it
        is not an option when the weight gets large.
        '''
        sig_on()
        precision = nbits2prec(precision)
        cdef GEN _ret = zetamultinit(maxw, precision)
        return new_gen(_ret)

    def znchar(self, D):
        r'''
        Given a datum :math:`D` describing a group :math:`(\mathbb{Z}/N\mathbb{Z})^*` and a Dirichlet
        character :math:`\chi`, return the pair :literal:`[G, chi]`, where :literal:`G` is
        :literal:`znstar(N, 1)`) and :literal:`chi` is a GP character.

        The following possibilities for :math:`D` are supported

        - a non-zero :literal:`t_INT` congruent to :math:`0,1` modulo :math:`4`, return the real
        character modulo :math:`D` given by the Kronecker symbol :math:`(D/.)`;

        - a :literal:`t_INTMOD` :literal:`Mod(m, N)`, return the Conrey character
        modulo :math:`N` of index :math:`m` (see :literal:`znconreylog`).

        - a modular form space as per :literal:`mfinit`:math:`([N,k,\chi])` or a modular
        form for such a space, return the underlying Dirichlet character :math:`\chi`
        (which may be defined modulo a divisor of :math:`N` but need not be primitive).

        In the remaining cases, :literal:`G` is initialized by :literal:`znstar(N, 1)`.

        - a pair :literal:`[G, chi]`, where :literal:`chi` is a standard GP Dirichlet
        character :math:`c = (c_j)` on :literal:`G` (generic character :literal:`t_VEC` or
        Conrey characters :literal:`t_COL` or :literal:`t_INT`); given
        generators :math:`G = \oplus (\mathbb{Z}/d_j\mathbb{Z}) g_j`, :math:`\chi (g_j) = e(c_j/d_j)`.

        - a pair :literal:`[G, chin]`, where :literal:`chin` is a :emphasis:`normalized`
        representation :math:`[n, ~{c}]` of the Dirichlet character :math:`c`; :math:`\chi (g_j)
        = e(~{c}_j / n)` where :math:`n` is minimal (order of :math:`\chi`).

        ::

        ? [G,chi] = znchar(-3);
        ? G.cyc
        %2 = [2]
        ? chareval(G, chi, 2)
        %3 = 1/2
        ? kronecker(-3,2)
        %4 = -1
        ? znchartokronecker(G,chi)
        %5 = -3
        ? mf = mfinit([28, 5/2, Mod(2,7)]); [f] = mfbasis(mf);
        ? [G,chi] = znchar(mf); [G.mod, chi]
        %7 = [7, [2]~]
        ? [G,chi] = znchar(f); chi
        %8 = [28, [0, 2]~]
        '''
        D = objtogen(D)
        sig_on()
        cdef GEN _D = (<Gen>D).g
        cdef GEN _ret = znchar(_D)
        return new_gen(_ret)

    def zncharconductor(self, G, chi):
        r'''
        Let :emphasis:`G` be attached to :math:`(\mathbb{Z}/q\mathbb{Z})^*` (as per
        :literal:`G = znstar(q, 1)`) and :literal:`chi` be a Dirichlet character on
        :math:`(\mathbb{Z}/q\mathbb{Z})^*` (see ``dirichletchar`` (in the PARI manual) or :literal:`??character`).
        Return the conductor of :literal:`chi`:

        ::

        ? G = znstar(126000, 1);
        ? zncharconductor(G,11) \\ primitive
        %2 = 126000
        ? zncharconductor(G,1) \\ trivial character, not primitive!
        %3 = 1
        ? zncharconductor(G,1009) \\ character mod 5^3
        %4 = 125
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = zncharconductor(_G, _chi)
        return new_gen(_ret)

    def znchardecompose(self, G, chi, Q):
        r'''
        Let :math:`N = \prod_p p^{e_p}` and a Dirichlet character :math:`\chi`,
        we have a decomposition :math:`\chi = \prod_p \chi_p` into character modulo :math:`N`
        where the conductor of :math:`\chi_p` divides :math:`p^{e_p}`; it equals :math:`p^{e_p}` for
        all :math:`p` if and only if :math:`\chi` is primitive.

        Given a :emphasis:`znstar` G describing a group :math:`(\mathbb{Z}/N\mathbb{Z})^*`, a Dirichlet
        character :literal:`chi` and an integer :math:`Q`, return :math:`\prod_{p \| (Q,N)} \chi_p`.
        For instance, if :math:`Q = p` is a prime divisor of :math:`N`, the function returns
        :math:`\chi_p` (as a character modulo :math:`N`), given as a Conrey character (:literal:`t_COL`).

        ::

        ? G = znstar(40, 1);
        ? G.cyc
        %2 = [4, 2, 2]
        ? chi = [2, 1, 1];
        ? chi2 = znchardecompose(G, chi, 2)
        %4 = [1, 1, 0]~
        ? chi5 = znchardecompose(G, chi, 5)
        %5 = [0, 0, 2]~
        ? znchardecompose(G, chi, 3)
        %6 = [0, 0, 0]~
        ? c = charmul(G, chi2, chi5)
        %7 = [1, 1, 2]~ \\ t_COL: in terms of Conrey generators !
        ? znconreychar(G,c)
        %8 = [2, 1, 1] \\ t_VEC: in terms of SNF generators
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        Q = objtogen(Q)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _Q = (<Gen>Q).g
        cdef GEN _ret = znchardecompose(_G, _chi, _Q)
        return new_gen(_ret)

    def znchargauss(self, G, chi, a=None, long precision=DEFAULT_BITPREC):
        r'''
        Given a Dirichlet character :math:`\chi` on :math:`G = (\mathbb{Z}/N\mathbb{Z})^*` (see
        :literal:`znchar`), return the complex Gauss sum

        .. MATH::

        g(\chi,a) = \sum_{n = 1}^N \chi (n) e(a n/N)

        ::

        ? [G,chi] = znchar(-3); \\ quadratic Gauss sum: I*sqrt(3)
        ? znchargauss(G,chi)
        %2 = 1.7320508075688772935274463415058723670*I
        ? [G,chi] = znchar(5);
        ? znchargauss(G,chi) \\ sqrt(5)
        %2 = 2.2360679774997896964091736687312762354
        ? G = znstar(300,1); chi = [1,1,12]~;
        ? znchargauss(G,chi) / sqrt(300) - exp(2*I*Pi*11/25) \\ = 0
        %4 = 2.350988701644575016 E-38 + 1.4693679385278593850 E-39*I
        ? lfuntheta([G,chi], 1) \\ = 0
        %5 = -5.79[...] E-39 - 2.71[...] E-40*I
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        cdef bint _have_a = (a is not None)
        if _have_a:
            a = objtogen(a)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _a = NULL
        if _have_a:
            _a = (<Gen>a).g
        cdef GEN _ret = znchargauss(_G, _chi, _a, precision)
        return new_gen(_ret)

    def zncharinduce(self, G, chi, N):
        r'''
        Let :math:`G` be attached to :math:`(\mathbb{Z}/q\mathbb{Z})^*` (as per :literal:`G = znstar(q,1)`)
        and let :literal:`chi` be a Dirichlet character on :math:`(\mathbb{Z}/q\mathbb{Z})^*`, given by

        - a :literal:`t_VEC`: a standard character on :literal:`bid.gen`,

        - a :literal:`t_INT` or a :literal:`t_COL`: a Conrey index in :math:`(\mathbb{Z}/q\mathbb{Z})^*` or its
        Conrey logarithm;
        see ``dirichletchar`` (in the PARI manual) or :literal:`??character`.

        Let :math:`N` be a multiple of :math:`q`, return the character modulo :math:`N` extending
        :literal:`chi`. As usual for arithmetic functions, the new modulus :math:`N` can be
        given as a :literal:`t_INT`, via a factorization matrix or a pair
        :literal:`[N, factor(N)]`, or by :literal:`znstar(N,1)`.

        ::

        ? G = znstar(4, 1);
        ? chi = znconreylog(G,1); \\ trivial character mod 4
        ? zncharinduce(G, chi, 80) \\ now mod 80
        %3 = [0, 0, 0]~
        ? zncharinduce(G, 1, 80) \\ same using directly Conrey label
        %4 = [0, 0, 0]~
        ? G2 = znstar(80, 1);
        ? zncharinduce(G, 1, G2) \\ same
        %4 = [0, 0, 0]~
        
        ? chi = zncharinduce(G, 3, G2) \\ extend the non-trivial character mod 4
        %5 = [1, 0, 0]~
        ? [G0,chi0] = znchartoprimitive(G2, chi);
        ? G0.mod
        %7 = 4
        ? chi0
        %8 = [1]~

        Here is a larger example:

        ::

        ? G = znstar(126000, 1);
        ? label = 1009;
        ? chi = znconreylog(G, label)
        %3 = [0, 0, 0, 14, 0]~
        ? [G0,chi0] = znchartoprimitive(G, label); \\ works also with 'chi'
        ? G0.mod
        %5 = 125
        ? chi0 \\ primitive character mod 5^3 attached to chi
        %6 = [14]~
        ? G0 = znstar(N0, 1);
        ? zncharinduce(G0, chi0, G) \\ induce back
        %8 = [0, 0, 0, 14, 0]~
        ? znconreyexp(G, %)
        %9 = 1009
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        N = objtogen(N)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _N = (<Gen>N).g
        cdef GEN _ret = zncharinduce(_G, _chi, _N)
        return new_gen(_ret)

    def zncharisodd(self, G, chi):
        r'''
        Let :math:`G` be attached to :math:`(\mathbb{Z}/N\mathbb{Z})^*` (as per :literal:`G = znstar(N,1)`)
        and let :literal:`chi` be a Dirichlet character on :math:`(\mathbb{Z}/N\mathbb{Z})^*`, given by

        - a :literal:`t_VEC`: a standard character on :literal:`G.gen`,

        - a :literal:`t_INT` or a :literal:`t_COL`: a Conrey index in :math:`(\mathbb{Z}/q\mathbb{Z})^*` or its
        Conrey logarithm;
        see ``dirichletchar`` (in the PARI manual) or :literal:`??character`.

        Return :math:`1` if and only if :literal:`chi`:math:`(-1) = -1` and :math:`0` otherwise.

        ::

        ? G = znstar(8, 1);
        ? zncharisodd(G, 1) \\ trivial character
        %2 = 0
        ? zncharisodd(G, 3)
        %3 = 1
        ? chareval(G, 3, -1)
        %4 = 1/2
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef long _ret = zncharisodd(_G, _chi)
        clear_stack()
        return _ret

    def znchartokronecker(self, G, chi, long flag=0):
        r'''
        Let :math:`G` be attached to :math:`(\mathbb{Z}/N\mathbb{Z})^*` (as per :literal:`G = znstar(N,1)`)
        and let :literal:`chi` be a Dirichlet character on :math:`(\mathbb{Z}/N\mathbb{Z})^*`, given by

        - a :literal:`t_VEC`: a standard character on :literal:`bid.gen`,

        - a :literal:`t_INT` or a :literal:`t_COL`: a Conrey index in :math:`(\mathbb{Z}/q\mathbb{Z})^*` or its
        Conrey logarithm;
        see ``dirichletchar`` (in the PARI manual) or :literal:`??character`.

        If :math:`flag = 0`, return the discriminant :math:`D` if :literal:`chi` is real equal to the
        Kronecker symbol :math:`(D/.)` and :math:`0` otherwise. The discriminant :math:`D` is
        fundamental if and only if :literal:`chi` is primitive.

        If :math:`flag = 1`, return the fundamental discriminant attached to the
        corresponding primitive character.

        ::

        ? G = znstar(8,1); CHARS = [1,3,5,7]; \\ Conrey labels
        ? apply(t->znchartokronecker(G,t), CHARS)
        %2 = [4, -8, 8, -4]
        ? apply(t->znchartokronecker(G,t,1), CHARS)
        %3 = [1, -8, 8, -4]
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = znchartokronecker(_G, _chi, flag)
        return new_gen(_ret)

    def znchartoprimitive(self, G, chi):
        r'''
        Let :emphasis:`G` be attached to :math:`(\mathbb{Z}/q\mathbb{Z})^*` (as per
        :literal:`G = znstar(q, 1)`) and :literal:`chi` be a Dirichlet character on
        :math:`(\mathbb{Z}/q\mathbb{Z})^*`, of conductor :math:`q_0 \| q`.

        ::

        ? G = znstar(126000, 1);
        ? [G0,chi0] = znchartoprimitive(G,11)
        ? G0.mod
        %3 = 126000
        ? chi0
        %4 = 11
        ? [G0,chi0] = znchartoprimitive(G,1);\\ trivial character, not primitive!
        ? G0.mod
        %6 = 1
        ? chi0
        %7 = []~
        ? [G0,chi0] = znchartoprimitive(G,1009)
        ? G0.mod
        %4 = 125
        ? chi0
        %5 = [14]~

        Note that :literal:`znconreyconductor` is more efficient since
        it can return :math:`\chi_0` and its conductor :math:`q_0` without needing to initialize
        :math:`G_0`. (The price to pay is a more cryptic format and the need to
        initalize :math:`G_0` later but the can be done once for all characters
        of conductor :math:`q_0`.)
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = znchartoprimitive(_G, _chi)
        return new_gen(_ret)

    def znconreychar(self, G, m):
        r'''
        Given a :emphasis:`znstar` :math:`G` attached to :math:`(\mathbb{Z}/q\mathbb{Z})^*` (as per
        :literal:`G = znstar(q,1)`), this function returns the Dirichlet character
        attached to :math:`m \in (\mathbb{Z}/q\mathbb{Z})^*` via Conrey's logarithm, which
        establishes a "canonical" bijection between :math:`(\mathbb{Z}/q\mathbb{Z})^*` and its dual.

        Let :math:`q = \prod_p p^{e_p}` be the factorization of :math:`q` into distinct primes.
        For all odd :math:`p` with :math:`e_p > 0`, let :math:`g_p` be the element in :math:`(\mathbb{Z}/q\mathbb{Z})^*`
        which is

        - congruent to :math:`1` mod :math:`q/p^{e_p}`,

        - congruent mod :math:`p^{e_p}` to the smallest positive integer that generates
        :math:`(\mathbb{Z}/p^2\mathbb{Z})^*`.

        For :math:`p = 2`, we let :math:`g_4` (if :math:`2^{e_2} >= 4`) and :math:`g_8` (if furthermore
        (:math:`2^{e_2} >= 8`) be the elements in :math:`(\mathbb{Z}/q\mathbb{Z})^*` which are

        - congruent to :math:`1` mod :math:`q/2^{e_2}`,

        - :math:`g_4 = -1 mod 2^{e_2}`,

        - :math:`g_8 = 5 mod 2^{e_2}`.

        Then the :math:`g_p` (and the extra :math:`g_4` and :math:`g_8` if :math:`2^{e_2} >= 2`) are
        independent generators of :math:`(\mathbb{Z}/q\mathbb{Z})^*`, i.e. every :math:`m` in :math:`(\mathbb{Z}/q\mathbb{Z})^*` can be
        written uniquely as :math:`\prod_p g_p^{m_p}`, where :math:`m_p` is defined modulo the
        order :math:`o_p` of :math:`g_p` and :math:`p \in S_q`, the set of prime divisors of :math:`q`
        together with :math:`4` if :math:`4 \| q` and :math:`8` if :math:`8 \| q`. Note that the :math:`g_p`
        are in general :emphasis:`not` SNF generators as produced by :literal:`znstar` whenever
        :math:`\omega (q) >= 2`, although their number is the same. They however allow
        to handle the finite abelian group :math:`(\mathbb{Z}/q\mathbb{Z})^*` in a fast and elegant way.
        (Which unfortunately does not generalize to ray class groups or Hecke
        characters.)

        The Conrey logarithm of :math:`m` is the vector :math:`(m_p)_{p\in S_q}`, obtained
        via :literal:`znconreylog`. The Conrey character :math:`\chi_q(m,.)` attached to
        :math:`m` mod :math:`q` maps
        each :math:`g_p`, :math:`p\in S_q` to :math:`e(m_p / o_p)`, where :math:`e(x) = \exp (2i\pi x)`.
        This function returns the Conrey character expressed in the standard PARI
        way in terms of the SNF generators :literal:`G.gen`.

        ::

        ? G = znstar(8,1);
        ? G.cyc
        %2 = [2, 2] \\ Z/2 x Z/2
        ? G.gen
        %3 = [7, 3]
        ? znconreychar(G,1) \\ 1 is always the trivial character
        %4 = [0, 0]
        ? znconreychar(G,2) \\ 2 is not coprime to 8 !!!
        *** at top-level: znconreychar(G,2)
        *** ^-----------------
        *** znconreychar: elements not coprime in Zideallog:
        2
        8
        *** Break loop: type 'break' to go back to GP prompt
        break>
        
        ? znconreychar(G,3)
        %5 = [0, 1]
        ? znconreychar(G,5)
        %6 = [1, 1]
        ? znconreychar(G,7)
        %7 = [1, 0]

        We indeed get all 4 characters of :math:`(\mathbb{Z}/8\mathbb{Z})^*`.

        For convenience, we allow to input the :emphasis:`Conrey logarithm` of :math:`m`
        instead of :math:`m`:

        ::

        ? G = znstar(55, 1);
        ? znconreychar(G,7)
        %2 = [7, 0]
        ? znconreychar(G, znconreylog(G,7))
        %3 = [7, 0]
        '''
        G = objtogen(G)
        m = objtogen(m)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _m = (<Gen>m).g
        cdef GEN _ret = znconreychar(_G, _m)
        return new_gen(_ret)

    def znconreyconductor(self, G, chi, chi0=None):
        r'''
        Let :emphasis:`G` be attached to :math:`(\mathbb{Z}/q\mathbb{Z})^*` (as per
        :literal:`G = znstar(q, 1)`) and :literal:`chi` be a Dirichlet character on
        :math:`(\mathbb{Z}/q\mathbb{Z})^*`, given by

        - a :literal:`t_VEC`: a standard character on :literal:`bid.gen`,

        - a :literal:`t_INT` or a :literal:`t_COL`: a Conrey index in :math:`(\mathbb{Z}/q\mathbb{Z})^*` or its
        Conrey logarithm;
        see ``dirichletchar`` (in the PARI manual) or :literal:`??character`.

        Return the conductor of :literal:`chi`, as the :literal:`t_INT` :literal:`bid.mod`
        if :literal:`chi` is primitive, and as a pair :literal:`[N, faN]` (with :literal:`faN` the
        factorization of :math:`N`) otherwise.

        If :literal:`chi0` is present, set it to the Conrey logarithm of the attached
        primitive character.

        ::

        ? G = znstar(126000, 1);
        ? znconreyconductor(G,11) \\ primitive
        %2 = 126000
        ? znconreyconductor(G,1) \\ trivial character, not primitive!
        %3 = [1, matrix(0,2)]
        ? N0 = znconreyconductor(G,1009, &chi0) \\ character mod 5^3
        %4 = [125, Mat([5, 3])]
        ? chi0
        %5 = [14]~
        ? G0 = znstar(N0, 1); \\ format [N,factor(N)] accepted
        ? znconreyexp(G0, chi0)
        %7 = 9
        ? znconreyconductor(G0, chi0) \\ now primitive, as expected
        %8 = 125

        The group :literal:`G0` is not computed as part of
        :literal:`znconreyconductor` because it needs to be computed only once per
        conductor, not once per character.
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        cdef bint _have_chi0 = (chi0 is not None)
        if _have_chi0:
            raise NotImplementedError("optional argument chi0 not available")
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN * _chi0 = NULL
        cdef GEN _ret = znconreyconductor(_G, _chi, _chi0)
        return new_gen(_ret)

    def znconreyexp(self, G, chi):
        r'''
        Given a :emphasis:`znstar` :math:`G` attached to :math:`(\mathbb{Z}/q\mathbb{Z})^*` (as per
        :literal:`G = znstar(q, 1)`), this function returns the Conrey exponential of
        the character :emphasis:`chi`: it returns the integer
        :math:`m \in (\mathbb{Z}/q\mathbb{Z})^*` such that :literal:`znconreylog(G, :math:`m`)` is :emphasis:`chi`.

        The character :emphasis:`chi` is given either as a

        - :literal:`t_VEC`: in terms of the generators :literal:`G.gen`;

        - :literal:`t_COL`: a Conrey logarithm.

        ::

        ? G = znstar(126000, 1)
        ? znconreylog(G,1)
        %2 = [0, 0, 0, 0, 0]~
        ? znconreyexp(G,%)
        %3 = 1
        ? G.cyc \\ SNF generators
        %4 = [300, 12, 2, 2, 2]
        ? chi = [100, 1, 0, 1, 0]; \\ some random character on SNF generators
        ? znconreylog(G, chi) \\ in terms of Conrey generators
        %6 = [0, 3, 3, 0, 2]~
        ? znconreyexp(G, %) \\ apply to a Conrey log
        %7 = 18251
        ? znconreyexp(G, chi) \\ ... or a char on SNF generators
        %8 = 18251
        ? znconreychar(G,%)
        %9 = [100, 1, 0, 1, 0]
        '''
        G = objtogen(G)
        chi = objtogen(chi)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _chi = (<Gen>chi).g
        cdef GEN _ret = znconreyexp(_G, _chi)
        return new_gen(_ret)

    def znconreylog(self, G, m):
        r'''
        Given a :emphasis:`znstar` attached to :math:`(\mathbb{Z}/q\mathbb{Z})^*` (as per
        :literal:`G = znstar(q,1)`), this function returns the Conrey logarithm of
        :math:`m \in (\mathbb{Z}/q\mathbb{Z})^*`.

        Let :math:`q = \prod_p p^{e_p}` be the factorization of :math:`q` into distinct primes,
        where we assume :math:`e_2 = 0` or :math:`e_2 >= 2`. (If :math:`e_2 = 1`, we can ignore :math:`2`
        from the factorization, as if we replaced :math:`q` by :math:`q/2`, since :math:`(\mathbb{Z}/q\mathbb{Z})^*
        ~ (\mathbb{Z}/(q/2)\mathbb{Z})^*`.)

        For all odd :math:`p` with :math:`e_p > 0`, let :math:`g_p` be the element in :math:`(\mathbb{Z}/q\mathbb{Z})^*`
        which is

        - congruent to :math:`1` mod :math:`q/p^{e_p}`,

        - congruent mod :math:`p^{e_p}` to the smallest positive integer that generates
        :math:`(\mathbb{Z}/p^2\mathbb{Z})^*`.

        For :math:`p = 2`, we let :math:`g_4` (if :math:`2^{e_2} >= 4`) and :math:`g_8` (if furthermore
        (:math:`2^{e_2} >= 8`) be the elements in :math:`(\mathbb{Z}/q\mathbb{Z})^*` which are

        - congruent to :math:`1` mod :math:`q/2^{e_2}`,

        - :math:`g_4 = -1 mod 2^{e_2}`,

        - :math:`g_8 = 5 mod 2^{e_2}`.

        Then the :math:`g_p` (and the extra :math:`g_4` and :math:`g_8` if :math:`2^{e_2} >= 2`) are
        independent generators of :math:`\mathbb{Z}/q\mathbb{Z}^*`, i.e. every :math:`m` in :math:`(\mathbb{Z}/q\mathbb{Z})^*` can be
        written uniquely as :math:`\prod_p g_p^{m_p}`, where :math:`m_p` is defined modulo the
        order :math:`o_p` of :math:`g_p` and :math:`p \in S_q`, the set of prime divisors of :math:`q`
        together with :math:`4` if :math:`4 \| q` and :math:`8` if :math:`8 \| q`. Note that the :math:`g_p`
        are in general :emphasis:`not` SNF generators as produced by :literal:`znstar` whenever
        :math:`\omega (q) >= 2`, although their number is the same. They however allow
        to handle the finite abelian group :math:`(\mathbb{Z}/q\mathbb{Z})^*` in a fast and elegant way.
        (Which unfortunately does not generalize to ray class groups or Hecke
        characters.)

        The Conrey logarithm of :math:`m` is the vector :math:`(m_p)_{p\in S_q}`. The inverse
        function :literal:`znconreyexp` recovers the Conrey label :math:`m` from a character.

        ::

        ? G = znstar(126000, 1);
        ? znconreylog(G,1)
        %2 = [0, 0, 0, 0, 0]~
        ? znconreyexp(G, %)
        %3 = 1
        ? znconreylog(G,2) \\ 2 is not coprime to modulus !!!
        *** at top-level: znconreylog(G,2)
        *** ^-----------------
        *** znconreylog: elements not coprime in Zideallog:
        2
        126000
        *** Break loop: type 'break' to go back to GP prompt
        break>
        ? znconreylog(G,11) \\ wrt. Conrey generators
        %4 = [0, 3, 1, 76, 4]~
        ? log11 = ideallog(,11,G) \\ wrt. SNF generators
        %5 = [178, 3, -75, 1, 0]~

        For convenience, we allow to input the ordinary discrete log of :math:`m`,
        :math:`ideallog(,m,bid)`, which allows to convert discrete logs
        from :literal:`bid.gen` generators to Conrey generators.

        ::

        ? znconreylog(G, log11)
        %7 = [0, 3, 1, 76, 4]~

        We also allow a character (:literal:`t_VEC`) on :literal:`bid.gen` and
        return its representation on the Conrey generators.

        ::

        ? G.cyc
        %8 = [300, 12, 2, 2, 2]
        ? chi = [10,1,0,1,1];
        ? znconreylog(G, chi)
        %10 = [1, 3, 3, 10, 2]~
        ? n = znconreyexp(G, chi)
        %11 = 84149
        ? znconreychar(G, n)
        %12 = [10, 1, 0, 1, 1]
        '''
        G = objtogen(G)
        m = objtogen(m)
        sig_on()
        cdef GEN _G = (<Gen>G).g
        cdef GEN _m = (<Gen>m).g
        cdef GEN _ret = znconreylog(_G, _m)
        return new_gen(_ret)

    def zncoppersmith(self, P, N, X, B=None):
        r'''
        :math:`N` being an integer and :math:`P\in \mathbb{Z}[X]`, finds all integers :math:`x` with
        :math:`\|x\| <= X` such that

        .. MATH::

        \mathrm{gcd} (N, P(x)) >= B,

        using Coppersmith's algorithm, a famous application of the LLL
        algorithm meant to help in the factorization of :math:`N`. The parameter :math:`X` must be
        smaller than
        :math:`\exp (\log^2 (B/p) / (\deg (P) \log (N/p)))`, where :math:`p` is the gcd of the
        leading coefficient of :math:`P` and :math:`N`. In applications to factorization,
        we should have :math:`p = 1` (otherwise we have factored :math:`N` if :math:`p != N`
        or we can reduce the degree of :math:`P`); for :math:`B = N` and :math:`p = 1`, the condition
        means :math:`X < N^{1/\deg (P)}`. Some :math:`x` larger than :math:`X` may be returned if you are
        very lucky. The routine runs in polynomial time in :math:`\deg (P)` and :math:`\log N`
        but the smaller :math:`B`, or the larger :math:`X`, the slower.
        The strength of Coppersmith method is the ability to find roots modulo a
        general :emphasis:`composite` :math:`N`: if :math:`N` is a prime or a prime power,
        :literal:`polrootsmod` or :literal:`polrootspadic` will be much faster.

        We shall now present two simple applications. The first one is
        finding non-trivial factors of :math:`N`, given some partial information on the
        factors; in that case :math:`B` must obviously be smaller than the largest
        non-trivial divisor of :math:`N`.

        ::

        setrand(1); \\ to make the example reproducible
        [a,b] = [10^30, 10^31]; D = 20;
        p = randomprime([a,b]);
        q = randomprime([a,b]); N = p*q;
        \\ assume we know 0) p | N; 1) p in [a,b]; 2) the last D digits of p
        p0 = p % 10^D;
        
        ? L = zncoppersmith(10^D*x + p0, N, b \ 10^D, a)
        time = 1ms.
        %6 = [738281386540]
        ? gcd(L[1] * 10^D + p0, N) == p
        %7 = 1

        and we recovered :math:`p`, faster than by trying all
        possibilities :math:`x < 10^{11}`.

        The second application is an attack on RSA with low exponent, when the
        message :math:`x` is short and the padding :math:`P` is known to the attacker. We use
        the same RSA modulus :math:`N` as in the first example:

        ::

        setrand(1);
        P = random(N); \\ known padding
        e = 3; \\ small public encryption exponent
        X = floor(N^0.3); \\ N^(1/e - epsilon)
        x0 = random(X); \\ unknown short message
        C = lift( (Mod(x0,N) + P)^e ); \\ known ciphertext, with padding P
        zncoppersmith((P + x)^3 - C, N, X)
        
        \\ result in 244ms.
        %14 = [2679982004001230401]
        
        ? %[1] == x0
        %15 = 1

        We guessed an integer of the order of :math:`10^{18}`, almost instantly.
        '''
        P = objtogen(P)
        N = objtogen(N)
        X = objtogen(X)
        cdef bint _have_B = (B is not None)
        if _have_B:
            B = objtogen(B)
        sig_on()
        cdef GEN _P = (<Gen>P).g
        cdef GEN _N = (<Gen>N).g
        cdef GEN _X = (<Gen>X).g
        cdef GEN _B = NULL
        if _have_B:
            _B = (<Gen>B).g
        cdef GEN _ret = zncoppersmith(_P, _N, _X, _B)
        return new_gen(_ret)

    def znlog(self, x, g, o=None):
        r'''
        This functions allows two distinct modes of operation depending
        on :math:`g`:

        - if :math:`g` is the output of :literal:`znstar` (with initialization),
        we compute the discrete logarithm of :math:`x` with respect to the generators
        contained in the structure. See :literal:`ideallog` for details.

        - else :math:`g` is an explicit element in :math:`(\mathbb{Z}/N\mathbb{Z})^*`, we compute the
        discrete logarithm of :math:`x` in :math:`(\mathbb{Z}/N\mathbb{Z})^*` in base :math:`g`. The rest of this
        entry describes the latter possibility.

        The result is :math:`[]` when :math:`x` is not a power of :math:`g`, though the function may
        also enter an infinite loop in this case.

        If present, :math:`o` represents the multiplicative order of :math:`g`, see
        ``DLfun`` (in the PARI manual); the preferred format for this parameter is
        :literal:`[ord, factor(ord)]`, where :literal:`ord` is the order of :math:`g`.
        This provides a definite speedup when the discrete log problem is simple:

        ::

        ? p = nextprime(10^4); g = znprimroot(p); o = [p-1, factor(p-1)];
        ? for(i=1,10^4, znlog(i, g, o))
        time = 163 ms.
        ? for(i=1,10^4, znlog(i, g))
        time = 200 ms. \\ a little slower

        The result is undefined if :math:`g` is not invertible mod :math:`N` or if the supplied
        order is incorrect.

        This function uses

        - a combination of generic discrete log algorithms (see below).

        - in :math:`(\mathbb{Z}/N\mathbb{Z})^*` when :math:`N` is prime: a linear sieve index calculus
        method, suitable for :math:`N < 10^{50}`, say, is used for large prime divisors of
        the order.

        The generic discrete log algorithms are:

        - Pohlig-Hellman algorithm, to reduce to groups of prime order :math:`q`,
        where :math:`q \| p-1` and :math:`p` is an odd prime divisor of :math:`N`,

        - Shanks baby-step/giant-step (:math:`q < 2^{32}` is small),

        - Pollard rho method (:math:`q > 2^{32}`).

        The latter two algorithms require :math:`O(\sqrt{q})` operations in the group on
        average, hence will not be able to treat cases where :math:`q > 10^{30}`, say.
        In addition, Pollard rho is not able to handle the case where there are no
        solutions: it will enter an infinite loop.

        ::

        ? g = znprimroot(101)
        %1 = Mod(2,101)
        ? znlog(5, g)
        %2 = 24
        ? g^24
        %3 = Mod(5, 101)
        
        ? G = znprimroot(2 * 101^10)
        %4 = Mod(110462212541120451003, 220924425082240902002)
        ? znlog(5, G)
        %5 = 76210072736547066624
        ? G^% == 5
        %6 = 1
        ? N = 2^4*3^2*5^3*7^4*11; g = Mod(13, N); znlog(g^110, g)
        %7 = 110
        ? znlog(6, Mod(2,3)) \\ no solution
        %8 = []

        For convenience, :math:`g` is also allowed to be a :math:`p`-adic number:

        ::

        ? g = 3+O(5^10); znlog(2, g)
        %1 = 1015243
        ? g^%
        %2 = 2 + O(5^10)
        '''
        x = objtogen(x)
        g = objtogen(g)
        cdef bint _have_o = (o is not None)
        if _have_o:
            o = objtogen(o)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _g = (<Gen>g).g
        cdef GEN _o = NULL
        if _have_o:
            _o = (<Gen>o).g
        cdef GEN _ret = znlog0(_x, _g, _o)
        return new_gen(_ret)

    def znorder(self, x, o=None):
        r'''
        :math:`x` must be an integer mod :math:`n`, and the
        result is the order of :math:`x` in the multiplicative group :math:`(\mathbb{Z}/n\mathbb{Z})^*`. Returns
        an error if :math:`x` is not invertible.
        The parameter o, if present, represents a non-zero
        multiple of the order of :math:`x`, see ``DLfun`` (in the PARI manual); the preferred format for
        this parameter is :literal:`[ord, factor(ord)]`, where :literal:`ord = eulerphi(n)`
        is the cardinality of the group.
        '''
        x = objtogen(x)
        cdef bint _have_o = (o is not None)
        if _have_o:
            o = objtogen(o)
        sig_on()
        cdef GEN _x = (<Gen>x).g
        cdef GEN _o = NULL
        if _have_o:
            _o = (<Gen>o).g
        cdef GEN _ret = znorder(_x, _o)
        return new_gen(_ret)

    def znprimroot(self, n):
        r'''
        Returns a primitive root (generator) of :math:`(\mathbb{Z}/n\mathbb{Z})^*`, whenever this
        latter group is cyclic (:math:`n = 4` or :math:`n = 2p^k` or :math:`n = p^k`, where :math:`p` is an
        odd prime and :math:`k >= 0`). If the group is not cyclic, the result is
        undefined. If :math:`n` is a prime power, then the smallest positive primitive
        root is returned. This may not be true for :math:`n = 2p^k`, :math:`p` odd.

        Note that this function requires factoring :math:`p-1` for :math:`p` as above,
        in order to determine the exact order of elements in
        :math:`(\mathbb{Z}/n\mathbb{Z})^*`: this is likely to be costly if :math:`p` is large.
        '''
        n = objtogen(n)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = znprimroot(_n)
        return new_gen(_ret)

    def znstar(self, n, long flag=0):
        r'''
        Gives the structure of the multiplicative group :math:`(\mathbb{Z}/n\mathbb{Z})^*`.
        The output :math:`G` depends on the value of :emphasis:`flag`:

        - :math:`flag = 0` (default), an abelian group structure :math:`[h,d,g]`,
        where :math:`h = \phi (n)` is the order (:literal:`G.no`), :math:`d` (:literal:`G.cyc`)
        is a :math:`k`-component row-vector :math:`d` of integers :math:`d_i` such that :math:`d_i > 1`,
        :math:`d_i \| d_{i-1}` for :math:`i >= 2` and
        

        .. MATH::

        (\mathbb{Z}/n\mathbb{Z})^* ~ \prod_{i = 1}^k (\mathbb{Z}/d_i\mathbb{Z}),

        and :math:`g` (:literal:`G.gen`) is a :math:`k`-component row vector giving generators of
        the image of the cyclic groups :math:`\mathbb{Z}/d_i\mathbb{Z}`.

        - :math:`flag = 1` the result is a :literal:`bid` structure;
        this allows computing discrete logarithms using :literal:`znlog` (also in the
        non-cyclic case!).

        ::

        ? G = znstar(40)
        %1 = [16, [4, 2, 2], [Mod(17, 40), Mod(21, 40), Mod(11, 40)]]
        ? G.no \\ eulerphi(40)
        %2 = 16
        ? G.cyc \\ cycle structure
        %3 = [4, 2, 2]
        ? G.gen \\ generators for the cyclic components
        %4 = [Mod(17, 40), Mod(21, 40), Mod(11, 40)]
        ? apply(znorder, G.gen)
        %5 = [4, 2, 2]

        For user convenience, we define :literal:`znstar(0)` as
        :literal:`[2, [2], [-1]]`, corresponding to :math:`\mathbb{Z}^*`, but :math:`flag = 1` is not
        implemented in this trivial case.
        '''
        n = objtogen(n)
        sig_on()
        cdef GEN _n = (<Gen>n).g
        cdef GEN _ret = znstar0(_n, flag)
        return new_gen(_ret)

DEF HAVE_PLOT_SVG = True