Esempio n. 1
0
def enumerate_totallyreal_fields_all(n, B, verbose=0, return_seqs=False):
    r"""
    Enumerates *all* totally real fields of degree `n` with discriminant `\le B`,
    primitive or otherwise.

    EXAMPLES::

        sage: enumerate_totallyreal_fields_all(4, 2000)
        [[725, x^4 - x^3 - 3*x^2 + x + 1],
        [1125, x^4 - x^3 - 4*x^2 + 4*x + 1],
        [1600, x^4 - 6*x^2 + 4],
        [1957, x^4 - 4*x^2 - x + 1],
        [2000, x^4 - 5*x^2 + 5]]

    In practice most of these will be found by :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`, which is guaranteed to return all primitive fields but often returns many non-primitive ones as well. For instance, only one of the five fields in the example above is primitive, but :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim` finds four out of the five (the exception being `x^4 - 6x^2 + 4`).

    TESTS:

    The following was fixed in :trac:`13101`::

        sage: enumerate_totallyreal_fields_all(8, 10^6)  # long time (about 2 s)
        []
    """

    S = []
    counts = [0,0,0]
    if len(divisors(n)) > 4:
        raise ValueError, "Only implemented for n = p*q with p,q prime"
    for d in divisors(n):
        if d > 1 and d < n:
            Sds = enumerate_totallyreal_fields_prim(d, int(math.floor((1.*B)**(1.*d/n))), verbose=verbose)
            for i in range(len(Sds)):
                if verbose:
                    print "="*80
                    print "Taking F =", Sds[i][1]
                F = NumberField(ZZx(Sds[i][1]), 't')
                T = enumerate_totallyreal_fields_rel(F, n/d, B, verbose=verbose, return_seqs=return_seqs)
                if return_seqs:
                    for i in range(3):
                        counts[i] += T[0][i]
                    S += [[t[0],pari(t[1]).Polrev()] for t in T[1]]
                else:
                    S += [[t[0],t[1]] for t in T]
                j = i+1
                for E in enumerate_totallyreal_fields_prim(n/d, int(math.floor((1.*B)**(1./d)/(1.*Sds[i][0])**(n*1./d**2)))):
                    for EF in F.composite_fields(NumberField(ZZx(E[1]), 'u')):
                        if EF.degree() == n and EF.disc() <= B:
                            S.append([EF.disc(), pari(EF.absolute_polynomial())])
    S += enumerate_totallyreal_fields_prim(n, B, verbose=verbose)
    S.sort()
    weed_fields(S)

    # Output.
    if verbose:
        saveout = sys.stdout
        if type(verbose) == str:
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
        print "="*80
        print "Polynomials tested:", counts[0]
        print "Irreducible polynomials:", counts[1]
        print "Polynomials with nfdisc <= B:", counts[2]
        for i in range(len(S)):
            print S[i]
        if type(verbose) == str:
            fsock.close()
        sys.stdout = saveout

    if return_seqs:
        return [counts,[[s[0],s[1].reverse().Vec()] for s in S]]
    else:
        return S
Esempio n. 2
0
def enumerate_totallyreal_fields_all(n, B, verbose=0, return_seqs=False,
                                     return_pari_objects=True):
    r"""
    Enumerates *all* totally real fields of degree ``n`` with discriminant
    at most ``B``, primitive or otherwise.

    INPUT:

    - ``n`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``verbose`` -- boolean or nonnegative integer or string (default: 0)
      give a verbose description of the computations being performed. If
      ``verbose`` is set to ``2`` or more then it outputs some extra
      information. If ``verbose`` is a string then it outputs to a file
      specified by ``verbose``
    - ``return_seqs`` -- (boolean, default False) If ``True``, then return
      the polynomials as sequences (for easier exporting to a file). This
      also returns a list of four numbers, as explained in the OUTPUT
      section below.
    - ``return_pari_objects`` -- (boolean, default: True) if both
      ``return_seqs`` and ``return_pari_objects`` are ``False`` then it
      returns the elements as Sage objects; otherwise it returns pari
      objects.

    EXAMPLES::

        sage: enumerate_totallyreal_fields_all(4, 2000)
        [[725, x^4 - x^3 - 3*x^2 + x + 1],
        [1125, x^4 - x^3 - 4*x^2 + 4*x + 1],
        [1600, x^4 - 6*x^2 + 4],
        [1957, x^4 - 4*x^2 - x + 1],
        [2000, x^4 - 5*x^2 + 5]]
        sage: enumerate_totallyreal_fields_all(1, 10)
        [[1, x - 1]]

    TESTS:

    Each of the outputs must be elements of Sage if ``return_pari_objects``
    is set to ``False``::

        sage: enumerate_totallyreal_fields_all(2, 10)
        [[5, x^2 - x - 1], [8, x^2 - 2]]
        sage: enumerate_totallyreal_fields_all(2, 10)[0][1].parent()
        Interface to the PARI C library
        sage: enumerate_totallyreal_fields_all(2, 10, return_pari_objects=False)[0][1].parent()
        Univariate Polynomial Ring in x over Rational Field


    In practice most of these will be found by
    :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`,
    which is guaranteed to return all primitive fields but often returns
    many non-primitive ones as well. For instance, only one of the five
    fields in the example above is primitive, but
    :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`
    finds four out of the five (the exception being `x^4 - 6x^2 + 4`).

    The following was fixed in :trac:`13101`::

        sage: enumerate_totallyreal_fields_all(8, 10^6)  # long time (about 2 s)
        []
    """

    S = []
    counts = [0,0,0,0]
    if len(divisors(n)) > 4:
        raise ValueError("Only implemented for n = p*q with p,q prime")
    for d in divisors(n):
        if d > 1 and d < n:
            Sds = enumerate_totallyreal_fields_prim(d, int(math.floor((1.*B)**(1.*d/n))), verbose=verbose)
            for i in range(len(Sds)):
                if verbose:
                    print "="*80
                    print "Taking F =", Sds[i][1]
                F = NumberField(ZZx(Sds[i][1]), 't')
                T = enumerate_totallyreal_fields_rel(F, n/d, B, verbose=verbose, return_seqs=return_seqs)
                if return_seqs:
                    for i in range(4):
                        counts[i] += T[0][i]
                    S += [[t[0],pari(t[1]).Polrev()] for t in T[1]]
                else:
                    S += [[t[0],t[1]] for t in T]
                j = i+1
                for E in enumerate_totallyreal_fields_prim(n/d, int(math.floor((1.*B)**(1./d)/(1.*Sds[i][0])**(n*1./d**2)))):
                    for EF in F.composite_fields(NumberField(ZZx(E[1]), 'u')):
                        if EF.degree() == n and EF.disc() <= B:
                            S.append([EF.disc(), pari(EF.absolute_polynomial())])
    S += enumerate_totallyreal_fields_prim(n, B, verbose=verbose)
    S.sort(cmp=lambda x, y: cmp(x[0], y[0]) or cmp(x[1], y[1]))
    weed_fields(S)

    # Output.
    if verbose:
        saveout = sys.stdout
        if isinstance(verbose, str):
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
        print "="*80
        print "Polynomials tested: {}".format(counts[0])
        print ( "Polynomials with discriminant with large enough square"
                " divisor: {}".format(counts[1]))
        print "Irreducible polynomials: {}".format(counts[2])
        print "Polynomials with nfdisc <= B: {}".format(counts[3])
        for i in range(len(S)):
            print S[i]
        if isinstance(verbose, str):
            fsock.close()
        sys.stdout = saveout

    # Make sure to return elements that belong to Sage
    if return_seqs:
        return [[ZZ(_) for _ in counts],
                [[ZZ(s[0]), [QQ(_) for _ in s[1].polrecip().Vec()]] for s in S]]
    elif return_pari_objects:
        return S
    else:
        Px = PolynomialRing(QQ, 'x')
        return [[ZZ(s[0]), Px([QQ(_) for _ in s[1].list()])]
                for s in S]
Esempio n. 3
0
def enumerate_totallyreal_fields_rel(F, m, B, a = [], verbose=0, return_seqs=False):
    r"""
    This function enumerates (primitive) totally real field extensions of
    degree `m>1` of the totally real field F with discriminant `d \leq B`;
    optionally one can specify the first few coefficients, where the sequence ``a``
    corresponds to a polynomial by

    ::

        a[d]*x^n + ... + a[0]*x^(n-d)

    if ``length(a) = d+1``, so in particular always ``a[d] = 1``.
    If verbose == 1 (or 2), then print to the screen (really) verbosely; if
    verbose is a string, then print verbosely to the file specified by verbose.
    If return_seqs, then return the polynomials as sequences (for easier
    exporting to a file).

    NOTE:
    This is guaranteed to give all primitive such fields, and
    seems in practice to give many imprimitive ones.

    INPUT:

    - ``F`` -- number field, the base field
    - ``m`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``a`` -- list (default: []), the coefficient list to begin with
    - ``verbose`` -- boolean or string (default: 0)
    - ``return_seqs`` -- boolean (default: False)

    OUTPUT:

    the list of fields with entries [d,fabs,f], where
    d is the discriminant, fabs is an absolute defining polynomial,
    and f is a defining polynomial relative to F,
    sorted by discriminant.

    EXAMPLES::

        sage: ZZx = ZZ['x']
        sage: F.<t> = NumberField(x^2-2)
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)
        [[1600, x^4 - 6*x^2 + 4, xF^2 + xF - 1]]

    AUTHORS:

    - John Voight (2007-11-01)
    """

    if not isinstance(m, Integer):
        try:
            m = Integer(m)
        except TypeError:
            raise TypeError, "cannot coerce m (= %s) to an integer" % m
    if (m < 1):
        raise ValueError, "m must be at least 1."

    n = F.degree()*m

    # Initialize
    T = tr_data_rel(F,m,B,a)
    S = []
    Srel = []
    dB_odlyzko = odlyzko_bound_totallyreal(n)
    dB = math.ceil(40000*dB_odlyzko**n)
    counts = [0,0,0,0]

    # Trivial case
    if m == 1:
        g = pari(F.defining_polynomial()).reverse().Vec()
        if return_seqs:
            return [[0,0,0,0],[1,g,[-1,1]]]
        else:
            return [[1,pari('x-1'),g]]

    if verbose:
        saveout = sys.stdout
        if type(verbose) == str:
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
    f_out = [0]*m + [1]
    if verbose == 2:
        T.incr(f_out,verbose)
    else:
        T.incr(f_out)

    Fx = PolynomialRing(F, 'xF')

    nfF = pari(str(F.defining_polynomial()).replace('x', str(F.primitive_element()) ) )
    parit = pari(str(F.primitive_element()))

    while f_out[m] != 0:
        counts[0] += 1
        if verbose:
            print "==>", f_out,

        f_str = ''
        for i in range(len(f_out)):
            f_str += '(' + str(f_out[i]) + ')*x^' + str(i)
            if i < len(f_out)-1:
                f_str += '+'
        nf = pari(f_str)
        if nf.poldegree('t') == 0:
            nf = nf.subst('x', 'x-t')
        nf = nf.polresultant(nfF, parit)
        d = nf.poldisc()
        counts[0] += 1
        if d > 0 and nf.polsturm_full() == n:
            da = int_has_small_square_divisor(Integer(d))
            if d > dB or d <= B*da:
                counts[1] += 1
                if nf.polisirreducible():
                    counts[2] += 1
                    [zk,d] = nf.nfbasis_d()

                    if d <= B:
                        if verbose:
                            print "has discriminant", d,

                        # Find a minimal lattice element
                        counts[3] += 1
                        ng = pari([nf,zk]).polredabs()

                        # Check if K is contained in the list.
                        found = False
                        ind = bisect.bisect_left(S, [d,ng])
                        while ind < len(S) and S[ind][0] == d:
                            if S[ind][1] == ng:
                                if verbose:
                                    print "but is not new"
                                found = True
                                break
                            ind += 1
                        if not found:
                            if verbose:
                                print "and is new!"
                            S.insert(ind, [d,ng])
                            Srel.insert(ind, Fx(f_out))
                    else:
                        if verbose:
                            print "has discriminant", abs(d), "> B"
                else:
                    if verbose:
                        print "is not absolutely irreducible"
            else:
                if verbose:
                    print "has discriminant", abs(d), "with no large enough square divisor"
        else:
            if verbose:
                if d == 0:
                    print "is not squarefree"
                else:
                    print "is not totally real"
        if verbose == 2:
            T.incr(f_out,verbose=verbose)
        else:
            T.incr(f_out)

    # In the application of Smyth's theorem above, we exclude finitely
    # many possibilities which we must now throw back in.
    if m == 2:
        if Fx([-1,1,1]).is_irreducible():
            K = F.extension(Fx([-1,1,1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                ind = bisect.bisect_left(S, [d,ng])
                S.insert(ind, [d,ng])
                Srel.insert(ind, Fx([-1,1,1]))
        elif F.degree() == 2:
            for ff in [[1,-7,13,-7,1],[1,-8,14,-7,1]]:
                f = Fx(ff).factor()[0][0]
                K = F.extension(f, 'tK')
                Kabs = K.absolute_field('tKabs')
                Kabs_pari = pari(Kabs.defining_polynomial())
                d = K.absolute_discriminant()
                if abs(d) <= B:
                    ng = Kabs_pari.polredabs()
                    ind = bisect.bisect_left(S, [d,ng])
                    S.insert(ind, [d,ng])
                    Srel.insert(ind, f)
    elif m == 3:
        if Fx([-1,6,-5,1]).is_irreducible():
            K = F.extension(Fx([-1,6,-5,1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                ind = bisect.bisect_left(S, [d,ng])
                S.insert(ind, [d,ng])
                Srel.insert(ind, Fx([-1,6,-5,1]))

    # Now check for isomorphic fields
    S = [[S[i][0],S[i][1],Srel[i]] for i in range(len(S))]
    weed_fields(S)

    # Output.
    if verbose:
        print "="*80
        print "Polynomials tested:", counts[0]
        print "Irreducible polynomials:", counts[1]
        print "Polynomials with nfdisc <= B:", counts[2]
        for i in range(len(S)):
            print S[i]
        if type(verbose) == str:
            fsock.close()
        sys.stdout = saveout

    if return_seqs:
        return [counts,[[s[0],s[1].reverse().Vec(),s[2].coeffs()] for s in S]]
    else:
        return S
Esempio n. 4
0
def enumerate_totallyreal_fields_rel(F, m, B, a = [], verbose=0,
                                     return_seqs=False,
                                     return_pari_objects=True):
    r"""
    This function enumerates (primitive) totally real field extensions of
    degree `m>1` of the totally real field F with discriminant `d \leq B`;
    optionally one can specify the first few coefficients, where the sequence ``a``
    corresponds to a polynomial by

    ::

        a[d]*x^n + ... + a[0]*x^(n-d)

    if ``length(a) = d+1``, so in particular always ``a[d] = 1``.

    .. note::

        This is guaranteed to give all primitive such fields, and
        seems in practice to give many imprimitive ones.

    INPUT:

    - ``F`` -- number field, the base field
    - ``m`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``a`` -- list (default: []), the coefficient list to begin with
    - ``verbose`` -- boolean or nonnegative integer or string (default: 0)
      give a verbose description of the computations being performed. If
      ``verbose`` is set to ``2`` or more then it outputs some extra
      information. If ``verbose`` is a string then it outputs to a file
      specified by ``verbose``
    - ``return_seqs`` -- (boolean, default False) If ``True``, then return
      the polynomials as sequences (for easier exporting to a file). This
      also returns a list of four numbers, as explained in the OUTPUT
      section below.
    - ``return_pari_objects`` -- (boolean, default: True) if
      both ``return_seqs`` and ``return_pari_objects`` are ``False`` then
      it returns the elements as Sage objects; otherwise it returns pari
      objects.

    OUTPUT:

    - the list of fields with entries ``[d,fabs,f]``, where ``d`` is the
      discriminant, ``fabs`` is an absolute defining polynomial, and ``f``
      is a defining polynomial relative to ``F``, sorted by discriminant.

    - if ``return_seqs`` is ``True``, then the first field of the list is
      a list containing the count of four items as explained below

      - the first entry gives the number of polynomials tested
      - the second entry gives the number of polynomials with its
        discriminant having a large enough square divisor
      - the third entry is the number of irreducible polynomials
      - the fourth entry is the number of irreducible polynomials with
        discriminant at most ``B``

    EXAMPLES::

        sage: ZZx = ZZ['x']
        sage: F.<t> = NumberField(x^2-2)
        sage: enumerate_totallyreal_fields_rel(F, 1, 2000)
        [[1, [-2, 0, 1], xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)
        [[1600, x^4 - 6*x^2 + 4, xF^2 + xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)
        [[9, 6, 5, 0], [[1600, [4, 0, -6, 0, 1], [-1, 1, 1]]]]

    TESTS:

    Each of the outputs must be elements of Sage if ``return_pari_objects``
    is set to ``False``::

        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)[0][1].parent()
        Interface to the PARI C library
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][0].parent()
        Integer Ring
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][1].parent()
        Univariate Polynomial Ring in x over Rational Field
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][2].parent()
        Univariate Polynomial Ring in xF over Number Field in t with defining polynomial x^2 - 2
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)[1][0][1][0].parent()
        Rational Field

    AUTHORS:

    - John Voight (2007-11-01)
    """

    if not isinstance(m, Integer):
        try:
            m = Integer(m)
        except TypeError:
            raise TypeError("cannot coerce m (= %s) to an integer" % m)
    if (m < 1):
        raise ValueError("m must be at least 1.")

    n = F.degree()*m

    # Initialize
    S = {}        # dictionary of the form {(d, fabs): f, ...}
    dB_odlyzko = odlyzko_bound_totallyreal(n)
    dB = math.ceil(40000*dB_odlyzko**n)
    counts = [0,0,0,0]

    # Trivial case
    if m == 1:
        g = pari(F.defining_polynomial()).polrecip().Vec()
        if return_seqs:
            return [[0,0,0,0], [1, [-1, 1], g]]
        elif return_pari_objects:
            return [[1, g, pari('xF-1')]]
        else:
            Px = PolynomialRing(QQ, 'xF')
            return [[ZZ(1), [QQ(_) for _ in g], Px.gen()-1]]

    if verbose:
        saveout = sys.stdout
        if isinstance(verbose, str):
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
    f_out = [0]*m + [1]
    T = tr_data_rel(F,m,B,a)
    if verbose == 2:
        T.incr(f_out,verbose)
    else:
        T.incr(f_out)

    Fx = PolynomialRing(F, 'xF')

    nfF = pari(str(F.defining_polynomial()).replace('x', str(F.primitive_element()) ) )
    parit = pari(str(F.primitive_element()))

    while f_out[m] != 0:
        counts[0] += 1
        if verbose:
            print "==>", f_out,

        f_str = ''
        for i in range(len(f_out)):
            f_str += '(' + str(f_out[i]) + ')*x^' + str(i)
            if i < len(f_out)-1:
                f_str += '+'
        nf = pari(f_str)
        if nf.poldegree('t') == 0:
            nf = nf.subst('x', 'x-t')
        nf = nf.polresultant(nfF, parit)
        d = nf.poldisc()
        #counts[0] += 1
        if d > 0 and nf.polsturm() == n:
            da = int_has_small_square_divisor(Integer(d))
            if d > dB or d <= B*da:
                counts[1] += 1
                if nf.polisirreducible():
                    counts[2] += 1
                    [zk,d] = nf.nfbasis_d()

                    if d <= B:
                        if verbose:
                            print "has discriminant", d,

                        # Find a minimal lattice element
                        counts[3] += 1
                        ng = pari([nf,zk]).polredabs()

                        # Check if K is contained in the list.
                        if (d, ng) in S:
                            if verbose:
                                print "but is not new"
                        else:
                            if verbose:
                                print "and is new!"
                            S[(d, ng)] = Fx(f_out)
                    else:
                        if verbose:
                            print "has discriminant", abs(d), "> B"
                else:
                    if verbose:
                        print "is not absolutely irreducible"
            else:
                if verbose:
                    print "has discriminant", abs(d), "with no large enough square divisor"
        else:
            if verbose:
                if d == 0:
                    print "is not squarefree"
                else:
                    print "is not totally real"
        if verbose == 2:
            T.incr(f_out,verbose=verbose)
        else:
            T.incr(f_out)

    # In the application of Smyth's theorem above, we exclude finitely
    # many possibilities which we must now throw back in.
    if m == 2:
        if Fx([-1,1,1]).is_irreducible():
            K = F.extension(Fx([-1,1,1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1,1,1])
        elif F.degree() == 2:
            for ff in [[1,-7,13,-7,1],[1,-8,14,-7,1]]:
                f = Fx(ff).factor()[0][0]
                K = F.extension(f, 'tK')
                Kabs = K.absolute_field('tKabs')
                Kabs_pari = pari(Kabs.defining_polynomial())
                d = K.absolute_discriminant()
                if abs(d) <= B:
                    ng = Kabs_pari.polredabs()
                    S[(d, ng)] = f
    elif m == 3:
        if Fx([-1,6,-5,1]).is_irreducible():
            K = F.extension(Fx([-1,6,-5,1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1,6,-5,1])

    # Convert S to a sorted list of triples [d, fabs, f], taking care
    # to use cmp() and not the comparison operators on PARI polynomials.
    S = [[s[0], s[1], t] for s, t in S.items()]
    S.sort(cmp=lambda x, y: cmp(x[0], y[0]) or cmp(x[1], y[1]))

    # Now check for isomorphic fields
    weed_fields(S)

    # Output.
    if verbose:
        print "="*80
        print "Polynomials tested: {}".format(counts[0])
        print ( "Polynomials with discriminant with large enough square"
                " divisor: {}".format(counts[1]))
        print "Irreducible polynomials: {}".format(counts[2])
        print "Polynomials with nfdisc <= B: {}".format(counts[3])
        for i in range(len(S)):
            print S[i]
        if isinstance(verbose, str):
            fsock.close()
        sys.stdout = saveout

    # Make sure to return elements that belong to Sage
    if return_seqs:
        return [[ZZ(x) for x in counts],
                [[s[0], [QQ(x) for x in s[1].polrecip().Vec()], s[2].coefficients(sparse=False)]
                 for s in S]
               ]
    elif return_pari_objects:
        return S
    else:
        Px = PolynomialRing(QQ, 'x')
        return [[s[0], Px([QQ(_) for _ in s[1].list()]), s[2]] for s in S]
Esempio n. 5
0
def enumerate_totallyreal_fields_all(n,
                                     B,
                                     verbose=0,
                                     return_seqs=False,
                                     return_pari_objects=True):
    r"""
    Enumerates *all* totally real fields of degree ``n`` with discriminant
    at most ``B``, primitive or otherwise.

    INPUT:

    - ``n`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``verbose`` -- boolean or nonnegative integer or string (default: 0)
      give a verbose description of the computations being performed. If
      ``verbose`` is set to ``2`` or more then it outputs some extra
      information. If ``verbose`` is a string then it outputs to a file
      specified by ``verbose``
    - ``return_seqs`` -- (boolean, default False) If ``True``, then return
      the polynomials as sequences (for easier exporting to a file). This
      also returns a list of four numbers, as explained in the OUTPUT
      section below.
    - ``return_pari_objects`` -- (boolean, default: True) if both
      ``return_seqs`` and ``return_pari_objects`` are ``False`` then it
      returns the elements as Sage objects; otherwise it returns pari
      objects.

    EXAMPLES::

        sage: enumerate_totallyreal_fields_all(4, 2000)
        [[725, x^4 - x^3 - 3*x^2 + x + 1],
        [1125, x^4 - x^3 - 4*x^2 + 4*x + 1],
        [1600, x^4 - 6*x^2 + 4],
        [1957, x^4 - 4*x^2 - x + 1],
        [2000, x^4 - 5*x^2 + 5]]
        sage: enumerate_totallyreal_fields_all(1, 10)
        [[1, x - 1]]

    TESTS:

    Each of the outputs must be elements of Sage if ``return_pari_objects``
    is set to ``False``::

        sage: enumerate_totallyreal_fields_all(2, 10)
        [[5, x^2 - x - 1], [8, x^2 - 2]]
        sage: type(enumerate_totallyreal_fields_all(2, 10)[0][1])
        <type 'cypari2.gen.Gen'>
        sage: enumerate_totallyreal_fields_all(2, 10, return_pari_objects=False)[0][1].parent()
        Univariate Polynomial Ring in x over Rational Field


    In practice most of these will be found by
    :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`,
    which is guaranteed to return all primitive fields but often returns
    many non-primitive ones as well. For instance, only one of the five
    fields in the example above is primitive, but
    :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`
    finds four out of the five (the exception being `x^4 - 6x^2 + 4`).

    The following was fixed in :trac:`13101`::

        sage: enumerate_totallyreal_fields_all(8, 10^6)  # long time (about 2 s)
        []
    """

    S = []
    counts = [0, 0, 0, 0]
    if len(divisors(n)) > 4:
        raise ValueError("Only implemented for n = p*q with p,q prime")
    for d in divisors(n):
        if d > 1 and d < n:
            Sds = enumerate_totallyreal_fields_prim(
                d, int(math.floor((1. * B)**(1. * d / n))), verbose=verbose)
            for i in range(len(Sds)):
                if verbose:
                    print("=" * 80)
                    print("Taking F =", Sds[i][1])
                F = NumberField(ZZx(Sds[i][1]), 't')
                T = enumerate_totallyreal_fields_rel(F,
                                                     n / d,
                                                     B,
                                                     verbose=verbose,
                                                     return_seqs=return_seqs)
                if return_seqs:
                    for i in range(4):
                        counts[i] += T[0][i]
                    S += [[t[0], pari(t[1]).Polrev()] for t in T[1]]
                else:
                    S += [[t[0], t[1]] for t in T]
                for E in enumerate_totallyreal_fields_prim(
                        n / d,
                        int(
                            math.floor((1. * B)**(1. / d) /
                                       (1. * Sds[i][0])**(n * 1. / d**2)))):
                    for EF in F.composite_fields(NumberField(ZZx(E[1]), 'u')):
                        if EF.degree() == n and EF.disc() <= B:
                            S.append(
                                [EF.disc(),
                                 pari(EF.absolute_polynomial())])
    S += enumerate_totallyreal_fields_prim(n, B, verbose=verbose)
    S.sort(key=lambda x: (x[0], [QQ(cf) for cf in x[1].polrecip().Vec()]))
    weed_fields(S)

    # Output.
    if verbose:
        saveout = sys.stdout
        if isinstance(verbose, str):
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
        print("=" * 80)
        print("Polynomials tested: {}".format(counts[0]))
        print("Polynomials with discriminant with large enough square"
              " divisor: {}".format(counts[1]))
        print("Irreducible polynomials: {}".format(counts[2]))
        print("Polynomials with nfdisc <= B: {}".format(counts[3]))
        for i in range(len(S)):
            print(S[i])
        if isinstance(verbose, str):
            fsock.close()
        sys.stdout = saveout

    # Make sure to return elements that belong to Sage
    if return_seqs:
        return [[ZZ(_) for _ in counts],
                [[ZZ(s[0]), [QQ(_) for _ in s[1].polrecip().Vec()]]
                 for s in S]]
    elif return_pari_objects:
        return S
    else:
        Px = PolynomialRing(QQ, 'x')
        return [[ZZ(s[0]), Px([QQ(_) for _ in s[1].list()])] for s in S]
Esempio n. 6
0
def enumerate_totallyreal_fields_rel(F,
                                     m,
                                     B,
                                     a=[],
                                     verbose=0,
                                     return_seqs=False,
                                     return_pari_objects=True):
    r"""
    This function enumerates (primitive) totally real field extensions of
    degree `m>1` of the totally real field F with discriminant `d \leq B`;
    optionally one can specify the first few coefficients, where the sequence ``a``
    corresponds to a polynomial by

    ::

        a[d]*x^n + ... + a[0]*x^(n-d)

    if ``length(a) = d+1``, so in particular always ``a[d] = 1``.

    .. note::

        This is guaranteed to give all primitive such fields, and
        seems in practice to give many imprimitive ones.

    INPUT:

    - ``F`` -- number field, the base field
    - ``m`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``a`` -- list (default: []), the coefficient list to begin with
    - ``verbose`` -- boolean or nonnegative integer or string (default: 0)
      give a verbose description of the computations being performed. If
      ``verbose`` is set to ``2`` or more then it outputs some extra
      information. If ``verbose`` is a string then it outputs to a file
      specified by ``verbose``
    - ``return_seqs`` -- (boolean, default False) If ``True``, then return
      the polynomials as sequences (for easier exporting to a file). This
      also returns a list of four numbers, as explained in the OUTPUT
      section below.
    - ``return_pari_objects`` -- (boolean, default: True) if
      both ``return_seqs`` and ``return_pari_objects`` are ``False`` then
      it returns the elements as Sage objects; otherwise it returns pari
      objects.

    OUTPUT:

    - the list of fields with entries ``[d,fabs,f]``, where ``d`` is the
      discriminant, ``fabs`` is an absolute defining polynomial, and ``f``
      is a defining polynomial relative to ``F``, sorted by discriminant.

    - if ``return_seqs`` is ``True``, then the first field of the list is
      a list containing the count of four items as explained below

      - the first entry gives the number of polynomials tested
      - the second entry gives the number of polynomials with its
        discriminant having a large enough square divisor
      - the third entry is the number of irreducible polynomials
      - the fourth entry is the number of irreducible polynomials with
        discriminant at most ``B``

    EXAMPLES::

        sage: ZZx = ZZ['x']
        sage: F.<t> = NumberField(x^2-2)
        sage: enumerate_totallyreal_fields_rel(F, 1, 2000)
        [[1, [-2, 0, 1], xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)
        [[1600, x^4 - 6*x^2 + 4, xF^2 + xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)
        [[9, 6, 5, 0], [[1600, [4, 0, -6, 0, 1], [-1, 1, 1]]]]

    TESTS:

    Each of the outputs must be elements of Sage if ``return_pari_objects``
    is set to ``False``::

        sage: type(enumerate_totallyreal_fields_rel(F, 2, 2000)[0][1])
        <type 'cypari2.gen.Gen'>
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][0].parent()
        Integer Ring
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][1].parent()
        Univariate Polynomial Ring in x over Rational Field
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][2].parent()
        Univariate Polynomial Ring in xF over Number Field in t with defining polynomial x^2 - 2
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)[1][0][1][0].parent()
        Rational Field

    AUTHORS:

    - John Voight (2007-11-01)
    """

    if not isinstance(m, Integer):
        try:
            m = Integer(m)
        except TypeError:
            raise TypeError("cannot coerce m (= %s) to an integer" % m)
    if (m < 1):
        raise ValueError("m must be at least 1.")

    n = F.degree() * m

    # Initialize
    S = {}  # dictionary of the form {(d, fabs): f, ...}
    dB_odlyzko = odlyzko_bound_totallyreal(n)
    dB = math.ceil(40000 * dB_odlyzko**n)
    counts = [0, 0, 0, 0]

    # Trivial case
    if m == 1:
        g = pari(F.defining_polynomial()).polrecip().Vec()
        if return_seqs:
            return [[0, 0, 0, 0], [1, [-1, 1], g]]
        elif return_pari_objects:
            return [[1, g, pari('xF-1')]]
        else:
            Px = PolynomialRing(QQ, 'xF')
            return [[ZZ(1), [QQ(_) for _ in g], Px.gen() - 1]]

    if verbose:
        saveout = sys.stdout
        if isinstance(verbose, str):
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
    f_out = [0] * m + [1]
    T = tr_data_rel(F, m, B, a)
    if verbose == 2:
        T.incr(f_out, verbose)
    else:
        T.incr(f_out)

    Fx = PolynomialRing(F, 'xF')

    nfF = pari(
        str(F.defining_polynomial()).replace('x', str(F.primitive_element())))
    parit = pari(str(F.primitive_element()))

    while f_out[m] != 0:
        counts[0] += 1
        if verbose:
            print("==>", f_out, end="")

        f_str = ''
        for i in range(len(f_out)):
            f_str += '(' + str(f_out[i]) + ')*x^' + str(i)
            if i < len(f_out) - 1:
                f_str += '+'
        nf = pari(f_str)
        if nf.poldegree('t') == 0:
            nf = nf.subst('x', 'x-t')
        nf = nf.polresultant(nfF, parit)
        d = nf.poldisc()
        #counts[0] += 1
        if d > 0 and nf.polsturm() == n:
            da = int_has_small_square_divisor(Integer(d))
            if d > dB or d <= B * da:
                counts[1] += 1
                if nf.polisirreducible():
                    counts[2] += 1
                    [zk, d] = nf.nfbasis_d()

                    if d <= B:
                        if verbose:
                            print("has discriminant", d, end="")

                        # Find a minimal lattice element
                        counts[3] += 1
                        ng = pari([nf, zk]).polredabs()

                        # Check if K is contained in the list.
                        if (d, ng) in S:
                            if verbose:
                                print("but is not new")
                        else:
                            if verbose:
                                print("and is new!")
                            S[(d, ng)] = Fx(f_out)
                    else:
                        if verbose:
                            print("has discriminant", abs(d), "> B")
                else:
                    if verbose:
                        print("is not absolutely irreducible")
            else:
                if verbose:
                    print("has discriminant", abs(d),
                          "with no large enough square divisor")
        else:
            if verbose:
                if d == 0:
                    print("is not squarefree")
                else:
                    print("is not totally real")
        if verbose == 2:
            T.incr(f_out, verbose=verbose)
        else:
            T.incr(f_out)

    # In the application of Smyth's theorem above, we exclude finitely
    # many possibilities which we must now throw back in.
    if m == 2:
        if Fx([-1, 1, 1]).is_irreducible():
            K = F.extension(Fx([-1, 1, 1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1, 1, 1])
        elif F.degree() == 2:
            for ff in [[1, -7, 13, -7, 1], [1, -8, 14, -7, 1]]:
                f = Fx(ff).factor()[0][0]
                K = F.extension(f, 'tK')
                Kabs = K.absolute_field('tKabs')
                Kabs_pari = pari(Kabs.defining_polynomial())
                d = K.absolute_discriminant()
                if abs(d) <= B:
                    ng = Kabs_pari.polredabs()
                    S[(d, ng)] = f
    elif m == 3:
        if Fx([-1, 6, -5, 1]).is_irreducible():
            K = F.extension(Fx([-1, 6, -5, 1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1, 6, -5, 1])

    # Convert S to a sorted list of triples [d, fabs, f], taking care
    # not to use the comparison operators on PARI polynomials.
    S = [[s[0], s[1], t] for s, t in S.items()]
    S.sort(key=lambda x: (x[0], [QQ(cf) for cf in x[1].polrecip().Vec()]))

    # Now check for isomorphic fields
    weed_fields(S)

    # Output.
    if verbose:
        print("=" * 80)
        print("Polynomials tested: {}".format(counts[0]))
        print("Polynomials with discriminant with large enough square"
              " divisor: {}".format(counts[1]))
        print("Irreducible polynomials: {}".format(counts[2]))
        print("Polynomials with nfdisc <= B: {}".format(counts[3]))
        for i in range(len(S)):
            print(S[i])
        if isinstance(verbose, str):
            fsock.close()
        sys.stdout = saveout

    # Make sure to return elements that belong to Sage
    if return_seqs:
        return [[ZZ(x) for x in counts],
                [[
                    s[0], [QQ(x) for x in s[1].polrecip().Vec()],
                    s[2].coefficients(sparse=False)
                ] for s in S]]
    elif return_pari_objects:
        return S
    else:
        Px = PolynomialRing(QQ, 'x')
        return [[s[0], Px([QQ(_) for _ in s[1].list()]), s[2]] for s in S]
Esempio n. 7
0
def enumerate_totallyreal_fields_all(n, B, verbose=0, return_seqs=False):
    r"""
    Enumerates *all* totally real fields of degree `n` with discriminant `\le B`,
    primitive or otherwise.
    
    EXAMPLES::
    
        sage: enumerate_totallyreal_fields_all(4, 2000)
        [[725, x^4 - x^3 - 3*x^2 + x + 1], 
        [1125, x^4 - x^3 - 4*x^2 + 4*x + 1], 
        [1600, x^4 - 6*x^2 + 4], 
        [1957, x^4 - 4*x^2 - x + 1], 
        [2000, x^4 - 5*x^2 + 5]]
    
    In practice most of these will be found by :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`, which is guaranteed to return all primitive fields but often returns many non-primitive ones as well. For instance, only one of the five fields in the example above is primitive, but :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim` finds four out of the five (the exception being `x^4 - 6x^2 + 4`).
    """

    S = []
    counts = [0, 0, 0]
    if len(divisors(n)) > 4:
        raise ValueError, "Only implemented for n = p*q with p,q prime"
    for d in divisors(n):
        if d > 1 and d < n:
            Sds = enumerate_totallyreal_fields_prim(d, int(math.floor((1.0 * B) ** (1.0 * d / n))), verbose=verbose)
            for i in range(len(Sds)):
                if verbose:
                    print "=" * 80
                    print "Taking F =", Sds[i][1]
                F = NumberField(ZZx(Sds[i][1]), "t")
                T = enumerate_totallyreal_fields_rel(F, n / d, B, verbose=verbose, return_seqs=return_seqs)
                if return_seqs:
                    for i in range(3):
                        counts[i] += T[0][i]
                    S += [[t[0], pari(t[1]).Polrev()] for t in T[1]]
                else:
                    S += [[t[0], t[1]] for t in T]
                j = i + 1
                for E in enumerate_totallyreal_fields_prim(
                    n / d, int(math.floor((1.0 * B) ** (1.0 / d) / (1.0 * Sds[i][0]) ** (n * 1.0 / d ** 2)))
                ):
                    for EF in F.composite_fields(NumberField(ZZx(E[1]), "u")):
                        if EF.degree() == n and EF.disc() <= B:
                            S.append([EF.disc(), pari(EF.absolute_polynomial())])
    S += enumerate_totallyreal_fields_prim(n, B, verbose=verbose)
    S.sort()
    weed_fields(S)

    # Output.
    if verbose:
        saveout = sys.stdout
        if type(verbose) == str:
            fsock = open(verbose, "w")
            sys.stdout = fsock
        # Else, print to screen
        print "=" * 80
        print "Polynomials tested:", counts[0]
        print "Irreducible polynomials:", counts[1]
        print "Polynomials with nfdisc <= B:", counts[2]
        for i in range(len(S)):
            print S[i]
        if type(verbose) == str:
            fsock.close()
        sys.stdout = saveout

    if return_seqs:
        return [counts, [[s[0], s[1].reverse().Vec()] for s in S]]
    else:
        return S
Esempio n. 8
0
def enumerate_totallyreal_fields_rel(F, m, B, a=[], verbose=0, return_seqs=False):
    r"""
    This function enumerates (primitive) totally real field extensions of
    degree `m>1` of the totally real field F with discriminant `d \leq B`; 
    optionally one can specify the first few coefficients, where the sequence ``a``
    corresponds to a polynomial by
    
    ::
    
        a[d]*x^n + ... + a[0]*x^(n-d)
        
    if ``length(a) = d+1``, so in particular always ``a[d] = 1``.
    If verbose == 1 (or 2), then print to the screen (really) verbosely; if
    verbose is a string, then print verbosely to the file specified by verbose.
    If return_seqs, then return the polynomials as sequences (for easier
    exporting to a file).

    NOTE:
    This is guaranteed to give all primitive such fields, and 
    seems in practice to give many imprimitive ones.

    INPUT:
    
    - ``F`` -- number field, the base field
    - ``m`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``a`` -- list (default: []), the coefficient list to begin with
    - ``verbose`` -- boolean or string (default: 0)
    - ``return_seqs`` -- boolean (default: False)

    OUTPUT:
    
    the list of fields with entries [d,fabs,f], where
    d is the discriminant, fabs is an absolute defining polynomial,
    and f is a defining polynomial relative to F,
    sorted by discriminant.

    EXAMPLES::
    
        sage: ZZx = ZZ['x']
        sage: F.<t> = NumberField(x^2-2)
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)
        [[1600, x^4 - 6*x^2 + 4, xF^2 + xF - 1]]

    AUTHORS:
    
    - John Voight (2007-11-01)
    """

    if not isinstance(m, Integer):
        try:
            m = Integer(m)
        except TypeError:
            raise TypeError, "cannot coerce m (= %s) to an integer" % m
    if m < 1:
        raise ValueError, "m must be at least 1."

    n = F.degree() * m

    # Initialize
    T = tr_data_rel(F, m, B, a)
    S = []
    Srel = []
    dB_odlyzko = odlyzko_bound_totallyreal(n)
    dB = math.ceil(40000 * dB_odlyzko ** n)
    counts = [0, 0, 0, 0]

    # Trivial case
    if m == 1:
        g = pari(F.defining_polynomial()).reverse().Vec()
        if return_seqs:
            return [[0, 0, 0, 0], [1, g, [-1, 1]]]
        else:
            return [[1, pari("x-1"), g]]

    if verbose:
        saveout = sys.stdout
        if type(verbose) == str:
            fsock = open(verbose, "w")
            sys.stdout = fsock
        # Else, print to screen
    f_out = [0] * m + [1]
    if verbose == 2:
        T.incr(f_out, verbose)
    else:
        T.incr(f_out)

    Fx = PolynomialRing(F, "xF")

    nfF = pari(str(F.defining_polynomial()).replace("x", str(F.primitive_element())))
    parit = pari(str(F.primitive_element()))

    while f_out[m] <> 0:
        counts[0] += 1
        if verbose:
            print "==>", f_out,

        f_str = ""
        for i in range(len(f_out)):
            f_str += "(" + str(f_out[i]) + ")*x^" + str(i)
            if i < len(f_out) - 1:
                f_str += "+"
        nf = pari(f_str)
        if nf.poldegree("t") == 0:
            nf = nf.subst("x", "x-t")
        nf = nf.polresultant(nfF, parit)
        d = nf.poldisc()
        counts[0] += 1
        if d > 0 and nf.polsturm_full() == n:
            da = int_has_small_square_divisor(Integer(d))
            if d > dB or d <= B * da:
                counts[1] += 1
                if nf.polisirreducible():
                    counts[2] += 1
                    [zk, d] = nf.nfbasis_d()

                    if d <= B:
                        if verbose:
                            print "has discriminant", d,

                        # Find a minimal lattice element
                        counts[3] += 1
                        ng = pari([nf, zk]).polredabs()

                        # Check if K is contained in the list.
                        found = False
                        ind = bisect.bisect_left(S, [d, ng])
                        while ind < len(S) and S[ind][0] == d:
                            if S[ind][1] == ng:
                                if verbose:
                                    print "but is not new"
                                found = True
                                break
                            ind += 1
                        if not found:
                            if verbose:
                                print "and is new!"
                            S.insert(ind, [d, ng])
                            Srel.insert(ind, Fx(f_out))
                    else:
                        if verbose:
                            print "has discriminant", abs(d), "> B"
                else:
                    if verbose:
                        print "is not absolutely irreducible"
            else:
                if verbose:
                    print "has discriminant", abs(d), "with no large enough square divisor"
        else:
            if verbose:
                if d == 0:
                    print "is not squarefree"
                else:
                    print "is not totally real"
        if verbose == 2:
            T.incr(f_out, verbose=verbose)
        else:
            T.incr(f_out)

    # In the application of Smyth's theorem above, we exclude finitely
    # many possibilities which we must now throw back in.
    if m == 2:
        if Fx([-1, 1, 1]).is_irreducible():
            K = F.extension(Fx([-1, 1, 1]), "tK")
            Kabs = K.absolute_field("tKabs")
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                ind = bisect.bisect_left(S, [d, ng])
                S.insert(ind, [d, ng])
                Srel.insert(ind, Fx([-1, 1, 1]))
        elif F.degree() == 2:
            for ff in [[1, -7, 13, -7, 1], [1, -8, 14, -7, 1]]:
                f = Fx(ff).factor()[0][0]
                K = F.extension(f, "tK")
                Kabs = K.absolute_field("tKabs")
                Kabs_pari = pari(Kabs.defining_polynomial())
                d = K.absolute_discriminant()
                if abs(d) <= B:
                    ng = Kabs_pari.polredabs()
                    ind = bisect.bisect_left(S, [d, ng])
                    S.insert(ind, [d, ng])
                    Srel.insert(ind, f)
    elif m == 3:
        if Fx([-1, 6, -5, 1]).is_irreducible():
            K = F.extension(Fx([-1, 6, -5, 1]), "tK")
            Kabs = K.absolute_field("tKabs")
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                ind = bisect.bisect_left(S, [d, ng])
                S.insert(ind, [d, ng])
                Srel.insert(ind, Fx([-1, 6, -5, 1]))

    # Now check for isomorphic fields
    S = [[S[i][0], S[i][1], Srel[i]] for i in range(len(S))]
    weed_fields(S)

    # Output.
    if verbose:
        print "=" * 80
        print "Polynomials tested:", counts[0]
        print "Irreducible polynomials:", counts[1]
        print "Polynomials with nfdisc <= B:", counts[2]
        for i in range(len(S)):
            print S[i]
        if type(verbose) == str:
            fsock.close()
        sys.stdout = saveout

    if return_seqs:
        return [counts, [[s[0], s[1].reverse().Vec(), s[2].coeffs()] for s in S]]
    else:
        return S