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

cdef class gen_auto(RingElement):
    """
    Part of the :class:`gen` class containing auto-generated functions.

    This class is not meant to be used directly, use the derived class
    :class:`gen` instead.
    """
    def Col(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\|`.
        
        Note that the function :literal:`Colrev` does not exist, use :literal:`Vecrev`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtocol0(_x, n)
        return pari_instance.new_gen(_ret)

    def Colrev(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtocolrev0(_x, n)
        return pari_instance.new_gen(_ret)

    def List(x):
        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`. Note that,
        except when :math:`x` is omitted, this function creates a small memory leak; so,
        either initialize all lists to the empty list, or use them sparingly.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtolist(_x)
        return pari_instance.new_gen(_ret)

    def Map(x):
        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, create an empty map, which
        may be filled later via :literal:`mapput`
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtomap(_x)
        return pari_instance.new_gen(_ret)

    def Mat(x):
        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 associated big matrix is returned.
        If :math:`x` is a binary quadratic form, creates the associated :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 GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtomat(_x)
        return pari_instance.new_gen(_ret)

    def Mod(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`.
        """
        cdef GEN _a = a.g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        pari_catch_sig_on()
        cdef GEN _ret = gmodulo(_a, _b)
        return pari_instance.new_gen(_ret)

    def Pol(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.
        """
        cdef GEN _t = t.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = gtopoly(_t, _v)
        return pari_instance.new_gen(_ret)

    def Polrev(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`).
        """
        cdef GEN _t = t.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = gtopolyrev(_t, _v)
        return pari_instance.new_gen(_ret)

    def Qfb(a, b, c, D=None, long precision=0):
        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.
        """
        cdef GEN _a = a.g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        c = objtogen(c)
        cdef GEN _c = (<gen>c).g
        cdef GEN _D = NULL
        if D is not None:
            D = objtogen(D)
            _D = (<gen>D).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = Qfb0(_a, _b, _c, _D, precision)
        return pari_instance.new_gen(_ret)

    def Ser(s, v=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
        
        ::
        
            ? Ser(1, 'y, 5)
            %1 = 1 + O(y^5)
            ? Ser(x^2,, 5)
            %2 = x^2 + O(x^7)
            ? T = polcyclo(100)
            %3 = x^40 - x^30 + x^20 - x^10 + 1
            ? Ser(T, 'x, 11)
            %4 = 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.
        
        If :math:`s` is a vector, on the other hand, 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)`), and the precision :math:`d` is ignored:
        in other words, in this case, we convert :literal:`t_VEC` / :literal:`t_COL` to the power
        series whose significant terms are exactly given by the vector entries.
        Finally, if :math:`s` is already a power series in :math:`v`, we return it verbatim,
        ignoring :math:`d` again. If :math:`d` significant terms are desired in the last two
        cases, convert/truncate to :literal:`t_POL` first.
        
        ::
        
            ? v = [1,2,3]; Ser(v, t, 7)
            %5 = 1 + 2*t + 3*t^2 + O(t^3) \\ 3 terms: 7 is ignored!
            ? Ser(Polrev(v,t), t, 7)
            %6 = 1 + 2*t + 3*t^2 + O(t^7)
            ? s = 1+x+O(x^2); Ser(s, x, 7)
            %7 = 1 + x + O(x^2) \\ 2 terms: 7 ignored
            ? Ser(truncate(s), x, 7)
            %8 = 1 + x + O(x^7)
        
        The warning given for :literal:`Pol` also applies here: this is not a substitution
        function.
        """
        cdef GEN _s = s.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        pari_catch_sig_on()
        cdef GEN _ret = gtoser(_s, _v, serprec)
        return pari_instance.new_gen(_ret)

    def Set(x):
        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 GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtoset(_x)
        return pari_instance.new_gen(_ret)

    def Strchr(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"
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = Strchr(_x)
        return pari_instance.new_gen(_ret)

    def Vec(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 (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: return the vector of columns comprising the matrix.
        
        - a character string: return the vector of individual characters.
        
        - an error context (:literal:`t_ERROR`): return the error components, see
          :literal:`iferr`.
        
        In the last three cases (matrix, character string, 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\|`. Variant: :literal:`GEN :strong:`gtovec`(GEN x)` is also available.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtovec0(_x, n)
        return pari_instance.new_gen(_ret)

    def Vecrev(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtovecrev0(_x, n)
        return pari_instance.new_gen(_ret)

    def Vecsmall(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).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtovecsmall0(_x, n)
        return pari_instance.new_gen(_ret)

    def abs(x, long precision=0):
        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.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gabs(_x, precision)
        return pari_instance.new_gen(_ret)

    def acos(x, long precision=0):
        r"""
        Principal branch of :math:`{cos}^{-1}(x) = -i \log (x + i\sqrt{1-x^2})`.
        In particular, :math:`{Re(acos}(x)) belongs to [0,\Pi]` and if :math:`x belongs to \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`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gacos(_x, precision)
        return pari_instance.new_gen(_ret)

    def acosh(x, long precision=0):
        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:`{In}({acosh}(x)) belongs to ]-\Pi,\Pi]0`; if :math:`x belongs to \mathbb{R}` and :math:`x < 1`, then
        :math:`{acosh}(x)` is complex.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gacosh(_x, precision)
        return pari_instance.new_gen(_ret)

    def addprimes(x):
        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 GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = addprimes(_x)
        return pari_instance.new_gen(_ret)

    def agm(x, y, long precision=0):
        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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = agm(_x, _y, precision)
        return pari_instance.new_gen(_ret)

    def algabsdim(al):
        r"""
        Given an algebra :emphasis:`al` output by :literal:`alginit` or by
        :literal:`algtableinit`, returns the dimension of :emphasis:`al` over its prime subfield
        (:math:`\mathbb{Q}` or :math:`\mathbb{F}_p`).
        
        ::
        
            ? nf = nfinit(y^3-y+1);
            ? A = alginit(nf, [-1,-1]);
            ? algabsdim(A)
            %3 = 12
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef long _ret = algabsdim(_al)
        pari_instance.clear_stack()
        return _ret

    def algadd(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`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = algadd(_al, _x, _y)
        return pari_instance.new_gen(_ret)

    def algalgtobasis(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]~
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = algalgtobasis(_al, _x)
        return pari_instance.new_gen(_ret)

    def algaut(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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algaut(_al)
        return pari_instance.new_gen(_ret)

    def algb(al):
        r"""
        Given a cyclic algebra :math:`al = (L/K,\sigma,b)` output by
        :literal:`alginit`, returns the element :math:`b belongs to 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)
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algb(_al)
        return pari_instance.new_gen(_ret)

    def algbasis(al):
        r"""
        Given an central simple algebra :emphasis:`al` output by :literal:`alginit`, returns
        a :math:`\mathbb{Z}`-basis of the order :math:`{\\cal 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]
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algbasis(_al)
        return pari_instance.new_gen(_ret)

    def algbasistoalg(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]~
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = algbasistoalg(_al, _x)
        return pari_instance.new_gen(_ret)

    def algcenter(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
        for 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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = gp_algcenter(_al)
        return pari_instance.new_gen(_ret)

    def algcentralproj(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\oplus \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
        """
        cdef GEN _al = al.g
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        pari_catch_sig_on()
        cdef GEN _ret = alg_centralproj(_al, _z, maps)
        return pari_instance.new_gen(_ret)

    def algchar(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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algchar(_al)
        return pari_instance.new_gen(_ret)

    def algcharpoly(al, b, v=None):
        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`, 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`, 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
        
        Also accepts a square matrix with coefficients in :emphasis:`al`.
        """
        cdef GEN _al = al.g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = algcharpoly(_al, _b, _v)
        return pari_instance.new_gen(_ret)

    def algdecomposition(al):
        r"""
        :emphasis:`al` being a table algebra output by :literal:`algtableinit`, returns
        :math:`[J,[al_1,...,al_n]]` where :math:`J` is a basis of the Jacobson radical of
        :emphasis:`al` and :math:`al_1,...,al_n` are the simple factors of the semisimple
        algebra :math:`al/J`.
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = alg_decomposition(_al)
        return pari_instance.new_gen(_ret)

    def algdegree(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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef long _ret = algdegree(_al)
        pari_instance.clear_stack()
        return _ret

    def algdep(x, long k, long flag=0):
        r"""
        :math:`x` being real/complex, or :math:`p`-adic, finds a polynomial of degree at most
        :math:`k` with integer coefficients having :math:`x` 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`).
        
        Internally, :literal:`lindep`:math:`([1,x,...,x^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 (this truncates the number, throwing away the least
        significant bits), but default values are usually sufficient:
        
        ::
        
            ? \p200
            ? algdep(2^(1/6)+3^(1/5), 30); \\ wrong in 0.8s
            ? algdep(2^(1/6)+3^(1/5), 30, 100); \\ wrong in 0.4s
            ? algdep(2^(1/6)+3^(1/5), 30, 170); \\ right in 0.8s
            ? algdep(2^(1/6)+3^(1/5), 30, 200); \\ wrong in 1.0s
            ? \p250
            ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 1.0s
            ? algdep(2^(1/6)+3^(1/5), 30, 200); \\ right in 1.0s
            ? \p500
            ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 2.9s
            ? \p1000
            ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 10.6s
        
        The changes in :literal:`defaultprecision` 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 205 digits, and from then on a
        steady stream of correct results.
        
        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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = algdep0(_x, k, flag)
        return pari_instance.new_gen(_ret)

    def algdim(al):
        r"""
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, returns
        the dimension of :emphasis:`al` over its center. Given a table algebra :emphasis:`al`
        output by :literal:`algtableinit`, returns the dimension of :emphasis:`al` over its prime
        subfield (:math:`\mathbb{Q}` or :math:`\mathbb{F}_p`).
        
        ::
        
            ? nf = nfinit(y^3-y+1);
            ? A = alginit(nf, [-1,-1]);
            ? algdim(A)
            %3 = 4
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef long _ret = algdim(_al)
        pari_instance.clear_stack()
        return _ret

    def algdisc(al):
        r"""
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, computes
        the discriminant of the order :math:`{\\cal O}_0` stored in :emphasis:`al`, that is the
        determinant of the trace form :math:`\\rm{Tr} : {\\cal O}_0 x {\\cal 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 = algabsdim(A);
            ? 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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algdisc(_al)
        return pari_instance.new_gen(_ret)

    def algdivl(al, x, y):
        r"""
        Given two elements :math:`x` and :math:`y` in :emphasis:`al`, computes their left quotient
        :math:`x\\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`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = algdivl(_al, _x, _y)
        return pari_instance.new_gen(_ret)

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

    def alghasse(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
        """
        cdef GEN _al = al.g
        pl = objtogen(pl)
        cdef GEN _pl = (<gen>pl).g
        pari_catch_sig_on()
        cdef GEN _ret = alghasse(_al, _pl)
        return pari_instance.new_gen(_ret)

    def alghassef(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`.
        
        ::
        
            ? 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])
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = alghassef(_al)
        return pari_instance.new_gen(_ret)

    def alghassei(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])
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = alghassei(_al)
        return pari_instance.new_gen(_ret)

    def algindex(al, pl=None):
        r"""
        Return 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_d(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
        """
        cdef GEN _al = al.g
        cdef GEN _pl = NULL
        if pl is not None:
            pl = objtogen(pl)
            _pl = (<gen>pl).g
        pari_catch_sig_on()
        cdef long _ret = algindex(_al, _pl)
        pari_instance.clear_stack()
        return _ret

    def alginit(B, C, v=None, long flag=1):
        r"""
        Initialize 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:`K[e_1,...,e_n]` describes a central simple algebra over :math:`K`; :math:`v` and :math:`flag`
          are ignored.
        
        ::
        
            { 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, 0;
             0, 0,-1, 0;
             0, 1, 0, 0;
             1, 0, 0,-1];
             A = alginit(nfinit(y), [matid(4), m_i,m_j,m_k], 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 :emphasis:`rnf` structure associated with 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 :emphasis:`nf`
          structure associated with 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 :emphasis:`nf` structure associated with 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
          (:emphasis:`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 associated with 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 :emphasis:`nf` structure associated
          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:`flag = 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 same splitting field :math:`L` in :literal:`nfinit` format.
        
        - 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:`{\\cal O}_0` expressed on the basis of the natural
          order, accessed with :literal:`algord`.
        
        - A basis of the natural order expressed on the basis of :math:`{\\cal O}_0`,
          accessed with :literal:`alginvord`.
        
        - The left multiplication table of :math:`{\\cal 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:`{\\cal 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:`{\cal B}` of :math:`A` expressed on the :math:`\mathbb{Z}`-basis of
          :math:`{\cal O}_0`, and a :literal:`t_MAT` representing the :math:`\mathbb{Z}`-basis of :math:`{\cal O}_0`
          expressed on :math:`{\cal B}`. This data is accessed with :literal:`algsplittingdata`.
        """
        cdef GEN _B = B.g
        C = objtogen(C)
        cdef GEN _C = (<gen>C).g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = alginit(_B, _C, _v, flag)
        return pari_instance.new_gen(_ret)

    def alginv(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`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = alginv(_al, _x)
        return pari_instance.new_gen(_ret)

    def alginvbasis(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:`{\\cal
        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]
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = alginvbasis(_al)
        return pari_instance.new_gen(_ret)

    def algisassociative(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).
        """
        cdef GEN _mt = mt.g
        cdef GEN _p
        if p is None:
            _p = gen_0
        else:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef int _ret = algisassociative(_mt, _p)
        pari_instance.clear_stack()
        return _ret

    def algiscommutative(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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef int _ret = algiscommutative(_al)
        pari_instance.clear_stack()
        return _ret

    def algisdivision(al, pl=None):
        r"""
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, test
        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
        test 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
        """
        cdef GEN _al = al.g
        cdef GEN _pl = NULL
        if pl is not None:
            pl = objtogen(pl)
            _pl = (<gen>pl).g
        pari_catch_sig_on()
        cdef int _ret = algisdivision(_al, _pl)
        pari_instance.clear_stack()
        return _ret

    def algisramified(al, pl=None):
        r"""
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, test
        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 test 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
        """
        cdef GEN _al = al.g
        cdef GEN _pl = NULL
        if pl is not None:
            pl = objtogen(pl)
            _pl = (<gen>pl).g
        pari_catch_sig_on()
        cdef int _ret = algisramified(_al, _pl)
        pari_instance.clear_stack()
        return _ret

    def algissemisimple(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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef int _ret = algissemisimple(_al)
        pari_instance.clear_stack()
        return _ret

    def algissimple(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 sum F_4+F_2
            ? algissimple(A)
            %13 = 0
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef int _ret = algissimple(_al, ss)
        pari_instance.clear_stack()
        return _ret

    def algissplit(al, pl=None):
        r"""
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, test
        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 test 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
        """
        cdef GEN _al = al.g
        cdef GEN _pl = NULL
        if pl is not None:
            pl = objtogen(pl)
            _pl = (<gen>pl).g
        pari_catch_sig_on()
        cdef int _ret = algissplit(_al, _pl)
        pari_instance.clear_stack()
        return _ret

    def algmul(al, x, y):
        r"""
        Given two elements :math:`x` and :math:`y` in :emphasis:`al`, computes their product :math:`x*y`
        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`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = algmul(_al, _x, _y)
        return pari_instance.new_gen(_ret)

    def algmultable(al, x=None):
        r"""
        Given an element :emphasis:`x` in :emphasis:`al`, computes its left multiplication
        table. If :emphasis:`x` is given in basis form, returns its multiplication table on
        the integral basis; if :emphasis:`x` is given in algebraic form, returns its
        multiplication table on the basis corresponding to the algebraic form of
        elements of :emphasis:`al`. In every case, if :emphasis:`x` is a :literal:`t_COL` of length :math:`n`,
        then the output is a :math:`n x n` :literal:`t_MAT`.
        Also accepts a square matrix with coefficients in :emphasis:`al`.
        
        If :emphasis:`x` is not set, 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:`{\\cal O}_0` stored in :emphasis:`al`.
        
        ::
        
            ? A = alginit(nfinit(y), [-1,-1]);
            ? algmultable(A,[0,1,0,0]~)
            %2 =
            [0 -1 1 0]
            
            [1 0 1 1]
            
            [0 0 1 1]
            
            [0 0 -2 -1]
        
        Another example:
        
        ::
        
            ? A = alginit(nfinit(y), [-1,-1]);
            ? M = algmultable(A);
            ? #M
            %3 = 4
            ? M[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]
        """
        cdef GEN _al = al.g
        cdef GEN _x = NULL
        if x is not None:
            x = objtogen(x)
            _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = gp_algmultable(_al, _x)
        return pari_instance.new_gen(_ret)

    def algneg(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`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = algneg(_al, _x)
        return pari_instance.new_gen(_ret)

    def algnorm(al, x):
        r"""
        Given an element :emphasis:`x` in :emphasis:`al`, computes its norm. If :emphasis:`al` is
        a table algebra output by :literal:`algtableinit`, 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`, 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
        
        Also accepts a square matrix with coefficients in :emphasis:`al`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = algnorm(_al, _x)
        return pari_instance.new_gen(_ret)

    def algpoleval(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`.
        """
        cdef GEN _al = al.g
        T = objtogen(T)
        cdef GEN _T = (<gen>T).g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        pari_catch_sig_on()
        cdef GEN _ret = algpoleval(_al, _T, _b)
        return pari_instance.new_gen(_ret)

    def algpow(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`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        n = objtogen(n)
        cdef GEN _n = (<gen>n).g
        pari_catch_sig_on()
        cdef GEN _ret = algpow(_al, _x, _n)
        return pari_instance.new_gen(_ret)

    def algprimesubalg(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]
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algprimesubalg(_al)
        return pari_instance.new_gen(_ret)

    def algquotient(al, I, long flag=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:`flag = 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
        """
        cdef GEN _al = al.g
        I = objtogen(I)
        cdef GEN _I = (<gen>I).g
        pari_catch_sig_on()
        cdef GEN _ret = alg_quotient(_al, _I, flag)
        return pari_instance.new_gen(_ret)

    def algradical(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)`, generated by :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}`, 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]
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algradical(_al)
        return pari_instance.new_gen(_ret)

    def algramifiedplaces(al):
        r"""
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, return 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]]
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algramifiedplaces(_al)
        return pari_instance.new_gen(_ret)

    def algrandom(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]`.
        """
        cdef GEN _al = al.g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        pari_catch_sig_on()
        cdef GEN _ret = algrandom(_al, _b)
        return pari_instance.new_gen(_ret)

    def algrelmultable(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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algrelmultable(_al)
        return pari_instance.new_gen(_ret)

    def algsimpledec(al, long flag=0):
        r"""
        :emphasis:`al` being the output of :literal:`algtableinit` representing a semisimple
        algebra, returns a :literal:`t_VEC` :math:`[al_1,al_2,...,al_n]` such
        that :emphasis:`al` is isomorphic to the direct sum of the simple algebras
        :math:`al_i`. When :math:`flag = 1`, each component is instead 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
        on the :math:`i`-th factor and a section of it.
        
        :strong:`Warning.` The images of the :math:`lift_i` are not guaranteed to form a direct sum.
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algsimpledec(_al, flag)
        return pari_instance.new_gen(_ret)

    def algsplittingdata(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]
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algsplittingdata(_al)
        return pari_instance.new_gen(_ret)

    def algsplittingfield(al):
        r"""
        Given a central simple algebra :emphasis:`al` output by :literal:`alginit`, returns
        an :emphasis:`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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef GEN _ret = algsplittingfield(_al)
        return pari_instance.new_gen(_ret)

    def algsplittingmatrix(al, x):
        r"""
        A central simple algebra :emphasis:`al` output by :literal:`alginit` contains data
        describing an isomorphism :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`. Returns
        the matrix :math:`\phi(x)`.
        
        ::
        
            ? A = alginit(nfinit(y), [-1,-1]);
            ? algsplittingmatrix(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)]
        
        Also accepts matrices with coefficients in :emphasis:`al`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = algsplittingmatrix(_al, _x)
        return pari_instance.new_gen(_ret)

    def algsqr(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`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = algsqr(_al, _x)
        return pari_instance.new_gen(_ret)

    def algsub(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`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = algsub(_al, _x, _y)
        return pari_instance.new_gen(_ret)

    def algsubalg(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, returns an
        algebra isomorphic to :emphasis:`B`.
        
        ::
        
            ? 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)
            %5 = 2
        """
        cdef GEN _al = al.g
        B = objtogen(B)
        cdef GEN _B = (<gen>B).g
        pari_catch_sig_on()
        cdef GEN _ret = algsubalg(_al, _B)
        return pari_instance.new_gen(_ret)

    def algtableinit(mt, p=None):
        r"""
        Initialize the associative algebra over :math:`K = \mathbb{Q}` (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]
        """
        cdef GEN _mt = mt.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = algtableinit(_mt, _p)
        return pari_instance.new_gen(_ret)

    def algtensor(al1, al2, long maxord=1):
        r"""
        Given two algebras :emphasis:`al1` and :emphasis:`al2`, computes their tensor
        product. For table algebras output by :literal:`algtableinit`, the flag
        :emphasis:`maxord` is ignored. For central simple algebras output by :literal:`alginit`,
        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`.
        """
        cdef GEN _al1 = al1.g
        al2 = objtogen(al2)
        cdef GEN _al2 = (<gen>al2).g
        pari_catch_sig_on()
        cdef GEN _ret = algtensor(_al1, _al2, maxord)
        return pari_instance.new_gen(_ret)

    def algtrace(al, x):
        r"""
        Given an element :emphasis:`x` in :emphasis:`al`, computes its trace. If :emphasis:`al` is
        a table algebra output by :literal:`algtableinit`, 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`, 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
        
        Also accepts a square matrix with coefficients in :emphasis:`al`.
        """
        cdef GEN _al = al.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = algtrace(_al, _x)
        return pari_instance.new_gen(_ret)

    def algtype(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
        """
        cdef GEN _al = al.g
        pari_catch_sig_on()
        cdef long _ret = algtype(_al)
        pari_instance.clear_stack()
        return _ret

    def allocatemem(s):
        r"""
        This special operation changes the stack size :emphasis:`after`
        initialization. :math:`x` must be a non-negative integer. If :math:`x > 0`, a new stack
        of at least :math:`x` bytes is allocated. We may allocate more than :math:`x` bytes if
        :math:`x` is way too small, or for alignment reasons: the current formula is
        :math:`\\max(16*ceil{x/16}, 500032)` bytes.
        
        If :math:`x = 0`, the size of the new stack is twice the size of the old one.
        
        This command is much more useful if :literal:`parisizemax` is non-zero, and we
        describe this case first. With :literal:`parisizemax` enabled, there are three
        sizes of interest:
        
        - a virtual stack size, :literal:`parisizemax`, which is an absolute upper
          limit for the stack size; this is set by :literal:`default(parisizemax, ...)`.
        
        - the desired typical stack size, :literal:`parisize`, that will grow as
          needed, up to :literal:`parisizemax`; this is set by :literal:`default(parisize, ...)`.
        
        - the current stack size, which is less that :literal:`parisizemax`,
          typically equal to :literal:`parisize` but possibly larger and increasing
          dynamically as needed; :literal:`allocatemem` allows to change that one
          explicitly.
        
        The :literal:`allocatemem` command forces stack
        usage to increase temporarily (up to :literal:`parisizemax` of course); for
        instance if you notice using :literal:`\\gm2` that we seem to collect garbage a
        lot, e.g.
        
        ::
        
            ? \gm2
             debugmem = 2
            ? default(parisize,"32M")
             *** Warning: new stack size = 32000000 (30.518 Mbytes).
            ? bnfinit('x^2+10^30-1)
             *** bnfinit: collecting garbage in hnffinal, i = 1.
             *** bnfinit: collecting garbage in hnffinal, i = 2.
             *** bnfinit: collecting garbage in hnffinal, i = 3.
        
        and so on for hundred of lines. Then, provided the
        :literal:`breakloop` default is set, you can interrupt the computation, type
        :literal:`allocatemem(100*10^6)` at the break loop prompt, then let the
        computation go on by typing :literal:` < Enter > `. Back at the :literal:`gp` prompt,
        the desired stack size of :literal:`parisize` is restored. Note that changing either
        :literal:`parisize` or :literal:`parisizemax` at the break loop prompt would interrupt
        the computation, contrary to the above.
        
        In most cases, :literal:`parisize` will increase automatically (up to
        :literal:`parisizemax`) and there is no need to perform the above maneuvers.
        But that the garbage collector is sufficiently efficient that
        a given computation can still run without increasing the stack size,
        albeit very slowly due to the frequent garbage collections.
        
        :strong:`Deprecated: when :literal:`parisizemax.` is unset`
        This is currently still the default behavior in order not to break backward
        compatibility. The rest of this section documents the
        behavior of :literal:`allocatemem` in that (deprecated) situation: it becomes a
        synonym for :literal:`default(parisize,...)`. In that case, there is no
        notion of a virtual stack, and the stack size is always equal to
        :literal:`parisize`. If more memory is needed, the PARI stack overflows, aborting
        the computation.
        
        Thus, increasing :literal:`parisize` via :literal:`allocatemem` or
        :literal:`default(parisize,...)` before a big computation is important.
        Unfortunately, either must be typed at the :literal:`gp` prompt in
        interactive usage, or left by itself at the start of batch files.
        They cannot be used meaningfully in loop-like constructs, or as part of a
        larger expression sequence, e.g
        
        ::
        
             allocatemem(); x = 1; \\ This will not set x!
        
        In fact, all loops are immediately exited, user functions terminated, and
        the rest of the sequence following :literal:`allocatemem()` is silently
        discarded, as well as all pending sequences of instructions. We just go on
        reading the next instruction sequence from the file we are in (or from the
        user). In particular, we have the following possibly unexpected behavior: in
        
        ::
        
             read("file.gp"); x = 1
        
        were :literal:`file.gp` contains an :literal:`allocatemem` statement,
        the :literal:`x = 1` is never executed, since all pending instructions in the
        current sequence are discarded.
        
        The reason for these unfortunate side-effects is that, with
        :literal:`parisizemax` disabled, increasing the stack size physically
        moves the stack, so temporary objects created during the current expression
        evaluation are not correct anymore. (In particular byte-compiled expressions,
        which are allocated on the stack.) To avoid accessing obsolete pointers to
        the old stack, this routine ends by a :literal:`longjmp`.
        """
        cdef GEN _s = s.g
        pari_catch_sig_on()
        gp_allocatemem(_s)
        pari_instance.clear_stack()

    def apply(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]
        """
        cdef GEN _f = f.g
        A = objtogen(A)
        cdef GEN _A = (<gen>A).g
        pari_catch_sig_on()
        cdef GEN _ret = apply0(_f, _A)
        return pari_instance.new_gen(_ret)

    def arg(x, long precision=0):
        r"""
        Argument of the complex number :math:`x`, such that :math:`-\Pi < {arg}(x) <= \Pi`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = garg(_x, precision)
        return pari_instance.new_gen(_ret)

    def asin(x, long precision=0):
        r"""
        Principal branch of :math:`{sin}^{-1}(x) = -i \log(ix + \sqrt{1 - x^2})`.
        In particular, :math:`{Re(asin}(x)) belongs to [-\Pi/2,\Pi/2]` and if :math:`x belongs to \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)`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gasin(_x, precision)
        return pari_instance.new_gen(_ret)

    def asinh(x, long precision=0):
        r"""
        Principal branch of :math:`{sinh}^{-1}(x) = \log(x + \sqrt{1+x^2})`. In
        particular :math:`{Im(asinh}(x)) belongs to [-\Pi/2,\Pi/2]`.
        The branch cut is in two pieces: [-i oo ,-i], continuous with quadrant III
        and [i,+i oo [ continuous with quadrant I.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gasinh(_x, precision)
        return pari_instance.new_gen(_ret)

    def atan(x, long precision=0):
        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:`i {atan}(x) = 
        -i{atanh}(ix)` for all :math:`x != ± i`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gatan(_x, precision)
        return pari_instance.new_gen(_ret)

    def atanh(x, long precision=0):
        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 belongs to \mathbb{R}` and :math:`\|x\| > 1` then :math:`{atanh}(x)` is complex.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gatanh(_x, precision)
        return pari_instance.new_gen(_ret)

    def besselh1(nu, x, long precision=0):
        r"""
        :math:`H^1`-Bessel function of index :emphasis:`nu` and argument :math:`x`.
        """
        cdef GEN _nu = nu.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = hbessel1(_nu, _x, precision)
        return pari_instance.new_gen(_ret)

    def besselh2(nu, x, long precision=0):
        r"""
        :math:`H^2`-Bessel function of index :emphasis:`nu` and argument :math:`x`.
        """
        cdef GEN _nu = nu.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = hbessel2(_nu, _x, precision)
        return pari_instance.new_gen(_ret)

    def besseli(nu, x, long precision=0):
        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).
        """
        cdef GEN _nu = nu.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ibessel(_nu, _x, precision)
        return pari_instance.new_gen(_ret)

    def besselj(nu, x, long precision=0):
        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).
        """
        cdef GEN _nu = nu.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = jbessel(_nu, _x, precision)
        return pari_instance.new_gen(_ret)

    def besseljh(n, x, long precision=0):
        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.8.0`, this function is not very accurate when :math:`x` is small.
        """
        cdef GEN _n = n.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = jbesselh(_n, _x, precision)
        return pari_instance.new_gen(_ret)

    def besselk(nu, x, long precision=0):
        r"""
        :math:`K`-Bessel function of index :emphasis:`nu` and argument :math:`x`.
        """
        cdef GEN _nu = nu.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = kbessel(_nu, _x, precision)
        return pari_instance.new_gen(_ret)

    def besseln(nu, x, long precision=0):
        r"""
        :math:`N`-Bessel function of index :emphasis:`nu` and argument :math:`x`.
        """
        cdef GEN _nu = nu.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = nbessel(_nu, _x, precision)
        return pari_instance.new_gen(_ret)

    def bestappr(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:`[]`.
        """
        cdef GEN _x = x.g
        cdef GEN _B = NULL
        if B is not None:
            B = objtogen(B)
            _B = (<gen>B).g
        pari_catch_sig_on()
        cdef GEN _ret = bestappr(_x, _B)
        return pari_instance.new_gen(_ret)

    def bestapprPade(x, long B=-1):
        r"""
        Using variants of the extended Euclidean algorithm, 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_RFRAC` or :literal:`t_SER`, this function uses continued
          fractions.
        
        ::
        
            ? bestapprPade((1-x^11)/(1-x)+O(x^11))
            %1 = 1/(-x + 1)
            ? bestapprPade([1/(1+x+O(x^10)), (x^3-2)/(x^3+1)], 1)
            %2 = [1/(x + 1), -2]
        
        - If :math:`x` is a :literal:`t_POLMOD` modulo :math:`N` or a :literal:`t_SER` of precision :math:`N = 
          t^k`, 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` which is congruent to :math:`x` modulo
          :math:`N`. Omitting :math:`B` amounts to choosing it of the order of :math:`N/2`. If rational
          reconstruction is not possible (no suitable :math:`a/b` exists), returns :math:`[]`.
        
        ::
        
            ? bestapprPade(Mod(1+x+x^2+x^3+x^4, x^4-2))
            %1 = (2*x - 1)/(x - 1)
            ? % * Mod(1,x^4-2)
            %2 = Mod(x^3 + x^2 + x + 3, x^4 - 2)
            ? bestapprPade(Mod(1+x+x^2+x^3+x^5, x^9))
            %2 = []
            ? bestapprPade(Mod(1+x+x^2+x^3+x^5, x^10))
            %3 = (2*x^4 + x^3 - x - 1)/(-x^5 + x^3 + x^2 - 1)
        
        The function applies recursively to components of complex objects
        (polynomials, vectors,...). If rational reconstruction fails for even a
        single entry, return :math:`[]`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = bestapprPade(_x, B)
        return pari_instance.new_gen(_ret)

    def bezout(x, y):
        r"""
        Deprecated alias for :literal:`gcdext`
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = gcdext0(_x, _y)
        return pari_instance.new_gen(_ret)

    def bezoutres(A, B, v=None):
        r"""
        Deprecated alias for :literal:`polresultantext`
        """
        cdef GEN _A = A.g
        B = objtogen(B)
        cdef GEN _B = (<gen>B).g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = polresultantext0(_A, _B, _v)
        return pari_instance.new_gen(_ret)

    def bigomega(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = bigomega(_x)
        pari_instance.clear_stack()
        return _ret

    def binary(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = binaire(_x)
        return pari_instance.new_gen(_ret)

    def binomial(x, long y):
        r"""
        binomial coefficient :math:`binom{x}{y}`.
        Here :math:`y` must be an integer, but :math:`x` can be any PARI object.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = binomial(_x, y)
        return pari_instance.new_gen(_ret)

    def bitand(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
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = gbitand(_x, _y)
        return pari_instance.new_gen(_ret)

    def bitneg(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gbitneg(_x, n)
        return pari_instance.new_gen(_ret)

    def bitnegimply(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = gbitnegimply(_x, _y)
        return pari_instance.new_gen(_ret)

    def bitor(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = gbitor(_x, _y)
        return pari_instance.new_gen(_ret)

    def bittest(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, 3)
            %1 = 1 \\ the 3rd bit is 1
            ? bittest(7, 4)
            %2 = 0 \\ the 4th bit is 0
        
        See ``bitand`` (in the PARI manual) for the behavior at negative arguments.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gbittest(_x, n)
        return pari_instance.new_gen(_ret)

    def bitxor(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = gbitxor(_x, _y)
        return pari_instance.new_gen(_ret)

    def bnfcertify(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
        """
        cdef GEN _bnf = bnf.g
        pari_catch_sig_on()
        cdef long _ret = bnfcertify0(_bnf, flag)
        pari_instance.clear_stack()
        return _ret

    def bnfcompress(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]`.
        """
        cdef GEN _bnf = bnf.g
        pari_catch_sig_on()
        cdef GEN _ret = bnfcompress(_bnf)
        return pari_instance.new_gen(_ret)

    def bnfdecodemodule(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[1][2]
            %1 = [[Mat([8, 1]), [[0, 0, 0]]], [Mat([9, 1]), [[0, 0, 0]]]]
            ? bnfdecodemodule(K, s[1][1])
            %2 =
            [2 0]
            
            [0 1]
        """
        cdef GEN _nf = nf.g
        m = objtogen(m)
        cdef GEN _m = (<gen>m).g
        pari_catch_sig_on()
        cdef GEN _ret = decodemodule(_nf, _m)
        return pari_instance.new_gen(_ret)

    def bnfinit(P, long flag=0, tech=None, long precision=0):
        r"""
        Initializes a
        :emphasis:`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).
        """
        cdef GEN _P = P.g
        cdef GEN _tech = NULL
        if tech is not None:
            tech = objtogen(tech)
            _tech = (<gen>tech).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = bnfinit0(_P, flag, _tech, precision)
        return pari_instance.new_gen(_ret)

    def bnfisintnorm(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`.
        """
        cdef GEN _bnf = bnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = bnfisintnorm(_bnf, _x)
        return pari_instance.new_gen(_ret)

    def bnfisnorm(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`.
        """
        cdef GEN _bnf = bnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = bnfisnorm(_bnf, _x, flag)
        return pari_instance.new_gen(_ret)

    def bnfisprincipal(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 :literal:`bnf` 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:`very` lengthy computations.
        """
        cdef GEN _bnf = bnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = bnfisprincipal0(_bnf, _x, flag)
        return pari_instance.new_gen(_ret)

    def bnfissunit(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.
        If :math:`x` is not a unit, outputs an empty vector.
        """
        cdef GEN _bnf = bnf.g
        sfu = objtogen(sfu)
        cdef GEN _sfu = (<gen>sfu).g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = bnfissunit(_bnf, _sfu, _x)
        return pari_instance.new_gen(_ret)

    def bnfisunit(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.)
        """
        cdef GEN _bnf = bnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = bnfisunit(_bnf, _x)
        return pari_instance.new_gen(_ret)

    def bnfnarrow(bnf):
        r"""
        :math:`bnf` being as output by
        :literal:`bnfinit`, computes the narrow class group of :math:`bnf`. The output is
        a 3-component row vector :math:`v` analogous to the corresponding class group
        component :literal:`:emphasis:`bnf`.clgp` (:literal:`:emphasis:`bnf`[8][1]`): 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`.
        """
        cdef GEN _bnf = bnf.g
        pari_catch_sig_on()
        cdef GEN _ret = buchnarrow(_bnf)
        return pari_instance.new_gen(_ret)

    def bnfsignunit(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(S,d,K);
            
             S = bnfsignunit(bnf); d = matsize(S);
             S = matrix(d[1],d[2], i,j, if (S[i,j] < 0, 1,0));
             S = concat(vectorv(d[1],i,1), S); \\ add sign(-1)
             K = lift(matker(S * Mod(1,2)));
             if (K, mathnfmodid(K, 2), 2*matid(d[1]))
            }
            
            /* totally positive units */
            tpu(bnf)=
            { my(vu = bnf.tufu, ex = tpuexpo(bnf));
            
             vector(#ex-1, i, factorback(vu, ex[,i+1])) \\ ex[,1] is 1
            }
        """
        cdef GEN _bnf = bnf.g
        pari_catch_sig_on()
        cdef GEN _ret = signunits(_bnf)
        return pari_instance.new_gen(_ret)

    def bnfsunit(bnf, S, long precision=0):
        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`.
        """
        cdef GEN _bnf = bnf.g
        S = objtogen(S)
        cdef GEN _S = (<gen>S).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = bnfsunit(_bnf, _S, precision)
        return pari_instance.new_gen(_ret)

    def bnrL1(bnr, H=None, long flag=0, long precision=0):
        r"""
        Let :emphasis:`bnr` be the number field data output by :literal:`bnrinit(,,1)` 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 associated 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 associated 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,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,1);
            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).
        """
        cdef GEN _bnr = bnr.g
        cdef GEN _H = NULL
        if H is not None:
            H = objtogen(H)
            _H = (<gen>H).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = bnrL1(_bnr, _H, flag, precision)
        return pari_instance.new_gen(_ret)

    def bnrclassno(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 associated :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.
        """
        cdef GEN _A = A.g
        cdef GEN _B = NULL
        if B is not None:
            B = objtogen(B)
            _B = (<gen>B).g
        cdef GEN _C = NULL
        if C is not None:
            C = objtogen(C)
            _C = (<gen>C).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrclassno0(_A, _B, _C)
        return pari_instance.new_gen(_ret)

    def bnrclassnolist(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
        """
        cdef GEN _bnf = bnf.g
        list = objtogen(list)
        cdef GEN _list = (<gen>list).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrclassnolist(_bnf, _list)
        return pari_instance.new_gen(_ret)

    def bnrconductor(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,1)`.
        """
        cdef GEN _A = A.g
        cdef GEN _B = NULL
        if B is not None:
            B = objtogen(B)
            _B = (<gen>B).g
        cdef GEN _C = NULL
        if C is not None:
            C = objtogen(C)
            _C = (<gen>C).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrconductor0(_A, _B, _C, flag)
        return pari_instance.new_gen(_ret)

    def bnrconductorofchar(bnr, chi):
        r"""
        :emphasis:`bnr` being a big
        ray number field as output by :literal:`bnrinit`, and :emphasis:`chi` being a row vector
        representing a character as expressed on the generators of the ray
        class group, gives the conductor of this character as a modulus.
        """
        cdef GEN _bnr = bnr.g
        chi = objtogen(chi)
        cdef GEN _chi = (<gen>chi).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrconductorofchar(_bnr, _chi)
        return pari_instance.new_gen(_ret)

    def bnrdisc(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:`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.
        """
        cdef GEN _A = A.g
        cdef GEN _B = NULL
        if B is not None:
            B = objtogen(B)
            _B = (<gen>B).g
        cdef GEN _C = NULL
        if C is not None:
            C = objtogen(C)
            _C = (<gen>C).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrdisc0(_A, _B, _C, flag)
        return pari_instance.new_gen(_ret)

    def bnrdisclist(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 of vectors, where :math:`v[i][j]` is understood to be in
        fact :math:`V[2^{15}(i-1)+j]` of a unique big vector :math:`V`. (This awkward scheme
        allows for larger vectors than could be otherwise represented.)
        
        :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 associated 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` is more efficient.
        """
        cdef GEN _bnf = bnf.g
        bound = objtogen(bound)
        cdef GEN _bound = (<gen>bound).g
        cdef GEN _arch = NULL
        if arch is not None:
            arch = objtogen(arch)
            _arch = (<gen>arch).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrdisclist0(_bnf, _bound, _arch)
        return pari_instance.new_gen(_ret)

    def bnrgaloisapply(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`.
        """
        cdef GEN _bnr = bnr.g
        mat = objtogen(mat)
        cdef GEN _mat = (<gen>mat).g
        H = objtogen(H)
        cdef GEN _H = (<gen>H).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrgaloisapply(_bnr, _mat, _H)
        return pari_instance.new_gen(_ret)

    def bnrgaloismatrix(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.
        """
        cdef GEN _bnr = bnr.g
        aut = objtogen(aut)
        cdef GEN _aut = (<gen>aut).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrgaloismatrix(_bnr, _aut)
        return pari_instance.new_gen(_ret)

    def bnrinit(bnf, f, long flag=0):
        r"""
        :math:`bnf` is as
        output by :literal:`bnfinit`, :math:`f` is a modulus, initializes data linked to
        the ray class group structure corresponding to this module, a so-called
        :emphasis:`bnr` structure. One can input the associated :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 :emphasis:`bid` structure associated 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.
        """
        cdef GEN _bnf = bnf.g
        f = objtogen(f)
        cdef GEN _f = (<gen>f).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrinit0(_bnf, _f, flag)
        return pari_instance.new_gen(_ret)

    def bnrisconductor(A, B=None, C=None):
        r"""
        :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`.
        """
        cdef GEN _A = A.g
        cdef GEN _B = NULL
        if B is not None:
            B = objtogen(B)
            _B = (<gen>B).g
        cdef GEN _C = NULL
        if C is not None:
            C = objtogen(C)
            _C = (<gen>C).g
        pari_catch_sig_on()
        cdef long _ret = bnrisconductor0(_A, _B, _C)
        pari_instance.clear_stack()
        return _ret

    def bnrisgalois(bnr, gal, H):
        r"""
        Check whether the class field associated 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 associated 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.
        """
        cdef GEN _bnr = bnr.g
        gal = objtogen(gal)
        cdef GEN _gal = (<gen>gal).g
        H = objtogen(H)
        cdef GEN _H = (<gen>H).g
        pari_catch_sig_on()
        cdef long _ret = bnrisgalois(_bnr, _gal, _H)
        pari_instance.clear_stack()
        return _ret

    def bnrisprincipal(bnr, x, long flag=1):
        r"""
        :emphasis:`bnr` being the
        number field data which is output by :literal:`bnrinit`:math:`(,,1)` and :math:`x` being an
        ideal in any form, outputs the components of :math:`x` on the ray class group
        generators in a way similar to :literal:`bnfisprincipal`. That is 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]` gives on the integral basis an element :math:`\alpha` such
        that :math:`x = \alpha\prod_ig_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)`
        If :math:`x` is not coprime to the modulus of :emphasis:`bnr` the result is undefined.
        """
        cdef GEN _bnr = bnr.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = bnrisprincipal(_bnr, _x, flag)
        return pari_instance.new_gen(_ret)

    def bnrrootnumber(bnr, chi, long flag=0, long precision=0):
        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 associated
        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 associated to :math:`L`.
        
        The generators of the ray class group are needed, and 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]], 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).
        """
        cdef GEN _bnr = bnr.g
        chi = objtogen(chi)
        cdef GEN _chi = (<gen>chi).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = bnrrootnumber(_bnr, _chi, flag, precision)
        return pari_instance.new_gen(_ret)

    def bnrstark(bnr, subgroup=None, long precision=0):
        r"""
        :emphasis:`bnr` being as output by :literal:`bnrinit(,,1)`, 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, 1);
            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, 1);
            ? 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)
        """
        cdef GEN _bnr = bnr.g
        cdef GEN _subgroup = NULL
        if subgroup is not None:
            subgroup = objtogen(subgroup)
            _subgroup = (<gen>subgroup).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = bnrstark(_bnr, _subgroup, precision)
        return pari_instance.new_gen(_ret)

    def ceil(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gceil(_x)
        return pari_instance.new_gen(_ret)

    def centerlift(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 belongs to \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)`.
        """
        cdef GEN _x = x.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = centerlift0(_x, _v)
        return pari_instance.new_gen(_ret)

    def characteristic(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = characteristic(_x)
        return pari_instance.new_gen(_ret)

    def charpoly(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`).
        """
        cdef GEN _A = A.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = charpoly0(_A, _v, flag)
        return pari_instance.new_gen(_ret)

    def chinese(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.
        """
        cdef GEN _x = x.g
        cdef GEN _y = NULL
        if y is not None:
            y = objtogen(y)
            _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = chinese(_x, _y)
        return pari_instance.new_gen(_ret)

    def cmp(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`, and its
        restriction to integers coincides with the customary one. Besides that,
        it has no useful mathematical meaning.
        
        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)`.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef int _ret = cmp_universal(_x, _y)
        pari_instance.clear_stack()
        return _ret

    def component(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = compo(_x, n)
        return pari_instance.new_gen(_ret)

    def concat(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]
        """
        cdef GEN _x = x.g
        cdef GEN _y = NULL
        if y is not None:
            y = objtogen(y)
            _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = concat(_x, _y)
        return pari_instance.new_gen(_ret)

    def conj(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).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gconj(_x)
        return pari_instance.new_gen(_ret)

    def conjvec(z, long precision=0):
        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`.
        """
        cdef GEN _z = z.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = conjvec(_z, precision)
        return pari_instance.new_gen(_ret)

    def content(x):
        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 in :math:`[-2^{BIL-1}, 2^{BIL-1}[`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = content(_x)
        return pari_instance.new_gen(_ret)

    def contfrac(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`)`.
        """
        cdef GEN _x = x.g
        cdef GEN _b = NULL
        if b is not None:
            b = objtogen(b)
            _b = (<gen>b).g
        pari_catch_sig_on()
        cdef GEN _ret = contfrac0(_x, _b, nmax)
        return pari_instance.new_gen(_ret)

    def contfraceval(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`.
        """
        cdef GEN _CF = CF.g
        t = objtogen(t)
        cdef GEN _t = (<gen>t).g
        pari_catch_sig_on()
        cdef GEN _ret = contfraceval(_CF, _t, lim)
        return pari_instance.new_gen(_ret)

    def contfracinit(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.
        """
        cdef GEN _M = M.g
        pari_catch_sig_on()
        cdef GEN _ret = contfracinit(_M, lim)
        return pari_instance.new_gen(_ret)

    def contfracpnqn(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,20)
            %1 = [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1, 1, 2, 2, 2, 2]
            ? contfracpnqn(a,3)
            %2 =
            [3 22 333 355]
            
            [1 7 106 113]
            
            ? contfracpnqn(a,7)
            %3 =
            [3 22 333 355 103993 104348 208341 312689]
            
            [1 7 106 113 33102 33215 66317 99532]
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = contfracpnqn(_x, n)
        return pari_instance.new_gen(_ret)

    def core(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]`.
        """
        cdef GEN _n = n.g
        pari_catch_sig_on()
        cdef GEN _ret = core0(_n, flag)
        return pari_instance.new_gen(_ret)

    def coredisc(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 belongs to \mathbb{Q}^*`.
        """
        cdef GEN _n = n.g
        pari_catch_sig_on()
        cdef GEN _ret = coredisc0(_n, flag)
        return pari_instance.new_gen(_ret)

    def cos(x, long precision=0):
        r"""
        Cosine of :math:`x`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gcos(_x, precision)
        return pari_instance.new_gen(_ret)

    def cosh(x, long precision=0):
        r"""
        Hyperbolic cosine of :math:`x`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gcosh(_x, precision)
        return pari_instance.new_gen(_ret)

    def cotan(x, long precision=0):
        r"""
        Cotangent of :math:`x`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gcotan(_x, precision)
        return pari_instance.new_gen(_ret)

    def denominator(x):
        r"""
        Denominator of :math:`x`. The meaning of this
        is clear when :math:`x` is a rational number or function. If :math:`x` 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(x) )
        
        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 (minimal degree) polynomial representative.
        
        If :math:`x` 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).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = denom(_x)
        return pari_instance.new_gen(_ret)

    def deriv(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`.
        """
        cdef GEN _x = x.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = deriv(_x, _v)
        return pari_instance.new_gen(_ret)

    def diffop(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))
            }
        """
        cdef GEN _x = x.g
        v = objtogen(v)
        cdef GEN _v = (<gen>v).g
        d = objtogen(d)
        cdef GEN _d = (<gen>d).g
        pari_catch_sig_on()
        cdef GEN _ret = diffop0(_x, _v, _d, n)
        return pari_instance.new_gen(_ret)

    def digits(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.
        See :literal:`fromdigits` for the reverse operation.
        """
        cdef GEN _x = x.g
        cdef GEN _b = NULL
        if b is not None:
            b = objtogen(b)
            _b = (<gen>b).g
        pari_catch_sig_on()
        cdef GEN _ret = digits(_x, _b)
        return pari_instance.new_gen(_ret)

    def dilog(x, long precision=0):
        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`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = dilog(_x, precision)
        return pari_instance.new_gen(_ret)

    def dirdiv(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = dirdiv(_x, _y)
        return pari_instance.new_gen(_ret)

    def dirmul(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]
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = dirmul(_x, _y)
        return pari_instance.new_gen(_ret)

    def dirzetak(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.
        """
        cdef GEN _nf = nf.g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        pari_catch_sig_on()
        cdef GEN _ret = dirzetak(_nf, _b)
        return pari_instance.new_gen(_ret)

    def divisors(x):
        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.
        
        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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = divisors(_x)
        return pari_instance.new_gen(_ret)

    def divrem(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)
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = divrem(_x, _y, _v)
        return pari_instance.new_gen(_ret)

    def eint1(x, n=None, long precision=0):
        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.
        """
        cdef GEN _x = x.g
        cdef GEN _n = NULL
        if n is not None:
            n = objtogen(n)
            _n = (<gen>n).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = veceint1(_x, _n, precision)
        return pari_instance.new_gen(_ret)

    def ellL1(e, long r=0, long precision=0):
        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[...]
        """
        cdef GEN _e = e.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellL1(_e, r, precision)
        return pari_instance.new_gen(_ret)

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

    def ellak(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 :emphasis:`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([0,1]);
            ? ellak(E, 10)
            %2 = 0
            ? e = ellinit([5^4,5^6]); \\ not minimal at 5
            ? ellak(e, 5) \\ 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 = 820 ms.
            ? for(i=1,10^6, ellak(e,5)) \\ 5 is bad, markedly slower
            time = 1,249 ms.
            
            ? for(i=1,10^5,ellak(E,5*i))
            time = 977 ms.
            ? for(i=1,10^5,ellak(e,5*i)) \\ still slower but not so much on average
            time = 1,008 ms.
        """
        cdef GEN _E = E.g
        n = objtogen(n)
        cdef GEN _n = (<gen>n).g
        pari_catch_sig_on()
        cdef GEN _ret = akell(_E, _n)
        return pari_instance.new_gen(_ret)

    def ellan(E, long n):
        r"""
        Computes the vector of the first :math:`n` Fourier coefficients :math:`a_k`
        corresponding to the elliptic curve :math:`E`. The curve must be given by an
        integral model, not necessarily minimal, although a minimal model will make
        the function faster.
        """
        cdef GEN _E = E.g
        pari_catch_sig_on()
        cdef GEN _ret = anell(_E, n)
        return pari_instance.new_gen(_ret)

    def ellanalyticrank(e, eps=None, long precision=0):
        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 no value of :literal:`eps` is given, a value of half the current
        precision is used.
        
        ::
        
            ? 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]
        """
        cdef GEN _e = e.g
        cdef GEN _eps = NULL
        if eps is not None:
            eps = objtogen(eps)
            _eps = (<gen>eps).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellanalyticrank(_e, _eps, precision)
        return pari_instance.new_gen(_ret)

    def ellap(E, p=None):
        r"""
        Let :math:`E` be an :emphasis:`ell` structure as output by :literal:`ellinit`, defined over
        :math:`\mathbb{Q}` or a finite field :math:`\mathbb{F}_q`. The argument :math:`p` is best left omitted if the
        curve is defined over a finite field, and must be a prime number otherwise.
        This function computes the trace of Frobenius :math:`t` for the elliptic curve :math:`E`,
        defined by the equation :math:`\#E(\mathbb{F}_q) = q+1 - t`.
        
        If the curve is defined over :math:`\mathbb{Q}`, :math:`p` must be explicitly given and the
        function computes the trace of the reduction over :math:`\mathbb{F}_p`.
        The trace of Frobenius is also the :math:`a_p` coefficient in the curve :math:`L`-series
        :math:`L(E,s) = \sum_n a_n n^{-s}`, whence the function name. The equation must be
        integral at :math:`p` but need not be minimal at :math:`p`; of course, a minimal model
        will be more efficient.
        
        ::
        
            ? 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
            
            ? Fq = ffgen(ffinit(11,3), 'a); \\ defines F_q := F_{11^3}
            ? E = ellinit([a+1,a], Fq); \\ y^2 = x^3 + (a+1)x + a, defined over F_q
            ? ellap(E)
            %8 = -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`.
        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. If the :literal:`seadata` package is
        installed, the :literal:`SEA` algorithm becomes available, heuristically in
        :math:`~{O}(\log q)^4`, and primes of the order of 200 digits become feasible.
        In very small characteristic (2,3,5,7 or :math:`13`), we use Harley's algorithm.
        """
        cdef GEN _E = E.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = ellap(_E, _p)
        return pari_instance.new_gen(_ret)

    def ellbil(E, z1, z2, long precision=0):
        r"""
        Deprecated alias for :literal:`ellheight(E,P,Q)`.
        """
        cdef GEN _E = E.g
        z1 = objtogen(z1)
        cdef GEN _z1 = (<gen>z1).g
        z2 = objtogen(z2)
        cdef GEN _z2 = (<gen>z2).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = bilhell(_E, _z1, _z2, precision)
        return pari_instance.new_gen(_ret)

    def ellcard(E, p=None):
        r"""
        Let :math:`E` be an :emphasis:`ell` structure as output by :literal:`ellinit`, defined over
        :math:`\mathbb{Q}` or a finite field :math:`\mathbb{F}_q`. The argument :math:`p` is best left omitted if the
        curve is defined over a finite field, and must be a prime number otherwise.
        This function computes the order of the group :math:`E(\mathbb{F}_q)` (as would be
        computed by :literal:`ellgroup`).
        
        If the curve is defined over :math:`\mathbb{Q}`, :math:`p` must be explicitly given and the
        function computes the cardinality of the reduction over :math:`\mathbb{F}_p`; the
        equation need not be minimal at :math:`p`, but a minimal model will be more
        efficient. The reduction is allowed to be singular, and we return the order
        of the group of non-singular points in this case.
        """
        cdef GEN _E = E.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = ellcard(_E, _p)
        return pari_instance.new_gen(_ret)

    def ellchangecurve(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 :emphasis:`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.
        """
        cdef GEN _E = E.g
        v = objtogen(v)
        cdef GEN _v = (<gen>v).g
        pari_catch_sig_on()
        cdef GEN _ret = ellchangecurve(_E, _v)
        return pari_instance.new_gen(_ret)

    def ellchangepoint(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]
        """
        cdef GEN _x = x.g
        v = objtogen(v)
        cdef GEN _v = (<gen>v).g
        pari_catch_sig_on()
        cdef GEN _ret = ellchangepoint(_x, _v)
        return pari_instance.new_gen(_ret)

    def ellchangepointinv(x, v):
        r"""
        Changes the coordinates of the point or vector of points :math:`x` using
        the inverse of the isomorphism associated 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
        """
        cdef GEN _x = x.g
        v = objtogen(v)
        cdef GEN _v = (<gen>v).g
        pari_catch_sig_on()
        cdef GEN _ret = ellchangepointinv(_x, _v)
        return pari_instance.new_gen(_ret)

    def ellconvertname(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"
        """
        cdef GEN _name = name.g
        pari_catch_sig_on()
        cdef GEN _ret = ellconvertname(_name)
        return pari_instance.new_gen(_ret)

    def elldivpol(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]`.
        """
        cdef GEN _E = E.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = elldivpol(_E, n, _v)
        return pari_instance.new_gen(_ret)

    def elleisnum(w, long k, long flag=0, long precision=0):
        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`.
        """
        cdef GEN _w = w.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = elleisnum(_w, k, flag, precision)
        return pari_instance.new_gen(_ret)

    def elleta(w, long precision=0):
        r"""
        Returns the quasi-periods :math:`[\eta_1,\eta_2]`
        associated 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 associated 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]
        """
        cdef GEN _w = w.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = elleta(_w, precision)
        return pari_instance.new_gen(_ret)

    def ellformaldifferential(E, long serprec=-1, n=None):
        r"""
        Let :math:`\omega := dx / (2y+a_1x+a_3` be the invariant differential form
        associated 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)
        """
        cdef GEN _E = E.g
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        cdef long _n = -1
        if n is not None:
            _n = pari_instance.get_var(n)
        pari_catch_sig_on()
        cdef GEN _ret = ellformaldifferential(_E, serprec, _n)
        return pari_instance.new_gen(_ret)

    def ellformalexp(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)
        """
        cdef GEN _E = E.g
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        cdef long _n = -1
        if n is not None:
            _n = pari_instance.get_var(n)
        pari_catch_sig_on()
        cdef GEN _ret = ellformalexp(_E, serprec, _n)
        return pari_instance.new_gen(_ret)

    def ellformallog(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)
        """
        cdef GEN _E = E.g
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        cdef long _n = -1
        if n is not None:
            _n = pari_instance.get_var(n)
        pari_catch_sig_on()
        cdef GEN _ret = ellformallog(_E, serprec, _n)
        return pari_instance.new_gen(_ret)

    def ellformalpoint(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);
            ? x
            %2 = x^-2 - x + x^2 - x^4 + 2*x^5 + O(x^6)
            ? y
            %3 = -x^-3 + 1 - x + x^3 - 2*x^4 + O(x^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)]
        """
        cdef GEN _E = E.g
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        cdef long _n = -1
        if n is not None:
            _n = pari_instance.get_var(n)
        pari_catch_sig_on()
        cdef GEN _ret = ellformalpoint(_E, serprec, _n)
        return pari_instance.new_gen(_ret)

    def ellformalw(E, long serprec=-1, n=None):
        r"""
        Return the formal power series :math:`w` associated 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)
        """
        cdef GEN _E = E.g
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        cdef long _n = -1
        if n is not None:
            _n = pari_instance.get_var(n)
        pari_catch_sig_on()
        cdef GEN _ret = ellformalw(_E, serprec, _n)
        return pari_instance.new_gen(_ret)

    def ellfromeqn(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 Edward
        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);
            ? ellcard(E)
            %2 = 57896044618658097711785492504343953926856930875039260848015607506283634007912
        
        The elliptic curve associated to the sum of two cubes is given by
        
        ::
        
            ? ellfromeqn(x^3+y^3-a)
            %1 = [0,0,-9*a,0,-27*a^2]
        
        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`.
        
        ::
        
            ? 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([0,0,0,-16*n^2,0],n,23)))
            %2 = [168100/289,68053440/4913]
        """
        cdef GEN _P = P.g
        pari_catch_sig_on()
        cdef GEN _ret = ellfromeqn(_P)
        return pari_instance.new_gen(_ret)

    def ellfromj(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`.
        """
        cdef GEN _j = j.g
        pari_catch_sig_on()
        cdef GEN _ret = ellfromj(_j)
        return pari_instance.new_gen(_ret)

    def ellgenerators(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 associated 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)`.
        """
        cdef GEN _E = E.g
        pari_catch_sig_on()
        cdef GEN _ret = ellgenerators(_E)
        return pari_instance.new_gen(_ret)

    def ellglobalred(E):
        r"""
        Calculates the arithmetic conductor, the global
        minimal model of :math:`E` and the global Tamagawa number :math:`c`.
        :math:`E` must be an :emphasis:`ell` structure as output by :literal:`ellinit`, defined over
        :math:`\mathbb{Q}`. The result is a vector :math:`[N,v,c,F,L]`, where
        
        - :math:`N` is the arithmetic conductor of the curve,
        
        - :math:`v` gives the coordinate change for :math:`E` over :math:`\mathbb{Q}` to the minimal
          integral model (see :literal:`ellminimalmodel`),
        
        - :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` over :math:`\mathbb{Z}`.
        
        - :math:`L` is a vector, whose :math:`i`-th entry contains the local data
          at the :math:`i`-th prime divisor of :math:`N`, i.e. :literal:`L[i] = elllocalred(E,F[i,1])`,
          where the local coordinate change has been deleted, and replaced by a :math:`0`.
        """
        cdef GEN _E = E.g
        pari_catch_sig_on()
        cdef GEN _ret = ellglobalred(_E)
        return pari_instance.new_gen(_ret)

    def ellgroup(E, p=None, long flag=0):
        r"""
        Let :math:`E` be an :emphasis:`ell` structure as output by :literal:`ellinit`, defined over
        :math:`\mathbb{Q}` or a finite field :math:`\mathbb{F}_q`. The argument :math:`p` is best left omitted if the
        curve is defined over a finite field, and must be a prime number otherwise.
        This function computes the structure of the group :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 the curve is defined over :math:`\mathbb{Q}`, :math:`p` must be explicitly given and the
        function computes the structure of the reduction over :math:`\mathbb{F}_p`; the
        equation need not be minimal at :math:`p`, but a minimal model will be more
        efficient. The reduction is allowed to be singular, and we return the
        structure of the (cyclic) group of non-singular points in this case.
        
        If the flag is :math:`0` (default), return :math:`[d_1]` or :math:`[d_1, d_2]`, if :math:`d_2 > 1`.
        If the flag is :math:`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(E, P, Q, d1)` has order :math:`d_2`.
        
        ::
        
            ? 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)]]]
        
        If :math:`E` is defined over :math:`\mathbb{Q}`, we allow singular reduction and in this case we
        return the structure of the 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
        """
        cdef GEN _E = E.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = ellgroup0(_E, _p, flag)
        return pari_instance.new_gen(_ret)

    def ellheegner(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.
        """
        cdef GEN _E = E.g
        pari_catch_sig_on()
        cdef GEN _ret = ellheegner(_E)
        return pari_instance.new_gen(_ret)

    def ellheight(E, P, Q=None, long precision=0):
        r"""
        Global Néron-Tate height :math:`h(P)` of the point :math:`P` on the elliptic curve
        :math:`E/\mathbb{Q}`, using the normalization in 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.
        
        If the argument :math:`Q` is present, computes the value of the bilinear
        form :math:`(h(P+Q)-h(P-Q)) / 4`.
        """
        cdef GEN _E = E.g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        cdef GEN _Q = NULL
        if Q is not None:
            Q = objtogen(Q)
            _Q = (<gen>Q).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellheight0(_E, _P, _Q, precision)
        return pari_instance.new_gen(_ret)

    def ellheightmatrix(E, x, long precision=0):
        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.
        """
        cdef GEN _E = E.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellheightmatrix(_E, _x, precision)
        return pari_instance.new_gen(_ret)

    def ellidentify(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`.
        """
        cdef GEN _E = E.g
        pari_catch_sig_on()
        cdef GEN _ret = ellidentify(_E)
        return pari_instance.new_gen(_ret)

    def ellinit(x, D=None, long precision=0):
        r"""
        Initialize an :literal:`ell` structure, associated 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 :emphasis:`nf` or :emphasis:`bnf` structure.
        
        - a prime ideal :math:`p`, given by a :emphasis:`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.
        """
        cdef GEN _x = x.g
        cdef GEN _D = NULL
        if D is not None:
            D = objtogen(D)
            _D = (<gen>D).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellinit(_x, _D, precision)
        return pari_instance.new_gen(_ret)

    def ellisogeny(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]]
        """
        cdef GEN _E = E.g
        G = objtogen(G)
        cdef GEN _G = (<gen>G).g
        cdef long _x = -1
        if x is not None:
            _x = pari_instance.get_var(x)
        cdef long _y = -1
        if y is not None:
            _y = pari_instance.get_var(y)
        pari_catch_sig_on()
        cdef GEN _ret = ellisogeny(_E, _G, only_image, _x, _y)
        return pari_instance.new_gen(_ret)

    def ellisogenyapply(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:`x`:
        
        - if :math:`x` is a point :math:`P` in the domain of :math:`f`, return the image :math:`f(P)`;
        
        - if :math:`x` is a compatible isogeny :math:`g:E"\\to E'`, 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
        """
        cdef GEN _f = f.g
        g = objtogen(g)
        cdef GEN _g = (<gen>g).g
        pari_catch_sig_on()
        cdef GEN _ret = ellisogenyapply(_f, _g)
        return pari_instance.new_gen(_ret)

    def ellisoncurve(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.
        """
        cdef GEN _E = E.g
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        pari_catch_sig_on()
        cdef GEN _ret = ellisoncurve(_E, _z)
        return pari_instance.new_gen(_ret)

    def ellissupersingular(E, p=None):
        r"""
        Return 1 if the elliptic curve :math:`E` defined over Q or a finite field is supersingular
        at :math:`p`, and :math:`0` otherwise.
        If the curve is defined over :math:`\mathbb{Q}`, :math:`p` must be explicitly given and have good
        reduction at :math:`p`.
        Alternatively, :math:`E` can be given byt its :math:`j`-invariant in a finite field. In
        this case :math:`p` must be omitted.
        
        ::
        
            ? g = ffprimroot(ffgen(7^5))
            %1 = x^3 + 2*x^2 + 3*x + 1
            ? [g^n | n <- [1 .. 7^5 - 1], ellissupersingular(g^n)]
            %2 = [6]
        """
        cdef GEN _E = E.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef int _ret = ellissupersingular(_E, _p)
        pari_instance.clear_stack()
        return _ret

    def ellj(x, long precision=0):
        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.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = jell(_x, precision)
        return pari_instance.new_gen(_ret)

    def elllocalred(E, p):
        r"""
        Calculates the Kodaira type of the local fiber of the elliptic curve
        :math:`E` at :math:`p`. :math:`E` must be an :emphasis:`ell` structure as output by
        :literal:`ellinit`, over :math:`\mathbb{Q}` (:math:`p` a rational prime) or a number field :math:`K` (:math:`p`
        a maximal ideal given by a :emphasis:`prid` structure), and is assumed to have all
        its coefficients :math:`a_i` integral.
        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`.
        
        :strong:`Caveat.` If :math:`E` is not defined over :math:`\mathbb{Q}`, the current
        implementation requires that :math:`p` be above a prime :math:`>= 5`.
        """
        cdef GEN _E = E.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = elllocalred(_E, _p)
        return pari_instance.new_gen(_ret)

    def elllog(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
        """
        cdef GEN _E = E.g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        G = objtogen(G)
        cdef GEN _G = (<gen>G).g
        cdef GEN _o = NULL
        if o is not None:
            o = objtogen(o)
            _o = (<gen>o).g
        pari_catch_sig_on()
        cdef GEN _ret = elllog(_E, _P, _G, _o)
        return pari_instance.new_gen(_ret)

    def elllseries(E, s, A=None, long precision=0):
        r"""
        :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.
        """
        cdef GEN _E = E.g
        s = objtogen(s)
        cdef GEN _s = (<gen>s).g
        cdef GEN _A = NULL
        if A is not None:
            A = objtogen(A)
            _A = (<gen>A).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = elllseries(_E, _s, _A, precision)
        return pari_instance.new_gen(_ret)

    def ellmul(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.
        """
        cdef GEN _E = E.g
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        n = objtogen(n)
        cdef GEN _n = (<gen>n).g
        pari_catch_sig_on()
        cdef GEN _ret = ellmul(_E, _z, _n)
        return pari_instance.new_gen(_ret)

    def ellneg(E, z):
        r"""
        Opposite of the point :math:`z` on elliptic curve :math:`E`.
        """
        cdef GEN _E = E.g
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        pari_catch_sig_on()
        cdef GEN _ret = ellneg(_E, _z)
        return pari_instance.new_gen(_ret)

    def ellnonsingularmultiple(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 belongs to 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
        """
        cdef GEN _E = E.g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        pari_catch_sig_on()
        cdef GEN _ret = ellnonsingularmultiple(_E, _P)
        return pari_instance.new_gen(_ret)

    def ellorder(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.
        """
        cdef GEN _E = E.g
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        cdef GEN _o = NULL
        if o is not None:
            o = objtogen(o)
            _o = (<gen>o).g
        pari_catch_sig_on()
        cdef GEN _ret = ellorder(_E, _z, _o)
        return pari_instance.new_gen(_ret)

    def ellordinate(E, x, long precision=0):
        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.
        """
        cdef GEN _E = E.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellordinate(_E, _x, precision)
        return pari_instance.new_gen(_ret)

    def ellpadicL(E, p, long n, long r=0, D=None, character=None):
        r"""
        The :math:`p`-adic :math:`L` function is defined on the set of continuous characters
        of :math:`{Gal}(\mathbb{Q}(\mu_{p^{ oo }})/ \mathbb{Q})`, identified to :math:`\mathbb{Z}_p^*`
        via the cyclotomic character :math:`\chi_p` with values in :math:`\\overline{Q_p}^*`.
        Denote by :math:`tau:\mathbb{Z}_p^*\\to\mathbb{Z}_p^*` the Teichmüller character.
        
        When :math:`E` has good supersingular reduction, the :math:`L` function takes its
        values in :math:`\mathbb{Q}_p \\otimes H^1_{dR}(E/\mathbb{Q})` and satisfies
        
        .. MATH::
        
            (1-p^{-1} F)^{-2} L_p(E, \tau^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` its associated period on :math:`E(\mathbb{R})`. Here, :math:`\tau^0` represents
        the trivial character.
        
        The derivative is taken at :math:`s = 1` along :math:`<\chi_p^s>`.
        In other words, the function :math:`L_p` is defined as
        :math:`\int_{\mathbb{Z}_p^*} d \mu` for a certain :math:`p`-adic distribution :math:`\mu` on
        :math:`\mathbb{Z}_p^*`, and we have
        
        .. MATH::
        
            L_p^{(r)}(E, \tau^0) = \int_{\mathbb{Z}_p^*} \log_p^r(a) d\mu(a).
        
        The function returns the components of :math:`L_p{(r)}(E,\tau^0)` 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,\tau^0)` on the :math:`\alpha`-eigenspace,
        where :math:`\alpha` is the unit eigenvalue for :math:`F`. This is what the function
        returns. This value satisfies
        
        .. MATH::
        
            (1- \alpha^{-1})^{-2} L_{p,\alpha}(E,\tau^0) = L(E,1) / \Omega.
        
        ::
        
             ? cxL(e) = bestappr( ellL1(e,0) / e.omega[1] );
            
             ? e = ellinit("17a1"); p=3; \\ supersingular
             ? 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)
             %4 = [1 + O(3^4), O(3^4)]~
            
             ? p=5; ap = ellap(e,p); \\ ordinary
             ? L = ellpadicL(e,p,4);
             ? al = padicappr(x^2 - ap*x + p, ap + O(p^7))[1];
             ? (1-al^(-1))^(-2) * L / cxL(e)
             %8 = 1 + O(5^4)
            
             ? e = ellinit("116a1"); p=3; \\ supersingular
             ? L = ellpadicL(e,p,4);
             ? F = [0,-p; 1,ellap(e,p)];
             ? (1-p^(-1)*F)^-2*L~ / cxL(e)
             %12 = [1 + O(3^4), O(3^5)]~
            
             ? e = ellinit("26b1"); p=3;
             ? L = ellpadicL(e,p,4);
             ? F = [0,-p;1,ellap(e,p)];
             ? (1-p^(-1)*F)^-2*L~ / cxL(e)
             %16 = [1 + O(3^4), O(3^5)]~
        """
        cdef GEN _E = E.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        cdef GEN _D = NULL
        if D is not None:
            D = objtogen(D)
            _D = (<gen>D).g
        cdef GEN _character = NULL
        if character is not None:
            character = objtogen(character)
            _character = (<gen>character).g
        pari_catch_sig_on()
        cdef GEN _ret = ellpadicL(_E, _p, n, r, _D, _character)
        return pari_instance.new_gen(_ret)

    def ellpadicfrobenius(E, long p, long n):
        r"""
        If :math:`p > 2` is a prime and :math:`E` is a 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
        """
        cdef GEN _E = E.g
        pari_catch_sig_on()
        cdef GEN _ret = ellpadicfrobenius(_E, p, n)
        return pari_instance.new_gen(_ret)

    def ellpadicheight(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_{dR}(E) := 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 associates to
        :math:`P belongs to E(\mathbb{Q})` an element :math:`f \omega + g\eta` in :math:`D_{dR}`.
        This routine returns the vector :math:`[f, g]` to :math:`n` :math:`p`-adic digits.
        
        If :math:`P belongs to 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,4, P)
             %2 = [3*5 + 5^2 + 2*5^3 + O(5^4), 5^2 + 4*5^4 + O(5^6)]
             ? E = ellinit("11a1"); P = [5,5]; \\ torsion point
             ? ellpadicheight(E,19,6, P)
             %4 = O(19^6)
             ? E = ellinit([0,0,1,-4,2]); P = [-2,1];
             ? ellpadicheight(E,3,5, P)
             %6 = [2*3^2 + 2*3^3 + 3^4 + O(3^5), 2*3^2 + 3^4 + 2*3^5 + 3^6 + O(3^7)]
             ? ellpadicheight(E,3,5, P, elladd(E,P,P))
        
        One can replace the parameter :math:`p` prime by a vector :math:`[p,[a,b]]`, in which
        case the routine returns the :math:`p`-adic number :math:`af + bg`.
        
        When :math:`E` has good ordinary reduction at :math:`p`, the "canonical"
        :math:`p`-adic height is given by
        
        ::
        
            s2 = ellpadics2(E,p,n);
            ellpadicheight(E, [p,[1,-s2]], n, P)
        
        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;
            ? s2 = ellpadics2(E,p,n);
            ? M = ellpadicheightmatrix(E,[p,[1,-s2]], n, E.gen);
            ? matdet(M) \\ p-adic regulator
            %4 = 5 + 5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 5^6 + O(5^7)
        """
        cdef GEN _E = E.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        cdef GEN _Q = NULL
        if Q is not None:
            Q = objtogen(Q)
            _Q = (<gen>Q).g
        pari_catch_sig_on()
        cdef GEN _ret = ellpadicheight0(_E, _p, n, _P, _Q)
        return pari_instance.new_gen(_ret)

    def ellpadicheightmatrix(E, p, long n, v):
        r"""
        :math:`v` being a vector of points, this function outputs the Gram matrix of
        :math:`v` with respect to the cyclotomic :math:`p`-adic height, given to :math:`n` :math:`p`-adic
        digits; in other words, the :math:`(i,j)` component of the matrix is equal to
        :literal:`ellpadicheight`:math:`(E,p,n, v[i],v[j]) = [f,g]`.
        
        See :literal:`ellpadicheight`; in particular one can replace the parameter :math:`p`
        prime by a vector :math:`[p,[a,b]]`, in which case the routine returns the matrix
        containing the :math:`p`-adic numbers :math:`af + bg`.
        """
        cdef GEN _E = E.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        v = objtogen(v)
        cdef GEN _v = (<gen>v).g
        pari_catch_sig_on()
        cdef GEN _ret = ellpadicheightmatrix(_E, _p, n, _v)
        return pari_instance.new_gen(_ret)

    def ellpadiclog(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)`.
        """
        cdef GEN _E = E.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        pari_catch_sig_on()
        cdef GEN _ret = ellpadiclog(_E, _p, n, _P)
        return pari_instance.new_gen(_ret)

    def ellpadics2(E, p, long n):
        r"""
        If :math:`p > 2` is a prime and :math:`E/\mathbb{Q}` is a 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`.
        
        This slope is the unique :math:`c belongs to 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.
        """
        cdef GEN _E = E.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = ellpadics2(_E, _p, n)
        return pari_instance.new_gen(_ret)

    def ellperiods(w, long flag=0, long precision=0):
        r"""
        Let :math:`w` describe a complex period lattice (:math:`w = [w_1,w_2]`
        or an 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 associated to
        :math:`[W_1,W_2]`, satisfying :math:`\eta_1 W_2 - \eta_2 W_1 = 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.
        """
        cdef GEN _w = w.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellperiods(_w, flag, precision)
        return pari_instance.new_gen(_ret)

    def ellpointtoz(E, P, long precision=0):
        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 belongs to 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 = [6.372367644529809109 E-58, 7.646841173435770930 E-57]
            ? ellpointtoz(E, [0]) \\ the point at infinity
            %5 = 0
        
        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 behaviour 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) belongs to \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) belongs to 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 + O(11^5)
            ? z^5
            %5 = 1 + O(11^5)
            ? 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)
        """
        cdef GEN _E = E.g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = zell(_E, _P, precision)
        return pari_instance.new_gen(_ret)

    def ellpow(E, z, n):
        r"""
        Deprecated alias for :literal:`ellmul`.
        """
        cdef GEN _E = E.g
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        n = objtogen(n)
        cdef GEN _n = (<gen>n).g
        pari_catch_sig_on()
        cdef GEN _ret = ellmul(_E, _z, _n)
        return pari_instance.new_gen(_ret)

    def ellrootno(E, p=None):
        r"""
        :math:`E` being an :emphasis:`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. Note that the global root number is the sign of the functional
        equation and conjecturally is the parity of the rank of the \\idx{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.
        """
        cdef GEN _E = E.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef long _ret = ellrootno(_E, _p)
        pari_instance.clear_stack()
        return _ret

    def ellsearch(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` is a full curve name, e.g. :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 \\idx{Mordell-Weil
        group} associated 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 = []
        """
        cdef GEN _N = N.g
        pari_catch_sig_on()
        cdef GEN _ret = ellsearch(_N)
        return pari_instance.new_gen(_ret)

    def ellsigma(L, z=None, long flag=0, long precision=0):
        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 belongs to 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))`.
        """
        cdef GEN _L = L.g
        cdef GEN _z = NULL
        if z is not None:
            z = objtogen(z)
            _z = (<gen>z).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellsigma(_L, _z, flag, precision)
        return pari_instance.new_gen(_ret)

    def ellsub(E, z1, z2):
        r"""
        Difference of the points :math:`z1` and :math:`z2` on the
        elliptic curve corresponding to :math:`E`.
        """
        cdef GEN _E = E.g
        z1 = objtogen(z1)
        cdef GEN _z1 = (<gen>z1).g
        z2 = objtogen(z2)
        cdef GEN _z2 = (<gen>z2).g
        pari_catch_sig_on()
        cdef GEN _ret = ellsub(_E, _z1, _z2)
        return pari_instance.new_gen(_ret)

    def elltaniyama(E, long serprec=-1):
        r"""
        Computes the modular parametrization of the elliptic curve :math:`E/\mathbb{Q}`,
        where :math:`E` is an :emphasis:`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`.
        """
        cdef GEN _E = E.g
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        pari_catch_sig_on()
        cdef GEN _ret = elltaniyama(_E, serprec)
        return pari_instance.new_gen(_ret)

    def elltatepairing(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.
        """
        cdef GEN _E = E.g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        Q = objtogen(Q)
        cdef GEN _Q = (<gen>Q).g
        m = objtogen(m)
        cdef GEN _m = (<gen>m).g
        pari_catch_sig_on()
        cdef GEN _ret = elltatepairing(_E, _P, _Q, _m)
        return pari_instance.new_gen(_ret)

    def elltors(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
        :emphasis:`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]`.
        """
        cdef GEN _E = E.g
        pari_catch_sig_on()
        cdef GEN _ret = elltors(_E)
        return pari_instance.new_gen(_ret)

    def ellweilpairing(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`.
        """
        cdef GEN _E = E.g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        Q = objtogen(Q)
        cdef GEN _Q = (<gen>Q).g
        m = objtogen(m)
        cdef GEN _m = (<gen>m).g
        pari_catch_sig_on()
        cdef GEN _ret = ellweilpairing(_E, _P, _Q, _m)
        return pari_instance.new_gen(_ret)

    def ellwp(w, z=None, long flag=0, long precision=0):
        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)]`.
        """
        cdef GEN _w = w.g
        cdef GEN _z = NULL
        if z is not None:
            z = objtogen(z)
            _z = (<gen>z).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellwp0(_w, _z, flag, precision)
        return pari_instance.new_gen(_ret)

    def ellxn(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 abcissa of :math:`[n]P` and depend only on :math:`v`.
        """
        cdef GEN _E = E.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = ellxn(_E, n, _v)
        return pari_instance.new_gen(_ret)

    def ellzeta(w, z=None, long precision=0):
        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 belongs to 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)
        """
        cdef GEN _w = w.g
        cdef GEN _z = NULL
        if z is not None:
            z = objtogen(z)
            _z = (<gen>z).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ellzeta(_w, _z, precision)
        return pari_instance.new_gen(_ret)

    def ellztopoint(E, z, long precision=0):
        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 number :math:`z`. Hence this is the inverse function
        of :literal:`ellpointtoz`. In other words, if the curve is put in Weierstrass
        form :math:`y^2 = 4x^3 - g_2x - g_3`, :math:`[x,y]` represents the Weierstrass
        :math:`\wp`-function and its derivative. More
        precisely, we have
        
        .. MATH::
        
            x = \wp(z) - b_2/12, y = \wp'(z) - (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]`.
        """
        cdef GEN _E = E.g
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = pointell(_E, _z, precision)
        return pari_instance.new_gen(_ret)

    def erfc(x, long precision=0):
        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`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gerfc(_x, precision)
        return pari_instance.new_gen(_ret)

    def errname(E):
        r"""
        Returns the type of the error message :literal:`E` as a string.
        """
        cdef GEN _E = E.g
        pari_catch_sig_on()
        cdef GEN _ret = errname(_E)
        return pari_instance.new_gen(_ret)

    def eta(z, long flag=0, long precision=0):
        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}`.
        """
        cdef GEN _z = z.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = eta0(_z, flag, precision)
        return pari_instance.new_gen(_ret)

    def eulerphi(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 \\kbd{znstar:math:`(n)`.no = 
        eulerphi(n)} for all :math:`n belongs to \mathbb{Z}`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = eulerphi(_x)
        return pari_instance.new_gen(_ret)

    def exp(x, long precision=0):
        r"""
        Exponential of :math:`x`.
        :math:`p`-adic arguments with positive valuation are accepted.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gexp(_x, precision)
        return pari_instance.new_gen(_ret)

    def expm1(x, long precision=0):
        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 = 28 ms.
            ? default(realprecision, 10040); x = 1e-100;
            ? c = expm1(x); \\ reference point
            ? abs(a-c)/c \\ relative error in expm1(x)
            %7 = 0.E-10017
            ? 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 both faster and more accurate than :literal:`exp(x)-1`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gexpm1(_x, precision)
        return pari_instance.new_gen(_ret)

    def factor(x, lim=None):
        r"""
        General factorization function, where :math:`x` is a
        rational (including integers), a complex number with rational
        real and imaginary parts, or a rational function (including polynomials).
        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:`\mathbb{Q}` and :math:`\mathbb{Q}(i)`.`
        See :literal:`factorint` for more information about the algorithms used.
        The rational or Gaussian primes are in fact :emphasis:`pseudoprimes`
        (see :literal:`ispseudoprime`), a priori not rigorously proven primes. In fact,
        any factor which is :math:`<= 2^{64}` (whose norm is :math:`<= 2^{64}` for an
        irrational Gaussian prime) is a genuine prime. Use :literal:`isprime` to prove
        primality of other 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 set the global default :literal:`factor_proven`, which
        will perform a rigorous primality proof for each pseudoprime factor.
        
        A :literal:`t_INT` argument :emphasis:`lim` can be added, meaning that we look only for
        prime factors :math:`p < lim`. The limit :emphasis:`lim` 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:`lim^2`, then it is prime.
        
        ::
        
            ? factor(2^2^7 +1, 10^5)
            %3 =
            [340282366920938463463374607431768211457 1]
        
        :strong:`Deprecated feature.` Setting :math:`lim = 0` is the same
        as setting it to :math:`primelimit + 1`. Don't use this: it is unwise to
        rely on global variables when you can specify an explicit argument.
        
        This routine uses trial division and perfect power tests, and should not be
        used for huge values of :emphasis:`lim` (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 much more
        efficient way.
        
        ::
        
            ? F = (2^2^7 + 1) * 1009 * 100003; factor(F, 10^5) \\ fast, incomplete
            time = 0 ms.
            %4 =
            [1009 1]
            
            [34029257539194609161727850866999116450334371 1]
            
            ? factor(F, 10^9) \\ very slow
            time = 6,892 ms.
            %6 =
            [1009 1]
            
            [100003 1]
            
            [340282366920938463463374607431768211457 1]
            
            ? factorint(F, 1+8) \\ much faster, all small primes were found
            time = 12 ms.
            %7 =
            [1009 1]
            
            [100003 1]
            
            [340282366920938463463374607431768211457 1]
            
            ? factor(F) \\ complete factorisation
            time = 112 ms.
            %8 =
            [1009 1]
            
            [100003 1]
            
            [59649589127497217 1]
            
            [5704689200685129054721 1]
        
        Over :math:`\mathbb{Q}`, the prime factors are sorted in increasing order.
        
        :strong:`Rational functions.`
        The polynomials or rational functions to be factored must have scalar
        coefficients. In particular PARI does not know how to factor
        :emphasis:`multivariate` polynomials. The following domains 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, :literal:`factornf` for the algorithms
        over number fields. Over :math:`\mathbb{Q}`, van Hoeij's method is used, which is
        able to cope with hundreds of modular factors.
        
        The routine guesses a sensible ring over which to factor: the
        smallest ring 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). Factoring modulo a
        non-prime number is not supported; to factor in :math:`\mathbb{Q}_p`, use :literal:`t_PADIC`
        coefficients not :literal:`t_INTMOD` modulo :math:`p^n`.
        
        ::
        
            ? 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})
        
        In most cases, it is clearer and simpler to call an
        explicit variant than to rely on the generic :literal:`factor` function and
        the above detection mechanism:
        
        ::
        
            ? factormod(T, 3) \\ over F_3
            ? factorff(T, 3, t^2+t+2)) \\ 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
        
        Note that factorization of polynomials is done up to
        multiplication by a constant. In particular, the factors of rational
        polynomials will have integer coefficients, and the content of a polynomial
        or rational function is discarded and not included in the factorization. If
        needed, you can always ask for the content explicitly:
        
        ::
        
            ? factor(t^2 + 5/2*t + 1)
            %1 =
            [2*t + 1 1]
            
            [t + 2 1]
            
            ? content(t^2 + 5/2*t + 1)
            %2 = 1/2
        
        The irreducible factors are sorted by increasing degree.
        See also :literal:`nffactor`.
        """
        cdef GEN _x = x.g
        cdef GEN _lim = NULL
        if lim is not None:
            lim = objtogen(lim)
            _lim = (<gen>lim).g
        pari_catch_sig_on()
        cdef GEN _ret = gp_factor0(_x, _lim)
        return pari_instance.new_gen(_ret)

    def factorback(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
        """
        cdef GEN _f = f.g
        cdef GEN _e = NULL
        if e is not None:
            e = objtogen(e)
            _e = (<gen>e).g
        pari_catch_sig_on()
        cdef GEN _ret = factorback2(_f, _e)
        return pari_instance.new_gen(_ret)

    def factorcantor(x, p):
        r"""
        Factors the polynomial :math:`x` modulo the
        prime :math:`p`, using distinct degree plus
        Cantor-Zassenhaus. The coefficients of :math:`x` must be
        operation-compatible with :math:`\mathbb{Z}/p\mathbb{Z}`. The result is a two-column matrix, the
        first column being the irreducible polynomials dividing :math:`x`, and the second
        the exponents. If you want only the :emphasis:`degrees` of the irreducible
        polynomials (for example for computing an :math:`L`-function), use
        :math:`factormod(x,p,1)`. Note that the :literal:`factormod` algorithm is
        usually faster than :literal:`factorcantor`.
        """
        cdef GEN _x = x.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = factcantor(_x, _p)
        return pari_instance.new_gen(_ret)

    def factorff(x, p=None, a=None):
        r"""
        Factors the polynomial :math:`x` in the field
        :math:`\mathbb{F}_q` defined by the irreducible polynomial :math:`a` over :math:`\mathbb{F}_p`. The
        coefficients of :math:`x` must be operation-compatible with :math:`\mathbb{Z}/p\mathbb{Z}`. The result
        is a two-column matrix: the first column contains the irreducible factors of
        :math:`x`, and the second their exponents. If all the coefficients of :math:`x` are in
        :math:`\mathbb{F}_p`, a much faster algorithm is applied, using the computation of
        isomorphisms between finite fields.
        
        Either :math:`a` or :math:`p` can omitted (in which case both are ignored) if x has
        :literal:`t_FFELT` coefficients; the function then becomes identical to :literal:`factor`:
        
        ::
        
            ? factorff(x^2 + 1, 5, y^2+3) \\ over F_5[y]/(y^2+3) ~ F_25
            %1 =
            [Mod(Mod(1, 5), Mod(1, 5)*y^2 + Mod(3, 5))*x
             + Mod(Mod(2, 5), Mod(1, 5)*y^2 + Mod(3, 5)) 1]
            
            [Mod(Mod(1, 5), Mod(1, 5)*y^2 + Mod(3, 5))*x
             + Mod(Mod(3, 5), Mod(1, 5)*y^2 + Mod(3, 5)) 1]
            ? t = ffgen(y^2 + Mod(3,5), 't); \\ a generator for F_25 as a t_FFELT
            ? factorff(x^2 + 1) \\ not enough information to determine the base field
             *** at top-level: factorff(x^2+1)
             *** ^---------------
             *** factorff: incorrect type in factorff.
            ? factorff(x^2 + t^0) \\ make sure a coeff. is a t_FFELT
            %3 =
            [x + 2 1]
            
            [x + 3 1]
            ? factorff(x^2 + t + 1)
            %11 =
            [x + (2*t + 1) 1]
            
            [x + (3*t + 4) 1]
        
        Notice that the second syntax is easier to use and much more readable.
        """
        cdef GEN _x = x.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        cdef GEN _a = NULL
        if a is not None:
            a = objtogen(a)
            _a = (<gen>a).g
        pari_catch_sig_on()
        cdef GEN _ret = factorff(_x, _p, _a)
        return pari_instance.new_gen(_ret)

    def factorint(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 is 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).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = factorint(_x, flag)
        return pari_instance.new_gen(_ret)

    def factormod(x, p, long flag=0):
        r"""
        Factors the polynomial :math:`x` modulo the prime integer :math:`p`, using
        Berlekamp. The coefficients of :math:`x` must be operation-compatible with
        :math:`\mathbb{Z}/p\mathbb{Z}`. The result is a two-column matrix, the first column being the
        irreducible polynomials dividing :math:`x`, and the second the exponents. If :math:`flag`
        is non-zero, outputs only the :emphasis:`degrees` of the irreducible polynomials
        (for example, for computing an :math:`L`-function). A different algorithm for
        computing the mod :math:`p` factorization is :literal:`factorcantor` which is sometimes
        faster.
        """
        cdef GEN _x = x.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = factormod0(_x, _p, flag)
        return pari_instance.new_gen(_ret)

    def factornf(x, t):
        r"""
        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.
        """
        cdef GEN _x = x.g
        t = objtogen(t)
        cdef GEN _t = (<gen>t).g
        pari_catch_sig_on()
        cdef GEN _ret = polfnf(_x, _t)
        return pari_instance.new_gen(_ret)

    def factorpadic(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.
        """
        cdef GEN _pol = pol.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = factorpadic(_pol, _p, r)
        return pari_instance.new_gen(_ret)

    def ffgen(q, v=None):
        r"""
        Return a :literal:`t_FFELT` generator for the finite field with :math:`q` elements;
        :math:`q = p^f` must be a prime power. This functions computes an irreducible
        monic polynomial :math:`P belongs to \mathbb{F}_p[X]` of degree :math:`f` (via :literal:`ffinit`) and
        returns :math:`g = X (mod P(X))`. If :literal:`v` is given, the variable name is used
        to display :math:`g`, else the variable :math:`x` is used.
        
        ::
        
            ? g = ffgen(8, 't);
            ? g.mod
            %2 = t^3 + t^2 + 1
            ? g.p
            %3 = 2
            ? g.f
            %4 = 3
            ? ffgen(6)
             *** at top-level: ffgen(6)
             *** ^--------
             *** ffgen: not a prime number in ffgen: 6.
        
        Alternative syntax: instead of a prime power :math:`q = p^f`, one may
        input the pair :math:`[p,f]`:
        
        ::
        
            ? g = ffgen([2,4], 't);
            ? g.p
            %2 = 2
            ? g.mod
            %3 = t^4 + t^3 + t^2 + t + 1
        
        Finally, one may input
        directly the polynomial :math:`P` (monic, irreducible, with :literal:`t_INTMOD`
        coefficients), and the function returns the generator :math:`g = X (mod P(X))`,
        inferring :math:`p` from the coefficients of :math:`P`. If :literal:`v` is given, the
        variable name is used to display :math:`g`, else the variable of the polynomial
        :math:`P` is used. If :math:`P` is not irreducible, we create an invalid object and
        behaviour of functions dealing with the resulting :literal:`t_FFELT`
        is undefined; in fact, it is much more costly to test :math:`P` for
        irreducibility than it would be to produce it via :literal:`ffinit`.
        """
        cdef GEN _q = q.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = ffgen(_q, _v)
        return pari_instance.new_gen(_ret)

    def ffinit(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`.
        """
        cdef GEN _p = p.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = ffinit(_p, n, _v)
        return pari_instance.new_gen(_ret)

    def fflog(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
        """
        cdef GEN _x = x.g
        g = objtogen(g)
        cdef GEN _g = (<gen>g).g
        cdef GEN _o = NULL
        if o is not None:
            o = objtogen(o)
            _o = (<gen>o).g
        pari_catch_sig_on()
        cdef GEN _ret = fflog(_x, _g, _o)
        return pari_instance.new_gen(_ret)

    def ffnbirred(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`).
        """
        cdef GEN _q = q.g
        pari_catch_sig_on()
        cdef GEN _ret = ffnbirred0(_q, n, fl)
        return pari_instance.new_gen(_ret)

    def fforder(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
        """
        cdef GEN _x = x.g
        cdef GEN _o = NULL
        if o is not None:
            o = objtogen(o)
            _o = (<gen>o).g
        pari_catch_sig_on()
        cdef GEN _ret = fforder(_x, _o)
        return pari_instance.new_gen(_ret)

    def floor(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gfloor(_x)
        return pari_instance.new_gen(_ret)

    def fold(f, A):
        r"""
        Apply the :literal:`t_CLOSURE` :literal:`f` of arity :math:`2` to the entries of :literal:`A`
        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
        """
        cdef GEN _f = f.g
        A = objtogen(A)
        cdef GEN _A = (<gen>A).g
        pari_catch_sig_on()
        cdef GEN _ret = fold0(_f, _A)
        return pari_instance.new_gen(_ret)

    def frac(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[`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gfrac(_x)
        return pari_instance.new_gen(_ret)

    def fromdigits(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`. 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
        """
        cdef GEN _x = x.g
        cdef GEN _b = NULL
        if b is not None:
            b = objtogen(b)
            _b = (<gen>b).g
        pari_catch_sig_on()
        cdef GEN _ret = fromdigits(_x, _b)
        return pari_instance.new_gen(_ret)

    def galoisexport(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 ]
        """
        cdef GEN _gal = gal.g
        pari_catch_sig_on()
        cdef GEN _ret = galoisexport(_gal, flag)
        return pari_instance.new_gen(_ret)

    def galoisfixedfield(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)). Example:
        
        ::
        
            ? G = galoisinit(x^4+1);
            ? galoisfixedfield(G,G.group[2],2)
            %2 = [x^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)`
        """
        cdef GEN _gal = gal.g
        perm = objtogen(perm)
        cdef GEN _perm = (<gen>perm).g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = galoisfixedfield(_gal, _perm, flag, _v)
        return pari_instance.new_gen(_ret)

    def galoisidentify(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.
        """
        cdef GEN _gal = gal.g
        pari_catch_sig_on()
        cdef GEN _ret = galoisidentify(_gal)
        return pari_instance.new_gen(_ret)

    def galoisinit(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_g]` 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_A` 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 belongs to 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]`.
        """
        cdef GEN _pol = pol.g
        cdef GEN _den = NULL
        if den is not None:
            den = objtogen(den)
            _den = (<gen>den).g
        pari_catch_sig_on()
        cdef GEN _ret = galoisinit(_pol, _den)
        return pari_instance.new_gen(_ret)

    def galoisisabelian(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:`fl = 0`, :math:`1` if :math:`fl = 1`.
        
        This command also accepts subgroups returned by :literal:`galoissubgroups`.
        """
        cdef GEN _gal = gal.g
        pari_catch_sig_on()
        cdef GEN _ret = galoisisabelian(_gal, flag)
        return pari_instance.new_gen(_ret)

    def galoisisnormal(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`.
        """
        cdef GEN _gal = gal.g
        subgrp = objtogen(subgrp)
        cdef GEN _subgrp = (<gen>subgrp).g
        pari_catch_sig_on()
        cdef long _ret = galoisisnormal(_gal, _subgrp)
        pari_instance.clear_stack()
        return _ret

    def galoispermtopol(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`, associated with 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`.
        """
        cdef GEN _gal = gal.g
        perm = objtogen(perm)
        cdef GEN _perm = (<gen>perm).g
        pari_catch_sig_on()
        cdef GEN _ret = galoispermtopol(_gal, _perm)
        return pari_instance.new_gen(_ret)

    def galoissubcyclo(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`)`. :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})^*`
          (of type :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`, 1)` 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`.gen`.
        
        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
        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):
        
        ::
        
            polsubcyclo(n, d = -1)=
            { my(bnr,L,IndexBound);
             IndexBound = if (d < 0, n, [d]);
             bnr = bnrinit(bnfinit(y), [n,[1]], 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`.
        """
        cdef GEN _N = N.g
        cdef GEN _H = NULL
        if H is not None:
            H = objtogen(H)
            _H = (<gen>H).g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = galoissubcyclo(_N, _H, fl, _v)
        return pari_instance.new_gen(_ret)

    def galoissubfields(G, long flags=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
        the flag :emphasis:`fl` is the same as for :literal:`galoisfixedfield`.
        """
        cdef GEN _G = G.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = galoissubfields(_G, flags, _v)
        return pari_instance.new_gen(_ret)

    def galoissubgroups(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])
        """
        cdef GEN _G = G.g
        pari_catch_sig_on()
        cdef GEN _ret = galoissubgroups(_G)
        return pari_instance.new_gen(_ret)

    def gamma(s, long precision=0):
        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
        """
        cdef GEN _s = s.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ggamma(_s, precision)
        return pari_instance.new_gen(_ret)

    def gammah(x, long precision=0):
        r"""
        Gamma function evaluated at the argument :math:`x+1/2`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = ggammah(_x, precision)
        return pari_instance.new_gen(_ret)

    def gammamellininv(G, t, long m=0, long precision=0):
        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.
        """
        cdef GEN _G = G.g
        t = objtogen(t)
        cdef GEN _t = (<gen>t).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gammamellininv(_G, _t, m, precision)
        return pari_instance.new_gen(_ret)

    def gammamellininvasymp(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)`.
        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^{1-d+a+m(2/d-1)}e^{-d\Pi t^{2/d}}
            \sum_{n >= 0} M[n+1]t^{-2n/d}
        
        with :math:`a = (1-d+\sum_{1 <= j <= d}a_j)/d`.
        """
        cdef GEN _A = A.g
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        pari_catch_sig_on()
        cdef GEN _ret = gammamellininvasymp(_A, serprec, n)
        return pari_instance.new_gen(_ret)

    def gammamellininvinit(A, long m=0, long precision=0):
        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)`. 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
        """
        cdef GEN _A = A.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gammamellininvinit(_A, m, precision)
        return pari_instance.new_gen(_ret)

    def gcd(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:`bezout` 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`.
        """
        cdef GEN _x = x.g
        cdef GEN _y = NULL
        if y is not None:
            y = objtogen(y)
            _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = ggcd0(_x, _y)
        return pari_instance.new_gen(_ret)

    def gcdext(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = gcdext0(_x, _y)
        return pari_instance.new_gen(_ret)

    def genus2red(P, p=None):
        r"""
        Let :math:`P` be a polynomial with integer 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`. (The
        special fiber :math:`X_p` of the minimal regular model :math:`X` of :math:`C` over :math:`\mathbb{Z}`.)
        The special syntax :literal:`genus2red`:math:`([P,Q])` is also allowed, where the
        polynomials :math:`P` and :math:`Q` have integer coefficients, to represent the model
        :math:`y^2 + Q(x)y = P(x)`.
        
        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-bordeaux1.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` are 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 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, \\kbd{[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, :literal:`[:math:`K`-:math:`K'`-m]` and :literal:`[:math:`K'`-:math:`K`-m]` are the same.
        
        - :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)]`.
        """
        cdef GEN _P = P.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = genus2red(_P, _p)
        return pari_instance.new_gen(_ret)

    def hammingweight(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = hammingweight(_x)
        pari_instance.clear_stack()
        return _ret

    def hilbert(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.)
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef long _ret = hilbert(_x, _y, _p)
        pari_instance.clear_stack()
        return _ret

    def hyperellcharpoly(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.
        """
        cdef GEN _X = X.g
        pari_catch_sig_on()
        cdef GEN _ret = hyperellcharpoly(_X)
        return pari_instance.new_gen(_ret)

    def hyperellpadicfrobenius(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(E) = \mathbb{Q}_p \\otimes H^1_{dR}(E/\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` modlo :math:`p`. The matrix is computed to absolute :math:`p`-adic precision :math:`p^n`.
        """
        cdef GEN _Q = Q.g
        pari_catch_sig_on()
        cdef GEN _ret = hyperellpadicfrobenius(_Q, p, n)
        return pari_instance.new_gen(_ret)

    def hyperu(a, b, x, long precision=0):
        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.
        """
        cdef GEN _a = a.g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = hyperu(_a, _b, _x, precision)
        return pari_instance.new_gen(_ret)

    def idealadd(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))`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = idealadd(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def idealaddtoone(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 belongs to x`, :math:`b belongs to 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] belongs to x[i]` for
        :math:`1 <= i <= k` and :math:`\sum_{1 <= i <= k}e[i] = 1`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        cdef GEN _y = NULL
        if y is not None:
            y = objtogen(y)
            _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = idealaddtoone0(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def idealappr(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`.
        
        If :math:`flag` is non-zero, :math:`x` must be given as a prime ideal factorization, as
        output by :literal:`idealfactor`, but possibly with zero or negative exponents.
        This yields an element :math:`\alpha` such that for all prime ideals :math:`p`
        occurring in :math:`x`, :math:`v_{p}(\alpha)` is equal to the exponent of
        :math:`p` in :math:`x`, and for all other prime ideals,
        :math:`v_{p}(\alpha) >= 0`. This generalizes :math:`idealappr(nf,x,0)`
        since zero exponents are allowed. Note that the algorithm used is slightly
        different, so that
        
        ::
        
             idealappr(nf, idealfactor(nf,x))
        
        may not be the same as :literal:`idealappr(nf,x,1)`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = idealappr0(_nf, _x, flag)
        return pari_instance.new_gen(_ret)

    def idealchinese(nf, x, y):
        r"""
        :math:`x` being a prime ideal factorization
        (i.e. a 2 by 2 matrix whose first column contains prime ideals, and the second
        column 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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = idealchinese(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def idealcoprime(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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = idealcoprime(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def idealdiv(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.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = idealdiv0(_nf, _x, _y, flag)
        return pari_instance.new_gen(_ret)

    def idealfactor(nf, x):
        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, i.e. as 5-element vectors.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = idealfactor(_nf, _x)
        return pari_instance.new_gen(_ret)

    def idealfactorback(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.
        """
        cdef GEN _nf = nf.g
        f = objtogen(f)
        cdef GEN _f = (<gen>f).g
        cdef GEN _e = NULL
        if e is not None:
            e = objtogen(e)
            _e = (<gen>e).g
        pari_catch_sig_on()
        cdef GEN _ret = idealfactorback(_nf, _f, _e, flag)
        return pari_instance.new_gen(_ret)

    def idealfrobenius(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 :math:`pr` is the prime ideal :math:`P` in prid format, and that
        :math:`P` is unramified.
        This function returns a permutation of :literal:`gal.group` which defines the
        automorphism :math:`\sigma = (P\\over K/\mathbb{Q} )`, i.e the Frobenius
        element associated to :math:`P`. If :math:`p` is the unique prime number
        in :math:`P`, then :math:`\sigma(x) = x^p mod \\P` for all :math:`x belongs to \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`.
        """
        cdef GEN _nf = nf.g
        gal = objtogen(gal)
        cdef GEN _gal = (<gen>gal).g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = idealfrobenius(_nf, _gal, _pr)
        return pari_instance.new_gen(_ret)

    def idealhnf(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 :literal:`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.
        """
        cdef GEN _nf = nf.g
        u = objtogen(u)
        cdef GEN _u = (<gen>u).g
        cdef GEN _v = NULL
        if v is not None:
            v = objtogen(v)
            _v = (<gen>v).g
        pari_catch_sig_on()
        cdef GEN _ret = idealhnf0(_nf, _u, _v)
        return pari_instance.new_gen(_ret)

    def idealintersect(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,] )
            }
        """
        cdef GEN _nf = nf.g
        A = objtogen(A)
        cdef GEN _A = (<gen>A).g
        B = objtogen(B)
        cdef GEN _B = (<gen>B).g
        pari_catch_sig_on()
        cdef GEN _ret = idealintersect(_nf, _A, _B)
        return pari_instance.new_gen(_ret)

    def idealinv(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]`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = idealinv(_nf, _x)
        return pari_instance.new_gen(_ret)

    def ideallist(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` associated 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.
        """
        cdef GEN _nf = nf.g
        pari_catch_sig_on()
        cdef GEN _ret = ideallist0(_nf, bound, flag)
        return pari_instance.new_gen(_ret)

    def ideallistarch(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 the ray class group. 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];
            %6 = [2, 12, 2]
        """
        cdef GEN _nf = nf.g
        list = objtogen(list)
        cdef GEN _list = (<gen>list).g
        arch = objtogen(arch)
        cdef GEN _arch = (<gen>arch).g
        pari_catch_sig_on()
        cdef GEN _ret = ideallistarch(_nf, _list, _arch)
        return pari_instance.new_gen(_ret)

    def ideallog(nf, x, bid):
        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 associated real embeddings.
        See :literal:`znlog` for the limitations of the underlying discrete log algorithms.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        bid = objtogen(bid)
        cdef GEN _bid = (<gen>bid).g
        pari_catch_sig_on()
        cdef GEN _ret = ideallog(_nf, _x, _bid)
        return pari_instance.new_gen(_ret)

    def idealmin(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`.
        """
        cdef GEN _nf = nf.g
        ix = objtogen(ix)
        cdef GEN _ix = (<gen>ix).g
        cdef GEN _vdir = NULL
        if vdir is not None:
            vdir = objtogen(vdir)
            _vdir = (<gen>vdir).g
        pari_catch_sig_on()
        cdef GEN _ret = idealmin(_nf, _ix, _vdir)
        return pari_instance.new_gen(_ret)

    def idealmul(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
            %4 = [[4, 2; 0, 2], x]
            ? idealmul(nf, [2, x], [x+1, x]) \\ two extended ideals
            %5 = [[4, 2; 0, 2], [-1, 0]~]
        
        If :math:`flag` is non-zero, reduce the result using :literal:`idealred`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = idealmul0(_nf, _x, _y, flag)
        return pari_instance.new_gen(_ret)

    def idealnorm(nf, x):
        r"""
        Computes the norm of the ideal :math:`x` in the number field :math:`nf`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = idealnorm(_nf, _x)
        return pari_instance.new_gen(_ret)

    def idealnumden(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]]
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = idealnumden(_nf, _x)
        return pari_instance.new_gen(_ret)

    def idealpow(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 belongs to \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
        as :math:`idealpow(nf,x,k)` followed by reduction.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        k = objtogen(k)
        cdef GEN _k = (<gen>k).g
        pari_catch_sig_on()
        cdef GEN _ret = idealpow0(_nf, _x, _k, flag)
        return pari_instance.new_gen(_ret)

    def idealprimedec(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` and
        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 associated 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's 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
            %4 = [1, 1]
            ? [p2.e, p2.f] \\ the second is unramified of degree 2
            %5 = [1, 2]
            ? p1.gen
            %6 = [5, [2, 1, 0]~]
            ? nfbasistoalg(K, %[2]) \\ a uniformizer for p1
            %7 = Mod(x + 2, x^3 - 2)
            ? #idealprimedec(K, 5, 1) \\ restrict to f = 1
            %8 = 1 \\ now only p1
        """
        cdef GEN _nf = nf.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = idealprimedec_limit_f(_nf, _p, f)
        return pari_instance.new_gen(_ret)

    def idealprincipalunits(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
            [512, 256, 4] \\ Z/512 x Z/256 x Z/4
            ? G.gen
            %5 = [[-1, -2]~, 1021, [0, -1]~] \\ minimal generators of given order
        """
        cdef GEN _nf = nf.g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = idealprincipalunits(_nf, _pr, k)
        return pari_instance.new_gen(_ret)

    def idealramgroups(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 \\idx{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)
            %4 = [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]
            %4 = [[Vecsmall([2, 3, 1, 5, 6, 4])], Vecsmall([3])]
            ? nfdisc(galoisfixedfield(gal,iso,1))
            %5 = -3
        
        The field fixed by the inertia group of :math:`2` is not ramified at
        :math:`2`.
        """
        cdef GEN _nf = nf.g
        gal = objtogen(gal)
        cdef GEN _gal = (<gen>gal).g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = idealramgroups(_nf, _gal, _pr)
        return pari_instance.new_gen(_ret)

    def idealred(nf, I, v=None):
        r"""
        LLL reduction of
        the ideal :math:`I` in the number field :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 a "small" :math:`a` in :math:`I` (see the end for technical details).
        The result is the Hermite normal form of
        the "reduced" ideal :math:`J = r I/a`, where :math:`r` is the unique rational number such
        that :math:`J` is integral and primitive. (This is usually not a reduced ideal in
        the sense of Buchmann.)
        
        ::
        
            ? 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/r]`; this way,
        one can keep 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` 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` and is
        "expected to be small".
        """
        cdef GEN _nf = nf.g
        I = objtogen(I)
        cdef GEN _I = (<gen>I).g
        cdef GEN _v = NULL
        if v is not None:
            v = objtogen(v)
            _v = (<gen>v).g
        pari_catch_sig_on()
        cdef GEN _ret = idealred0(_nf, _I, _v)
        return pari_instance.new_gen(_ret)

    def idealstar(nf, I, long flag=1):
        r"""
        Outputs a :emphasis:`bid` structure,
        necessary for computing in the finite abelian group :math:`G = (\mathbb{Z}_K/I)^*`. Here,
        :emphasis:`nf` is a number field and :math:`I` 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 :emphasis:`bid` structure without
        generators.
        
        If :math:`flag = 2`, as :math:`flag = 1`, but including generators, which wastes some time.
        
        If :math:`flag = 0`, only outputs :math:`(\mathbb{Z}_K/I)^*` 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.
        """
        cdef GEN _nf = nf.g
        I = objtogen(I)
        cdef GEN _I = (<gen>I).g
        pari_catch_sig_on()
        cdef GEN _ret = idealstar0(_nf, _I, flag)
        return pari_instance.new_gen(_ret)

    def idealtwoelt(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.
        
        - 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 belongs to x` and returns
          :math:`\alpha belongs to 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 much slower than the
          default variant.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        cdef GEN _a = NULL
        if a is not None:
            a = objtogen(a)
            _a = (<gen>a).g
        pari_catch_sig_on()
        cdef GEN _ret = idealtwoelt0(_nf, _x, _a)
        return pari_instance.new_gen(_ret)

    def idealval(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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = gpidealval(_nf, _x, _pr)
        return pari_instance.new_gen(_ret)

    def imag(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)`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gimag(_x)
        return pari_instance.new_gen(_ret)

    def incgam(s, x, g=None, long precision=0):
        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.
        """
        cdef GEN _s = s.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        cdef GEN _g = NULL
        if g is not None:
            g = objtogen(g)
            _g = (<gen>g).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = incgam0(_s, _x, _g, precision)
        return pari_instance.new_gen(_ret)

    def incgamc(s, x, long precision=0):
        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`.
        """
        cdef GEN _s = s.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = incgamc(_s, _x, precision)
        return pari_instance.new_gen(_ret)

    def intformal(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
        """
        cdef GEN _x = x.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = integ(_x, _v)
        return pari_instance.new_gen(_ret)

    def intnuminit(a, b, long m=0, long precision=0):
        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 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 belongs to ]- 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 behaviour 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 behaviour
        of :math:`F` at endpoints, depending on :math:`z`.
        """
        cdef GEN _a = a.g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = intnuminit(_a, _b, m, precision)
        return pari_instance.new_gen(_ret)

    def isfundamental(x):
        r"""
        True (1) if :math:`x` is equal to 1 or to the discriminant of a quadratic
        field, false (0) otherwise.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = isfundamental(_x)
        pari_instance.clear_stack()
        return _ret

    def ispowerful(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = ispowerful(_x)
        pari_instance.clear_stack()
        return _ret

    def isprime(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 prime and has more than :math:`1000` digits, say.
        Use :literal:`ispseudoprime` to quickly check for compositeness. See also
        :literal:`factor`. It accepts vector/matrices arguments, and is then applied
        componentwise.
        
        If :math:`flag = 0`, use a combination of Baillie-PSW pseudo primality test (see
        :literal:`ispseudoprime`), Selfridge ":math:`p-1`" test if :math:`x-1` is smooth enough, and
        Adleman-Pomerance-Rumely-Cohen-Lenstra (APRCL) for general :math:`x`.
        
        If :math:`flag = 1`, use Selfridge-Pocklington-Lehmer ":math:`p-1`" test and output a
        primality certificate as follows: return
        
        - 0 if :math:`x` is composite,
        
        - 1 if :math:`x` is small enough that passing Baillie-PSW test guarantees
          its primality (currently :math:`x < 2^{64}`, as checked by Jan Feitsma),
        
        - :math:`2` if :math:`x` is a large prime whose primality could only sensibly be
          proven (given the algorithms implemented in PARI) using the APRCL test.
        
        - Otherwise (:math:`x` is large and :math:`x-1` is smooth) output a three column
          matrix as a primality certificate. The first column contains prime
          divisors :math:`p` of :math:`x-1` (such that :math:`\prod p^{v_p(x-1)} > x^{1/3}`), the second
          the corresponding elements :math:`a_p` as in Proposition 8.3.1 in GTM 138 , and the
          third the output of isprime(p,1).
        
        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
        :literal:`isprime` at a high enough debug level, you may see warnings about
        untested integers being declared primes. This is normal: we ask for partial
        factorisations (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 :literal:`isprime` procedure.
        
        If :math:`flag = 2`, use APRCL.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gisprime(_x, flag)
        return pari_instance.new_gen(_ret)

    def ispseudoprime(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` is a Baillie-Pomerance-Selfridge-Wagstaff
        pseudo prime (strong Rabin-Miller pseudo prime for base :math:`2`, followed by
        strong Lucas test for the sequence :math:`(P,-1)`, :math:`P` smallest positive integer
        such that :math:`P^2 - 4` is not a square mod :math:`x`).
        
        There are no known composite numbers passing this 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`).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gispseudoprime(_x, flag)
        return pari_instance.new_gen(_ret)

    def issquarefree(x):
        r"""
        True (1) if :math:`x` is squarefree, false (0) if not. Here :math:`x` can be an
        integer or a polynomial.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = issquarefree(_x)
        pari_instance.clear_stack()
        return _ret

    def kronecker(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`.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef long _ret = kronecker(_x, _y)
        pari_instance.clear_stack()
        return _ret

    def lambertw(y, long precision=0):
        r"""
        Lambert :math:`W` function, solution of the implicit equation :math:`xe^x = y`,
        for :math:`y > 0`.
        """
        cdef GEN _y = y.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = glambertW(_y, precision)
        return pari_instance.new_gen(_ret)

    def lcm(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.
        """
        cdef GEN _x = x.g
        cdef GEN _y = NULL
        if y is not None:
            y = objtogen(y)
            _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = glcm0(_x, _y)
        return pari_instance.new_gen(_ret)

    def length(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = glength(_x)
        pari_instance.clear_stack()
        return _ret

    def lex(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
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef int _ret = lexcmp(_x, _y)
        pari_instance.clear_stack()
        return _ret

    def lift(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).
        """
        cdef GEN _x = x.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = lift0(_x, _v)
        return pari_instance.new_gen(_ret)

    def liftall(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = liftall(_x)
        return pari_instance.new_gen(_ret)

    def liftint(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)
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = liftint(_x)
        return pari_instance.new_gen(_ret)

    def liftpol(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = liftpol(_x)
        return pari_instance.new_gen(_ret)

    def lindep(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, :math:`flag` is ignored and the function returns a non trivial
        kernel vector (combination of the columns).
        
        ::
        
            ? lindep([1,2,3;4,5,6;7,8,9])
            %3 = [1, -2, 1]~
        
        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
        """
        cdef GEN _v = v.g
        pari_catch_sig_on()
        cdef GEN _ret = lindep0(_v, flag)
        return pari_instance.new_gen(_ret)

    def lngamma(x, long precision=0):
        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
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = glngamma(_x, precision)
        return pari_instance.new_gen(_ret)

    def log(x, long precision=0):
        r"""
        Principal branch of the natural logarithm of
        :math:`x belongs to \mathbb{C}^*`, i.e. such that :math:`{Im(log}(x)) belongs to ]-\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 belongs to \mathbb{R}^*`. The result is complex
        (with imaginary part equal to :math:`\Pi`) if :math:`x belongs to \mathbb{R}` and :math:`x < 0`. In general,
        the algorithm uses the formula
        
        .. MATH::
        
            \log(x) ~ (\Pi)/(2{agm}(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`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = glog(_x, precision)
        return pari_instance.new_gen(_ret)

    def mapdelete(M, x):
        r"""
        Remove :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]
        """
        cdef GEN _M = M.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        mapdelete(_M, _x)
        pari_instance.clear_stack()

    def mapget(M, x):
        r"""
        Return 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
        """
        cdef GEN _M = M.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = mapget(_M, _x)
        return pari_instance.new_gen(_ret)

    def matadjoint(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.
        """
        cdef GEN _M = M.g
        pari_catch_sig_on()
        cdef GEN _ret = matadjoint0(_M, flag)
        return pari_instance.new_gen(_ret)

    def matalgtobasis(nf, x):
        r"""
        :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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = matalgtobasis(_nf, _x)
        return pari_instance.new_gen(_ret)

    def matbasistoalg(nf, x):
        r"""
        :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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = matbasistoalg(_nf, _x)
        return pari_instance.new_gen(_ret)

    def matcompanion(x):
        r"""
        The left companion matrix to the non-zero polynomial :math:`x`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = matcompanion(_x)
        return pari_instance.new_gen(_ret)

    def matconcat(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]
        """
        cdef GEN _v = v.g
        pari_catch_sig_on()
        cdef GEN _ret = matconcat(_v)
        return pari_instance.new_gen(_ret)

    def matdet(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = det0(_x, flag)
        return pari_instance.new_gen(_ret)

    def matdetint(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.
        """
        cdef GEN _B = B.g
        pari_catch_sig_on()
        cdef GEN _ret = detint(_B)
        return pari_instance.new_gen(_ret)

    def matdiagonal(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]
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = diagonal(_x)
        return pari_instance.new_gen(_ret)

    def mateigen(x, long flag=0, long precision=0):
        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`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = mateigen(_x, flag, precision)
        return pari_instance.new_gen(_ret)

    def matfrobenius(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`.
        """
        cdef GEN _M = M.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = matfrobenius(_M, flag, _v)
        return pari_instance.new_gen(_ret)

    def mathess(x):
        r"""
        Returns a matrix similar to the square matrix :math:`x`, which is in upper Hessenberg
        form (zero entries below the first subdiagonal).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = hess(_x)
        return pari_instance.new_gen(_ret)

    def mathnf(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 :math:`0,1,2,3` of :math:`flag` have a binary meaning, analogous to the one
        in :literal:`matsnf`; in this case, binary digits of :math:`flag` mean:
        
        - 1 (complete output): if set, outputs :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.
        
        - 2 (generic input): :emphasis:`Deprecated`. If set, assume that :math:`R = K[X]` is
          a polynomial ring; otherwise, assume that :math:`R = \mathbb{Z}`. This flag is now useless
          since the routine always checks whether the matrix has integral entries.
        
        For these 4 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 in general 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]
        """
        cdef GEN _M = M.g
        pari_catch_sig_on()
        cdef GEN _ret = mathnf0(_M, flag)
        return pari_instance.new_gen(_ret)

    def mathnfmod(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.
        """
        cdef GEN _x = x.g
        d = objtogen(d)
        cdef GEN _d = (<gen>d).g
        pari_catch_sig_on()
        cdef GEN _ret = hnfmod(_x, _d)
        return pari_instance.new_gen(_ret)

    def mathnfmodid(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]
        """
        cdef GEN _x = x.g
        d = objtogen(d)
        cdef GEN _d = (<gen>d).g
        pari_catch_sig_on()
        cdef GEN _ret = hnfmodid(_x, _d)
        return pari_instance.new_gen(_ret)

    def mathouseholder(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`.
        """
        cdef GEN _Q = Q.g
        v = objtogen(v)
        cdef GEN _v = (<gen>v).g
        pari_catch_sig_on()
        cdef GEN _ret = mathouseholder(_Q, _v)
        return pari_instance.new_gen(_ret)

    def matimage(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!).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = matimage0(_x, flag)
        return pari_instance.new_gen(_ret)

    def matimagecompl(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`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = imagecompl(_x)
        return pari_instance.new_gen(_ret)

    def matindexrank(x):
        r"""
        :math:`x` 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(x,y,z)` is
        invertible.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = indexrank(_x)
        return pari_instance.new_gen(_ret)

    def matintersect(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = intersect(_x, _y)
        return pari_instance.new_gen(_ret)

    def matinverseimage(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]
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = inverseimage(_x, _y)
        return pari_instance.new_gen(_ret)

    def matisdiagonal(x):
        r"""
        Returns true (1) if :math:`x` is a diagonal matrix, false (0) if not.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef int _ret = isdiagonal(_x)
        pari_instance.clear_stack()
        return _ret

    def matker(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`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = matker0(_x, flag)
        return pari_instance.new_gen(_ret)

    def matkerint(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = matkerint0(_x, flag)
        return pari_instance.new_gen(_ret)

    def matmuldiagonal(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)`.
        """
        cdef GEN _x = x.g
        d = objtogen(d)
        cdef GEN _d = (<gen>d).g
        pari_catch_sig_on()
        cdef GEN _ret = matmuldiagonal(_x, _d)
        return pari_instance.new_gen(_ret)

    def matmultodiagonal(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = matmultodiagonal(_x, _y)
        return pari_instance.new_gen(_ret)

    def matqr(M, long flag=0, long precision=0):
        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.
        """
        cdef GEN _M = M.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = matqr(_M, flag, precision)
        return pari_instance.new_gen(_ret)

    def matrank(x):
        r"""
        Rank of the matrix :math:`x`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = rank(_x)
        pari_instance.clear_stack()
        return _ret

    def matrixqz(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 belongs to 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]
        """
        cdef GEN _A = A.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = matrixqz0(_A, _p)
        return pari_instance.new_gen(_ret)

    def matsize(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).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = matsize(_x)
        return pari_instance.new_gen(_ret)

    def matsnf(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.
        """
        cdef GEN _X = X.g
        pari_catch_sig_on()
        cdef GEN _ret = matsnf0(_X, flag)
        return pari_instance.new_gen(_ret)

    def matsolve(M, B):
        r"""
        :math:`M` being an invertible matrix and :math:`B` a column
        vector, finds the solution :math:`X` of :math:`MX = B`, using Dixon :math:`p`-adic lifting method
        if :math:`M` and :math:`B` are integral and Gaussian elimination otherwise. This
        has the same effect as, but is faster, than :math:`M^{-1}*B`.
        """
        cdef GEN _M = M.g
        B = objtogen(B)
        cdef GEN _B = (<gen>B).g
        pari_catch_sig_on()
        cdef GEN _ret = gauss(_M, _B)
        return pari_instance.new_gen(_ret)

    def matsolvemod(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 a small 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 = [-2, 0]~
            ? matsolvemod(M, 3, 1) \\ M X = [1,1]~ over F_3
            %3 = [-1, 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 a small 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.
        """
        cdef GEN _M = M.g
        D = objtogen(D)
        cdef GEN _D = (<gen>D).g
        B = objtogen(B)
        cdef GEN _B = (<gen>B).g
        pari_catch_sig_on()
        cdef GEN _ret = matsolvemod0(_M, _D, _B, flag)
        return pari_instance.new_gen(_ret)

    def matsupplement(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = suppl(_x)
        return pari_instance.new_gen(_ret)

    def mattranspose(x):
        r"""
        Transpose of :math:`x` (also :math:`x~`).
        This has an effect only on vectors and matrices.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtrans(_x)
        return pari_instance.new_gen(_ret)

    def max(x, y):
        r"""
        Creates the maximum of :math:`x` and :math:`y` when they can be compared.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = gmax(_x, _y)
        return pari_instance.new_gen(_ret)

    def min(x, y):
        r"""
        Creates the maximum of :math:`x` and :math:`y` when they can be compared.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = gmin(_x, _y)
        return pari_instance.new_gen(_ret)

    def minpoly(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`.
        """
        cdef GEN _A = A.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = minpoly(_A, _v)
        return pari_instance.new_gen(_ret)

    def modreverse(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) belongs to \mathbb{Q}(u)` and :math:`B(v) belongs to \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
        """
        cdef GEN _z = z.g
        pari_catch_sig_on()
        cdef GEN _ret = modreverse(_z)
        return pari_instance.new_gen(_ret)

    def moebius(x):
        r"""
        Moebius :math:`\mu`-function of :math:`\|x\|`. :math:`x` must be of type integer.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = moebius(_x)
        pari_instance.clear_stack()
        return _ret

    def msatkinlehner(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
        """
        cdef GEN _M = M.g
        cdef GEN _H = NULL
        if H is not None:
            H = objtogen(H)
            _H = (<gen>H).g
        pari_catch_sig_on()
        cdef GEN _ret = msatkinlehner(_M, Q, _H)
        return pari_instance.new_gen(_ret)

    def mscuspidal(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]
        """
        cdef GEN _M = M.g
        pari_catch_sig_on()
        cdef GEN _ret = mscuspidal(_M, flag)
        return pari_instance.new_gen(_ret)

    def mseisenstein(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
        """
        cdef GEN _M = M.g
        pari_catch_sig_on()
        cdef GEN _ret = mseisenstein(_M)
        return pari_instance.new_gen(_ret)

    def mseval(M, s, p=None):
        r"""
        Let :math:`\Delta := {Div}^0(\\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:`{Hom}_G(\Delta, V)`, and let :math:`p = [a,b] belongs to \Delta` be a path between
        two elements in :math:`\\P^1(\mathbb{Q})`, return :math:`s(p) belongs to V`. The path extremities :math:`a` and
        :math:`b` may be given as :literal:`t_INT`, :literal:`t_FRAC` or :math:`oo = (1:0)`.
        The symbol :math:`s` is either
        
        - a :literal:`t_COL` coding an element of a modular symbol subspace in terms of
          the fixed basis of :math:`{Hom}_G(\Delta,V)` chosen in :math:`M`;
        
        - 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 the symbol :math:`s` to the second form: a vector of
        the :math:`s(g_i)`.
        
        ::
        
            ? M = msinit(2,8,1); \\ M_8(Gamma_0(2))^+
            ? g = mspathgens(M)[1]
            %2 = [[+oo, 0], [0, 1]]
            ? N = msnew(M)[1]; \\ Q-basis of new subspace
            ? s = N[,1] \\ t_COL representation
            %4 = [3, 30, 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])
            %6 = 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.
        """
        cdef GEN _M = M.g
        s = objtogen(s)
        cdef GEN _s = (<gen>s).g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = mseval(_M, _s, _p)
        return pari_instance.new_gen(_ret)

    def msfromell(E, long sign=1):
        r"""
        Let :math:`E/\mathbb{Q}` be an elliptic curve of conductor :math:`N`. Return the (cuspidal,
        new) modular symbol :math:`x^+` in :math:`H^1_c(X_0(N),\mathbb{Q})^+` (resp. :math:`x^-` in
        :math:`H^1_c(X_0(N),\mathbb{Q})^-` if :math:`sign = -1`) associated to
        :math:`E`. For all primes :math:`p` not dividing :math:`N` we have
        :math:`T_p(x^±) = a_p x^±`, where :math:`a_p = p+1-\#E(\mathbb{F}_p)`.
        This defines a unique symbol up to multiplication by a constant
        and we normalize it so that the associated :math:`p`-adic measure yields the
        :math:`p`-adic :math:`L`-function. Namely, we have
        
        .. MATH::
        
            x^{±}([0]-[ oo ]) = L(E,1) / \Omega,
        
        for :math:`\Omega` the real period of :math:`E` (which fixes :math:`x^{±}` unless :math:`L(E,1) = 0`).
        Furthermore, for all odd fundamental discriminants :math:`d` coprime to :math:`N` such
        that :math:`sign.d > 0` and :math:`L(E^{(d)},1) != 0`, we also have
        
        .. MATH::
        
            \sum_{0 <= a < \|d\|} (d\|a) x^{±}([a/\|d\|]-[ oo ])
            = L(E^{(d)},1) / \Omega_d,
        
        where :math:`(d\|a)` is the Kronecker symbol and :math:`\Omega_d` is the real
        period of the twist :math:`E^{(d)}`.
        
        This function returns the pair :math:`[M, x]`, where :math:`M` is
        :literal:`msinit`:math:`(N,2)` and :math:`x` is :math:`x^±` as a :literal:`t_COL` (in terms
        of the fixed basis of :math:`{Hom}_G(\Delta,\mathbb{Q})` chosen in :math:`M`).
        
        ::
        
            ? E=ellinit([0,-1,1,-10,-20]); \\ X_0(11)
            ? [M,xpm]= msfromell(E,1);
            ? xpm
            %3 = [1/5, -1/2, -1/2]~
            ? p = 101; (mshecke(M,p) - ellap(E,p))*xpm
            %4 = [0, 0, 0]~ \\ true at all primes
        """
        cdef GEN _E = E.g
        pari_catch_sig_on()
        cdef GEN _ret = msfromell(_E, sign)
        return pari_instance.new_gen(_ret)

    def mshecke(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 =
            [ 0]
            
            [-1]
            
            [-1]
            ? p = 1009; mshecke(M, p, N) \\ action of T_1009 on N
            %6 =
            [-10]
            ? ellap(ellinit("11a1"), p)
            %7 = -10
        """
        cdef GEN _M = M.g
        cdef GEN _H = NULL
        if H is not None:
            H = objtogen(H)
            _H = (<gen>H).g
        pari_catch_sig_on()
        cdef GEN _ret = mshecke(_M, p, _H)
        return pari_instance.new_gen(_ret)

    def msinit(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:`{Hom}_G({Div}^0(\\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 > 1`.
        The only supported representation is :math:`V_k = \mathbb{Q}[X,Y]_{k-2}`, coded by the
        integer :math:`k >= 2`.
        """
        cdef GEN _G = G.g
        V = objtogen(V)
        cdef GEN _V = (<gen>V).g
        pari_catch_sig_on()
        cdef GEN _ret = msinit(_G, _V, sign)
        return pari_instance.new_gen(_ret)

    def msissymbol(M, s):
        r"""
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`,
        check whether :math:`s` is a modular symbol associated to :math:`M`.
        
        ::
        
            ? M = msinit(7,8, 1); \\ M_8(Gamma_0(7))^+
            ? N = msnew(M)[1];
            ? s = N[,1];
            ? msissymbol(M, s)
            %4 = 1
            ? S = mseval(M,s);
            ? msissymbol(M, S)
            %6 = 1
            ? [g,R] = mspathgens(M); g
            %7 = [[+oo, 0], [0, 1/2], [1/2, 1]]
            ? #R \\ 3 relations among the generators g_i
            %8 = 3
            ? T = S; T[3]++; \\ randomly perturb S(g_3)
            ? msissymbol(M, T)
            %10 = 0 \\ no longer satisfies the relations
        """
        cdef GEN _M = M.g
        s = objtogen(s)
        cdef GEN _s = (<gen>s).g
        pari_catch_sig_on()
        cdef long _ret = msissymbol(_M, _s)
        pari_instance.clear_stack()
        return _ret

    def msnew(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
        """
        cdef GEN _M = M.g
        pari_catch_sig_on()
        cdef GEN _ret = msnew(_M)
        return pari_instance.new_gen(_ret)

    def mspathgens(M):
        r"""
        Let :math:`\Delta := {Div}^0(\\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 belongs to \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 coded by a "factorization matrix": the first
        column contains distinct elements of :math:`G`, and the second integers:
        
        ::
        
            ? 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 belongs to \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`.
        """
        cdef GEN _M = M.g
        pari_catch_sig_on()
        cdef GEN _ret = mspathgens(_M)
        return pari_instance.new_gen(_ret)

    def mspathlog(M, p):
        r"""
        Let :math:`\Delta := {Div}^0(\\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:`\\P^1(\mathbb{Q})` corresponds to
        :math:`[b]-[a] belongs to \Delta`. The path extremities :math:`a` and :math:`b` may be given as
        :literal:`t_INT`, :literal:`t_FRAC` or :math:`oo = (1:0)`.
        
        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]
            %6 =
            [[1, 0; 2, 1] 1]
            
            ? p[2]
            %7 =
            [ [1, 0; 0, 1] 1]
            
            [[3, -1; 4, -1] 1]
            
        
        Note that the output depends only on the group :math:`G`, not on the
        representation :math:`V`.
        """
        cdef GEN _M = M.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = mspathlog(_M, _p)
        return pari_instance.new_gen(_ret)

    def msqexpansion(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]
        """
        cdef GEN _M = M.g
        projH = objtogen(projH)
        cdef GEN _projH = (<gen>projH).g
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        pari_catch_sig_on()
        cdef GEN _ret = msqexpansion(_M, _projH, serprec)
        return pari_instance.new_gen(_ret)

    def mssplit(M, H):
        r"""
        :math:`M` being a full modular symbol space, as given by :literal:`msinit`:math:`(N,k,1)`
        or :math:`msinit(N,k,-1)`
        and :math:`H` being a Hecke-stable subspace of :literal:`msnew`:math:`(M)`, split :math:`H` into
        Hecke-simple subspaces.
        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, 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.
        """
        cdef GEN _M = M.g
        H = objtogen(H)
        cdef GEN _H = (<gen>H).g
        pari_catch_sig_on()
        cdef GEN _ret = mssplit(_M, _H)
        return pari_instance.new_gen(_ret)

    def msstar(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
        """
        cdef GEN _M = M.g
        cdef GEN _H = NULL
        if H is not None:
            H = objtogen(H)
            _H = (<gen>H).g
        pari_catch_sig_on()
        cdef GEN _ret = msstar(_M, _H)
        return pari_instance.new_gen(_ret)

    def newtonpoly(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:`LONG_MAX`, the biggest single precision
        integer representable on the machine (:math:`2^{31}-1` (resp. :math:`2^{63}-1`) on 32-bit
        (resp. 64-bit) machines), see ``valuation`` (in the PARI manual).
        """
        cdef GEN _x = x.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = newtonpoly(_x, _p)
        return pari_instance.new_gen(_ret)

    def nextprime(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`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = nextprime(_x)
        return pari_instance.new_gen(_ret)

    def nfalgtobasis(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))
            %4 = [0, 2]~
        
        This is the inverse function of :literal:`nfbasistoalg`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = algtobasis(_nf, _x)
        return pari_instance.new_gen(_ret)

    def nfbasistoalg(nf, x):
        r"""
        Given an algebraic number :math:`x` in the number field :literal:`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))
            %4 = Mod(y, y^2 + 4)
        
        This is the inverse function of :literal:`nfalgtobasis`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = basistoalg(_nf, _x)
        return pari_instance.new_gen(_ret)

    def nfcertify(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.
        
        The function returns a vector of 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
        them, then check whether :literal:`nfdisc(nf.pol)` is equal to :literal:`nf.disc`.
        """
        cdef GEN _nf = nf.g
        pari_catch_sig_on()
        cdef GEN _ret = nfcertify(_nf)
        return pari_instance.new_gen(_ret)

    def nfcompositum(nf, P, Q, long flag=0):
        r"""
        Let :emphasis:`nf` be a number field structure associated 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]`, associated 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 which 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/5})`, :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
            %3 = 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
            %4 = 0
            ? [T, X] = rnfpolredbest(K, R, 1);
            ? lift(T) \\ simpler defining polynomial for K[x]/(R)
            %6 = x^10 + (-11/2*y + 25/2)
            ? liftall(X) \\  root of R in K[x]/(T(x))
            %7 = (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)
            %8 = (-3/4*y - 7/4)*x^7 - 1/2*x^2
            ? a^5 - y
            %9 = 0
        """
        cdef GEN _nf = nf.g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        Q = objtogen(Q)
        cdef GEN _Q = (<gen>Q).g
        pari_catch_sig_on()
        cdef GEN _ret = nfcompositum(_nf, _P, _Q, flag)
        return pari_instance.new_gen(_ret)

    def nfdetint(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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = nfdetint(_nf, _x)
        return pari_instance.new_gen(_ret)

    def nfdisc(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)
            %1 = -24
            ? padicdisc(x^2 + 6, 2)
            %2 = 8
            ? padicdisc(x^2 + 6, 3)
            %3 = 3
        """
        cdef GEN _T = T.g
        pari_catch_sig_on()
        cdef GEN _ret = nfdisc(_T)
        return pari_instance.new_gen(_ret)

    def nfeltadd(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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = nfadd(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def nfeltdiv(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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = nfdiv(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def nfeltdiveuc(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))`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = nfdiveuc(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def nfeltdivmodpr(nf, x, y, pr):
        r"""
        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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = nfdivmodpr(_nf, _x, _y, _pr)
        return pari_instance.new_gen(_ret)

    def nfeltdivrem(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.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = nfdivrem(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def nfeltmod(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).
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = nfmod(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def nfeltmul(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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = nfmul(_nf, _x, _y)
        return pari_instance.new_gen(_ret)

    def nfeltmulmodpr(nf, x, y, pr):
        r"""
        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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = nfmulmodpr(_nf, _x, _y, _pr)
        return pari_instance.new_gen(_ret)

    def nfeltnorm(nf, x):
        r"""
        Returns the absolute norm of :math:`x`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = nfnorm(_nf, _x)
        return pari_instance.new_gen(_ret)

    def nfeltpow(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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        k = objtogen(k)
        cdef GEN _k = (<gen>k).g
        pari_catch_sig_on()
        cdef GEN _ret = nfpow(_nf, _x, _k)
        return pari_instance.new_gen(_ret)

    def nfeltpowmodpr(nf, x, k, pr):
        r"""
        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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        k = objtogen(k)
        cdef GEN _k = (<gen>k).g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = nfpowmodpr(_nf, _x, _k, _pr)
        return pari_instance.new_gen(_ret)

    def nfeltreduce(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.
        """
        cdef GEN _nf = nf.g
        a = objtogen(a)
        cdef GEN _a = (<gen>a).g
        id = objtogen(id)
        cdef GEN _id = (<gen>id).g
        pari_catch_sig_on()
        cdef GEN _ret = nfreduce(_nf, _a, _id)
        return pari_instance.new_gen(_ret)

    def nfeltreducemodpr(nf, x, pr):
        r"""
        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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = nfreducemodpr(_nf, _x, _pr)
        return pari_instance.new_gen(_ret)

    def nfelttrace(nf, x):
        r"""
        Returns the absolute trace of :math:`x`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = nftrace(_nf, _x)
        return pari_instance.new_gen(_ret)

    def nffactor(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
        compute the field discriminant due to integer factorization difficulties. In
        the latter case, if you must use a partial discriminant factorization (as
        allowed by both :literal:`nfdisc` or :literal:`nfbasis`) to build a partially correct
        :emphasis:`nf` structure, always input :literal:`nf.pol` to :literal:`nffactor`, and not your
        makeshift :emphasis:`nf`: otherwise factors could be missed.
        """
        cdef GEN _nf = nf.g
        T = objtogen(T)
        cdef GEN _T = (<gen>T).g
        pari_catch_sig_on()
        cdef GEN _ret = nffactor(_nf, _T)
        return pari_instance.new_gen(_ret)

    def nffactorback(nf, f, e=None):
        r"""
        Gives back the :literal:`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
        """
        cdef GEN _nf = nf.g
        f = objtogen(f)
        cdef GEN _f = (<gen>f).g
        cdef GEN _e = NULL
        if e is not None:
            e = objtogen(e)
            _e = (<gen>e).g
        pari_catch_sig_on()
        cdef GEN _ret = nffactorback(_nf, _f, _e)
        return pari_instance.new_gen(_ret)

    def nffactormod(nf, Q, pr):
        r"""
        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)
            [x + (2*y + 1) 1]
            
            [x + (2*y + 2) 1]
        
        Same result, of course, here about 10\% faster due to the
        precomputation.
        """
        cdef GEN _nf = nf.g
        Q = objtogen(Q)
        cdef GEN _Q = (<gen>Q).g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = nffactormod(_nf, _Q, _pr)
        return pari_instance.new_gen(_ret)

    def nfgaloisapply(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]
             %7 = 0 \\ !!!!
             ? idealval(nf, nfgaloisapply(nf, aut, P[2]), P[1])
             %8 = 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);
             ? l = nfgaloisconj(nf); aut = l[2] \\  automorphisms in basistoalg form
             %2 = -31/11*x^2 + 1109/11*x - 925/11
             ? L = matalgtobasis(nf, l); AUT = L[2] \\  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 = 1,451 ms.
             ? for (i=1,10^5, nfgaloisapply(nf, AUT, v))
             time = 1,045 ms. \\  but the latter is faster
        """
        cdef GEN _nf = nf.g
        aut = objtogen(aut)
        cdef GEN _aut = (<gen>aut).g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = galoisapply(_nf, _aut, _x)
        return pari_instance.new_gen(_ret)

    def nfgaloisconj(nf, long flag=0, d=None, long precision=0):
        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 = 2` (OBSOLETE), use complex approximations to the roots and an integral
        LLL. The result is not guaranteed to be complete: some
        conjugates may be missing (a warning is issued if the result is not proved
        complete), especially so if the corresponding polynomial has a huge index,
        and increasing the default precision may help. This variant is slow and
        unreliable: don't use it.
        
        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);
             R *= Mod(1, nfK.pol); \\ convert coeffs to polmod elts of K
             polabs = rnfequation(nfK, R);
             N = nfgaloisconj(polabs) % R; \\ Q-automorphisms of L
             \\ select the ones that fix K
             select(s->subst(R, variable(R), Mod(s,R)) == 0, N);
            }
            K = nfinit(y^2 + 7);
            rnfgaloisconj(K, x^4 - y*x^3 - 3*x^2 + y*x + 1) \\ K-automorphisms of L
        """
        cdef GEN _nf = nf.g
        cdef GEN _d = NULL
        if d is not None:
            d = objtogen(d)
            _d = (<gen>d).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = galoisconj0(_nf, flag, _d, precision)
        return pari_instance.new_gen(_ret)

    def nfgrunwaldwang(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 :literal:`Lpr[i]`, the extension has local degree a multiple of
          :literal:`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 :emphasis:`prid`
        structures. However, their primality is not checked and the behaviour 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)
        """
        cdef GEN _nf = nf.g
        Lpr = objtogen(Lpr)
        cdef GEN _Lpr = (<gen>Lpr).g
        Ld = objtogen(Ld)
        cdef GEN _Ld = (<gen>Ld).g
        pl = objtogen(pl)
        cdef GEN _pl = (<gen>pl).g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = nfgrunwaldwang(_nf, _Lpr, _Ld, _pl, _v)
        return pari_instance.new_gen(_ret)

    def nfhilbert(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`.
        """
        cdef GEN _nf = nf.g
        a = objtogen(a)
        cdef GEN _a = (<gen>a).g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        cdef GEN _pr = NULL
        if pr is not None:
            pr = objtogen(pr)
            _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef long _ret = nfhilbert0(_nf, _a, _b, _pr)
        pari_instance.clear_stack()
        return _ret

    def nfhnf(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 transfomation matrix :math:`U` such that
        :math:`AU = [0\|B]`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = nfhnf0(_nf, _x, flag)
        return pari_instance.new_gen(_ret)

    def nfhnfmod(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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        detx = objtogen(detx)
        cdef GEN _detx = (<gen>detx).g
        pari_catch_sig_on()
        cdef GEN _ret = nfhnfmod(_nf, _x, _detx)
        return pari_instance.new_gen(_ret)

    def nfinit(pol, long flag=0, long precision=0):
        r"""
        :emphasis:`pol` being a non-constant,
        preferably monic, irreducible polynomial in :math:`\mathbb{Z}[X]`, initializes a
        :emphasis:`number field` structure (:literal:`nf`) associated 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 specified 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 :emphasis:`nf` structure associated 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.
        
        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`.
        """
        cdef GEN _pol = pol.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = nfinit0(_pol, flag, precision)
        return pari_instance.new_gen(_ret)

    def nfisideal(nf, x):
        r"""
        Returns 1 if :math:`x` is an ideal in the number field :math:`nf`, 0 otherwise.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef long _ret = isideal(_nf, _x)
        pari_instance.clear_stack()
        return _ret

    def nfisincl(x, y):
        r"""
        Tests whether the number field :math:`K` defined
        by the polynomial :math:`x` is conjugate to a subfield of the field :math:`L` defined
        by :math:`y` (where :math:`x` and :math:`y` must be in :math:`\mathbb{Q}[X]`). If they are not, the output
        is the number 0. If they are, the output is a vector of polynomials, each
        polynomial :math:`a` representing an embedding of :math:`K` into :math:`L`, i.e. being such
        that :math:`y \| x o a`.
        
        If :math:`y` is a number field (:emphasis:`nf`), a much faster algorithm is used
        (factoring :math:`x` over :math:`y` using :literal:`nffactor`). Before version 2.0.14, this
        wasn't guaranteed to return all the embeddings, hence was triggered by a
        special flag. This is no more the case.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = nfisincl(_x, _y)
        return pari_instance.new_gen(_ret)

    def nfisisom(x, y):
        r"""
        As :literal:`nfisincl`, but tests for isomorphism. If either :math:`x` or :math:`y` is a
        number field, a much faster algorithm will be used.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = nfisisom(_x, _y)
        return pari_instance.new_gen(_ret)

    def nfkermodpr(nf, x, pr):
        r"""
        Kernel of the matrix :math:`a` in :math:`\mathbb{Z}_K/pr`, where :emphasis:`pr` is in
        :strong:`modpr` format (see :literal:`nfmodprinit`).
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = nfkermodpr(_nf, _x, _pr)
        return pari_instance.new_gen(_ret)

    def nfmodprinit(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`.
        """
        cdef GEN _nf = nf.g
        pr = objtogen(pr)
        cdef GEN _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = nfmodprinit(_nf, _pr)
        return pari_instance.new_gen(_ret)

    def nfnewprec(nf, long precision=0):
        r"""
        Transforms the number field :math:`nf`
        into the corresponding data using current (usually larger) precision. This
        function works as expected if :math:`nf` is in fact a :math:`bnf` (update
        :math:`bnf` to current precision) but may be quite slow (many generators of
        principal ideals have to be computed).
        """
        cdef GEN _nf = nf.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = nfnewprec(_nf, precision)
        return pari_instance.new_gen(_ret)

    def nfroots(nf, x):
        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 be computed internally. This is useful in two situations: when
        you don't need the :literal:`nf`, or when you can't compute its discriminant due
        to integer factorization difficulties. In the latter case, :literal:`addprimes` is
        a possibility but a dangerous one: roots will probably be missed if the
        (true) field discriminant and an :literal:`addprimes` entry are strictly divisible
        by some prime. If you have such an unsafe :emphasis:`nf`, it is safer to input
        :literal:`nf.pol`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = nfroots(_nf, _x)
        return pari_instance.new_gen(_ret)

    def nfrootsof1(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.
        """
        cdef GEN _nf = nf.g
        pari_catch_sig_on()
        cdef GEN _ret = rootsof1(_nf)
        return pari_instance.new_gen(_ret)

    def nfsnf(nf, x, long flag=0):
        r"""
        Given a torsion :math:`\mathbb{Z}_K`-module :math:`x` associated 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} belongs to 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`.
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = nfsnf0(_nf, _x, flag)
        return pari_instance.new_gen(_ret)

    def nfsolvemodpr(nf, a, b, P):
        r"""
        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]~
        """
        cdef GEN _nf = nf.g
        a = objtogen(a)
        cdef GEN _a = (<gen>a).g
        b = objtogen(b)
        cdef GEN _b = (<gen>b).g
        P = objtogen(P)
        cdef GEN _P = (<gen>P).g
        pari_catch_sig_on()
        cdef GEN _ret = nfsolvemodpr(_nf, _a, _b, _P)
        return pari_instance.new_gen(_ret)

    def nfsplitting(nf, d=None):
        r"""
        Defining polynomial for the splitting field of :emphasis:`nf`;
        if :math:`d` is given, it must be the degree of the splitting field. It
        is possible to input a defining polynomial :math:`T` instead but this is in
        general less efficient.
        
        ::
        
            ? K = nfinit(x^3-2);
            ? nfsplitting(K)
            %2 = x^6 + 108
            ? nfsplitting(x^8-2)
            %3 = x^16 + 272*x^8 + 64
        
        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.
        """
        cdef GEN _nf = nf.g
        cdef GEN _d = NULL
        if d is not None:
            d = objtogen(d)
            _d = (<gen>d).g
        pari_catch_sig_on()
        cdef GEN _ret = nfsplitting(_nf, _d)
        return pari_instance.new_gen(_ret)

    def nfsubfields(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).
        """
        cdef GEN _pol = pol.g
        pari_catch_sig_on()
        cdef GEN _ret = nfsubfields(_pol, d)
        return pari_instance.new_gen(_ret)

    def norm(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gnorm(_x)
        return pari_instance.new_gen(_ret)

    def norml2(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gnorml2(_x)
        return pari_instance.new_gen(_ret)

    def normlp(x, p=None, long precision=0):
        r"""
        :math:`L^p`-norm of :math:`x`; sup norm if :math:`p` is omitted. 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, :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
            ? M = [1,-2;-3,4]; normlp(M) \\ matrix
            %2 = 4
            ? T = (1+I) + I*x^2; normlp(T)
            %3 = 1.4142135623730950488016887242096980786
            ? normlp([[1,2], [3,4], 5, 6]) \\ recursively defined
            %4 = 6
            
            ? normlp(v, 1)
            %5 = 6
            ? normlp(M, 1)
            %6 = 10
            ? normlp(T, 1)
            %7 = 2.4142135623730950488016887242096980786
        """
        cdef GEN _x = x.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gnormlp(_x, _p, precision)
        return pari_instance.new_gen(_ret)

    def numbpart(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`.
        """
        cdef GEN _n = n.g
        pari_catch_sig_on()
        cdef GEN _ret = numbpart(_n)
        return pari_instance.new_gen(_ret)

    def numdiv(x):
        r"""
        Number of divisors of :math:`\|x\|`. :math:`x` must be of type integer.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = numdiv(_x)
        return pari_instance.new_gen(_ret)

    def numerator(x):
        r"""
        Numerator of :math:`x`. The meaning of this
        is clear when :math:`x` is a rational number or function. If :math:`x` is an integer
        or a polynomial, it is treated as a rational number or function,
        respectively, and the result is :math:`x` itself. For polynomials, you
        probably want to use
        
        ::
        
            numerator( content(x) )
        
        instead.
        
        In other cases, :literal:`numerator(x)` is defined to be
        :literal:`denominator(x)*x`. This is the case when :math:`x` is a vector or a
        matrix, but also for :literal:`t_COMPLEX` or :literal:`t_QUAD`. In particular since a
        :literal:`t_PADIC` or :literal:`t_INTMOD` has denominator :math:`1`, its numerator is
        itself.
        
        :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).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = numer(_x)
        return pari_instance.new_gen(_ret)

    def omega(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = omega(_x)
        pari_instance.clear_stack()
        return _ret

    def padicappr(pol, a):
        r"""
        Vector of :math:`p`-adic roots of the
        polynomial :math:`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 extension of :math:`\mathbb{Q}_p`, given as a :literal:`t_POLMOD`
        at least one of whose coefficients is a :literal:`t_PADIC`. In this case, the result
        is the vector of roots belonging to the same extension of :math:`\mathbb{Q}_p` as :math:`a`.
        """
        cdef GEN _pol = pol.g
        a = objtogen(a)
        cdef GEN _a = (<gen>a).g
        pari_catch_sig_on()
        cdef GEN _ret = padicappr(_pol, _a)
        return pari_instance.new_gen(_ret)

    def padicfields(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.
        """
        cdef GEN _p = p.g
        N = objtogen(N)
        cdef GEN _N = (<gen>N).g
        pari_catch_sig_on()
        cdef GEN _ret = padicfields0(_p, _N, flag)
        return pari_instance.new_gen(_ret)

    def padicprec(x, p):
        r"""
        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:`LONG_MAX`
        (:math:`2^{31}-1` for 32-bit machines or :math:`2^{63}-1` for 64-bit machines) if :math:`x` is
        an exact object.
        """
        cdef GEN _x = x.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef long _ret = padicprec(_x, _p)
        pari_instance.clear_stack()
        return _ret

    def parapply(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.
        """
        cdef GEN _f = f.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = parapply(_f, _x)
        return pari_instance.new_gen(_ret)

    def pareval(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = pareval(_x)
        return pari_instance.new_gen(_ret)

    def parselect(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.
        """
        cdef GEN _f = f.g
        A = objtogen(A)
        cdef GEN _A = (<gen>A).g
        pari_catch_sig_on()
        cdef GEN _ret = parselect(_f, _A, flag)
        return pari_instance.new_gen(_ret)

    def permtonum(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`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = permtonum(_x)
        return pari_instance.new_gen(_ret)

    def polclass(D, x=None):
        r"""
        Return the Hilbert class polynomial for the :math:`j` function for the imaginary quadratic
        discriminant :math:`D` in the variable :math:`x`.
        
        ::
        
            ? polclass(-163)
            %1 = x + 262537412640768000
            ? polclass(-51, 'z)
            %2 = z^2 + 5541101568*z + 6262062317568
        """
        cdef GEN _D = D.g
        cdef long _x = -1
        if x is not None:
            _x = pari_instance.get_var(x)
        pari_catch_sig_on()
        cdef GEN _ret = polclass(_D, _x)
        return pari_instance.new_gen(_ret)

    def polcoeff(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.
        
        For greater flexibility, :math:`x` can be a vector or matrix type and the
        function then returns :literal:`component(x,n)`.
        """
        cdef GEN _x = x.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = polcoeff0(_x, n, _v)
        return pari_instance.new_gen(_ret)

    def polcompositum(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]`, associated 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]
        """
        cdef GEN _P = P.g
        Q = objtogen(Q)
        cdef GEN _Q = (<gen>Q).g
        pari_catch_sig_on()
        cdef GEN _ret = polcompositum0(_P, _Q, flag)
        return pari_instance.new_gen(_ret)

    def polcyclofactors(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]
        """
        cdef GEN _f = f.g
        pari_catch_sig_on()
        cdef GEN _ret = polcyclofactors(_f)
        return pari_instance.new_gen(_ret)

    def poldegree(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.
        """
        cdef GEN _x = x.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = gppoldegree(_x, _v)
        return pari_instance.new_gen(_ret)

    def poldisc(pol, v=None):
        r"""
        Discriminant of the polynomial
        :emphasis:`pol` in the main variable if :math:`v` is omitted, in :math:`v` otherwise. The
        algorithm used is the subresultant algorithm.
        """
        cdef GEN _pol = pol.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = poldisc0(_pol, _v)
        return pari_instance.new_gen(_ret)

    def poldiscreduced(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`.
        """
        cdef GEN _f = f.g
        pari_catch_sig_on()
        cdef GEN _ret = reduceddiscsmith(_f)
        return pari_instance.new_gen(_ret)

    def polgalois(T, long precision=0):
        r"""
        Galois group of the non-constant
        polynomial :math:`T belongs to \mathbb{Q}[X]`. In the present version :strong:`2.8.0`, :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.
        """
        cdef GEN _T = T.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = polgalois(_T, precision)
        return pari_instance.new_gen(_ret)

    def polgraeffe(f):
        r"""
        Returns the Graeffe transform :math:`g` of :math:`f`, such that :math:`g(x^2) = f(x)
        f(-x)`.
        """
        cdef GEN _f = f.g
        pari_catch_sig_on()
        cdef GEN _ret = polgraeffe(_f)
        return pari_instance.new_gen(_ret)

    def polhensellift(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)
        """
        cdef GEN _A = A.g
        B = objtogen(B)
        cdef GEN _B = (<gen>B).g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = polhensellift(_A, _B, _p, e)
        return pari_instance.new_gen(_ret)

    def poliscyclo(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
        """
        cdef GEN _f = f.g
        pari_catch_sig_on()
        cdef long _ret = poliscyclo(_f)
        pari_instance.clear_stack()
        return _ret

    def poliscycloprod(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
        """
        cdef GEN _f = f.g
        pari_catch_sig_on()
        cdef long _ret = poliscycloprod(_f)
        pari_instance.clear_stack()
        return _ret

    def polisirreducible(pol):
        r"""
        :emphasis:`pol` being a polynomial (univariate in the present version :strong:`2.8.0`),
        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.
        """
        cdef GEN _pol = pol.g
        pari_catch_sig_on()
        cdef long _ret = isirreducible(_pol)
        pari_instance.clear_stack()
        return _ret

    def pollead(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.
        """
        cdef GEN _x = x.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = pollead(_x, _v)
        return pari_instance.new_gen(_ret)

    def polrecip(pol):
        r"""
        Reciprocal polynomial of :emphasis:`pol`, i.e. the coefficients are in
        reverse order. :emphasis:`pol` must be a polynomial.
        """
        cdef GEN _pol = pol.g
        pari_catch_sig_on()
        cdef GEN _ret = polrecip(_pol)
        return pari_instance.new_gen(_ret)

    def polred(T, long flag=0, _arg2=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 is equal to :math:`x-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 x^2 + 2]
            
            [1/4*x^3 x^4 + 2]
            
            [x x^4 + 8]
            ? minpoly(Mod(M[2,1], x^4+8))
            %2 = x^2 + 2
        """
        cdef GEN _T = T.g
        cdef GEN __arg2 = NULL
        if _arg2 is not None:
            _arg2 = objtogen(_arg2)
            __arg2 = (<gen>_arg2).g
        pari_catch_sig_on()
        cdef GEN _ret = polred0(_T, flag, __arg2)
        return pari_instance.new_gen(_ret)

    def polredabs(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.
        
        :strong:`Warning 1.` Using a :literal:`t_POL` :math:`T` requires fully factoring the
        discriminant of :math:`T`, which may be very hard. The format :literal:`[T, listP]`
        computes only a suborder of the maximal order and replaces this part of the
        algorithm by a polynomial time computation. In that case the polynomial :math:`P`
        is a priori no longer canonical, and it may happen that it does not have
        minimal :math:`T_2` norm. The routine attempts to certify the result independently
        of this order computation (as per :literal:`nfcertify`: we try to prove that the
        order is maximal); if it fails, the routine returns :math:`0` instead of :math:`P`.
        In order to force an output in that case as well, you may either use
        :literal:`polredbest`, or :literal:`polredabs(,16)`, or
        
        ::
        
             polredabs([T, nfbasis([T, listP])])
        
        (In all three 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]
        """
        cdef GEN _T = T.g
        pari_catch_sig_on()
        cdef GEN _ret = polredabs0(_T, flag)
        return pari_instance.new_gen(_ret)

    def polredbest(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 the ring of integers of
        :math:`\mathbb{Q}[X]/(T)`, then examines small linear combinations of the basis vectors,
        computing their characteristic polynomials. It returns the :emphasis:`separable`
        :math:`P` polynomial 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).
        """
        cdef GEN _T = T.g
        pari_catch_sig_on()
        cdef GEN _ret = polredbest(_T, flag)
        return pari_instance.new_gen(_ret)

    def polredord(x):
        r"""
        Finds polynomials with reasonably small
        coefficients and of the same degree as that of :math:`x` defining suborders of the
        order defined by :math:`x`. One of the polynomials always defines :math:`\mathbb{Q}` (hence
        is equal to :math:`(x-1)^n`, where :math:`n` is the degree), and another always defines
        the same order as :math:`x` if :math:`x` is irreducible. Useless function: try
        :literal:`polredbest`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = polredord(_x)
        return pari_instance.new_gen(_ret)

    def polresultant(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 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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = polresultant0(_x, _y, _v, flag)
        return pari_instance.new_gen(_ret)

    def polresultantext(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
        """
        cdef GEN _A = A.g
        B = objtogen(B)
        cdef GEN _B = (<gen>B).g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = polresultantext0(_A, _B, _v)
        return pari_instance.new_gen(_ret)

    def polroots(x, long precision=0):
        r"""
        Complex roots of the polynomial
        :emphasis:`x`, 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 A. Schönhage's
        root-finding algorithm, due to and originally implemented by X. Gourdon.
        Barring bugs, it is guaranteed to converge and to give the roots to the
        required accuracy.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = roots(_x, precision)
        return pari_instance.new_gen(_ret)

    def polrootsff(x, p=None, a=None):
        r"""
        Returns the vector of distinct roots of the polynomial :math:`x` in the field
        :math:`\mathbb{F}_q` defined by the irreducible polynomial :math:`a` over :math:`\mathbb{F}_p`. The
        coefficients of :math:`x` must be operation-compatible with :math:`\mathbb{Z}/p\mathbb{Z}`.
        Either :math:`a` or :math:`p` can omitted (in which case both are ignored) if x has
        :literal:`t_FFELT` coefficients:
        
        ::
        
            ? polrootsff(x^2 + 1, 5, y^2+3) \\ over F_5[y]/(y^2+3) ~ F_25
            %1 = [Mod(Mod(3, 5), Mod(1, 5)*y^2 + Mod(3, 5)),
             Mod(Mod(2, 5), Mod(1, 5)*y^2 + Mod(3, 5))]
            ? t = ffgen(y^2 + Mod(3,5), 't); \\ a generator for F_25 as a t_FFELT
            ? polrootsff(x^2 + 1) \\ not enough information to determine the base field
             *** at top-level: polrootsff(x^2+1)
             *** ^-----------------
             *** polrootsff: incorrect type in factorff.
            ? polrootsff(x^2 + t^0) \\ make sure one coeff. is a t_FFELT
            %3 = [3, 2]
            ? polrootsff(x^2 + t + 1)
            %4 = [2*t + 1, 3*t + 4]
        
        Notice that the second syntax is easier to use and much more readable.
        """
        cdef GEN _x = x.g
        cdef GEN _p = NULL
        if p is not None:
            p = objtogen(p)
            _p = (<gen>p).g
        cdef GEN _a = NULL
        if a is not None:
            a = objtogen(a)
            _a = (<gen>a).g
        pari_catch_sig_on()
        cdef GEN _ret = polrootsff(_x, _p, _a)
        return pari_instance.new_gen(_ret)

    def polrootsmod(pol, p, long flag=0):
        r"""
        Row vector of roots modulo :math:`p` of the polynomial :emphasis:`pol`.
        Multiple roots are :emphasis:`not` repeated.
        
        ::
        
            ? polrootsmod(x^2-1,2)
            %1 = [Mod(1, 2)]~
        
        If :math:`p` is very small, you may set :math:`flag = 1`, which uses a naive search.
        """
        cdef GEN _pol = pol.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = rootmod0(_pol, _p, flag)
        return pari_instance.new_gen(_ret)

    def polrootspadic(x, p, long r):
        r"""
        Vector of :math:`p`-adic roots of the polynomial :emphasis:`pol`, given to
        :math:`p`-adic precision :math:`r` :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 eact rational coefficients.
        """
        cdef GEN _x = x.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = rootpadic(_x, _p, r)
        return pari_instance.new_gen(_ret)

    def polrootsreal(T, ab=None, long precision=0):
        r"""
        Real roots of the polynomial :math:`T` with rational coefficients, multiple
        roots being included according to their multiplicity. 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 "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.
        """
        cdef GEN _T = T.g
        cdef GEN _ab = NULL
        if ab is not None:
            ab = objtogen(ab)
            _ab = (<gen>ab).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = realroots(_T, _ab, precision)
        return pari_instance.new_gen(_ret)

    def polsturm(T, ab=None, _arg2=None):
        r"""
        Number of real roots of the real squarefree 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, we use Sturm's algorithm and the result
        may be wrong due to round-off errors.
        
        ::
        
            ? 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
        """
        cdef GEN _T = T.g
        cdef GEN _ab = NULL
        if ab is not None:
            ab = objtogen(ab)
            _ab = (<gen>ab).g
        cdef GEN __arg2 = NULL
        if _arg2 is not None:
            _arg2 = objtogen(_arg2)
            __arg2 = (<gen>_arg2).g
        pari_catch_sig_on()
        cdef long _ret = sturmpart(_T, _ab, __arg2)
        pari_instance.clear_stack()
        return _ret

    def polsylvestermatrix(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = sylvestermatrix(_x, _y)
        return pari_instance.new_gen(_ret)

    def polsym(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = polsym(_x, n)
        return pari_instance.new_gen(_ret)

    def poltschirnhaus(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = tschirnhaus(_x)
        return pari_instance.new_gen(_ret)

    def powers(x, long n):
        r"""
        Return the vector :math:`[1,x,...,x^n]`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gpowers(_x, n)
        return pari_instance.new_gen(_ret)

    def precision(x, long n=0):
        r"""
        The function has two different behaviors according to whether :math:`n` is present or not.
        
        If :math:`n` is missing, the function returns the precision in decimal digits of the
        PARI object :math:`x`. If :math:`x` is
        an exact object, the largest single precision integer is returned.
        
        ::
        
            ? precision(exp(1e-100))
            %1 = 134 \\ 134 significant decimal digits
            ? precision(2 + x)
            %2 = 2147483647 \\ exact object
            ? precision(0.5 + O(x))
            %3 = 28 \\ floating point accuracy, NOT series precision
            ? precision( [ exp(1e-100), 0.5 ] )
            %4 = 28 \\ minimal accuracy among components
        
        The return value for exact objects is meaningless since it is not even the
        same on 32 and 64-bit machines. The proper way to test whether an object is
        exact is
        
        ::
        
            ? isexact(x) = precision(x) == precision(0)
        
        If :math:`n` is present, the function creates a new object equal to :math:`x` with a new
        "precision" :math:`n`. (This never changes the type of the result. In particular
        it is not possible to use it to obtain a polynomial from a power series; for
        that, see :literal:`truncate`.) Now the meaning of precision is different from the
        above (floating point accuracy), and depends on the type of :math:`x`:
        
        For exact types, no change. For :math:`x` a vector or a matrix, the operation is
        done componentwise.
        
        For real :math:`x`, :math:`n` is the number of desired significant :emphasis:`decimal`
        digits. If :math:`n` is smaller than the precision of :math:`x`, :math:`x` is truncated,
        otherwise :math:`x` is extended with zeros.
        
        For :math:`x` a :math:`p`-adic or a power series, :math:`n` is the desired number of
        :emphasis:`significant` :math:`p`-adic or :math:`X`-adic digits, where :math:`X` is the main
        variable of :math:`x`. (Note: yes, this is inconsistent.)
        Note that the precision is a priori distinct from the exponent :math:`k` appearing
        in :math:`O(*^k)`; it is indeed equal to :math:`k` if and only if :math:`x` is a :math:`p`-adic
        or :math:`X`-adic :emphasis:`unit`.
        
        ::
        
            ? precision(1 + O(x), 10)
            %1 = 1 + O(x^10)
            ? precision(x^2 + O(x^10), 3)
            %2 = x^2 + O(x^5)
            ? precision(7^2 + O(7^10), 3)
            %3 = 7^2 + O(7^5)
        
        For the last two examples, note that :math:`x^2 + O(x^5) = x^2(1 + O(x^3))`
        indeed has 3 significant coefficients
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = precision0(_x, n)
        return pari_instance.new_gen(_ret)

    def precprime(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`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = precprime(_x)
        return pari_instance.new_gen(_ret)

    def primepi(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = primepi(_x)
        return pari_instance.new_gen(_ret)

    def primes(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]
        """
        cdef GEN _n = n.g
        pari_catch_sig_on()
        cdef GEN _ret = primes0(_n)
        return pari_instance.new_gen(_ret)

    def psi(x, long precision=0):
        r"""
        The :math:`\psi`-function of :math:`x`, i.e. the logarithmic derivative
        :math:`\Gamma'(x)/\Gamma(x)`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gpsi(_x, precision)
        return pari_instance.new_gen(_ret)

    def qfauto(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.
        """
        cdef GEN _G = G.g
        cdef GEN _fl = NULL
        if fl is not None:
            fl = objtogen(fl)
            _fl = (<gen>fl).g
        pari_catch_sig_on()
        cdef GEN _ret = qfauto0(_G, _fl)
        return pari_instance.new_gen(_ret)

    def qfautoexport(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
        """
        cdef GEN _qfa = qfa.g
        pari_catch_sig_on()
        cdef GEN _ret = qfautoexport(_qfa, flag)
        return pari_instance.new_gen(_ret)

    def qfbclassno(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 above range, assuming GRH. We currently have no counter-examples but
        they should exist: we'd 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)
            time = 3,140 ms.
            %1 = 1
            ? quadclassunit(400000028).no
            time = 20 ms. \\{ much faster}
            %2 = 1
            ? qfbclassno(-400000028)
            time = 0 ms.
            %3 = 7253 \\{ correct, and fast enough}
            ? quadclassunit(-400000028).no
            time = 0 ms.
            %4 = 7253
        
        See also :literal:`qfbhclassno`.
        """
        cdef GEN _D = D.g
        pari_catch_sig_on()
        cdef GEN _ret = qfbclassno0(_D, flag)
        return pari_instance.new_gen(_ret)

    def qfbcompraw(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = qfbcompraw(_x, _y)
        return pari_instance.new_gen(_ret)

    def qfbhclassno(x):
        r"""
        Hurwitz class number of :math:`x`, where
        :math:`x` is non-negative and congruent to 0 or 3 modulo 4. For :math:`x > 5.
        10^5`, we assume the GRH, and use :literal:`quadclassunit` with default
        parameters.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = hclassno(_x)
        return pari_instance.new_gen(_ret)

    def qfbil(x, y, q=None):
        r"""
        Evaluate the bilinear form :math:`q` (symmetric matrix)
        at the vectors :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,0,1]~; qfbil(x,y)
            %1 = 2
            ? q = [1,2,3;2,2,-1;3,-1,0]; qfbil(x,y, q)
            %2 = -13
            ? for(i=1,10^6, qfbil(x,y,q))
            %3 = 568ms
            ? for(i=1,10^6, x~*q*y)
            %4 = 717ms
        
        The associated quadratic form is also available, as
        :literal:`qfnorm`, slightly faster:
        
        ::
        
            ? for(i=1,10^6, qfnorm(x,q))
            time = 444ms
            ? for(i=1,10^6, qfnorm(x))
            time = 176 ms.
            ? for(i=1,10^6, qfbil(x,y))
            time = 208 ms.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        cdef GEN _q = NULL
        if q is not None:
            q = objtogen(q)
            _q = (<gen>q).g
        pari_catch_sig_on()
        cdef GEN _ret = qfbil(_x, _y, _q)
        return pari_instance.new_gen(_ret)

    def qfbnucomp(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        L = objtogen(L)
        cdef GEN _L = (<gen>L).g
        pari_catch_sig_on()
        cdef GEN _ret = nucomp(_x, _y, _L)
        return pari_instance.new_gen(_ret)

    def qfbnupow(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`.
        """
        cdef GEN _x = x.g
        n = objtogen(n)
        cdef GEN _n = (<gen>n).g
        cdef GEN _L = NULL
        if L is not None:
            L = objtogen(L)
            _L = (<gen>L).g
        pari_catch_sig_on()
        cdef GEN _ret = nupow(_x, _n, _L)
        return pari_instance.new_gen(_ret)

    def qfbpowraw(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}`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = qfbpowraw(_x, n)
        return pari_instance.new_gen(_ret)

    def qfbprimeform(x, p, long precision=0):
        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.
        """
        cdef GEN _x = x.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = primeform(_x, _p, precision)
        return pari_instance.new_gen(_ret)

    def qfbred(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.
        """
        cdef GEN _x = x.g
        cdef GEN _d = NULL
        if d is not None:
            d = objtogen(d)
            _d = (<gen>d).g
        cdef GEN _isd = NULL
        if isd is not None:
            isd = objtogen(isd)
            _isd = (<gen>isd).g
        cdef GEN _sd = NULL
        if sd is not None:
            sd = objtogen(sd)
            _sd = (<gen>sd).g
        pari_catch_sig_on()
        cdef GEN _ret = qfbred0(_x, flag, _d, _isd, _sd)
        return pari_instance.new_gen(_ret)

    def qfbredsl2(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 :literal:`t_QFR`, the distance component is
        unaffected.
        """
        cdef GEN _x = x.g
        cdef GEN _data = NULL
        if data is not None:
            data = objtogen(data)
            _data = (<gen>data).g
        pari_catch_sig_on()
        cdef GEN _ret = qfbredsl2(_x, _data)
        return pari_instance.new_gen(_ret)

    def qfbsolve(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.
        """
        cdef GEN _Q = Q.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = qfbsolve(_Q, _p)
        return pari_instance.new_gen(_ret)

    def qfgaussred(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`.
        """
        cdef GEN _q = q.g
        pari_catch_sig_on()
        cdef GEN _ret = qfgaussred(_q)
        return pari_instance.new_gen(_ret)

    def qfisom(G, H, fl=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`.
        
        :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.
        """
        cdef GEN _G = G.g
        H = objtogen(H)
        cdef GEN _H = (<gen>H).g
        cdef GEN _fl = NULL
        if fl is not None:
            fl = objtogen(fl)
            _fl = (<gen>fl).g
        pari_catch_sig_on()
        cdef GEN _ret = qfisom0(_G, _H, _fl)
        return pari_instance.new_gen(_ret)

    def qfisominit(G, fl=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.
        
        Since this function computes the minimal vectors, it can become very lengthy
        as the dimension of :math:`G` grows.
        """
        cdef GEN _G = G.g
        cdef GEN _fl = NULL
        if fl is not None:
            fl = objtogen(fl)
            _fl = (<gen>fl).g
        pari_catch_sig_on()
        cdef GEN _ret = qfisominit0(_G, _fl)
        return pari_instance.new_gen(_ret)

    def qfjacobi(A, long precision=0):
        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
        """
        cdef GEN _A = A.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = jacobi(_A, precision)
        return pari_instance.new_gen(_ret)

    def qflll(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = qflll0(_x, flag)
        return pari_instance.new_gen(_ret)

    def qflllgram(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.
        """
        cdef GEN _G = G.g
        pari_catch_sig_on()
        cdef GEN _ret = qflllgram0(_G, flag)
        return pari_instance.new_gen(_ret)

    def qfminim(x, b=None, m=None, long flag=0, long precision=0):
        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), seeks at most :math:`2m` vectors. The result is a
        three-component vector, the first component being the number of vectors
        found, the second being the maximum norm found, and the last vector is a
        matrix whose columns are the vectors found, 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.
        """
        cdef GEN _x = x.g
        cdef GEN _b = NULL
        if b is not None:
            b = objtogen(b)
            _b = (<gen>b).g
        cdef GEN _m = NULL
        if m is not None:
            m = objtogen(m)
            _m = (<gen>m).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = qfminim0(_x, _b, _m, flag, precision)
        return pari_instance.new_gen(_ret)

    def qfnorm(x, q=None):
        r"""
        Evaluate the binary quadratic form :math:`q` (symmetric matrix)
        at the vector :math:`x`. If :math:`q` omitted, use the standard Euclidean form,
        corresponding to the identity matrix.
        
        Equivalent to :literal:`x~ * q * x`, but about twice faster and
        more convenient (does not distinguish between column and row vectors):
        
        ::
        
            ? x = [1,2,3]~; qfnorm(x)
            %1 = 14
            ? q = [1,2,3;2,2,-1;3,-1,0]; qfnorm(x, q)
            %2 = 23
            ? for(i=1,10^6, qfnorm(x,q))
            time = 384ms.
            ? for(i=1,10^6, x~*q*x)
            time = 729ms.
        
        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]; qfnorm(M) \\ Gram matrix
            %5 =
            [66 78 90]
            
            [78 93 108]
            
            [90 108 126]
            
            ? for(i=1,10^6, qfnorm(M,q))
            time = 2,144 ms.
            ? for(i=1,10^6, M~*q*M)
            time = 2,793 ms.
        
        The polar form is also available, as :literal:`qfbil`.
        """
        cdef GEN _x = x.g
        cdef GEN _q = NULL
        if q is not None:
            q = objtogen(q)
            _q = (<gen>q).g
        pari_catch_sig_on()
        cdef GEN _ret = qfnorm(_x, _q)
        return pari_instance.new_gen(_ret)

    def qfparam(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
        """
        cdef GEN _G = G.g
        sol = objtogen(sol)
        cdef GEN _sol = (<gen>sol).g
        pari_catch_sig_on()
        cdef GEN _ret = qfparam(_G, _sol, flag)
        return pari_instance.new_gen(_ret)

    def qfperfection(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.
        """
        cdef GEN _G = G.g
        pari_catch_sig_on()
        cdef GEN _ret = perf(_G)
        return pari_instance.new_gen(_ret)

    def qfrep(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}`).
        """
        cdef GEN _q = q.g
        B = objtogen(B)
        cdef GEN _B = (<gen>B).g
        pari_catch_sig_on()
        cdef GEN _ret = qfrep0(_q, _B, flag)
        return pari_instance.new_gen(_ret)

    def qfsign(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = qfsign(_x)
        return pari_instance.new_gen(_ret)

    def qfsolve(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
        """
        cdef GEN _G = G.g
        pari_catch_sig_on()
        cdef GEN _ret = qfsolve(_G)
        return pari_instance.new_gen(_ret)

    def quadclassunit(D, long flag=0, tech=None, long precision=0):
        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).
        """
        cdef GEN _D = D.g
        cdef GEN _tech = NULL
        if tech is not None:
            tech = objtogen(tech)
            _tech = (<gen>tech).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = quadclassunit0(_D, flag, _tech, precision)
        return pari_instance.new_gen(_ret)

    def quaddisc(x):
        r"""
        Discriminant of the étale algebra :math:`\mathbb{Q}(\sqrt{x})`, where :math:`x belongs to \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 belongs to \mathbb{Q}^*` and :math:`d belongs to \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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = quaddisc(_x)
        return pari_instance.new_gen(_ret)

    def quadgen(D):
        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.
        """
        cdef GEN _D = D.g
        pari_catch_sig_on()
        cdef GEN _ret = quadgen(_D)
        return pari_instance.new_gen(_ret)

    def quadhilbert(D, long precision=0):
        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.
        """
        cdef GEN _D = D.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = quadhilbert(_D, precision)
        return pari_instance.new_gen(_ret)

    def quadpoly(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.
        """
        cdef GEN _D = D.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = quadpoly0(_D, _v)
        return pari_instance.new_gen(_ret)

    def quadray(D, f, long precision=0):
        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.
        """
        cdef GEN _D = D.g
        f = objtogen(f)
        cdef GEN _f = (<gen>f).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = quadray(_D, _f, precision)
        return pari_instance.new_gen(_ret)

    def quadregulator(x, long precision=0):
        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.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = quadregulator(_x, precision)
        return pari_instance.new_gen(_ret)

    def quadunit(D):
        r"""
        Fundamental unit 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)).
        """
        cdef GEN _D = D.g
        pari_catch_sig_on()
        cdef GEN _ret = quadunit(_D)
        return pari_instance.new_gen(_ret)

    def random(N):
        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 GEN _N = N.g
        pari_catch_sig_on()
        cdef GEN _ret = genrand(_N)
        return pari_instance.new_gen(_ret)

    def randomprime(N):
        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 GEN _N = N.g
        pari_catch_sig_on()
        cdef GEN _ret = randomprime(_N)
        return pari_instance.new_gen(_ret)

    def real(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)`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = greal(_x)
        return pari_instance.new_gen(_ret)

    def removeprimes(x):
        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 GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = removeprimes(_x)
        return pari_instance.new_gen(_ret)

    def rnfalgtobasis(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.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfalgtobasis(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfbasis(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 an 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.
        """
        cdef GEN _bnf = bnf.g
        M = objtogen(M)
        cdef GEN _M = (<gen>M).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfbasis(_bnf, _M)
        return pari_instance.new_gen(_ret)

    def rnfbasistoalg(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.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfbasistoalg(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfcharpoly(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
        """
        cdef GEN _nf = nf.g
        T = objtogen(T)
        cdef GEN _T = (<gen>T).g
        a = objtogen(a)
        cdef GEN _a = (<gen>a).g
        cdef long _var = -1
        if var is not None:
            _var = pari_instance.get_var(var)
        pari_catch_sig_on()
        cdef GEN _ret = rnfcharpoly(_nf, _T, _a, _var)
        return pari_instance.new_gen(_ret)

    def rnfconductor(bnf, pol):
        r"""
        Given :math:`bnf`
        as output by :literal:`bnfinit`, and :emphasis:`pol` a relative polynomial defining an
        Abelian extension, computes the class field theory conductor of this
        Abelian extension. The result is a 3-component vector
        :math:`[conductor,rayclgp,subgroup]`, where :emphasis:`conductor` is
        the conductor of the extension given as a 2-component row vector
        :math:`[f_0,f_ oo ]`, :emphasis:`rayclgp` is the full ray class group corresponding to
        the conductor given as a 3-component vector [h,cyc,gen] as usual for a group,
        and :emphasis:`subgroup` is a matrix in HNF defining the subgroup of the ray class
        group on the given generators gen.
        """
        cdef GEN _bnf = bnf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfconductor(_bnf, _pol)
        return pari_instance.new_gen(_ret)

    def rnfdedekind(nf, pol, pr=None, long flag=0):
        r"""
        Given a number field :math:`K` coded by :math:`nf` and a monic
        polynomial :math:`P belongs to \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)
            %2 = [1, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]], 8]
            ? rnfdedekind(nf, P, pr3, 1)
            %3 = 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)
            %5 = 0
            ? rnfdedekind(nf, P, pr2)
            %6 = [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)
            %7 = [[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)
            %4 = 2
        
        It is possible to use this routine with non-monic
        :math:`P = \sum_{i <= n} a_i X^i belongs to \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).
        """
        cdef GEN _nf = nf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        cdef GEN _pr = NULL
        if pr is not None:
            pr = objtogen(pr)
            _pr = (<gen>pr).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfdedekind(_nf, _pol, _pr, flag)
        return pari_instance.new_gen(_ret)

    def rnfdet(nf, M):
        r"""
        Given a pseudo-matrix :math:`M` over the maximal
        order of :math:`nf`, computes its determinant.
        """
        cdef GEN _nf = nf.g
        M = objtogen(M)
        cdef GEN _M = (<gen>M).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfdet(_nf, _M)
        return pari_instance.new_gen(_ret)

    def rnfdisc(nf, pol):
        r"""
        Given a number field :math:`nf` as
        output by :literal:`nfinit` and a polynomial :emphasis:`pol` with coefficients in
        :math:`nf` defining a relative extension :math:`L` of :math:`nf`, computes the
        relative discriminant of :math:`L`. This is a two-element row 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:`nf^*/{nf^*}^2`. The main variable of
        :math:`nf` :emphasis:`must` be of lower priority than that of :emphasis:`pol`, see
        ``priority`` (in the PARI manual).
        """
        cdef GEN _nf = nf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfdiscf(_nf, _pol)
        return pari_instance.new_gen(_ret)

    def rnfeltabstorel(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 modulo the absolute equation
        :literal:`:emphasis:`rnf`.pol`, 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.pol
            %2 = x^4 + 1
            ? rnfeltabstorel(L, Mod(x, L.pol))
            %3 = Mod(x, x^2 + Mod(-y, y^2 + 1))
            ? rnfeltabstorel(L, Mod(2, L.pol))
            %4 = 2
            ? rnfeltabstorel(L, Mod(x, x^2-y))
             *** at top-level: rnfeltabstorel(L,Mod
             *** ^--------------------
             *** rnfeltabstorel: inconsistent moduli in rnfeltabstorel: x^2-y != x^4+1
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfeltabstorel(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfeltdown(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 :math:`K` as a polmod, assuming :math:`x` is in :math:`K` (otherwise 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(y, x^2-y))
            %4 = Mod(y, y^2 + 1)
            ? rnfeltdown(L, Mod(y,K.pol))
            %5 = 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
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfeltdown(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfeltnorm(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))
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfeltnorm(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfeltreltoabs(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)
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfeltreltoabs(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfelttrace(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:`N_{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))
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfelttrace(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfeltup(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:`K`, 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
            ? rnfeltup(L, Mod(y, K.pol))
            %4 = Mod(x^2, x^4 + 1)
            ? rnfeltup(L, y)
            %5 = Mod(x^2, x^4 + 1)
            ? rnfeltup(L, [1,2]~) \\ in terms of K.zk
            %6 = Mod(2*x^2 + 1, x^4 + 1)
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfeltup(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfequation(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`.
        
        ::
        
            ? T = y^3-2; pol = x^2 +x*y + y^2;
            ? [z,a,k] = rnfequation(T, pol, 1);
            ? z
            %4 = x^6 + 108
            ? subst(T, y, a)
            %5 = 0
            ? alpha= Mod(y, T);
            ? beta = Mod(x*Mod(1,T), pol);
            ? subst(z, x, beta + k*alpha)
            %8 = 0
        """
        cdef GEN _nf = nf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfequation0(_nf, _pol, flag)
        return pari_instance.new_gen(_ret)

    def rnfhnfbasis(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.
        """
        cdef GEN _bnf = bnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfhnfbasis(_bnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfidealabstorel(rnf, x):
        r"""
        Let :math:`rnf` be a relative
        number field extension :math:`L/K` as output by :literal:`rnfinit` and :math:`x` be an ideal of
        the absolute extension :math:`L/\mathbb{Q}` given by a :math:`\mathbb{Z}`-basis of elements of :math:`L`.
        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.
        
        The reason why the input does not use the customary HNF in terms of a fixed
        :math:`\mathbb{Z}`-basis for :math:`\mathbb{Z}_L` is precisely that no such basis has been explicitly
        specified. On the other hand, if you already computed an (absolute) :emphasis:`nf`
        structure :literal:`Labs` associated to :math:`L`, and :math:`m` is in HNF, defining
        an (absolute) ideal with respect to the :math:`\mathbb{Z}`-basis :literal:`Labs.zk`, then
        :literal:`Labs.zk * m` is a suitable :math:`\mathbb{Z}`-basis for the ideal, and
        
        ::
        
             rnfidealabstorel(rnf, Labs.zk * m)
        
        converts :math:`m` to a relative ideal.
        
        ::
        
            ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); Labs = nfinit(L);
            ? m = idealhnf(Labs, 17, x^3+2);
            ? B = rnfidealabstorel(L, Labs.zk * m)
            %3 = [[1, 8; 0, 1], [[17, 4; 0, 1], 1]] \\ pseudo-basis for m as Z_K-module
            ? A = rnfidealreltoabs(L, B)
            %4 = [17, x^2 + 4, x + 8, x^3 + 8*x^2] \\ Z-basis for m in Q[x]/(L.pol)
            ? mathnf(matalgtobasis(Labs, A))
            %5 =
            [17 8 4 2]
            
            [ 0 1 0 0]
            
            [ 0 0 1 0]
            
            [ 0 0 0 1]
            ? % == m
            %6 = 1
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfidealabstorel(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfidealdown(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`.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfidealdown(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfidealhnf(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 associated to
        :math:`x`, viewed as a :math:`\mathbb{Z}_K`-module.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfidealhnf(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfidealmul(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.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfidealmul(_rnf, _x, _y)
        return pari_instance.new_gen(_ret)

    def rnfidealnormabs(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.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfidealnormabs(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfidealnormrel(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.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfidealnormrel(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfidealreltoabs(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, 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}` in
        the form of a :math:`\mathbb{Z}`-basis, given by a vector of polynomials (modulo
        :literal:`rnf.pol`).
        
        The reason why we do not return the customary HNF in terms of a fixed
        :math:`\mathbb{Z}`-basis for :math:`\mathbb{Z}_L` is precisely that no such basis has been explicitly
        specified. On the other hand, if you already computed an (absolute) :emphasis:`nf`
        structure :literal:`Labs` associated to :math:`L`, then
        
        ::
        
             xabs = rnfidealreltoabs(L, x);
             xLabs = mathnf(matalgtobasis(Labs, xabs));
        
        computes a traditional HNF :literal:`xLabs` for :math:`x` in terms of
        the fixed :math:`\mathbb{Z}`-basis :literal:`Labs.zk`.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfidealreltoabs(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfidealtwoelt(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.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfidealtwoelement(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfidealup(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
        :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, given by a vector of polynomials (modulo
        :literal:`rnf.pol`).
        
        The reason why we do not return the customary HNF in terms of a fixed
        :math:`\mathbb{Z}`-basis for :math:`\mathbb{Z}_L` is precisely that no such basis has been explicitly
        specified. On the other hand, if you already computed an (absolute) :emphasis:`nf`
        structure :literal:`Labs` associated to :math:`L`, then
        
        ::
        
             xabs = rnfidealup(L, x);
             xLabs = mathnf(matalgtobasis(Labs, xabs));
        
        computes a traditional HNF :literal:`xLabs` for :math:`x` in terms of
        the fixed :math:`\mathbb{Z}`-basis :literal:`Labs.zk`.
        """
        cdef GEN _rnf = rnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfidealup(_rnf, _x)
        return pari_instance.new_gen(_ret)

    def rnfinit(nf, pol):
        r"""
        :math:`nf` being a number field in :literal:`nfinit`
        format considered as base field, and :emphasis:`pol` a polynomial defining a relative
        extension over :math:`nf`, this computes data to work in the
        relative extension. The main variable of :emphasis:`pol` must be of higher priority
        (see ``priority`` (in the PARI manual)) than that of :math:`nf`, and the coefficients of
        :emphasis:`pol` must be in :math:`nf`.
        
        The result is a row vector, whose components are technical. In the following
        description, we let :math:`K` be the base field defined by :math:`nf` and :math:`L/K`
        the large field associated to the :emphasis:`rnf`. Furthermore, 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.
        
        Note that a subsequent :literal:`nfinit`:math:`(rnf)` will explicitly add an
        :emphasis:`nf` structure associated to :math:`L` to :emphasis:`rnf` (and return it as well).
        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.
        
        :math:`rnf[1]`(:literal:`rnf.pol`) contains the relative polynomial :emphasis:`pol`.
        
        :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(pol)\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:`pol`) 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, pol, 1)`. Namely, a
        vector :math:`[P, a, k, K.pol, pol]` 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 :emphasis:`pol`
        and :math:`\alpha` the generator of :math:`K` given above, then :math:`P(\beta + k\alpha) = 0`.
        
        :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, pol, 1);
             if (k, pol = subst(pol, x, x - k*Mod(y, K.pol)));
             L = rnfinit(K, pol);
        
        :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).
        """
        cdef GEN _nf = nf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfinit(_nf, _pol)
        return pari_instance.new_gen(_ret)

    def rnfisabelian(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
        """
        cdef GEN _nf = nf.g
        T = objtogen(T)
        cdef GEN _T = (<gen>T).g
        pari_catch_sig_on()
        cdef long _ret = rnfisabelian(_nf, _T)
        pari_instance.clear_stack()
        return _ret

    def rnfisfree(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.
        """
        cdef GEN _bnf = bnf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef long _ret = rnfisfree(_bnf, _x)
        pari_instance.clear_stack()
        return _ret

    def rnfisnorm(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).
        """
        cdef GEN _T = T.g
        a = objtogen(a)
        cdef GEN _a = (<gen>a).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfisnorm(_T, _a, flag)
        return pari_instance.new_gen(_ret)

    def rnfisnorminit(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.
        """
        cdef GEN _pol = pol.g
        polrel = objtogen(polrel)
        cdef GEN _polrel = (<gen>polrel).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfisnorminit(_pol, _polrel, flag)
        return pari_instance.new_gen(_ret)

    def rnfkummer(bnr, subgp=None, long d=0, long precision=0):
        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.
        """
        cdef GEN _bnr = bnr.g
        cdef GEN _subgp = NULL
        if subgp is not None:
            subgp = objtogen(subgp)
            _subgp = (<gen>subgp).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = rnfkummer(_bnr, _subgp, d, precision)
        return pari_instance.new_gen(_ret)

    def rnflllgram(nf, pol, order, long precision=0):
        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.
        """
        cdef GEN _nf = nf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        order = objtogen(order)
        cdef GEN _order = (<gen>order).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = rnflllgram(_nf, _pol, _order, precision)
        return pari_instance.new_gen(_ret)

    def rnfnormgroup(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.
        """
        cdef GEN _bnr = bnr.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfnormgroup(_bnr, _pol)
        return pari_instance.new_gen(_ret)

    def rnfpolred(nf, pol, long precision=0):
        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.8.0`, 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.
        """
        cdef GEN _nf = nf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = rnfpolred(_nf, _pol, precision)
        return pari_instance.new_gen(_ret)

    def rnfpolredabs(nf, pol, long flag=0):
        r"""
        THIS FUNCTION IS OBSOLETE: use :literal:`rnfpolredbest` instead.
        Relative version of :literal:`polredabs`. Given a monic polynomial :emphasis:`pol`
        with coefficients in :math:`nf`, finds a simpler relative polynomial defining
        the same field. The binary digits of :math:`flag` mean
        
        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.
        Same as but faster than
        
        ::
        
             rnfequation(nf, rnfpolredabs(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.
        See ``polredabs`` (in the PARI manual).
        
        :strong:`Warning.` In the present implementation, :literal:`rnfpolredabs`
        produces smaller polynomials than :literal:`rnfpolred` and is usually
        faster, but its complexity is still exponential in the absolute degree.
        The function :literal:`rnfpolredbest` runs in polynomial time, and tends to
        return polynomials with smaller discriminants.
        """
        cdef GEN _nf = nf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfpolredabs(_nf, _pol, flag)
        return pari_instance.new_gen(_ret)

    def rnfpolredbest(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
        """
        cdef GEN _nf = nf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfpolredbest(_nf, _pol, flag)
        return pari_instance.new_gen(_ret)

    def rnfpseudobasis(nf, pol):
        r"""
        Given a number field
        :math:`nf` as output by :literal:`nfinit` and a polynomial :emphasis:`pol` with
        coefficients in :math:`nf` defining a relative extension :math:`L` of :math:`nf`,
        computes a pseudo-basis :math:`(A,I)` for the maximal order :math:`\mathbb{Z}_L` viewed as a
        :math:`\mathbb{Z}_K`-module, and the relative discriminant of :math:`L`. This is output as a
        four-element row vector :math:`[A,I,D,d]`, where :math:`D` is the relative ideal
        discriminant and :math:`d` is the relative discriminant considered as an element of
        :math:`nf^*/{nf^*}^2`.
        """
        cdef GEN _nf = nf.g
        pol = objtogen(pol)
        cdef GEN _pol = (<gen>pol).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfpseudobasis(_nf, _pol)
        return pari_instance.new_gen(_ret)

    def rnfsteinitz(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)`).
        """
        cdef GEN _nf = nf.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef GEN _ret = rnfsteinitz(_nf, _x)
        return pari_instance.new_gen(_ret)

    def select(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))
        """
        cdef GEN _f = f.g
        A = objtogen(A)
        cdef GEN _A = (<gen>A).g
        pari_catch_sig_on()
        cdef GEN _ret = select0(_f, _A, flag)
        return pari_instance.new_gen(_ret)

    def seralgdep(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`.
        """
        cdef GEN _s = s.g
        pari_catch_sig_on()
        cdef GEN _ret = seralgdep(_s, p, r)
        return pari_instance.new_gen(_ret)

    def serconvol(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`.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = convol(_x, _y)
        return pari_instance.new_gen(_ret)

    def serlaplace(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`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = laplace(_x)
        return pari_instance.new_gen(_ret)

    def serreverse(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)
        """
        cdef GEN _s = s.g
        pari_catch_sig_on()
        cdef GEN _ret = serreverse(_s)
        return pari_instance.new_gen(_ret)

    def setbinop(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]
        """
        cdef GEN _f = f.g
        X = objtogen(X)
        cdef GEN _X = (<gen>X).g
        cdef GEN _Y = NULL
        if Y is not None:
            Y = objtogen(Y)
            _Y = (<gen>Y).g
        pari_catch_sig_on()
        cdef GEN _ret = setbinop(_f, _X, _Y)
        return pari_instance.new_gen(_ret)

    def setintersect(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = setintersect(_x, _y)
        return pari_instance.new_gen(_ret)

    def setisset(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]
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = setisset(_x)
        pari_instance.clear_stack()
        return _ret

    def setminus(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = setminus(_x, _y)
        return pari_instance.new_gen(_ret)

    def setrand(n):
        r"""
        Reseeds the random number generator using the seed :math:`n`. No value is
        returned. The seed is either a technical array output by :literal:`getrand`, or a
        small positive integer, used to generate deterministically a suitable state
        array. For instance, running a randomized computation starting by
        :literal:`setrand(1)` twice will generate the exact same output.
        """
        cdef GEN _n = n.g
        pari_catch_sig_on()
        setrand(_n)
        pari_instance.clear_stack()

    def setsearch(S, x, long flag=0):
        r"""
        Determines whether :math:`x` belongs to the set :math:`S` (see :literal:`setisset`).
        
        We first describe the default behaviour, 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])
        """
        cdef GEN _S = S.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        pari_catch_sig_on()
        cdef long _ret = setsearch(_S, _x, flag)
        pari_instance.clear_stack()
        return _ret

    def setunion(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.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        pari_catch_sig_on()
        cdef GEN _ret = setunion(_x, _y)
        return pari_instance.new_gen(_ret)

    def shift(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`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gshift(_x, n)
        return pari_instance.new_gen(_ret)

    def shiftmul(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gmul2n(_x, n)
        return pari_instance.new_gen(_ret)

    def sigma(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = sumdivk(_x, k)
        return pari_instance.new_gen(_ret)

    def sign(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef int _ret = gsigne(_x)
        pari_instance.clear_stack()
        return _ret

    def simplify(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:`\\y`, that is.)
        In particular
        
        ::
        
            ? type(%1)
            %4 = "t_INT"
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = simplify(_x)
        return pari_instance.new_gen(_ret)

    def sin(x, long precision=0):
        r"""
        Sine of :math:`x`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gsin(_x, precision)
        return pari_instance.new_gen(_ret)

    def sinc(x, long precision=0):
        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`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gsinc(_x, precision)
        return pari_instance.new_gen(_ret)

    def sinh(x, long precision=0):
        r"""
        Hyperbolic sine of :math:`x`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gsinh(_x, precision)
        return pari_instance.new_gen(_ret)

    def sizebyte(x):
        r"""
        Outputs the total number of bytes occupied by the tree representing the
        PARI object :math:`x`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = gsizebyte(_x)
        pari_instance.clear_stack()
        return _ret

    def sizedigit(x):
        r"""
        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,
        
        This function is DEPRECATED, essentially meaningless, and provided for
        backwards compatibility only. Don't use it!
        
        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)`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef long _ret = sizedigit(_x)
        pari_instance.clear_stack()
        return _ret

    def sqr(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).
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gsqr(_x)
        return pari_instance.new_gen(_ret)

    def sqrt(x, long precision=0):
        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)) belongs to ]-\Pi/2, \Pi/2]`, and if :math:`x belongs to \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.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gsqrt(_x, precision)
        return pari_instance.new_gen(_ret)

    def sqrtint(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
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = sqrtint(_x)
        return pari_instance.new_gen(_ret)

    def sqrtnint(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`
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = sqrtnint(_x, n)
        return pari_instance.new_gen(_ret)

    def subgrouplist(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`.)
        """
        cdef GEN _bnr = bnr.g
        cdef GEN _bound = NULL
        if bound is not None:
            bound = objtogen(bound)
            _bound = (<gen>bound).g
        pari_catch_sig_on()
        cdef GEN _ret = subgrouplist0(_bnr, _bound, flag)
        return pari_instance.new_gen(_ret)

    def subst(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.
        """
        cdef GEN _x = x.g
        cdef long _y = pari_instance.get_var(y)
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        pari_catch_sig_on()
        cdef GEN _ret = gsubst(_x, _y, _z)
        return pari_instance.new_gen(_ret)

    def substpol(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)
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        pari_catch_sig_on()
        cdef GEN _ret = gsubstpol(_x, _y, _z)
        return pari_instance.new_gen(_ret)

    def substvec(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]
        """
        cdef GEN _x = x.g
        v = objtogen(v)
        cdef GEN _v = (<gen>v).g
        w = objtogen(w)
        cdef GEN _w = (<gen>w).g
        pari_catch_sig_on()
        cdef GEN _ret = gsubstvec(_x, _v, _w)
        return pari_instance.new_gen(_ret)

    def sumdedekind(h, k):
        r"""
        Returns the Dedekind sum associated 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))
        """
        cdef GEN _h = h.g
        k = objtogen(k)
        cdef GEN _k = (<gen>k).g
        pari_catch_sig_on()
        cdef GEN _ret = sumdedekind(_h, _k)
        return pari_instance.new_gen(_ret)

    def sumdigits(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.
        """
        cdef GEN _n = n.g
        cdef GEN _B = NULL
        if B is not None:
            B = objtogen(B)
            _B = (<gen>B).g
        pari_catch_sig_on()
        cdef GEN _ret = sumdigits0(_n, _B)
        return pari_instance.new_gen(_ret)

    def sumformal(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
        """
        cdef GEN _f = f.g
        cdef long _v = -1
        if v is not None:
            _v = pari_instance.get_var(v)
        pari_catch_sig_on()
        cdef GEN _ret = sumformal(_f, _v)
        return pari_instance.new_gen(_ret)

    def sumnuminit(asymp, long precision=0):
        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 GEN _asymp = asymp.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = sumnuminit(_asymp, precision)
        return pari_instance.new_gen(_ret)

    def tan(x, long precision=0):
        r"""
        Tangent of :math:`x`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gtan(_x, precision)
        return pari_instance.new_gen(_ret)

    def tanh(x, long precision=0):
        r"""
        Hyperbolic tangent of :math:`x`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gtanh(_x, precision)
        return pari_instance.new_gen(_ret)

    def taylor(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.
        """
        cdef GEN _x = x.g
        cdef long _t = pari_instance.get_var(t)
        if serprec < 0:
            serprec = pari_instance.get_series_precision()
        pari_catch_sig_on()
        cdef GEN _ret = tayl(_x, _t, serprec)
        return pari_instance.new_gen(_ret)

    def teichmuller(x):
        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`.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = teich(_x)
        return pari_instance.new_gen(_ret)

    def theta(q, z, long precision=0):
        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).
        """
        cdef GEN _q = q.g
        z = objtogen(z)
        cdef GEN _z = (<gen>z).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = theta(_q, _z, precision)
        return pari_instance.new_gen(_ret)

    def thetanullk(q, long k, long precision=0):
        r"""
        :math:`k`-th derivative at :math:`z = 0` of :math:`theta(q,z)`.
        """
        cdef GEN _q = q.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = thetanullk(_q, k, precision)
        return pari_instance.new_gen(_ret)

    def thue(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
        associated 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.
        """
        cdef GEN _tnf = tnf.g
        a = objtogen(a)
        cdef GEN _a = (<gen>a).g
        cdef GEN _sol = NULL
        if sol is not None:
            sol = objtogen(sol)
            _sol = (<gen>sol).g
        pari_catch_sig_on()
        cdef GEN _ret = thue(_tnf, _a, _sol)
        return pari_instance.new_gen(_ret)

    def thueinit(P, long flag=0, long precision=0):
        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 use
        :literal:`bnfisintnorm`):
        
        ::
        
            ? 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 associated 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.
        """
        cdef GEN _P = P.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = thueinit(_P, flag, precision)
        return pari_instance.new_gen(_ret)

    def trace(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.
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gtrace(_x)
        return pari_instance.new_gen(_ret)

    def type(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`".
        """
        cdef GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = type0(_x)
        return pari_instance.new_gen(_ret)

    def valuation(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.
        """
        cdef GEN _x = x.g
        p = objtogen(p)
        cdef GEN _p = (<gen>p).g
        pari_catch_sig_on()
        cdef GEN _ret = gpvaluation(_x, _p)
        return pari_instance.new_gen(_ret)

    def variable(x):
        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 associated 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 GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = gpolvar(_x)
        return pari_instance.new_gen(_ret)

    def variables(x):
        r"""
        Returns the list of all variables occuring 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 GEN _x = x.g
        pari_catch_sig_on()
        cdef GEN _ret = variables_vec(_x)
        return pari_instance.new_gen(_ret)

    def vecextract(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``.
        """
        cdef GEN _x = x.g
        y = objtogen(y)
        cdef GEN _y = (<gen>y).g
        cdef GEN _z = NULL
        if z is not None:
            z = objtogen(z)
            _z = (<gen>z).g
        pari_catch_sig_on()
        cdef GEN _ret = extract0(_x, _y, _z)
        return pari_instance.new_gen(_ret)

    def vecsearch(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).
        
        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
        
        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
        """
        cdef GEN _v = v.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        cdef GEN _cmpf = NULL
        if cmpf is not None:
            cmpf = objtogen(cmpf)
            _cmpf = (<gen>cmpf).g
        pari_catch_sig_on()
        cdef long _ret = vecsearch(_v, _x, _cmpf)
        pari_instance.clear_stack()
        return _ret

    def vecsort(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). 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 an integer which is :math:`< 0`, :math:`> 0` or :math:`= 0` if :math:`x < y`, :math:`x > y` or
          :math:`x = y` respectively. The :literal:`sign` function is very useful in this context:
        
        ::
        
            ? vecsort([3,0,2; 1,0,2]) \\ sort columns according to lex order
            %1 =
            [0 2 3]
            
            [0 2 1]
            ? vecsort(v, (x,y)->sign(y-x)) \\ reverse sort
            ? vecsort(v, (x,y)->sign(abs(x)-abs(y))) \\ sort by increasing absolute value
            ? cmpf(x,y) = my(dx = poldisc(x), dy = poldisc(y)); sign(abs(dx) - abs(dy))
            ? vecsort([x^2+1, x^3-2, x^4+5*x+1], cmpf)
        
        The last example used the named :literal:`cmpf` instead of an anonymous function,
        and sorts polynomials with respect to the absolute value of their
        discriminant. A more efficient approach would use precomputations to ensure
        a given discriminant is computed only once:
        
        ::
        
            ? DISC = vector(#v, i, abs(poldisc(v[i])));
            ? perm = vecsort(vector(#v,i,i), (x,y)->sign(DISC[x]-DISC[y]))
            ? vecextract(v, perm)
        
        Similar ideas apply whenever we sort according to the values
        of a function which is expensive to compute.
        
        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]]
        """
        cdef GEN _x = x.g
        cdef GEN _cmpf = NULL
        if cmpf is not None:
            cmpf = objtogen(cmpf)
            _cmpf = (<gen>cmpf).g
        pari_catch_sig_on()
        cdef GEN _ret = vecsort0(_x, _cmpf, flag)
        return pari_instance.new_gen(_ret)

    def vecsum(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
        """
        cdef GEN _v = v.g
        pari_catch_sig_on()
        cdef GEN _ret = vecsum(_v)
        return pari_instance.new_gen(_ret)

    def weber(x, long flag=0, long precision=0):
        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`.
        """
        cdef GEN _x = x.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = weber0(_x, flag, precision)
        return pari_instance.new_gen(_ret)

    def zeta(s, long precision=0):
        r"""
        For :math:`s` 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.
        
        For :math:`s` 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`).
        """
        cdef GEN _s = s.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gzeta(_s, precision)
        return pari_instance.new_gen(_ret)

    def zetak(nfz, x, long flag=0, long precision=0):
        r"""
        :emphasis:`znf` being a number
        field initialized by :literal:`zetakinit` (:emphasis:`not` by :literal:`nfinit`),
        computes the value of the Dedekind zeta function of the number
        field at the complex number :math:`x`. If :math:`flag = 1` computes Dedekind :math:`\Lambda`
        function instead (i.e. the product of the Dedekind zeta function by its gamma
        and exponential factors).
        
        :strong:`CAVEAT.` This implementation is not satisfactory and must be
        rewritten. In particular
        
        - The accuracy of the result depends in an essential way on the
          accuracy of both the :literal:`zetakinit` program and the current accuracy.
          Be wary in particular that :math:`x` of large imaginary part or, on the
          contrary, very close to an ordinary integer will suffer from precision
          loss, yielding fewer significant digits than expected. Computing with 28
          digits of relative accuracy, we have
        
        ::
        
            ? zeta(3)
            %1 = 1.202056903159594285399738161
            ? zeta(3-1e-20)
            %2 = 1.202056903159594285401719424
            ? zetak(zetakinit(x), 3-1e-20)
            %3 = 1.2020569031595952919 \\ 5 digits are wrong
            ? zetak(zetakinit(x), 3-1e-28)
            %4 = -25.33411749 \\ junk
        
        - As the precision increases, results become unexpectedly
          completely wrong:
        
        ::
        
            ? \p100
            ? zetak(zetakinit(x^2-5), -1) - 1/30
            %1 = 7.26691813 E-108 \\ perfect
            ? \p150
            ? zetak(zetakinit(x^2-5), -1) - 1/30
            %2 = -2.486113578 E-156 \\ perfect
            ? \p200
            ? zetak(zetakinit(x^2-5), -1) - 1/30
            %3 = 4.47... E-75 \\ more than half of the digits are wrong
            ? \p250
            ? zetak(zetakinit(x^2-5), -1) - 1/30
            %4 = 1.6 E43 \\ junk
        """
        cdef GEN _nfz = nfz.g
        x = objtogen(x)
        cdef GEN _x = (<gen>x).g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = gzetakall(_nfz, _x, flag, precision)
        return pari_instance.new_gen(_ret)

    def zetakinit(bnf, long precision=0):
        r"""
        Computes a number of initialization data
        concerning the number field associated to :literal:`bnf` so as to be able
        to compute the Dedekind zeta and lambda functions, respectively
        :math:`zetak(x)` and :math:`zetak(x,1)`, at the current real precision. If
        you do not need the :literal:`bnfinit` data somewhere else, you may call it
        with an irreducible polynomial instead of a :emphasis:`bnf`: it will call
        :literal:`bnfinit` itself.
        
        The result is a 9-component vector :math:`v` whose components are very technical
        and cannot really be used except through the :literal:`zetak` function.
        
        This function is very inefficient and should be rewritten. It needs to
        computes millions of coefficients of the corresponding Dirichlet series if
        the precision is big. Unless the discriminant is small it will not be able
        to handle more than 9 digits of relative precision. For instance,
        :literal:`zetakinit(x^8 - 2)` needs 440MB of memory at default precision.
        
        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 the number field is too large).
        """
        cdef GEN _bnf = bnf.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = initzeta(_bnf, precision)
        return pari_instance.new_gen(_ret)

    def zetamult(s, long precision=0):
        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
        """
        cdef GEN _s = s.g
        precision = prec_bits_to_words(precision)
        pari_catch_sig_on()
        cdef GEN _ret = zetamult(_s, precision)
        return pari_instance.new_gen(_ret)

    def zncoppersmith(P, N, X, B=None):
        r"""
        :math:`N` being an integer and :math:`P belongs to \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). :math:`X` must be smaller than :math:`\exp(\log^2 B / (\deg(P) \log N))`:
        for :math:`B = N`, this means :math:`X < N^{1/\deg(P)}`. Some :math:`x` larger than :math:`X` may
        be returned if you are very lucky. The smaller :math:`B` (or the larger :math:`X`), the
        slower the routine will be. 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
            interval = [10^30, 10^31];
            p = randomprime(interval);
            q = randomprime(interval); N = p*q;
            p0 = p % 10^20; \\ assume we know 1) p > 10^29, 2) the last 19 digits of p
            L = zncoppersmith(10^19*x + p0, N, 10^12, 10^29)
            
            \\ result in 10ms.
            %6 = [738281386540]
            ? gcd(L[1] * 10^19 + p0, N) == p
            %2 = 1
        
        and we recovered :math:`p`, faster than by trying all
        possibilities :math:`< 10^{12}`.
        
        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
            %4 = 1
        
        We guessed an integer of the order of :math:`10^{18}`, almost instantly.
        """
        cdef GEN _P = P.g
        N = objtogen(N)
        cdef GEN _N = (<gen>N).g
        X = objtogen(X)
        cdef GEN _X = (<gen>X).g
        cdef GEN _B = NULL
        if B is not None:
            B = objtogen(B)
            _B = (<gen>B).g
        pari_catch_sig_on()
        cdef GEN _ret = zncoppersmith(_P, _N, _X, _B)
        return pari_instance.new_gen(_ret)

    def znlog(x, g, o=None):
        r"""
        Discrete logarithm of :math:`x` in :math:`(\mathbb{Z}/N\mathbb{Z})^*` in base :math:`g`.
        The result is :math:`[]` when :math:`x` is not a power of :math:`g`.
        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 = 205 ms.
            ? for(i=1,10^4, znlog(i, g))
            time = 244 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)
        """
        cdef GEN _x = x.g
        g = objtogen(g)
        cdef GEN _g = (<gen>g).g
        cdef GEN _o = NULL
        if o is not None:
            o = objtogen(o)
            _o = (<gen>o).g
        pari_catch_sig_on()
        cdef GEN _ret = znlog(_x, _g, _o)
        return pari_instance.new_gen(_ret)

    def znorder(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.
        """
        cdef GEN _x = x.g
        cdef GEN _o = NULL
        if o is not None:
            o = objtogen(o)
            _o = (<gen>o).g
        pari_catch_sig_on()
        cdef GEN _ret = znorder(_x, _o)
        return pari_instance.new_gen(_ret)

    def znprimroot(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.
        """
        cdef GEN _n = n.g
        pari_catch_sig_on()
        cdef GEN _ret = znprimroot(_n)
        return pari_instance.new_gen(_ret)

    def znstar(n):
        r"""
        Gives the structure of the multiplicative group
        :math:`(\mathbb{Z}/n\mathbb{Z})^*` as a 3-component row vector :math:`v`, where :math:`v[1] = \phi(n)` is the
        order of that group, :math:`v[2]` is a :math:`k`-component row-vector :math:`d` of integers
        :math:`d[i]` such that :math:`d[i] > 1` and :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:`v[3]` is a :math:`k`-component row
        vector giving generators of the image of the cyclic groups :math:`\mathbb{Z}/d[i]\mathbb{Z}`.
        
        ::
        
            ? 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]
        
        According to the above definitions, :literal:`znstar(0)` is
        :literal:`[2, [2], [-1]]`, corresponding to :math:`\mathbb{Z}^*`.
        """
        cdef GEN _n = n.g
        pari_catch_sig_on()
        cdef GEN _ret = znstar(_n)
        return pari_instance.new_gen(_ret)

