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