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
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]
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]
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