def primes_iter(K, bound=oo, cache=True): if cache and not hasattr(K, "_prime_factorizations_cache"): K._prime_factorizations_cache = {} for p in primes(1, bound): if cache and p in K._prime_factorizations_cache: F = K._prime_factorizations_cache[p] else: F = (K * p).factor() if cache: K._prime_factorizations_cache[p] = F for pp, _ in F: if pp.absolute_norm() < bound: yield pp
def split_primes_iter(K, bound=oo, cache=True): if cache and not hasattr(K, "_prime_factorizations_cache"): K._prime_factorizations_cache = {} for p in primes(1, bound): if cache and p in K._prime_factorizations_cache: F = K._prime_factorizations_cache[p] else: F = (K * p).factor() if cache: K._prime_factorizations_cache[p] = F if not len(F) == K.absolute_degree(): continue for pp, _ in F: yield pp
def deg_one_primes_iter(K, principal_only=False): r""" Return an iterator over degree 1 primes of ``K``. INPUT: - ``K`` -- a number field - ``principal_only`` -- bool; if ``True``, only yield principal primes OUTPUT: An iterator over degree 1 primes of `K` up to the given norm, optionally yielding only principal primes. EXAMPLES:: sage: K.<a> = QuadraticField(-5) sage: from sage.schemes.elliptic_curves.gal_reps_number_field import deg_one_primes_iter sage: it = deg_one_primes_iter(K) sage: [next(it) for _ in range(6)] [Fractional ideal (2, a + 1), Fractional ideal (3, a + 1), Fractional ideal (3, a + 2), Fractional ideal (-a), Fractional ideal (7, a + 3), Fractional ideal (7, a + 4)] sage: it = deg_one_primes_iter(K, True) sage: [next(it) for _ in range(6)] [Fractional ideal (-a), Fractional ideal (-2*a + 3), Fractional ideal (2*a + 3), Fractional ideal (a + 6), Fractional ideal (a - 6), Fractional ideal (-3*a + 4)] """ # imaginary quadratic fields have no principal primes of norm < disc / 4 start = K.discriminant().abs() // 4 if principal_only and K.signature( ) == (0, 1) else 2 from sage.arith.misc import primes from sage.rings.infinity import infinity for p in primes(start=start, stop=infinity): for P in K.primes_above(p, degree=1): if not principal_only or P.is_principal(): yield P
def Step4Test(E, B, oldB=0, verbose=False): r""" Apply local Q-curve test to E at all primes up to B. INPUT: - `E` (elliptic curve): an elliptic curve defined over a number field - `B` (integer): upper bound on primes to test - `oldB` (integer, default 0): lower bound on primes to test - `verbose` (boolean, default ``False``): verbosity flag OUTPUT: Either (``False``, `p`), if the local test at `p` proves that `E` is not a `\QQ`-curve, or (``True``, `0`) if all local tests at primes between ``oldB`` and ``B`` fail to prove that `E` is not a `\QQ`-curve. ALGORITHM (see [CrNa2020]_ for details): This local test at `p` only applies if `E` has good reduction at all of the primes lying above `p` in the base field `K` of `E`. It tests whether (1) `E` is either ordinary at all `P\mid p`, or supersingular at all; (2) if ordinary at all, it tests that the squarefree part of `a_P^2-4N(P)` is the same for all `P\mid p`. EXAMPLES: A non-`\QQ`-curve over a quartic field (with LMFDB label '4.4.8112.1-12.1-a1') fails this test at `p=13`:: sage: from sage.schemes.elliptic_curves.Qcurves import Step4Test sage: R.<x> = PolynomialRing(QQ) sage: K.<a> = NumberField(R([3, 0, -5, 0, 1])) sage: E = EllipticCurve([K([-3,-4,1,1]),K([4,-1,-1,0]),K([-2,0,1,0]),K([-621,778,138,-178]),K([9509,2046,-24728,10380])]) sage: Step4Test(E, 100, verbose=True) No: inconsistency at the 2 ordinary primes dividing 13 - Frobenius discriminants mod squares: [-3, -1] (False, 13) A `\QQ`-curve over a sextic field (with LMFDB label '6.6.1259712.1-64.1-a6') passes this test for all `p<100`:: sage: from sage.schemes.elliptic_curves.Qcurves import Step4Test sage: R.<x> = PolynomialRing(QQ) sage: K.<a> = NumberField(R([-3, 0, 9, 0, -6, 0, 1])) sage: E = EllipticCurve([K([1,-3,0,1,0,0]),K([5,-3,-6,1,1,0]),K([1,-3,0,1,0,0]),K([-139,-129,331,277,-76,-63]),K([2466,1898,-5916,-4582,1361,1055])]) sage: Step4Test(E, 100, verbose=True) (True, 0) """ from sage.arith.misc import primes K = E.base_field() NN = E.conductor().norm() for p in primes(B): if p <= oldB or p.divides(NN): continue Plist = K.primes_above(p) if len(Plist) < 2: continue EmodP = [E.reduction(P) for P in Plist] # (a) Check all are ordinary or all supersingular: ordinary = [Ei.is_ordinary() for Ei in EmodP] consistent = all(ordinary) or not any(ordinary) if not consistent: if verbose: print("No: inconsistency at the {} primes dividing {} ".format( len(Plist), p)) print(" - ordinary: {}".format(ordinary)) return False, p # (b) Skip if all are supersingular: if not ordinary[0]: continue # else compare a_P^2-4*N(P) which should have the same squarefree part: discs = [(Ei.trace_of_frobenius()**2 - 4 * P.norm()).squarefree_part() for P, Ei in zip(Plist, EmodP)] if any(d != discs[0] for d in discs[1:]): if verbose: print( "No: inconsistency at the {} ordinary primes dividing {} ". format(len(Plist), p)) print(" - Frobenius discriminants mod squares: {}".format( discs)) return False, p # Now we have failed to prove that E is not a Q-curve return True, 0
def field_of_constant_degree_of_polynomial(G, return_field=False): r""" Return the degree of the field of constants of a polynomial. INPUT: - ``G`` -- an irreducible monic polynomial over a rational function field - ``return_field`` -- a boolean (default:`False`) OUTPUT: the degree of the field of constants of the function field defined by ``G``. If ``return_field`` is ``True`` then the actual field of constants is returned. This is currently implemented for finite fields only. This is a helper function for ``SmoothProjectiveCurve.field_of_constants_degree``. """ from sage.rings.function_field.function_field import RationalFunctionField from sage.rings.function_field.constructor import FunctionField from sage.rings.number_field.number_field import NumberFields from sage.arith.misc import primes from mclf.semistable_reduction.reduction_trees import make_function_field F = G.base_ring() assert isinstance(F, RationalFunctionField) K = F.constant_base_field() R = F._ring # the polynomial ring underlying F n = G.degree() if K.is_finite(): d = 1 # will be the degree of the field of constants at the end for p in primes(2,n+1): while p.divides(n): try: K1 = K.extension(p) except: # if K is not a true finite field the above fails # we use a helper function which construct an extension # of the desired degree K1 = extension_of_finite_field(K, p) F1 = FunctionField(K1, F.variable_name()) G1 = G.change_ring(F1) G2 = G1.factor()[0][0] # the first irreducible factor of G1 if G2.degree() < n: # G becomes reducible over K1 d = d*p # we replace G by G2 and adapt K = K1 # the values of n, d, K, G G = G2 n = G.degree() else: # G is irreducible over K1 break # we try the next prime if return_field: return K else: return d elif K in NumberFields(): from sage.rings.integer_ring import ZZ from sage.rings.all import GaussValuation if return_field: raise NotImplementedError('Computation of field of constants for number fields is not yet implemented.') d = n count = 0 for p in K.primes_of_bounded_norm_iter(ZZ(1000)): vp = K.valuation(p) v0 = F.valuation(GaussValuation(R, vp)) v = GaussValuation(G.parent(), v0) if v(G) == 0: Gb = v.reduce(G) Fb, _, _ = make_function_field(Gb.base_ring()) Gb = Gb.change_ring(Fb) if Gb.is_irreducible(): dp = field_of_constant_degree_of_polynomial(Gb) d = d.gcd(dp) count += 1 if d == 1 or count > 10: break return d else: raise NotImplementedError('Constant base field has to be finite or a number field.')