示例#1
0
def is_torsion_same(p, K, chi, B=30, uniform=False):
    """Returns true if the minus part of J0(p) does not gain new torsion when
    base changing to K"""
    M = ModularSymbols(p)
    S = M.cuspidal_subspace()
    T = S.atkin_lehner_operator()
    S_min = (T + parent(T)(1)).kernel()
    J0_min = S_min.abelian_variety()

    d = K.degree()

    if uniform:
        frob_poly_data = [(q, d) for q in prime_range(d + 2, B) if q != p]
    else:
        frob_poly_data = [(q, 1) if chi(q) == 1 else (q, d)
                          for q in prime_range(d + 2, B) if gcd(q, p) == 1]

    point_counts = []

    for q, i in frob_poly_data:
        frob_pol_q = J0_min.frobenius_polynomial(q)
        frob_mat = companion_matrix(frob_pol_q)
        point_counts.append((frob_mat**i).charpoly()(1))

    # Recall that the rational torsion on J0(p) is entirely contained in
    # the minus part (theorem of Mazur), so checking no-growth of torsion
    # in minus part is done simply as follows

    return J0(p).rational_torsion_order(proof=False) == gcd(point_counts)
示例#2
0
文件: compute.py 项目: fredstro/mfdb
    def find_known(self):
        """
        Return iterator of 5-tuples of Python ints, defined as follows:

            (N, k, i, newforms, maxp)
            (37, 2, 0, 2, 10000)

        Here N = level, k = weight, i = character, newforms = number of newforms,
        maxp = integer such that a_p is known for p<=maxp.

        If no newforms are known but there are newforms (they just
        haven't been computed), then newforms is set to -1.
        """
        for Nki in os.listdir(self._data):
            z = Nki.split('-')
            if len(z) == 3:
                N, k, i = parse_Nki(z)
                newforms = [x for x in os.listdir(os.path.join(self._data, Nki)) if x.isdigit()]
                if len(newforms) == 0:
                    # maybe nothing computed?
                    if i == 0:
                        # program around a bug in dimension_new_cusp_forms: Trac 12640
                        d = dimension_new_cusp_forms(N)
                    else:
                        chi = character(N, i)
                        d = dimension_new_cusp_forms(chi, k)
                    if d == 0:
                        # definitely no newforms
                        yield (N,k,i,0,0)
                    else:
                        # we just don't know the newforms yet
                        yield (N,k,i,-1,0)
                else:
                    maxp = None
                    for n in newforms:
                        v = set([])
                        this_maxp = 0
                        for X in os.listdir(os.path.join(self._data, Nki, n)):
                            if X.startswith('aplist') and 'meta' not in X:
                                args = [int(a) for a in X.rstrip('.sobj').split('-')[1:]]
                                v.update(prime_range(*args))
                                this_maxp = max(this_maxp, max(args))
                        if len(v) != len(prime_range(this_maxp)):
                            # something missing!
                            print "data ranges are missing in the aplist data for %s"%Nki
                            maxp = 100
                        else:
                            maxp = this_maxp if maxp is None else min(this_maxp, maxp)

                    yield (N,k,i,len(newforms),maxp)
示例#3
0
def frobs(nf):
    frob_at_p = residue_field_degrees_function(nf.gpK())
    D = nf.disc()
    ans = []
    seeram = False
    for p in prime_range(2, 60):
        if not ZZ(p).divides(D):
            # [3] ,   [2,1]
            dec = frob_at_p(p)
            vals = list(set(dec))
            vals = sorted(vals, reverse=True)
            dec = [[x, dec.count(x)] for x in vals]
            #dec2 = ["$" + str(x[0]) + ('^{' + str(x[1]) + '}$' if x[1] > 1 else '$') for x in dec]
            s = '$'
            firstone = True
            for j in dec:
                if not firstone:
                    s += r'{,}\,'
                if j[0]<15:
                    s += r'{\href{%s}{%d} }'%(url_for('local_fields.by_label',
                        label="%d.%d.0.1"%(p,j[0])), j[0])
                else:
                    s += str(j[0])
                if j[1] > 1:
                    s += '^{' + str(j[1]) + '}'
                firstone = False
            s += '$'
            ans.append([p, s])
        else:
            ans.append([p, 'R'])
            seeram = True
    return ans, seeram
示例#4
0
def see_frobs(frob_data):
    ans = []
    seeram = False
    plist = [p for p in prime_range(2, 60)]
    for i in range(len(plist)):
        p = plist[i]
        dec = frob_data[i][1]
        if dec[0] == 0:
            ans.append([p, 'R'])
            seeram = True
        else:
            s = '$'
            firstone = True
            for j in dec:
                if not firstone:
                    s += r'{,}\,'
                if j[0]<15:
                    s += r'{\href{%s}{%d} }'%(url_for('local_fields.by_label',
                        label="%d.%d.0.1"%(p,j[0])), j[0])
                else:
                    s += str(j[0])
                if j[1] > 1:
                    s += '^{' + str(j[1]) + '}'
                firstone = False
            s += '$'
            ans.append([p, s])
    return ans, seeram
示例#5
0
def get_type_2_primes(K, aux_prime_count=5, bound=None):
    """Compute a list containing the type 2 primes"""

    # First compute the superset of type 2 primes which are not of Momose Type 2

    output = get_type_2_not_momose(K, aux_prime_count)

    # Now deal with Momose Type 2

    # First get the bound
    if bound is None:
        bound = get_type_2_bound(K)
        print("type_2_bound = {}".format(bound))

    # We need to include all primes up to 25
    # see Larson/Vaintrob's proof of Theorem 6.4
    output = output.union(set(prime_range(25)))

    for p in pari.primes(25, bound):
        p_int = Integer(p)
        if p_int % 4 == 3:  # Momose Type 2 primes are necessarily congruent to 3 mod 4
            if satisfies_condition_CC(K, p_int):
                output.add(p_int)

    # Sort and return
    output = list(output)
    output.sort()
    return output
示例#6
0
def anlist_over_nf(E, bound):
    """
    Caution: This method is slow, especially for curves of high
    conductor, or defined over number fields of high degree. 
    The method is to take the Euler product form, and retrieve 
    the coefficients by expanding each product factor as a power 
    series. The bottleneck is counting points over good reductions.

    TODO: Cache this method: it is computed when initializing the 
    class dokchitser, if cached would have .num_coeffs() of a_i stored.

    EXAMPLE::

        sage: K.<i> = NumberField(x^2+1) 
        sage: E = EllipticCurve(K,[0,-1,1,0,0])
        sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_nf
        sage: anlist_over_nf(E, 20)
        [0, 1, -2, 0, 2, 2, 0, 0, 0, -5, -4, 0, 0, 8, 0, 0, -4, -4, 10, 0, 4]
    """
    conductor = E.conductor()
    coefficients = [0, 1] + [0] * (bound - 1)
    for p in prime_range(bound + 1):
        accuracy_p = int(math.floor(old_div(math.log(bound), math.log(p)))) + 1
        series_p = get_coeffs_p_over_nf(E, p, accuracy_p, conductor)
        for i in range(1, accuracy_p):
            coefficients[p**i] = series_p[i]
    extend_multiplicatively_generic(coefficients)
    return coefficients
示例#7
0
    def __init__(self,
                 signature=0,
                 weight=2,
                 level_limit=34,
                 rank_limit=4,
                 primes=None,
                 simple_color=None,
                 nonsimple_color=None,
                 reduction=True,
                 bound=0):
        """
            Initialize a SimpleModulesGraph containing finite quadratic modules of signature ``signature``.
            They are checked for being ``weight``-simple if their minimal number of generators
            is at most `rank_limit`.

            INPUT:
            - ``signature``: the signature of the modules
            - ``weight``: check for cusp forms of weight ``weight``
            - ``level_limit``: only check for anisotropic modules with level smaller than ``level_limit``
            - ``rank_limit``: an upper bound for the minimal number of generators
            - ``bound``: upper bound for the dimension (for considered being simple), default=0

            OUTPUT:
            A SimpleModulesGraph object. No computations are done after initialization.
            Start the computation using the method ``compute()``.
        """
        ###########################
        # basic parameters
        ###########################
        self._level_limit = Integer(level_limit)
        self._rank_limit = Integer(rank_limit)
        self._signature = Integer(signature) % 8
        self._weight = QQ(weight)
        self._reduction = reduction
        self._bound = bound
        #########################################################
        # Initialize the primes that need to be checked
        # According to Theorem 4.21 in [BEF],
        # in the worst case, we need to check primes p for which
        # prime_pol_simple(p, weight) <= bound.
        #########################################################
        if primes is None:
            p = 2
            while True:
                if prime_pol_simple(p, weight) > self._bound:
                    primes = list(prime_range(p))
                    break
                else:
                    p = next_prime(p)
        self._primes = primes
        self._simple_color = colors.darkred.rgb(
        ) if simple_color is None else simple_color
        self._nonsimple_color = colors.darkgreen.rgb(
        ) if nonsimple_color is None else nonsimple_color
        self._vertex_colors = dict()
        self._vertex_colors[self._simple_color] = list()
        self._vertex_colors[self._nonsimple_color] = list()
        self._heights = dict()  # a height function for plotting
        self._simple = list()  # will contain the list of k-simple modules
        super(SimpleModulesGraph, self).__init__()
示例#8
0
 def check_prime_count(self):
     """
     check that every prime p < 100 occurs exactly once for each hecke_orbit_code
     """
     # TIME about 30s
     cnt = db.mf_newforms.count({'field_poly':{'$exists':True}})
     return accumulate_failures(self.check_count(cnt, {'p': p}) for p in prime_range(100))
示例#9
0
def load_result_list(first_prime,last_prime,result_dir="kamienny_run"):
    l=[]
    for i in prime_range(first_prime,last_prime):
        l.append(get_results_from_dir(i,0,result_dir=result_dir))
        l.append(get_results_from_dir(i,1,result_dir=result_dir))
    l=sum(l,[])
    return l
def type_2_primes(K, embeddings, bound=None):
    """Compute a list containing the type 2 primes"""

    logger.debug("Starting Type 2 computation ...")

    # First compute the superset of type 2 primes which are not of Momose Type 2

    output = get_type_2_not_momose(K, embeddings)
    logger.debug("Type 2 not Momose = {}".format(sorted(output)))
    # Now deal with Momose Type 2

    # First get the bound
    if bound is None:
        bound = get_type_2_bound(K)
        logger.info("type_2_bound = {}".format(bound))

    # We need to include all primes up to 25
    # see Larson/Vaintrob's proof of Theorem 6.4
    output = output.union(set(prime_range(25)))

    for p in pari.primes(25, bound):
        p_int = Integer(p)
        if p_int % 4 == 3:  # Type 2 primes necessarily congruent to 3 mod 4
            if satisfies_condition_CC(K, p_int):
                output.add(p_int)

    output = list(output)
    output.sort()
    return output
示例#11
0
def load_result_list(first_prime,last_prime,result_dir="kamienny_run"):
    l=[]
    for i in prime_range(first_prime,last_prime):
        l.append(get_results_from_dir(i,0,result_dir=result_dir))
        l.append(get_results_from_dir(i,1,result_dir=result_dir))
    l=sum(l,[])
    return l
示例#12
0
def anlist_over_nf(E, bound):
    """
    Caution: This method is slow, especially for curves of high
    conductor, or defined over number fields of high degree. 
    The method is to take the Euler product form, and retrieve 
    the coefficients by expanding each product factor as a power 
    series. The bottleneck is counting points over good reductions.

    TODO: Cache this method: it is computed when initializing the 
    class dokchitser, if cached would have .num_coeffs() of a_i stored.

    EXAMPLE::

        sage: K.<i> = NumberField(x^2+1) 
        sage: E = EllipticCurve(K,[0,-1,1,0,0])
        sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_nf
        sage: anlist_over_nf(E, 20)
        [0, 1, -2, 0, 2, 2, 0, 0, 0, -5, -4, 0, 0, 8, 0, 0, -4, -4, 10, 0, 4]
    """    
    conductor = E.conductor()
    coefficients = [0,1] + [0]*(bound-1)
    for p in prime_range(bound+1):
        accuracy_p = int(math.floor(math.log(bound)/math.log(p))) + 1
        series_p = get_coeffs_p_over_nf(E, p, accuracy_p, conductor)
        for i in range(1, accuracy_p):
            coefficients[p**i] = series_p[i]
    extend_multiplicatively_generic(coefficients)
    return coefficients
示例#13
0
    def verify_criterion_range(self,degree,n_min,n_max,q_min,q_max,t1mod,v=None,use_rand_vec=True, verbose=False,stop_if_satisfied=True):
        torsion_order=self.p
        congruence_type=self.congruence_type
        algorithm=self.algorithm
        dependency_spaces=[]
        results=[]
        for t1n in range(n_min,n_max):
            if self.t1_prime(t1n, t1mod) == 0:
                results.append({"torsion_order":torsion_order,"congruence_type":congruence_type,
                            "algorithm":algorithm,"degree":degree,"n":t1n,
                            "satisfied":False,"message":"","use_rand_vec":use_rand_vec,
                            "result_type":"t1n_is_zero"})
                continue

            for t2q in prime_range(q_min,q_max):
                if t2q==torsion_order:
                    continue
                satisfied,message,dependencies=self.verify_criterion(degree,n=t1n,p=t1mod,q=t2q,use_rand_vec=use_rand_vec,verbose=verbose)
                dependency_spaces.append(dependencies)
                results.append({"torsion_order":torsion_order,"congruence_type":congruence_type,
                            "algorithm":algorithm,"degree":degree,"n":t1n,"p":t1mod,
                            "q":t2q,"satisfied":satisfied,"message":message,"use_rand_vec":use_rand_vec,
                            "result_type":"single"})
                if stop_if_satisfied and satisfied:
                    break
            if stop_if_satisfied and satisfied:
                break

        print [len(i) for i in dependency_spaces]
示例#14
0
def get_all_results_in_range(begin,end,result_dir="kamienny_run"):
    primes=prime_range(begin,end)
    l=[]
    for prime in primes:
        for congruence_type in (0,1):
            l.extend(get_results_from_dir(prime,congruence_type,result_dir=result_dir))
    return l
示例#15
0
def type_1_primes(K, C_K, norm_bound=50):
    """Compute the type 1 primes"""

    # Get bad formal immersion data

    bad_formal_immersion_list, bad_aux_prime_dict = cached_bad_formal_immersion_data(
        K.degree())

    aux_primes = prime_range(3, norm_bound + 1)

    if not aux_primes:
        # i.e. the user has inserted a silly value of norm_bound, so we add
        # one aux prime as in the generic case
        aux_primes = [3]

    bound_so_far = 0

    for q in aux_primes:
        bound_so_far = get_C_integer_type1(K, q, bad_aux_prime_dict, C_K,
                                           bound_so_far)

    bound_at_2 = get_C_integer_type1(K, 2, bad_aux_prime_dict, C_K,
                                     bound_so_far)

    output = set(bound_so_far.prime_divisors())
    logger.debug("Type 1 primes before BFI data = {}".format(sorted(output)))
    output = apply_formal_immersion_at_2(output, bound_at_2, K.degree())
    output = output.union(set(bad_formal_immersion_list))

    return sorted(output)
示例#16
0
def get_all_results_in_range(begin,end,result_dir="kamienny_run"):
    primes=prime_range(begin,end)
    l=[]
    for prime in primes:
        for congruence_type in (0,1):
            l.extend(get_results_from_dir(prime,congruence_type,result_dir=result_dir))
    return l
示例#17
0
 def check_prime_count(self):
     """
     check that every prime p < 100 occurs exactly once for each hecke_orbit_code
     """
     # TIME about 30s
     cnt = db.mf_newforms.count({'field_poly':{'$exists':True}})
     return accumulate_failures(self.check_count(cnt, {'p': p}) for p in prime_range(100))
示例#18
0
文件: ap.py 项目: merbst/psage
def populate_db(address, level_min, level_max, pmax=100,
                ncpus=sage.parallel.ncpus.ncpus()):
    """
    Compute and insert into the MongoDB database with the given
    address the Fourier coefficients a_p for p up to pmax for the optimal
    elliptic curves of the given range of levels (top level not
    included), using the given number of threads.

    Only curves with ap not yet set are affected by this function.
    """
    user, password = userpass()
    import math, random
    from sage.all import prime_range, parallel, pari

    level_min = int(level_min); level_max = int(level_max)
    P = prime_range(pmax)
    s = int(math.ceil((level_max - level_min)/float(ncpus)))
    blocks = [(level_min+i*s, min(level_max,level_min+(i+1)*s)) for i in range(ncpus)]
    
    @parallel(ncpus)
    def f(l_min, l_max):
        from pymongo import Connection
        C = Connection(address).research
        C.authenticate(user, password)
        C = C.ellcurves
        for v in C.find({'level':{'$gte':level_min, '$lt':level_max},
                         'number':1,
                         'ap':{'$exists':False}}):
            E = pari('ellinit(%s,1)'%v['weq'])
            ap = dict([(str(p),int(E.ellap(p))) for p in P])
            C.update({'_id':v['_id']}, {'$set':{'ap':ap}})

    for ans in f(blocks):
        print ans
示例#19
0
    def set_euler_factors(self):
        # Sets:
        # - euler_factors
        # - bad_lfactors
        bound = 100
        power = self.power
        if self.curve.genus() == 1:
            E = self.curve
            ZZT = PolynomialRing(ZZ, "T")
            T = ZZT.gen()
            K = E.base_field()
            if K == QQ:
                K = NumberField(T,"a") # making sure SAGE sees K as a numberfield
                E = E.change_ring(K)
            N = (E.conductor() * K.discriminant()**2).absolute_norm()
            assert N == self.conductor


            def get_eulerfactor(p):
                Lp = 1
                for f, _ in K.fractional_ideal(p).factor():
                    f = K.fractional_ideal(f)
                    if f.divides(N):
                        local_factor = (1 - E.local_data(f).bad_reduction_type() * T)
                        Lp *=  local_factor( T ** f.absolute_norm().valuation(p) )
                    else:
                        frob = ZZT(E.local_data(f).minimal_model().change_ring(f.residue_field()).frobenius_polynomial())
                        Lp *= frob.reverse()( T ** f.absolute_norm().valuation(p) )
                return list(map(int, Lp))

            if power > 1:
                euler_factors = {}
                for p, v in self.hard_factors.items():
                    euler_factors[p] = v
                for p in prime_range(bound):
                    if p in self.hard_factors:
                        continue
                    _, ma, p = euler_factors(p)
                    euler_factors[p] = sym_pol_ECQ(-ma, p, power)
            else:
                euler_factors = {p: get_eulerfactor(p) for p in prime_range(bound)}

        else:
            raise NotImplementedError("only implemented for genus 1 at the moment")

        self.euler_factors = [euler_factors[p] for p in prime_range(bound)]
        self.bad_lfactors = [[p, euler_factors[p]] for p in Integer(self.conductor).prime_divisors()]
示例#20
0
def upper_bound_index_cusps_in_JG_torsion(G, d, bound=60):
    """
    INPUT:
        
    - G - a congruence subgroup
    - d - integer, the size of the rational cuspidal subgroup
    - bound (optional, default = 60) - the bound for the primes p up to which to use
      the hecke matrix `T_p - <p> - p` for bounding the torsion subgroup
    
    OUTPUT:
        
    - an integer `i` such that `(\#J_G(\QQ)_{tors})/d` is a divisor of `i`.
    
    EXAMPLES::

        sage: from mdsage import *
        sage: d = rational_cuspidal_classgroup(Gamma1(23)).cardinality()
        sage: upper_bound_index_cusps_in_JG_torsion(Gamma1(23),d)
        1

    """
    N = G.level()
    M = ModularSymbols(G)
    Sint = cuspidal_integral_structure(M)
    kill_mat = (M.star_involution().matrix().restrict(Sint) - 1)
    kill = kill_mat.transpose().change_ring(ZZ).row_module()
    for p in prime_range(3, bound):
        if not N % p == 0:
            kill += kill_torsion_coprime_to_q(
                p, M).restrict(Sint).change_ring(ZZ).transpose().row_module()
        if kill.matrix().is_square() and kill.matrix().determinant() == d:
            #print p
            break
    kill_mat = kill.matrix().transpose()
    #print N,"index of torsion in stuff killed",kill.matrix().determinant()/d
    if kill.matrix().determinant() == d:
        return 1

    pm = integral_period_mapping(M)
    period_images1 = [
        sum([M.coordinate_vector(M([c, infinity])) for c in cusps]) * pm
        for cusps in galois_orbits(G)
    ]

    m = (Matrix(period_images1) * kill_mat).stack(kill_mat)
    diag = m.change_ring(ZZ).echelon_form().diagonal()
    #print diag,prod(diag)
    assert prod(diag) == kill.matrix().determinant() / d

    period_images2 = [
        M.coordinate_vector(M([c, infinity])) * pm for c in G.cusps()
        if c != Cusp(oo)
    ]
    m = (Matrix(period_images2) * kill_mat).stack(kill_mat)
    m, denom = m._clear_denom()
    diag = (m.change_ring(ZZ).echelon_form() / denom).diagonal()
    #print diag
    #print prod(i.numerator() for i in diag),"if this is 1 then :)"
    return prod(i.numerator() for i in diag)
示例#21
0
def criterion_iterator(torsion_order,degrees=list(range(3,8)),t1n_bound=12,t1mod=65521,t2q_bound=14):
    iterator=[]
    for deg in degrees:
        for t1n in range(2,t1n_bound):
            for q in prime_range(3,t2q_bound):
                if q!=torsion_order:
                    iterator.append((deg,t1n,t1mod,q))
    return iterator
示例#22
0
 def __init__(self, E, N, K):
     self.E = E
     self.ap = [K(ap) for ap in E.aplist(N)]
     self.N = N
     self.primes = [K(p) for p in prime_range(N)]
     self.K = K
     self.log_primes = [p.log() for p in self.primes]
     self.I = K(I)
示例#23
0
def criterion_iterator(torsion_order,degrees=range(3,8),t1n_bound=12,t1mod=65521,t2q_bound=14):
    iterator=[]
    for deg in degrees:
        for t1n in range(2,t1n_bound):
            for q in prime_range(3,t2q_bound):
                if q!=torsion_order:
                    iterator.append((deg,t1n,t1mod,q))
    return iterator
示例#24
0
文件: game2.py 项目: merbst/psage
 def __init__(self, E, N, K):
     self.E = E
     self.ap = [K(ap) for ap in E.aplist(N)]
     self.N = N
     self.primes = [K(p) for p in prime_range(N)]
     self.K = K
     self.log_primes = [p.log() for p in self.primes]
     self.I = K(I)
示例#25
0
def Yoshida_Lift(F, hhecke_evals, hlevel, hweight=[2, 2], primeprec=100):
    weight = (hweight[1] + 2) / 2
    level = F.disc()**2 * hlevel.norm()
    lam = {}
    mu = {}
    for p in prime_range(primeprec):
        v = level.valuation(p)
        if v == 0:
            if len(F.primes_above(p)) == 1:
                lam[p] = 0
                mu[p] = p**(2 * (weight - 3)) * (
                    -p**2 - p * hhecke_evals[F.prime_above(p)] - 1)
            else:
                lam[p] = p**(
                    (weight - 3)) * p * (hhecke_evals[F.primes_above(p)[0]] +
                                         hhecke_evals[F.primes_above(p)[1]])
                mu[p] = p**(2 * (weight - 3)) * (
                    p**2 + p * hhecke_evals[F.primes_above(p)[0]] *
                    hhecke_evals[F.primes_above(p)[1]] - 1)
        if v == 1:
            if hlevel.valuation(F.primes_above(p)[0]) == 1:
                po = F.primes_above(p)[0]
                pt = F.primes_above(p)[1]
            else:
                pt = F.primes_above(p)[0]
                po = F.primes_above(p)[1]
            lam[p] = p**((weight - 3)) * (p * hhecke_evals[po] +
                                          (p + 1) * hhecke_evals[pt])
            mu[p] = p**(2 *
                        (weight - 3)) * (p * hhecke_evals[F.primes_above(p)[0]]
                                         * hhecke_evals[F.primes_above(p)[1]])
        else:
            if len(F.primes_above(p)) == 2:
                lam[p] = p**(
                    (weight - 3)) * p * (hhecke_evals[F.primes_above(p)[0]] +
                                         hhecke_evals[F.primes_above(p)[1]])
                if hlevel.valuation(F.primes_above(p)[0]) * hlevel.valuation(
                        F.primes_above(p)[1]) == 0:
                    mu[p] = 0
                else:
                    mu[p] = p**(2 * (weight - 3)) * (-p**2)
            else:
                if F.ideal(p).valuation(F.prime_above(p)) == 2:
                    lam[p] = p * hhecke_evals[F.prime_above(p)]
                    if hlevel.valuation(F.prime_above(p)) == 0:
                        mu[p] = 0
                    else:
                        mu[p] = p**(2 * (weight - 3)) * (-p**2)
                else:
                    lam[p] = 0
                    mu[p] = p**(2 * (weight - 3)) * (
                        -p**2 - p * hhecke_evals[F.prime_above(p)])
    return {
        'paramodular_level': level,
        'weight': weight,
        'T(1,1,p,p)': lam,
        'T(1,p,p,p^2)': mu
    }
示例#26
0
def ssp(e, nssp=5, maxp=10000000):
    pp = []
    for p in prime_range(maxp):
        if e.is_supersingular(p):
            pp.append(p)
        if len(pp) == nssp:
            return pp
    print("{} has only {} supersingular primes up to {}".format(
        Elabel(e), len(pp), maxp))
    return pp
示例#27
0
文件: main.py 项目: molguin-qc/lmfdb
def render_modlmf_webpage(**args):
    C = getDBConnection()
    data = None
    if 'label' in args:
        lab = args.get('label')
        data = C.mod_l_eigenvalues.modlmf.find_one({'label': lab })
    if data is None:
        t = "mod &#x2113; modular form search error"
        bread = [('mod &#x2113; Modular Forms', url_for(".modlmf_render_webpage"))]
        flash(Markup("Error: <span style='color:black'>%s</span> is not a valid label for a mod &#x2113; modular form in the database." % (lab)),"error")
        return render_template("modlmf-error.html", title=t, properties=[], bread=bread, learnmore=learnmore_list())
    info = {}
    info.update(data)

    info['friends'] = []

    bread=[('Modular Forms', "/ModularForm"),('GL(2)',""),('mod &#x2113;', url_for(".modlmf_render_webpage")), ('%s' % data['label'], ' ')]
    credit = modlmf_credit
    f = C.mod_l_eigenvalues.modlmf.find_one({'characteristic':data['characteristic'], 'deg' : data['deg'], 'level' : data['level'],'conductor' : data['conductor'],'min_weight': data['min_weight'], 'dirchar' : data['dirchar'], 'atkinlehner': data['atkinlehner'],'n_coeffs': data['n_coeffs'],'coeffs': data['coeffs']})
    for m in ['characteristic','deg','level','conductor','min_weight', 'n_coeffs']:
        info[m]=int(f[m])
    for m in ['coeffs', 'atkinlehner']:
        info[m]=f[m]
    info['dirchar']=str(f['dirchar'])

    if f['deg'] == int(1):
        info['field']=str('&#120125;<sub>%s</sub>' %f['characteristic'])
    else:

        try:
            pol=str(conway_polynomial(f['characteristic'], f['deg']))
            info['field']=str('&#120125;<sub>%s<sup>%s</sup></sub>&#120125;<sub>%s</sub>[x]/(%s)' %(str(f['characteristic']), str(f['deg']), str(f['characteristic']), pol))
        except:
            info['field']=""

    ncoeff=int(round(50/f['deg']))
    if f['coeffs'] != "":
        coeff=[f['coeffs'][i] for i in range(ncoeff+1)]
        info['q_exp']=my_latex(print_q_expansion(coeff))
        info['q_exp_display'] = url_for(".q_exp_display", label=f['label'], number="")
        p_range=prime_range(100)
        info['table_list']=[[p_range[i], f['coeffs'][p_range[i]]] for i in range(len(p_range))]
        info['download_q_exp'] = [
            (i, url_for(".render_modlmf_webpage_download", label=info['label'], lang=i)) for i in ['gp', 'magma','sage']]

        t = "mod &#x2113; Modular Form "+info['label']
    info['properties'] = [
        ('Field characteristic', '%s' %info['characteristic']),
        ('Field degree', '%s' %info['deg']),
        ('Level', '%s' %info['level']),
        ('Conductor', '%s' %info['conductor']),
        ('Minimal weight', '%s' %info['min_weight']),
        ('Label', '%s' %info['label'])]
    return render_template("modlmf-single.html", info=info, credit=credit, title=t, bread=bread, properties2=info['properties'], learnmore=learnmore_list())
示例#28
0
 def check_angles(self, rec, verbose=False):
     """
     check that angles are null exactly for p dividing the level
     """
     # TIME about 200000s for full table?
     level = int(rec['label'].split('.')[0])
     for p, angle in zip(prime_range(1000), rec['angles']):
         if (level % p == 0) != (angle is None):
             if verbose:
                 print "Angle presence failure", p, ZZ(level).factor(), angle
             return False
     return True
示例#29
0
文件: compute.py 项目: fredstro/mfdb
def compute_aplists(N, k, i, *args):
    if i == 'all':
        G = DirichletGroup(N).galois_orbits()
        sgn = (-1)**k
        for j, g in enumerate(G):
            if g[0](-1) == sgn:
                compute_aplists(N,k,j,*args)
        return

    if i == 'quadratic':
        G = DirichletGroup(N).galois_orbits()
        sgn = (-1)**k
        for j, g in enumerate(G):
            if g[0](-1) == sgn and g[0].order()==2:
                compute_aplists(N,k,j,*args)
        return

    if len(args) == 0:
        args = (100, )

    filename = filenames.ambient(N, k, i)
    if not os.path.exists(filename):
        print "Ambient (%s,%s,%s) space not computed."%(N,k,i)
        return
        #compute_ambient_space(N, k, i)

    print "computing aplists for (%s,%s,%s)"%(N,k,i)
        
    m = filenames.number_of_known_factors(N, k, i)

    if m == 0:
        # nothing to do
        return
    
    M = load_ambient_space(N, k, i)
    for d in range(m):
        aplist_file = filenames.factor_aplist(N, k, i, d, False, *args)
        if os.path.exists(aplist_file):
            print "skipping computing aplist(%s) for (%s,%s,%s,%s) since it already exists"%(args, N,k,i,d)
            # already done
            continue
        
        # compute aplist
        print "computing aplist(%s) for (%s,%s,%s,%s)"%(args, N,k,i,d)
        t = cputime()
        A = load_factor(N, k, i, d, M)
        aplist, _ = A.compact_system_of_eigenvalues(prime_range(*args), 'a')
        print aplist, aplist_file
        save(aplist, aplist_file)
        tm = cputime(t)
        meta = {'cputime':tm, 'version':version()}
        save(meta, filenames.meta(aplist_file))
示例#30
0
def tensor_get_an_no_deg1(L1, L2, d1, d2, BadPrimeInfo):
    """
    Same as the above in the case no dimension is 1
    """
    if d1==1 or d2==1:
        raise ValueError('min(d1,d2) should not be 1, use direct method then')
    s1 = len(L1)
    s2 = len(L2)
    if s1 < s2:
        S = s1
    if s2 <= s1:
        S = s2
    BadPrimes = []
    for bpi in BadPrimeInfo:
        BadPrimes.append(bpi[0])
    P = prime_range(S+1)
    Z = S * [1]
    S = RealField()(S)
    for p in P:
        f = S.log(base=p).floor()
        q = 1
        E1 = []
        E2 = []
        if not p in BadPrimes:
            for i in range(f):
                q=q*p
                E1.append(L1[q-1])
                E2.append(L2[q-1])
            e1 = list_to_euler_factor(E1,f+1)
            e2 = list_to_euler_factor(E2,f+1)
            # ld1 = d1 # not used
            # ld2 = d2 # not used
        else: # either convolve, or have one input be the answer and other 1-t
            i = BadPrimes.index(p)
            e1 = BadPrimeInfo[i][1]
            e2 = BadPrimeInfo[i][2]
            # ld1 = e1.degree() # not used
            # ld2 = e2.degree() # not used
            F = e1.list()[0].parent().fraction_field()
            R = PowerSeriesRing(F, "T", default_prec=f+1)
            e1 = R(e1)
            e2 = R(e2)
        E = tensor_local_factors(e1,e2,f)
        A = euler_factor_to_list(E,f)
        while len(A) < f:
            A.append(0)
        q = 1
        for i in range(f):
            q = q*p
            Z[q-1]=A[i]
    all_an_from_prime_powers(Z)
    return Z
示例#31
0
def upper_bound_index_cusps_in_JG_torsion(G,d, bound = 60):
    """
    INPUT:
        
    - G - a congruence subgroup
    - d - integer, the size of the rational cuspidal subgroup
    - bound (optional, default = 60) - the bound for the primes p up to which to use
      the hecke matrix `T_p - <p> - p` for bounding the torsion subgroup
    
    OUTPUT:
        
    - an integer `i` such that `(\#J_G(\QQ)_{tors})/d` is a divisor of `i`.
    
    EXAMPLES::

        sage: from mdsage import *
        sage: d = rational_cuspidal_classgroup(Gamma1(23)).cardinality()
        sage: upper_bound_index_cusps_in_JG_torsion(Gamma1(23),d)
        1

    """
    N = G.level()
    M=ModularSymbols(G);
    Sint=cuspidal_integral_structure(M)
    kill_mat=(M.star_involution().matrix().restrict(Sint)-1)
    kill=kill_mat.transpose().change_ring(ZZ).row_module()
    for p in prime_range(3,bound):
        if not N % p ==0:
            kill+=kill_torsion_coprime_to_q(p,M).restrict(Sint).change_ring(ZZ).transpose().row_module()
        if kill.matrix().is_square() and kill.matrix().determinant()==d:
            #print p
            break
    kill_mat=kill.matrix().transpose()
    #print N,"index of torsion in stuff killed",kill.matrix().determinant()/d
    if kill.matrix().determinant()==d:
        return 1
        
    pm=integral_period_mapping(M)
    period_images1=[sum([M.coordinate_vector(M([c,infinity])) for c in cusps])*pm for cusps in galois_orbits(G)]
    
    m=(Matrix(period_images1)*kill_mat).stack(kill_mat)
    diag=m.change_ring(ZZ).echelon_form().diagonal()
    #print diag,prod(diag)
    assert prod(diag)==kill.matrix().determinant()/d
    
    period_images2=[M.coordinate_vector(M([c,infinity]))*pm for c in G.cusps() if c != Cusp(oo)]
    m=(Matrix(period_images2)*kill_mat).stack(kill_mat)
    m,denom=m._clear_denom()
    diag=(m.change_ring(ZZ).echelon_form()/denom).diagonal()
    #print diag
    #print prod(i.numerator() for i in diag),"if this is 1 then :)"
    return prod(i.numerator() for i in diag)
示例#32
0
def tensor_get_an_no_deg1(L1, L2, d1, d2, BadPrimeInfo):
    """
    Same as the above in the case no dimension is 1
    """
    if d1 == 1 or d2 == 1:
        raise ValueError('min(d1,d2) should not be 1, use direct method then')
    s1 = len(L1)
    s2 = len(L2)
    if s1 < s2:
        S = s1
    if s2 <= s1:
        S = s2
    BadPrimes = []
    for bpi in BadPrimeInfo:
        BadPrimes.append(bpi[0])
    P = prime_range(S + 1)
    Z = S * [1]
    S = RealField()(S)
    for p in P:
        f = S.log(base=p).floor()
        q = 1
        E1 = []
        E2 = []
        if not p in BadPrimes:
            for i in range(f):
                q = q * p
                E1.append(L1[q - 1])
                E2.append(L2[q - 1])
            e1 = list_to_euler_factor(E1, f + 1)
            e2 = list_to_euler_factor(E2, f + 1)
            # ld1 = d1 # not used
            # ld2 = d2 # not used
        else:  # either convolve, or have one input be the answer and other 1-t
            i = BadPrimes.index(p)
            e1 = BadPrimeInfo[i][1]
            e2 = BadPrimeInfo[i][2]
            # ld1 = e1.degree() # not used
            # ld2 = e2.degree() # not used
            F = e1.list()[0].parent().fraction_field()
            R = PowerSeriesRing(F, "T", default_prec=f + 1)
            e1 = R(e1)
            e2 = R(e2)
        E = tensor_local_factors(e1, e2, f)
        A = euler_factor_to_list(E, f)
        while len(A) < f:
            A.append(0)
        q = 1
        for i in range(f):
            q = q * p
            Z[q - 1] = A[i]
    all_an_from_prime_powers(Z)
    return Z
示例#33
0
 def check_amn_slow(self, rec, verbose=False):
     """
     Check that a_{pn} = a_p * a_n for p < 32 prime, n prime to p
     """
     Z = [0] + [CC(*elt) for elt in rec['an_normalized']]
     for pp in prime_range(len(Z)-1):
         for k in range(1, (len(Z) - 1)//pp + 1):
             if gcd(k, pp) == 1:
                 if (Z[pp*k] - Z[pp]*Z[k]).abs() > 1e-13:
                     if verbose:
                         print "amn failure", k, pp, Z[pp*k], Z[pp]*Z[k]
                     return False
     return True
示例#34
0
    def __init__(self, signature=0, weight=2, level_limit=34, rank_limit=4, primes=None, simple_color=None, nonsimple_color=None,
                 reduction=True, bound=0):
        """
            Initialize a SimpleModulesGraph containing finite quadratic modules of signature ``signature``.
            They are checked for being ``weight``-simple if their minimal number of generators
            is at most `rank_limit`.

            INPUT:
            - ``signature``: the signature of the modules
            - ``weight``: check for cusp forms of weight ``weight``
            - ``level_limit``: only check for anisotropic modules with level smaller than ``level_limit``
            - ``rank_limit``: an upper bound for the minimal number of generators
            - ``bound``: upper bound for the dimension (for considered being simple), default=0

            OUTPUT:
            A SimpleModulesGraph object. No computations are done after initialization.
            Start the computation using the method ``compute()``.
        """
        ###########################
        # basic parameters
        ###########################
        self._level_limit = Integer(level_limit)
        self._rank_limit = Integer(rank_limit)
        self._signature = Integer(signature) % 8
        self._weight = QQ(weight)
        self._reduction = reduction
        self._bound = bound
        #########################################################
        # Initialize the primes that need to be checked
        # According to Theorem 4.21 in [BEF],
        # in the worst case, we need to check primes p for which
        # prime_pol_simple(p, weight) <= bound.
        #########################################################
        if primes is None:
            p = 2
            while True:
                if prime_pol_simple(p, weight) > self._bound:
                    primes = list(prime_range(p))
                    break
                else:
                    p = next_prime(p)
        self._primes = primes
        self._simple_color = colors.darkred.rgb() if simple_color is None else simple_color
        self._nonsimple_color = colors.darkgreen.rgb() if nonsimple_color is None else nonsimple_color
        self._vertex_colors = dict()
        self._vertex_colors[self._simple_color] = list()
        self._vertex_colors[self._nonsimple_color] = list()
        self._heights = dict() # a height function for plotting
        self._simple = list() # will contain the list of k-simple modules
        super(SimpleModulesGraph, self).__init__()
示例#35
0
def JG_torsion_upperbound(G, bound=60):
    """
    INPUT:
        
    - G - a congruence subgroup
    - bound (optional, default = 60) - the bound for the primes p up to which to use
      the hecke matrix `T_p - <p> - p` for bounding the torsion subgroup
    
    OUTPUT:
        
    - A subgroup of `(S_2(G) \otimes \QQ) / S_2(G)` that is guaranteed to contain
      the rational torison subgroup, together with a subgroup generated by the
      rational cusps.
      The subgroup is given as a subgroup of `S_2(G)/NS_2(G)` for a suitable integer N

    EXAMPLES::
        
        sage: from mdsage import *
        sage: d = rational_cuspidal_classgroup(Gamma1(23)).cardinality()
        sage: upper_bound_index_cusps_in_JG_torsion(Gamma1(23),d)
        1

    """
    N = G.level()
    M = ModularSymbols(G)
    Sint = cuspidal_integral_structure(M)
    kill_mat = (M.star_involution().matrix().restrict(Sint) - 1)
    kill = kill_mat.transpose().change_ring(ZZ).row_module()
    for p in prime_range(3, bound):
        if not N % p == 0:
            kill += kill_torsion_coprime_to_q(
                p, M).restrict(Sint).change_ring(ZZ).transpose().row_module()
        #if kill.matrix().is_square() and kill.matrix().determinant()==d:
        #    #print p
        #    break
    kill_mat = kill.matrix().transpose()
    #print N,"index of torsion in stuff killed",kill.matrix().determinant()/d
    #if kill.matrix().determinant()==d:
    #    return 1
    d = prod(kill_mat.smith_form()[0].diagonal())
    pm = integral_period_mapping(M)
    #period_images1=[sum([M.coordinate_vector(M([c,infinity])) for c in cusps])*pm for cusps in galois_orbits(G)]
    period_images2 = [
        M.coordinate_vector(M([c, infinity])) * pm for c in G.cusps()
        if c != Cusp(oo)
    ]

    m = (Matrix(period_images2) * kill_mat).stack(kill_mat)
    m, d2 = m._clear_denom()
    d = gcd(d, d2)
def satisfies_condition_CC_uniform(possible_odd_f, p):
    """Determine whether degrees,p satisfies condition CC.
    Args:
        K ([NumberField]): the number field
        p ([Prime]): the prime p
    Returns: boolean
    """
    if p % 4 == 1 or p == 2:
        return False
    for q in prime_range((p / 4) ^ (1 / max(possible_odd_f)) + 1):
        if legendre_symbol(q, p) == 1:
            if all((q**(2 * f) + q**f + 1) % p != 0 for f in possible_odd_f):
                return False
    return True
示例#37
0
def check_ap2_slow(rec):
    # Check a_{p^2} = a_p^2 - chi(p) for primes up to 31
    ls = rec['lfunction_label'].split('.')
    level, weight, chi = map(int, [ls[0], ls[1], ls[-2]])
    char = DirichletGroup_conrey(level, CC)[chi]
    Z = rec['an_normalized[0:1000]']
    for p in prime_range(31+1):
        if level % p != 0:
            # a_{p^2} = a_p^2 - chi(p)
            charval = CC(2*char.logvalue(int(p)) * CC.pi()*CC.gens()[0]).exp()
        else:
            charval = 0
        if  (CC(*Z[p**2 - 1]) - (CC(*Z[p-1])**2 - charval)).abs() > 1e-11:
            return False
    return True
示例#38
0
def bad_formal_immersion_data(d):
    """
    This is the Oesterlé for type 1 primes with modular symbols main routine.
    The computation is actually a two step rocket. First Proposition 6.8 of
    Derickx-Kamienny-Stein-Stoll is used to replace Parents polynomial of
    degree 6 bound by something reasonable, and then Proposition 6.3 is used
    to go from something reasonable to the exact list.
    """
    assert d > 0

    p_bad = prime_range(11)
    p_done = {}
    q_to_bad_p = {}

    M = construct_M(d)[0]

    for p in prime_range(11, 2 * M * d):
        # first do a relatively cheap test
        if is_formal_immersion_fast(d, p):
            continue
        # this is less cheap but still quite fast
        if is_formal_immersion_medium(d, p) == 1:
            continue
        # this is the most expensive but give the correct answer
        is_formal = is_formal_immersion(d, p)
        if is_formal:
            if is_formal > 1:
                p_done[p] = is_formal
        else:
            p_bad.append(p)

    for p, q_prod in p_done.items():
        for q in prime_divisors(q_prod):
            q_to_bad_p[q] = q_to_bad_p.get(q, 1) * p

    return p_bad, q_to_bad_p
示例#39
0
def satisfies_condition_CC(K, p):
    """Determine whether K,p satisfies condition CC.

    Args:
        K ([NumberField]): the number field
        p ([Prime]): the prime p

    Returns: boolean
    """
    for q in prime_range(p / 4):
        if (q ** 2 + q + 1) % p != 0:
            if not K.ideal(q).is_prime():
                if legendre_symbol(q, p) == 1:  # i.e. not inert
                    return False
    return True
示例#40
0
def check_ap2_slow(rec):
    # Check a_{p^2} = a_p^2 - chi(p) for primes up to 31
    ls = rec['lfunction_label'].split('.')
    level, weight, chi = map(int, [ls[0], ls[1], ls[-2]])
    char = DirichletGroup_conrey(level, CC)[chi]
    Z = rec['an_normalized[0:1000]']
    for p in prime_range(31+1):
        if level % p != 0:
            # a_{p^2} = a_p^2 - chi(p)
            charval = CC(2*char.logvalue(int(p)) * CC.pi()*CC.gens()[0]).exp()
        else:
            charval = 0
        if  (CC(*Z[p**2 - 1]) - (CC(*Z[p-1])**2 - charval)).abs() > 1e-11:
            return False
    return True
示例#41
0
def JG_torsion_upperbound(G, bound = 60):
    """
    INPUT:
        
    - G - a congruence subgroup
    - bound (optional, default = 60) - the bound for the primes p up to which to use
      the hecke matrix `T_p - <p> - p` for bounding the torsion subgroup
    
    OUTPUT:
        
    - A subgroup of `(S_2(G) \otimes \QQ) / S_2(G)` that is guaranteed to contain
      the rational torison subgroup, together with a subgroup generated by the
      rational cusps.
      The subgroup is given as a subgroup of `S_2(G)/NS_2(G)` for a suitable integer N

    EXAMPLES::
        
        sage: from mdsage import *
        sage: d = rational_cuspidal_classgroup(Gamma1(23)).cardinality()
        sage: upper_bound_index_cusps_in_JG_torsion(Gamma1(23),d)
        1

    """
    N = G.level()
    M=ModularSymbols(G);
    Sint=cuspidal_integral_structure(M)
    kill_mat=(M.star_involution().matrix().restrict(Sint)-1)
    kill=kill_mat.transpose().change_ring(ZZ).row_module()
    for p in prime_range(3,bound):
        if not N % p ==0:
            kill+=kill_torsion_coprime_to_q(p,M).restrict(Sint).change_ring(ZZ).transpose().row_module()
        #if kill.matrix().is_square() and kill.matrix().determinant()==d:
        #    #print p
        #    break
    kill_mat=kill.matrix().transpose()
    #print N,"index of torsion in stuff killed",kill.matrix().determinant()/d
    #if kill.matrix().determinant()==d:
    #    return 1
    d = prod(kill_mat.smith_form()[0].diagonal())    
    pm=integral_period_mapping(M)
    #period_images1=[sum([M.coordinate_vector(M([c,infinity])) for c in cusps])*pm for cusps in galois_orbits(G)]
    period_images2=[M.coordinate_vector(M([c,infinity]))*pm for c in G.cusps() if c != Cusp(oo)]
    
    m=(Matrix(period_images2)*kill_mat).stack(kill_mat)
    m,d2=m._clear_denom()
    d=gcd(d,d2)
示例#42
0
def test_real_quadratic(minp=1, maxp=100, minwt=2, maxwt=1000):
    for p in prime_range(minp, maxp):
        if p % 4 == 1:
            print("p = ", p)
            gram = Matrix(ZZ, 2, 2, [2, 1, 1, (1 - p) / 2])
            M = VectorValuedModularForms(gram)
            if is_odd(minwt):
                minwt = minwt + 1
            for kk in range(minwt, round(maxwt / 2 - minwt)):
                k = minwt + 2 * kk
                if M.dimension_cusp_forms(k) - dimension_cusp_forms(
                        kronecker_character(p), k) / 2 != 0:
                    print("ERROR: {0},{1},{2}".format(
                        k, M.dimension_cusp_forms(k),
                        dimension_cusp_forms(kronecker_character(p), k / 2)))
                    return False
    return True
def satisfies_condition_CC(K, p):
    """Determine whether K,p satisfies condition CC.

    Args:
        K ([NumberField]): the number field
        p ([Prime]): the prime p

    Returns: boolean
    """
    for q in prime_range(p / 4):
        for frak_q in K.primes_above(q):
            f = frak_q.residue_class_degree()
            if f % 2 == 1 and q**f < p / 4:
                if (q**(2 * f) + q**f + 1) % p != 0:
                    if legendre_symbol(q, p) == 1:  # i.e. not inert
                        return False
    return True
示例#44
0
def all_an_from_prime_powers(L):
    """
    L is a list of an such that the terms
    are correct for all n which are prime powers
    and all others are equal to 1;
    this function changes the list in place to make
    the correct ans for all n
    """
    S = ZZ(len(L))
    for p in prime_range(S + 1):
        q = 1
        Sr = RealField()(len(L))
        f = Sr.log(base=p).floor()
        for k in range(f):
            q = q * p
            for m in range(2, 1 + (S // q)):
                if (m % p) != 0:
                    L[m * q - 1] = L[m * q - 1] * L[q - 1]
示例#45
0
def all_an_from_prime_powers(L):
    """
    L is a list of an such that the terms
    are correct for all n which are prime powers
    and all others are equal to 1;
    this function changes the list in place to make
    the correct ans for all n
    """
    S = ZZ(len(L))
    for p in prime_range(S+1):
        q = 1
        Sr = RealField()(len(L))
        f = Sr.log(base=p).floor()
        for k in range(f):
            q = q*p
            for m in range(2, 1+(S//q)):
                if (m%p) != 0:
                    L[m*q-1] = L[m*q-1] * L[q-1]
    def set_is_CM(self,insert_in_db=True):
        r"""
        Checks if f has complex multiplication and if it has then it returns the character.

        OUTPUT:

        -''[t,x]'' -- string saying whether f is CM or not and if it is, the corresponding character

        EXAMPLES::

        """
        if(len(self._is_CM) > 0):
            return self._is_CM
        max_nump = self._number_of_hecke_eigenvalues_to_check()
        # E,v = self._f.compact_system_of_eigenvalues(max_nump+1)
        try:
            coeffs = self.coefficients(range(max_nump + 1),insert_in_db=insert_in_db)
        except IndexError: 
           return None,None
        nz = coeffs.count(0)  # number of zero coefficients
        nnz = len(coeffs) - nz  # number of non-zero coefficients
        if(nz == 0):
            self._is_CM = [False, 0]
            return self._is_CM
        # probaly checking too many
        for D in range(3, ceil(QQ(max_nump) / QQ(2))):
            try:
                for x in DirichletGroup(D):
                    if(x.order() != 2):
                        continue
                    # we know that for CM we need x(p) = -1 => c(p)=0
                    # (for p not dividing N)
                    if(x.values().count(-1) > nz):
                        raise StopIteration()  # do not have CM with this char
                    for p in prime_range(max_nump + 1):
                        if(x(p) == -1 and coeffs[p] != 0):
                            raise StopIteration()  # do not have CM with this char
                    # if we are here we have CM with x.
                    self._is_CM = [True, x]
                    return self._is_CM
            except StopIteration:
                pass
        self._is_CM = [False, 0]
        return self._is_CM
示例#47
0
 def check_ap2_slow(self, rec, verbose=False):
     """
     Check a_{p^2} = a_p^2 - chi(p) for primes up to 31
     """
     ls = rec['label'].split('.')
     level, weight, chi = map(int, [ls[0], ls[1], ls[-2]])
     char = DirichletGroup_conrey(level, CC)[chi]
     Z = rec['an_normalized']
     for p in prime_range(31+1):
         if level % p != 0:
             # a_{p^2} = a_p^2 - chi(p)
             charval = CC(2*char.logvalue(int(p)) * CC.pi()*CC.gens()[0]).exp()
         else:
             charval = 0
         if (CC(*Z[p**2 - 1]) - (CC(*Z[p-1])**2 - charval)).abs() > 1e-13:
             if verbose:
                 print "ap2 failure", p, CC(*Z[p**2 - 1]), CC(*Z[p-1])**2 - charval
             return False
     return True
示例#48
0
 def check_inert_primes(self, rec, verbose=False):
     """
     for each discriminant D in self_twist_discs, check that for
     each prime p not dividing the level for which (D/p) = -1,
     check that traces[p] = 0 (we could also check values in
     mf_hecke_nf and/or mf_hecke_cc, but this would be far more
     costly)
     """
     # TIME about 3600s for full table
     N = rec['level']
     traces = [0] + rec['traces']  # shift so indexing correct
     primes = [p for p in prime_range(len(traces)) if N % p != 0]
     for D in rec['self_twist_discs']:
         for p in primes:
             if kronecker_symbol(D, p) == -1 and traces[p] != 0:
                 if verbose:
                     print("CM failure", D, p, traces[p])
                 return False
     return True
示例#49
0
 def check_inert_primes(self, rec, verbose=False):
     """
     for each discriminant D in self_twist_discs, check that for
     each prime p not dividing the level for which (D/p) = -1,
     check that traces[p] = 0 (we could also check values in
     mf_hecke_nf and/or mf_hecke_cc, but this would be far more
     costly)
     """
     # TIME about 3600s for full table
     N = rec['level']
     traces = [0] + rec['traces'] # shift so indexing correct
     primes = [p for p in prime_range(len(traces)) if N % p != 0]
     for D in rec['self_twist_discs']:
         for p in primes:
             if kronecker_symbol(D, p) == -1 and traces[p] != 0:
                 if verbose:
                     print "CM failure", D, p, traces[p]
                 return False
     return True
示例#50
0
def Yoshida_Lift(F, hhecke_evals, hlevel, hweight = [2,2], primeprec = 100):
	weight = (hweight[1] + 2)/2
	level = F.disc()**2*hlevel.norm()
	lam = {}
	mu = {}
	for p in prime_range(primeprec):
		v = level.valuation(p)
		if v == 0:
			if len(F.primes_above(p)) == 1:
				lam[p] = 0
				mu[p] = p**(2*(weight -3))*(-p**2 - p*hhecke_evals[F.prime_above(p)] - 1)
			else:
				lam[p] = p**((weight  - 3))*p*(hhecke_evals[F.primes_above(p)[0]] + hhecke_evals[F.primes_above(p)[1]])
				mu[p] = p**(2*(weight - 3))*(p**2 + p*hhecke_evals[F.primes_above(p)[0]]*hhecke_evals[F.primes_above(p)[1]] - 1)
		if v == 1:
			if hlevel.valuation(F.primes_above(p)[0]) == 1:
				po = F.primes_above(p)[0]
				pt = F.primes_above(p)[1]
			else:
				pt = F.primes_above(p)[0]
				po = F.primes_above(p)[1]
			lam[p] =  p**((weight  - 3))*(p*hhecke_evals[po] + (p + 1)*hhecke_evals[pt])
			mu[p] = p**(2*(weight  - 3))*(p*hhecke_evals[F.primes_above(p)[0]]*hhecke_evals[F.primes_above(p)[1]])
		else:
			if len(F.primes_above(p)) == 2:
				lam[p] = p**((weight  - 3))*p*(hhecke_evals[F.primes_above(p)[0]] + hhecke_evals[F.primes_above(p)[1]])
				if hlevel.valuation(F.primes_above(p)[0])*hlevel.valuation(F.primes_above(p)[1]) == 0:
					mu[p] = 0
				else:
					mu[p] = p**(2*(weight  - 3))*(-p**2)
			else:
				if F.ideal(p).valuation(F.prime_above(p)) == 2:
					lam[p] = p*hhecke_evals[F.prime_above(p)]
					if hlevel.valuation(F.prime_above(p)) == 0:
						mu[p] = 0
					else:
						mu[p] = p**(2*(weight  - 3))*(-p**2)
				else:
					lam[p] = 0
					mu[p] = p**(2*(weight  - 3))*(-p**2-p*hhecke_evals[F.prime_above(p)])
	return {'paramodular_level':level, 'weight':weight, 'T(1,1,p,p)':lam, 'T(1,p,p,p^2)':mu}
示例#51
0
def tensor_get_an_deg1(L, D, BadPrimeInfo):
    """
    Same as above, except that the BadPrimeInfo
    is now a list of lists of the form
    [p,f] where f is a polynomial.
    """
    s1 = len(L)
    s2 = len(D)
    if s1 < s2:
        S = s1
    if s2 <= s1:
        S = s2
    BadPrimes = []
    for bpi in BadPrimeInfo:
        BadPrimes.append(bpi[0])
    P = prime_range(S+1)
    Z = S * [1]
    S = RealField()(S) # fix bug
    for p in P:
        f = S.log(base=p).floor()
        q = 1
        u = 1
        e = D[p-1]
        if not p in BadPrimes:
            for i in range(f):
                q = q*p
                u = u*e
                Z[q-1] = u*L[q-1]
        else:
            i = BadPrimes.index(p)
            e = BadPrimeInfo[i][1]
            F = e.list()[0].parent().fraction_field()
            R = PowerSeriesRing(F, "T", default_prec=f+1)
            e = R(e)
            A = euler_factor_to_list(e,f)
            for i in range(f):
                q = q*p
                Z[q-1] = A[i]
    all_an_from_prime_powers(Z)
    return Z
示例#52
0
文件: utilities.py 项目: LMFDB/lmfdb
def an_list(euler_factor_polynomial_fn,
            upperbound=100000, base_field=QQ):
    """
    Takes a fn that gives for each prime the Euler polynomial of the associated
    with the prime, given as a list, with independent coefficient first. This
    list is of length the degree+1.
    Output the first `upperbound` coefficients built from the Euler polys.

    Example:
    The `euler_factor_polynomial_fn` should in practice come from an L-function
    or data. For a simple example, we construct just the 2 and 3 factors of the
    Riemann zeta function, which have Euler factors (1 - 1*2^(-s))^(-1) and
    (1 - 1*3^(-s))^(-1).
    >>> euler = lambda p: [1, -1] if p <= 3 else [1, 0]
    >>> an_list(euler)[:20]
    [1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0]
    """
    from math import ceil, log
    PP = PowerSeriesRing(base_field, 'x', 1 + ceil(log(upperbound) / log(2.)))

    prime_l = prime_range(upperbound + 1)
    result = [1 for i in range(upperbound)]
    for p in prime_l:
        euler_factor = (1 / (PP(euler_factor_polynomial_fn(p)))).padded_list()
        if len(euler_factor) == 1:
            for j in range(1, 1 + upperbound // p):
                result[j * p - 1] = 0
            continue

        k = 1
        while True:
            if p ** k > upperbound:
                break
            for j in range(1, 1 + upperbound // (p ** k)):
                if j % p == 0:
                    continue
                result[j * p ** k - 1] *= euler_factor[k]
            k += 1
    return result
示例#53
0
 def check_hecke_ring_character_values_and_an(self, rec, verbose=False):
     """
     check that hecke_ring_character_values has the correct format, depending on whether hecke_ring_cyclotomic_generator is set or not
     check that an has length 100 and that each entry is either a list of integers of length hecke_ring_rank (if hecke_ring_cyclotomic_generator=0) or a list of pairs
     check that ap has length pi(maxp) and that each entry is formatted correctly (as for an)
     """
     # TIME about 4000s for full table
     an = rec['an']
     if len(an) != 100:
         if verbose:
             print "Length an", len(an)
         return False
     ap = rec['ap']
     maxp = rec['maxp']
     if len(ap) != prime_pi(maxp):
         if verbose:
             print "Length ap", len(ap), prime_pi(maxp)
         return False
     if maxp < 997:
         if verbose:
             print "Maxp", maxp
         return False
     m = rec['hecke_ring_cyclotomic_generator']
     d = rec['hecke_ring_rank']
     def check_val(val):
         if not isinstance(val, list):
             return False
         if m == 0:
             return len(val) == d and all(isinstance(c, integer_types) for c in val)
         else:
             for pair in val:
                 if len(pair) != 2:
                     return False
                 if not isinstance(pair[0], integer_types):
                     return False
                 e = pair[1]
                 if not (isinstance(e, integer_types) and 0 <= 2*e < m):
                     return False
             return True
     if not all(check_val(a) for a in an):
         if verbose:
             for n, a in enumerate(an, 1):
                 if not check_val(a):
                     print "Check an failure (m=%s, d=%s)"%(m, d), n, a
         return False
     if not all(check_val(a) for a in ap):
         if verbose:
             for p, a in zip(prime_range(maxp), ap):
                 if not check_val(a):
                     print "Check ap failure (m=%s, d=%s)"%(m, d), p, a
         return False
     for p, a in zip(prime_range(100), ap):
         if a != an[p-1]:
             if verbose:
                 print "Match failure", p, a, an[p-1]
             return False
     if rec['char_orbit_index'] != 1:
         if rec.get('hecke_ring_character_values') is None:
             if verbose:
                 print "No hecke_ring_character_values"
             return False
         N = rec['level']
         total_order = 1
         for g, val in rec['hecke_ring_character_values']:
             total_order *= mod(g, N).multiplicative_order()
             if not check_val(val):
                 if verbose:
                     print "Bad character val (m=%s, d=%s)"%(m, d), g, val
                 return False
         success = (total_order == euler_phi(N))
         if not success and verbose:
             print "Generators failed", total_order, euler_phi(N)
         return success
     return True
示例#54
0
    def multiple_of_order_using_frobp(self, maxp=None):
        """
        Return a multiple of the order of this torsion group.

        In the `Gamma_0` case, the multiple is computed using characteristic
        polynomials of Hecke operators of odd index not dividing the level. In
        the `Gamma_1` case, the multiple is computed by expressing the
        frobenius polynomial in terms of the characteristic polynomial of left
        multiplication by `a_p` for odd primes p not dividing the level.

        INPUT:


        -  ``maxp`` - (default: None) If maxp is None (the
           default), return gcd of best bound computed so far with bound
           obtained by computing GCD's of orders modulo p until this gcd
           stabilizes for 3 successive primes. If maxp is given, just use all
           primes up to and including maxp.


        EXAMPLES::

            sage: J = J0(11)
            sage: G = J.rational_torsion_subgroup()
            sage: G.multiple_of_order_using_frobp(11)
            5

        Increasing maxp may yield a tighter bound. If maxp=None, then Sage
        will use more primes until the multiple stabilizes for 3 successive
        primes.  ::

            sage: J = J0(389)
            sage: G = J.rational_torsion_subgroup(); G
            Torsion subgroup of Abelian variety J0(389) of dimension 32
            sage: G.multiple_of_order_using_frobp()
            97
            sage: [G.multiple_of_order_using_frobp(p) for p in prime_range(3,11)]
            [92645296242160800, 7275, 291]
            sage: [G.multiple_of_order_using_frobp(p) for p in prime_range(3,13)]
            [92645296242160800, 7275, 291, 97]
            sage: [G.multiple_of_order_using_frobp(p) for p in prime_range(3,19)]
            [92645296242160800, 7275, 291, 97, 97, 97]

        We can compute the multiple of order of the torsion subgroup for Gamma0
        and Gamma1 varieties, and their products. ::

            sage: A = J0(11) * J0(33)
            sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp()
            1000

            sage: A = J1(23)
            sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp()
            9406793
            sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp(maxp=50)
            408991

            sage: A = J1(19) * J0(21)
            sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp()
            35064

        The next example illustrates calling this function with a larger
        input and how the result may be cached when maxp is None::

            sage: T = J0(43)[1].rational_torsion_subgroup()
            sage: T.multiple_of_order_using_frobp()
            14
            sage: T.multiple_of_order_using_frobp(50)
            7
            sage: T.multiple_of_order_using_frobp()
            7

        This function is not implemented for general congruence subgroups
        unless the dimension is zero. ::

            sage: A = JH(13,[2]); A
            Abelian variety J0(13) of dimension 0
            sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp()
            1

            sage: A = JH(15, [2]); A
            Abelian variety JH(15,[2]) of dimension 1
            sage: A.rational_torsion_subgroup().multiple_of_order_using_frobp()
            Traceback (most recent call last):
            ...
            NotImplementedError: torsion multiple only implemented for Gamma0 and Gamma1
        """
        if maxp is None:
            try:
                return self.__multiple_of_order_using_frobp
            except AttributeError:
                pass
        A = self.abelian_variety()
        if A.dimension() == 0:
            T = ZZ(1)
            self.__multiple_of_order_using_frobp = T
            return T
        if not all((is_Gamma0(G) or is_Gamma1(G) for G in A.groups())):
            raise NotImplementedError("torsion multiple only implemented for Gamma0 and Gamma1")

        bnd = ZZ(0)
        N = A.level()
        cnt = 0
        if maxp is None:
            X = Primes()
        else:
            X = prime_range(maxp+1)
        for p in X:
            if (2*N) % p == 0:
                continue

            if (len(A.groups()) == 1 and is_Gamma0(A.groups()[0])):
                f = A.hecke_polynomial(p)
                b = ZZ(f(p+1))
            else:
                from .constructor import AbelianVariety
                D = [AbelianVariety(f) for f in
                     A.newform_decomposition('a')]
                b = 1
                for simple in D:
                    G = simple.newform_level()[1]
                    if is_Gamma0(G):
                        f = simple.hecke_polynomial(p)
                        b *= ZZ(f(p+1))
                    else:
                        f = simple.newform('a')
                        Kf = f.base_ring()
                        eps = f.character()
                        Qe = eps.base_ring()

                        if Kf != QQ:
                            # relativize number fields to compute charpoly of
                            # left multiplication of ap on Kf as a Qe-vector
                            # space.
                            Lf = Kf.relativize(Qe.gen(), 'a')
                            to_Lf = Lf.structure()[1]

                            name = Kf._names[0]
                            ap = to_Lf(f.modular_symbols(1).eigenvalue(p, name))

                            G_ps = ap.matrix().charpoly()
                            b *= ZZ(Qe(G_ps(1 + to_Lf(eps(p))*p)).norm())
                        else:
                            ap = f.modular_symbols(1).eigenvalue(p)
                            b *= ZZ(1 + eps(p)*p - ap)

            if bnd == 0:
                bnd = b
            else:
                bnd_last = bnd
                bnd = ZZ(gcd(bnd, b))
                if bnd == bnd_last:
                    cnt += 1
                else:
                    cnt = 0
                if maxp is None and cnt >= 2:
                    break

        # The code below caches the computed bound and
        # will be used if this function is called
        # again with maxp equal to None (the default).
        if maxp is None:
            # maxp is None but self.__multiple_of_order_using_frobp  is
            # not set, since otherwise we would have immediately
            # returned at the top of this function
            self.__multiple_of_order_using_frobp = bnd
        else:
            # maxp is given -- record new info we get as
            # a gcd...
            try:
                self.__multiple_of_order_using_frobp = \
                        gcd(self.__multiple_of_order_using_frobp, bnd)
            except AttributeError:
                # ... except in the case when
                # self.__multiple_of_order_using_frobp was never set.  In this
                # case, we just set it as long as the gcd stabilized for 3 in a
                # row.
                if cnt >= 2:
                    self.__multiple_of_order_using_frobp = bnd
        return bnd
示例#55
0
def elliptic_cm_form(E, n, prec, aplist_only=False, anlist_only=False):
    """
    Return q-expansion of the CM modular form associated to the n-th
    power of the Grossencharacter associated to the elliptic curve E.

    INPUT:
        - E -- CM elliptic curve
        - n -- positive integer
        - prec -- positive integer
        - aplist_only -- return list only of ap for p prime
        - anlist_only -- return list only of an

    OUTPUT:
        - power series with integer coefficients

    EXAMPLES::

        sage: from psage.modform.rational.special import elliptic_cm_form
        sage: f = CuspForms(121,4).newforms(names='a')[0]; f
        q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^6)
        sage: E = EllipticCurve('121b')
        sage: elliptic_cm_form(E, 3, 7)
        q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^7)
        sage: g = elliptic_cm_form(E, 3, 100)
        sage: g == f.q_expansion(100)
        True
    """
    if not E.has_cm():
        raise ValueError, "E must have CM"
    n = ZZ(n)
    if n <= 0:
        raise ValueError, "n must be positive"

    prec = ZZ(prec)
    if prec <= 0:
        return []
    elif prec <= 1:
        return [ZZ(0)]
    elif prec <= 2:
        return [ZZ(0), ZZ(1)]
    
    # Derive formula for sum of n-th powers of roots
    a,p,T = SR.var('a,p,T')
    roots = (T**2 - a*T + p).roots(multiplicities=False)
    s = sum(alpha**n for alpha in roots).simplify_full()
    
    # Create fast callable expression from formula
    g = fast_callable(s.polynomial(ZZ))

    # Compute aplist for the curve
    v = E.aplist(prec)

    # Use aplist to compute ap values for the CM form attached to n-th
    # power of Grossencharacter.
    P = prime_range(prec)

    if aplist_only:
        # case when we only want the a_p (maybe for computing an
        # L-series via Euler product)
        return [g(ap,p) for ap,p in zip(v,P)]

    # Default cause where we want all a_n
    anlist = [ZZ(0),ZZ(1)] + [None]*(prec-2)
    for ap,p in zip(v,P):
        anlist[p] = g(ap,p)

    # Fill in the prime power a_{p^r} for r >= 2.
    N = E.conductor()
    for p in P:
        prm2 = 1
        prm1 = p
        pr = p*p
        pn = p**n
        e = 1 if N%p else 0
        while pr < prec:
            anlist[pr] = anlist[prm1] * anlist[p]
            if e:
                anlist[pr] -= pn * anlist[prm2]
            prm2 = prm1
            prm1 = pr
            pr *= p

    # fill in a_n with n divisible by at least 2 primes
    extend_multiplicatively_generic(anlist)

    if anlist_only:
        return anlist

    f = Integer_list_to_polynomial(anlist, 'q')
    return ZZ[['q']](f, prec=prec)
示例#56
0
文件: main.py 项目: AurelPage/lmfdb
def render_modlmf_webpage(**args):
    C = getDBConnection()
    data = None
    if 'label' in args:
        lab = args.get('label')
        data = C.mod_l_eigenvalues.modlmf.find_one({'label': lab })
    if data is None:
        t = "Mod &#x2113; modular form search error"
        bread = [('mod &#x2113; Modular Forms', url_for(".modlmf_render_webpage"))]
        flash(Markup("Error: <span style='color:black'>%s</span> is not a valid label for a mod &#x2113; modular form in the database." % (lab)),"error")
        return render_template("modlmf-error.html", title=t, properties=[], bread=bread, learnmore=learnmore_list())
    info = {}
    info.update(data)

    info['friends'] = []

    bread=[('Modular Forms', "/ModularForm"),('mod &#x2113;', url_for(".modlmf_render_webpage")), ('%s' % data['label'], ' ')]
    credit = modlmf_credit

    f = C.mod_l_eigenvalues.modlmf.find_one({'characteristic':data['characteristic'], 'deg' : data['deg'], 'level' : data['level'],'weight_grading': data['weight_grading'], 'reducible' : data['reducible'], 'cuspidal_lift': data['cuspidal_lift'], 'dirchar' : data['dirchar'], 'atkinlehner': data['atkinlehner'],'n_coeffs': data['n_coeffs'],'coeffs': data['coeffs'], 'ordinary': data['ordinary'],'min_theta_weight': data['min_theta_weight'], 'theta_cycle' : data['theta_cycle']})

    for m in ['characteristic','deg','level','weight_grading', 'n_coeffs', 'min_theta_weight', 'ordinary']:
        info[m]=int(f[m])
    info['atkinlehner']=f['atkinlehner']
    info['dirchar']=str(f['dirchar'])
    info['label']=str(f['label'])
    if f['reducible']:
        info['reducible']=f['reducible']
    info['cuspidal_lift']=f['cuspidal_lift']
    info['cuspidal_lift_weight']=int(f['cuspidal_lift'][0])
    info['cuspidal_lift_orbit']=str(f['cuspidal_lift'][1])

    if f['cuspidal_lift'][2]=='x':
        info['cuspidal_hecke_field']=1
    else:
        info['cuspidal_hecke_field']=latex(f['cuspidal_lift'][2])

    info['cuspidal_lift_gen']=f['cuspidal_lift'][3]

    if f['theta_cycle']:
        info['theta_cycle']=f['theta_cycle']

    info['coeffs']=[str(s).replace('x','a').replace('*','') for s in f['coeffs']]

    if f['deg'] != int(1):
        try:
            pol=str(conway_polynomial(f['characteristic'], f['deg'])).replace('x','a').replace('*','')
            info['field']= pol
        except:
            info['field']=""


    ncoeff=int(round(20/f['deg']))
    av_coeffs=min(f['n_coeffs'],100)
    info['av_coeffs']=int(av_coeffs)
    if f['coeffs'] != "":
        coeff=[info['coeffs'][i] for i in range(ncoeff+1)]
        info['q_exp']=my_latex(print_q_expansion(coeff))
        info['q_exp_display'] = url_for(".q_exp_display", label=f['label'], number="")
        p_range=prime_range(av_coeffs)
        info['table_list']=[[p_range[i], info['coeffs'][p_range[i]]] for i in range(len(p_range))]
        info['download_q_exp'] = [
            (i, url_for(".render_modlmf_webpage_download", label=info['label'], lang=i)) for i in ['gp', 'magma','sage']]

        t = "Mod "+str(info['characteristic'])+" Modular Form "+info['label']
    info['properties'] = [
        ('Label', '%s' %info['label']),
        ('Field characteristic', '%s' %info['characteristic']),
        ('Field degree', '%s' %info['deg']),
        ('Level', '%s' %info['level']),
        ('Weight grading', '%s' %info['weight_grading'])]
    return render_template("modlmf-single.html", info=info, credit=credit, title=t, bread=bread, properties2=info['properties'], learnmore=learnmore_list())
示例#57
0
    display_float, display_complex, round_CBF_to_half_int, polyquo_knowl,
    display_knowl, factor_base_factorization_latex,
    integer_options, names_and_urls)
from lmfdb.number_fields.web_number_field import nf_display_knowl
from lmfdb.number_fields.number_field import field_pretty
from lmfdb.galois_groups.transitive_group import small_group_label_display_knowl
from lmfdb.sato_tate_groups.main import st_link
from web_space import convert_spacelabel_from_conrey, get_bread, cyc_display

LABEL_RE = re.compile(r"^[0-9]+\.[0-9]+\.[a-z]+\.[a-z]+$")
EMB_LABEL_RE = re.compile(r"^[0-9]+\.[0-9]+\.[a-z]+\.[a-z]+\.[0-9]+\.[0-9]+$")
INTEGER_RANGE_RE = re.compile(r"^([0-9]+)-([0-9]+)$")


# we may store alpha_p with p <= 3000
primes_for_angles = prime_range(3000)

def valid_label(label):
    return bool(LABEL_RE.match(label))

def valid_emb_label(label):
    return bool(EMB_LABEL_RE.match(label))

def decode_hecke_orbit(code):
    level = str(code % 2**24)
    weight = str((code >> 24) % 2**12)
    char_orbit_label = cremona_letter_code((code >> 36) % 2**16)
    hecke_orbit_label = cremona_letter_code(code >> 52)
    return '.'.join([level, weight, char_orbit_label, hecke_orbit_label])

def encode_hecke_orbit(label):