예제 #1
0
    def codeinit(self):
        self.exnum = self.galorbnums[0]
        self.exchi = ConreyCharacter(self.modulus, self.exnum)

        values_gens = db.char_dir_values.lookup(
            "{}.{}".format(self.modulus, self.exnum),
            projection='values_gens'
        )

        vals = [int(v) for g, v in values_gens]
        sage_zeta_order = self.exchi.sage_zeta_order(self.order)
        self._genvalues_for_code = get_sage_genvalues(self.modulus,
                                    self.order, vals, sage_zeta_order)

        return {
            'sage': [
                'from sage.modular.dirichlet import DirichletCharacter',
                'H = DirichletGroup({}, base_ring=CyclotomicField({}))'.format(
                    self.modulus, sage_zeta_order),
                'M = H._module',
                'chi = DirichletCharacter(H, M([{}]))'.format(
                    ','.join(str(val) for val in self._genvalues_for_code)
                ),
                'chi.galois_orbit()'
            ],
            'pari': [
                '[g,chi] = znchar(Mod(%i,%i))' % (self.exnum, self.modulus),
                'order = charorder(g,chi)',
                '[ charpow(g,chi, k % order) | k <-[1..order-1], gcd(k,order)==1 ]'
            ]
        }
예제 #2
0
 def nextprimchar(m, n):
     if m < 3:
         return 3, 2
     while 1:
         n += 1
         if n >= m:
             m, n = m + 1, 2
         if gcd(m, n) != 1:
             continue
         # we have a character, test if it is primitive
         chi = ConreyCharacter(m,n)
         if chi.is_primitive():
             return m, n
예제 #3
0
 def prevprimchar(m, n):
     if m <= 3:
         return 1, 1
     while True:
         n -= 1
         if n <= 1:  # (m,1) is never primitive for m>1
             m, n = m - 1, m - 1
         if m <= 2:
             return 1, 1
         if gcd(m, n) != 1:
             continue
         # we have a character, test if it is primitive
         chi = ConreyCharacter(m,n)
         if chi.is_primitive():
             return m, n
예제 #4
0
 def __init__(self, **kwargs):
     self.type = "Dirichlet"
     self.isorbit = True
     self.modulus = kwargs.get('modulus', None)
     if self.modulus:
         self.modulus = int(self.modulus)
     self.modlabel = self.modulus
     self.number = kwargs.get('number', None)
     if self.number:
         self.number = int(self.number)
     self.numlabel = self.number
     if self.modulus:
         # Needed for Gauss sums, etc
         self.H = PariConreyGroup(self.modulus)
         if self.number:
             self.chi = ConreyCharacter(self.modulus, self.number)
     self.codelangs = ('pari', 'sage')
     self.orbit_label = kwargs.get('orbit_label', None)  # this is what the user inserted, so might be banana
     self.label = "{}.{}".format(self.modulus, self.orbit_label)
     self.orbit_data = self.get_orbit_data(self.orbit_label)  # this is the meat
     self.maxrows = 30
     self.rowtruncate = False
     self._set_galoisorbit(self.orbit_data)
     self.maxcols = 10
     self._contents = None
     self._set_groupelts()
예제 #5
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 = ConreyCharacter(level, 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.conreyangle(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
예제 #6
0
def get_dirchar(char_mod, char_num, char_order):
    """Helper method to compute Dirichlet Character on the fly"""
    char_values_data = db.char_dir_values.lookup("{}.{}".format(
        char_mod, char_num))
    char_valuepairs = char_values_data['values_gens']
    char_genvalues = [int(v) for g, v in char_valuepairs]
    return ConreyCharacter(char_mod,
                           char_num).sage_character(char_order, char_genvalues)
예제 #7
0
 def __init__(self, **kwargs):
     self.type = "Dirichlet"
     self.modulus = kwargs.get('modulus', None)
     if self.modulus:
         self.modulus = int(self.modulus)
     self.modlabel = self.modulus
     self.number = kwargs.get('number', None)
     if self.number:
         self.number = int(self.number)
     self.numlabel = self.number
     if self.modulus:
         # Needed for Gauss sums, etc
         self.H = PariConreyGroup(self.modulus)
         if self.number:
             self.chi = ConreyCharacter(self.modulus, self.number)
     self.maxcols = 30
     self.codelangs = ('pari', 'sage')
     self._compute()
예제 #8
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 = ConreyCharacter(level, 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.conreyangle(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
예제 #9
0
    def jacobi_sum(self, val):

        mod, num = self.modulus, self.number

        try:
            val = int(val)
        except ValueError:
            raise Warning ("n must be a positive integer coprime to the modulus {} and no greater than it".format(mod))
        if gcd(mod, val) > 1:
            raise Warning ("n must be coprime to the modulus : %s"%mod)
        if val > mod:
            raise Warning ("n must be less than the modulus : %s"%mod)
        if val < 0:
            raise Warning ("n must be positive")

        chi_values_data = db.char_dir_values.lookup(
            "{}.{}".format(mod, num)
        )
        chi_valuepairs = chi_values_data['values_gens']
        chi_genvalues = [int(v) for g, v in chi_valuepairs]
        chi = self.chi.sage_character(self.order, chi_genvalues)

        psi = ConreyCharacter(self.modulus, val)
        psi_values_data = db.char_dir_values.lookup(
            "{}.{}".format(self.modulus, val)
        )
        psi_valuepairs = psi_values_data['values_gens']
        psi_genvalues = [int(v) for g, v in psi_valuepairs]
        psi = psi.sage_character(self.order, psi_genvalues)

        jacobi_sum = chi.jacobi_sum(psi)
        chitex = self.char2tex(mod, num, tag=False)
        psitex = self.char2tex(mod, val, tag=False)
        Gtex = r'\Z/%s\Z' % mod
        chitexr = self.char2tex(mod, num, 'r', tag=False)
        psitex1r = self.char2tex(mod, val, '1-r', tag=False)
        deftex = r'\sum_{r\in %s} %s %s'%(Gtex,chitexr,psitex1r)
        return r"\( \displaystyle J(%s,%s) = %s = %s \)" % (chitex, psitex, deftex, latex(jacobi_sum))
예제 #10
0
 def check_order_parity(self, rec, verbose=False):
     """
     check order and parity by constructing a Conrey character in Sage (use the first index in galois_orbit)
     """
     # TIME about 30000s for full table
     char = ConreyCharacter(rec['modulus'], rec['galois_orbit'][0])
     parity = 1 if char.is_even() else -1
     success = (parity == rec['parity']
                and char.conductor() == rec['conductor']
                and char.multiplicative_order() == rec['order'])
     if verbose and not success:
         print("Order-parity failure", parity, rec['parity'],
               char.conductor(), rec['conductor'],
               char.multiplicative_order(), rec['order'])
     return success
예제 #11
0
def get_character_modulus(a, b, limit=7):
    """ this function is also used by lfunctions/LfunctionPlot.py """
    headers = list(range(1, limit))
    headers.append("more")
    entries = {}
    rows = list(range(a, b + 1))
    for row in rows:
        if row != 1:
            G = Integers(row).list_of_elements_of_multiplicative_group()
        else:
            G = [1]
        for chi_n in G:
            chi = ConreyCharacter(row, chi_n)
            multorder = chi.multiplicative_order()
            if multorder <= limit:
                el = chi
                col = multorder
                entry = entries.get((row, col), [])
                entry.append(el)
                entries[(row, col)] = entry
    entries2 = {}
    out = lambda chi: (chi.number, chi.is_primitive(),
                       chi.multiplicative_order(), chi.is_even())
    for k, v in entries.items():
        l = []
        v = sorted(v, key=lambda x: x.number)
        while v:
            e1 = v.pop(0)
            e1_num = e1.number
            inv_num = 1 if e1_num == 1 else e1_num.inverse_mod(e1.modulus)

            inv = ConreyCharacter(e1.modulus, inv_num)

            if e1_num == inv_num:
                l.append((out(e1), ))
            else:
                l.append((out(e1), out(inv)))
                v = [
                    x for x in v
                    if (x.modulus, x.number) != (inv.modulus, inv.number)
                ]
        if k[1] == "more":
            l = sorted(l, key=lambda e: e[0][2])
        entries2[k] = l
    cols = headers
    return headers, entries2, rows, cols
예제 #12
0
class WebSmallDirichletCharacter(WebChar, WebDirichlet):
    """
    Heritage: WebChar -> __init__()
              WebDirichlet -> _compute()
    """

    def _compute(self):
        self.modulus = int(self.modlabel)
        self.number = int(self.numlabel)
        self.chi = ConreyCharacter(self.modulus, self.number)
        self.codelangs = ('pari', 'sage')

    @lazy_attribute
    def conductor(self):
        return self.chi.conductor()

    @lazy_attribute
    def indlabel(self):
        if self.chi.indlabel is not None:
            return self.chi.indlabel
        else:
            # Calling conductor computes the indlabel
            self.chi.conductor()
            return self.chi.indlabel

    @lazy_attribute
    def codeinit(self):
        return {
          'sage': [
                 'H = DirichletGroup(%i)'%(self.modulus),
                 'chi = H[%i]'%(self.number) ],
          'pari': '[g,chi] = znchar(Mod(%i,%i))'%(self.number,self.modulus),
          }

    @lazy_attribute
    def title(self):
        return r"Dirichlet character %s" % (self.texname)

    @lazy_attribute
    def texname(self):
        return self.char2tex(self.modulus, self.number)

    @lazy_attribute
    def codeisprimitive(self):
        return { 'sage': 'chi.is_primitive()',
                 'pari': '#znconreyconductor(g,chi)==1 \\\\ if not primitive returns [cond,factorization]' }

    @lazy_attribute
    def codecond(self):
        return { 'sage': 'chi.conductor()',
                 'pari': 'znconreyconductor(g,chi)' }

    @lazy_attribute
    def parity(self):
        return (parity_string(-1),parity_string(1))[self.chi.is_even()]

    @lazy_attribute
    def codeparity(self):
        return { 'sage': 'chi.is_odd()',
                 'pari': 'zncharisodd(g,chi)' }

    def symbol_numerator(self):
        """ chi is equal to a kronecker symbol if and only if it is real """
        if self.order != 2:
            return None
        return symbol_numerator(self.conductor, self.chi.is_odd())

    @lazy_attribute
    def symbol(self):
        return kronecker_symbol(self.symbol_numerator())

    @lazy_attribute
    def codesymbol(self):
        m = self.symbol_numerator()
        if m:
            return { 'sage': 'kronecker_character(%i)'%m,
                     'pari': 'znchartokronecker(g,chi)'
                     }
        return None

    @lazy_attribute
    def codegaloisorbit(self):
        return { 'sage': ['chi.galois_orbit()'],
                 'pari': [ 'order = charorder(g,chi)',
                           '[ charpow(g,chi, k % order) | k <-[1..order-1], gcd(k,order)==1 ]' ]
                 }
def set_info_for_gamma1(level,weight,weight2=None):
    dimension_table_name = WebModFormSpace._dimension_table_name
    if weight != None and weight2>weight:
        w1 = weight; w2 = weight2
    else:
        w1 = weight; w2 = weight
    table = {'galois_orbit':{},'galois_orbits_reps':{},'cells':{}}
    table['weights']=range(w1,w2+1)
    emf_logger.debug("dimension table name={0}".format(dimension_table_name))
    db_dim = getDBConnection()['modularforms2'][dimension_table_name]
    s = {'level':int(level),'weight':{"$lt":int(w2+1),"$gt":int(w1-1)},'cchi':{"$exists":True}}
    q = db_dim.find(s).sort([('cchi',int(1)),('weight',int(1))])
    if q.count() == 0:
        emf_logger.debug("No spaces in the database!")
        flash('The database does not currently contain any spaces matching these parameters. Please try again!')
        return None #'error':'The database does not currently contain any spaces matching these parameters!'}
    else:
        table['maxGalCount']=1
        for r in q:
            xi = r['cchi']
            orbit = r['character_orbit']
            k = r['weight']
            ## This is probably still quicker if it is in the database
            parity = r.get('character_parity','n/a')
            if parity == 'n/a':
                chi = ConreyCharacter(level,xi)
                if chi.is_odd():
                    parity = -1
                elif chi.is_even():
                    parity = 1
                else:
                    emf_logger.critical("Could not determine the parity of ConreyCharacter({0},{1})".format(xi,level))
                    trivial_trivially = ""
            if parity != 'n/a':
                if k % 2 == (1 + parity)/2:   # is space empty because of parity?
                    trivial_trivially = "yes"
                else:
                    trivial_trivially = ""
            if parity == 1:
                parity = 'even'
            elif parity == -1:
                parity = 'odd'
            d = r.get('d_newf',"n/a")
            indb = r.get('in_wdb',0)
            if d == 0:
                indb = 1
            if indb:
                url = url_for('emf.render_elliptic_modular_forms', level=level, weight=k, character=xi)
            else:
                url = ''
            if not table['galois_orbits_reps'].has_key(xi):
                table['galois_orbits_reps'][xi]={
                    'head' : "\(\chi_{{{0}}}({1},\cdot) \)".format(level,xi),  # yes, {{{ is required
                    'chi': "{0}".format(xi),
                    'url': url_for('characters.render_Dirichletwebpage', modulus=level, number=xi),
                    'parity':parity}
                table['galois_orbit'][xi]= [
                    {
                    #'head' : "\(\chi_{{{0}}}({1},\cdot) \)".format(level,xci),  # yes, {{{ is required
               ##     'head' : "\(S_{{{0}}}({1},\chi({2}, \cdot) ) \)".format(weight,level,xci),  # yes, {{{ is required
                ##    'head' : "\(S_{{{0}}}(\chi({1}, \cdot) ) \)".format(weight,xci),  # yes, {{{ is required
                    'head' : r"\(S_{{{0}}}(\chi_{{{1}}}({2}, \cdot)) \)".format(weight,level,xci),  # yes, {{{ is required
                    # 'head' : "\({0}\)".format(xci),
                     'chi': "{0}".format(xci),
                 #    'url': url_for('characters.render_Dirichletwebpage', modulus=level, number=xci)
                     'url': url_for('emf.render_elliptic_modular_forms', level=level, weight=k, character=xci) if indb else ''
                    }
                    for xci in orbit]
            if len(orbit)>table['maxGalCount']:
                table['maxGalCount']=len(orbit)
            table['cells'][xi]={}
            table['cells'][xi][k] ={'N': level, 'k': k, 'chi': xi, 'url': url, 'dim': d, 'trivial_trivially': trivial_trivially,}
    table['galois_orbits_reps_numbers']=table['galois_orbits_reps'].keys()
    table['galois_orbits_reps_numbers'].sort()
    #emf_logger.debug("Table:{0}".format(table))
    return table
예제 #14
0
class WebSmallDirichletCharacter(WebChar, WebDirichlet):
    """
    Heritage: WebChar -> __init__()
              WebDirichlet -> _compute()
    """

    def _compute(self):
        self.modulus = int(self.modlabel)
        self.number = int(self.numlabel)
        self.chi = ConreyCharacter(self.modulus, self.number)
        self.credit = ''
        self.codelangs = ('pari', 'sage')

    @property
    def conductor(self):
        return self.chi.conductor()

    @property
    def previous(self):   return None
    @property
    def next(self):       return None
    @property
    def genvalues(self):  return None
    @property
    def indlabel(self):  return None
    def value(self, *args): return None
    def charsums(self, *args): return False
    def gauss_sum(self, *args): return None
    def jacobi_sum(self, *args): return None
    def kloosterman_sum(self, *args): return None


    @property
    def codeinit(self):
        return {
          'sage': [ 'from dirichlet_conrey import DirichletGroup_conrey # requires nonstandard Sage package to be installed',
                 'H = DirichletGroup_conrey(%i)'%(self.modulus),
                 'chi = H[%i]'%(self.number) ],
          'pari': '[g,chi] = znchar(Mod(%i,%i))'%(self.number,self.modulus),
          }

    @property
    def title(self):
        return r"Dirichlet Character %s" % (self.texname)

    @property
    def texname(self):
        return self.char2tex(self.modulus, self.number)

    @property
    def codeisprimitive(self):
        return { 'sage': 'chi.is_primitive()',
                 'pari': '#znconreyconductor(g,chi)==1 \\\\ if not primitive returns [cond,factorization]' }

    @property
    def codecond(self):
        return { 'sage': 'chi.conductor()',
                 'pari': 'znconreyconductor(g,chi)' }


    @property
    def parity(self):
        return ('Odd', 'Even')[self.chi.is_even()]

    @property
    def codeparity(self):
        return { 'sage': 'chi.is_odd()',
                 'pari': 'zncharisodd(g,chi)' }

    @property
    def galoisorbit(self):
        order = self.order
        mod, num = self.modulus, self.number
        prim = self.isprimitive
        #beware this **must** be a generator
        orbit = ( power_mod(num, k, mod) for k in xsrange(1, order) if gcd(k, order) == 1) # use xsrange not xrange
        return ( self._char_desc(num, prim=prim) for num in orbit )

    def symbol_numerator(self):
        """ chi is equal to a kronecker symbol if and only if it is real """
        if self.order != 2:
            return None
        return symbol_numerator(self.conductor, self.chi.is_odd())

    @property
    def symbol(self):
        return kronecker_symbol(self.symbol_numerator())

    @property
    def codesymbol(self):
        m = self.symbol_numerator()
        if m:
            return { 'sage': 'kronecker_character(%i)'%m }
        return None

    @property
    def codegaloisorbit(self):
        return { 'sage': 'chi.sage_character().galois_orbit()',
                 'pari': [ 'order = charorder(g,chi)',
                           '[ charpow(g,chi, k % order) | k <-[1..order-1], gcd(k,order)==1 ]' ]
                 }
예제 #15
0
class WebDBDirichlet(WebDirichlet):
    """
    A base class using data stored in the database. Currently this is all
    Dirichlet characters with modulus up to 10000.
    """
    def __init__(self, **kwargs):
        self.type = "Dirichlet"
        self.modulus = kwargs.get('modulus', None)
        if self.modulus:
            self.modulus = int(self.modulus)
        self.modlabel = self.modulus
        self.number = kwargs.get('number', None)
        if self.number:
            self.number = int(self.number)
        self.numlabel = self.number
        if self.modulus:
            # Needed for Gauss sums, etc
            self.H = PariConreyGroup(self.modulus)
            if self.number:
                self.chi = ConreyCharacter(self.modulus, self.number)
        self.maxcols = 30
        self.codelangs = ('pari', 'sage')
        self._compute()

    @lazy_attribute
    def texname(self):
        return self.char2tex(self.modulus, self.number)

    def _compute(self):
        self._populate_from_db()

    def _populate_from_db(self):
        values_data = db.char_dir_values.lookup(
            "{}.{}".format(self.modulus, self.number)
        )

        self.orbit_index = int(values_data['orbit_label'].partition('.')[-1])
        # The -1 in the line below is because labels index at 1, while
        # the Cremona letter code indexes at 0
        self.orbit_label = cremona_letter_code(self.orbit_index - 1)
        self.order = int(values_data['order'])
        self.indlabel = int(values_data['prim_label'].partition('.')[-1])
        self._set_values_and_groupelts(values_data)
        self._set_generators_and_genvalues(values_data)

        orbit_data = db.char_dir_orbits.lucky(
            {'modulus': self.modulus, 'orbit_index': self.orbit_index}
        )

        self.conductor = int(orbit_data['conductor'])
        self._set_isprimitive(orbit_data)
        self._set_isminimal(orbit_data)
        self._set_parity(orbit_data)
        self._set_galoisorbit(orbit_data)
        self._set_kernel_field_poly(orbit_data)

    def _set_generators_and_genvalues(self, values_data):
        """
        The char_dir_values db collection contains `values_gens`, which
        contains the generators for the unit group U(modulus) and the values
        of the character on those generators.
        """
        valuepairs = values_data['values_gens']
        if self.modulus == 1:
            self.generators = r"\(1\)"
            self.genvalues = r"\(1\)"
        else:
            gens = [int(g) for g, v in valuepairs]
            vals = [int(v) for g, v in valuepairs]
            self._genvalues_for_code = get_sage_genvalues(self.modulus, self.order, vals, self.chi.sage_zeta_order(self.order))
            self.generators = self.textuple([str(g) for g in gens])
            self.genvalues = self.textuple([self._tex_value(v) for v in vals])

    def _set_values_and_groupelts(self, values_data):
        """
        The char_dir_values db collection contains `values`, which contains
        several group elements and the corresponding values.
        """
        valuepairs = values_data['values']
        if self.modulus == 1:
            self.groupelts = [1]
            self.values = [r"\(1\)"]
        else:
            self.groupelts = [int(g) for g, v in valuepairs]
            self.groupelts[0] = -1
            raw_values = [int(v) for g, v in valuepairs]
            self.values = [
                self._tex_value(v, self.order, texify=True) for v in raw_values
            ]

    def _tex_value(self, numer, denom=None, texify=False):
        r"""
        Formats the number e**(2 pi i * numer / denom), detecting if this
        simplifies to +- 1 or +- i.

        Surround the output i MathJax `\(..\)` tags if `texify` is True.
        `denom` defaults to self.order.
        """
        if not denom:
            denom = self.order

        g = gcd(numer, denom)
        if g > 1:
            numer = numer // g
            denom = denom // g

        # Reduce mod the denominator
        numer = (numer % denom)

        if denom == 1:
            ret = '1'
        elif (numer % denom) == 0:
            ret = '1'
        elif numer == 1 and denom == 2:
            ret = '-1'
        elif numer == 1 and denom == 4:
            ret = 'i'
        elif numer == 3 and denom == 4:
            ret = '-i'
        else:
            ret = r"e\left(\frac{%s}{%s}\right)" % (numer, denom)
        if texify:
            return r"\({}\)".format(ret)
        else:
            return ret

    def _set_isprimitive(self, orbit_data):
        self.isprimitive = bool_string(orbit_data['is_primitive'])

    def _set_isminimal(self, orbit_data):
        self.isminimal = bool_string(orbit_data['is_minimal'])

    def _set_parity(self, orbit_data):
        self.parity = parity_string(int(orbit_data['parity']))

    def _set_galoisorbit(self, orbit_data):
        if self.modulus == 1:
            self.galoisorbit = [self._char_desc(1, mod=1,prim=True)]
            return
        upper_limit = min(200, self.order + 1)
        orbit = orbit_data['galois_orbit'][:upper_limit]
        self.galoisorbit = list(
            self._char_desc(num, prim=self.isprimitive) for num in orbit
        )

    def _set_kernel_field_poly(self, orbit_data):
        if 'kernel_field_poly' in orbit_data.keys():
            self.kernel_field_poly = orbit_data['kernel_field_poly']
        else:
            self.kernel_field_poly = None
예제 #16
0
 def _compute(self):
     self.modulus = int(self.modlabel)
     self.number = int(self.numlabel)
     self.chi = ConreyCharacter(self.modulus, self.number)
     self.credit = ''
     self.codelangs = ('pari', 'sage')
예제 #17
0
def set_info_for_gamma1(level, weight, weight2=None):
    dimension_table_name = WebModFormSpace._dimension_table_name
    if weight != None and weight2 > weight:
        w1 = weight
        w2 = weight2
    else:
        w1 = weight
        w2 = weight
    table = {'galois_orbit': {}, 'galois_orbits_reps': {}, 'cells': {}}
    table['weights'] = range(w1, w2 + 1)
    emf_logger.debug("dimension table name={0}".format(dimension_table_name))
    db_dim = getDBConnection()['modularforms2'][dimension_table_name]
    s = {
        'level': int(level),
        'weight': {
            "$lt": int(w2 + 1),
            "$gt": int(w1 - 1)
        },
        'cchi': {
            "$exists": True
        }
    }
    q = db_dim.find(s).sort([('cchi', int(1)), ('weight', int(1))])
    if q.count() == 0:
        emf_logger.debug("No spaces in the database!")
        flash(
            'The database does not currently contain any spaces matching these parameters. Please try again!'
        )
        return None  #'error':'The database does not currently contain any spaces matching these parameters!'}
    else:
        table['maxGalCount'] = 1
        for r in q:
            xi = r['cchi']
            orbit = r['character_orbit']
            k = r['weight']
            ## This is probably still quicker if it is in the database
            parity = r.get('character_parity', 'n/a')
            if parity == 'n/a':
                chi = ConreyCharacter(level, xi)
                if chi.is_odd():
                    parity = -1
                elif chi.is_even():
                    parity = 1
                else:
                    emf_logger.critical(
                        "Could not determine the parity of ConreyCharacter({0},{1})"
                        .format(xi, level))
                    trivial_trivially = ""
            if parity != 'n/a':
                if k % 2 == (1 +
                             parity) / 2:  # is space empty because of parity?
                    trivial_trivially = "yes"
                else:
                    trivial_trivially = ""
            if parity == 1:
                parity = 'even'
            elif parity == -1:
                parity = 'odd'
            d = r.get('d_newf', "n/a")
            indb = r.get('in_wdb', 0)
            if d == 0:
                indb = 1
            if indb:
                url = url_for('emf.render_elliptic_modular_forms',
                              level=level,
                              weight=k,
                              character=xi)
            else:
                url = ''
            if not table['galois_orbits_reps'].has_key(xi):
                table['galois_orbits_reps'][xi] = {
                    'head':
                    "\(\chi_{{{0}}}({1},\cdot) \)".format(
                        level, xi),  # yes, {{{ is required
                    'chi':
                    "{0}".format(xi),
                    'url':
                    url_for('characters.render_Dirichletwebpage',
                            modulus=level,
                            number=xi),
                    'parity':
                    parity
                }
                table['galois_orbit'][xi] = [
                    {
                        #'head' : "\(\chi_{{{0}}}({1},\cdot) \)".format(level,xci),  # yes, {{{ is required
                        ##     'head' : "\(S_{{{0}}}({1},\chi({2}, \cdot) ) \)".format(weight,level,xci),  # yes, {{{ is required
                        ##    'head' : "\(S_{{{0}}}(\chi({1}, \cdot) ) \)".format(weight,xci),  # yes, {{{ is required
                        'head':
                        r"\(S_{{{0}}}(\chi_{{{1}}}({2}, \cdot)) \)".format(
                            weight, level, xci),  # yes, {{{ is required
                        # 'head' : "\({0}\)".format(xci),
                        'chi':
                        "{0}".format(xci),
                        #    'url': url_for('characters.render_Dirichletwebpage', modulus=level, number=xci)
                        'url':
                        url_for('emf.render_elliptic_modular_forms',
                                level=level,
                                weight=k,
                                character=xci) if indb else ''
                    } for xci in orbit
                ]
            if len(orbit) > table['maxGalCount']:
                table['maxGalCount'] = len(orbit)
            table['cells'][xi] = {}
            table['cells'][xi][k] = {
                'N': level,
                'k': k,
                'chi': xi,
                'url': url,
                'dim': d,
                'trivial_trivially': trivial_trivially,
            }
    table['galois_orbits_reps_numbers'] = table['galois_orbits_reps'].keys()
    table['galois_orbits_reps_numbers'].sort()
    #emf_logger.debug("Table:{0}".format(table))
    return table
예제 #18
0
 def charisprimitive(self,mod,num):
     return ConreyCharacter(mod, num).is_primitive()
예제 #19
0
 def _compute(self):
     self.modulus = int(self.modlabel)
     self.number = int(self.numlabel)
     self.chi = ConreyCharacter(self.modulus, self.number)
     self.codelangs = ('pari', 'sage')
예제 #20
0
class WebDBDirichletOrbit(WebChar, WebDBDirichlet):
    """
    A class using data stored in the database. Currently, this is all Dirichlet
    characters with modulus up to 10000.
    """

    headers = ['Character']

    _keys = [ 'title', 'codelangs', 'type',
              'nf', 'nflabel', 'nfpol', 'modulus', 'modlabel',
              'number', 'numlabel', 'texname', 'codeinit',
              'symbol', 'codesymbol','headers',
              'previous', 'next', 'conductor',
              'condlabel', 'codecond',
              'isprimitive', 'codeisprimitive',
              'inducing','rowtruncate','ind_orbit_label',
              'indlabel', 'codeind', 'order', 'codeorder', 'parity', 'codeparity',
              'isreal', 'generators', 'codegenvalues', 'genvalues', 'logvalues',
              'groupelts', 'values', 'codeval', 'galoisorbit', 'codegaloisorbit',
              'valuefield', 'vflabel', 'vfpol', 'kerfield', 'kflabel',
              'kfpol', 'contents', 'properties', 'friends', 'coltruncate',
              'charsums', 'codegauss', 'codejacobi', 'codekloosterman',
              'orbit_label', 'orbit_index', 'isminimal', 'isorbit', 'degree']

    def __init__(self, **kwargs):
        self.type = "Dirichlet"
        self.isorbit = True
        self.modulus = kwargs.get('modulus', None)
        if self.modulus:
            self.modulus = int(self.modulus)
        self.modlabel = self.modulus
        self.number = kwargs.get('number', None)
        if self.number:
            self.number = int(self.number)
        self.numlabel = self.number
        if self.modulus:
            # Needed for Gauss sums, etc
            self.H = PariConreyGroup(self.modulus)
            if self.number:
                self.chi = ConreyCharacter(self.modulus, self.number)
        self.codelangs = ('pari', 'sage')
        self.orbit_label = kwargs.get('orbit_label', None)  # this is what the user inserted, so might be banana
        self.label = "{}.{}".format(self.modulus, self.orbit_label)
        self.orbit_data = self.get_orbit_data(self.orbit_label)  # this is the meat
        self.maxrows = 30
        self.rowtruncate = False
        self._set_galoisorbit(self.orbit_data)
        self.maxcols = 10
        self._contents = None
        self._set_groupelts()

    @lazy_attribute
    def title(self):
        return "Dirichlet character orbit {}.{}".format(self.modulus, self.orbit_label)

    def _set_galoisorbit(self, orbit_data):
        if self.modulus == 1:
            self.galoisorbit = [self._char_desc(1, mod=1,prim=True)]
            return

        upper_limit = min(self.maxrows + 1, self.degree + 1)

        if self.maxrows < self.degree + 1:
            self.rowtruncate = True
        self.galorbnums = orbit_data['galois_orbit'][:upper_limit]
        self.galoisorbit = list(
            self._char_desc(num, prim=orbit_data['is_primitive']) for num in self.galorbnums
        )

    def get_orbit_data(self, orbit_label):
        mod_and_label = "{}.{}".format(self.modulus, orbit_label)
        orbit_data =  db.char_dir_orbits.lucky(
            {'modulus': self.modulus, 'label': mod_and_label}
        )

        if orbit_data is None:
            raise ValueError

        # Since we've got this, might as well set a bunch of stuff

        self.conductor = orbit_data['conductor']
        self.order = orbit_data['order']
        self.degree = orbit_data['char_degree']
        self.isprimitive = bool_string(orbit_data['is_primitive'])
        self.isminimal = bool_string(orbit_data['is_minimal'])
        self.parity = parity_string(int(orbit_data['parity']))
        self._set_kernel_field_poly(orbit_data)
        self.ind_orbit_label = cremona_letter_code(int(orbit_data['prim_orbit_index']) - 1)
        self.inducing = "{}.{}".format(self.conductor, self.ind_orbit_label)
        return orbit_data

    def _set_kernel_field_poly(self, orbit_data):
        if 'kernel_field_poly' in orbit_data.keys():
            self.kernel_field_poly = orbit_data['kernel_field_poly']
        else:
            self.kernel_field_poly = None

    @lazy_attribute
    def friends(self):
        friendlist = []
        cglink = url_character(type=self.type, modulus=self.modulus)
        friendlist.append( ("Character group", cglink) )
        if self.type == "Dirichlet" and self.isprimitive == bool_string(True):
            friendlist.append(
                ('Sato-Tate group', '/SatoTateGroup/0.1.%d' % self.order)
            )
        if len(self.vflabel) > 0:
            friendlist.append( ("Value field", '/NumberField/' + self.vflabel) )
        if self.symbol_numerator():
            if self.symbol_numerator() > 0:
                assoclabel = '2.2.%d.1' % self.symbol_numerator()
            else:
                assoclabel = '2.0.%d.1' % -self.symbol_numerator()
            friendlist.append(("Associated quadratic field", '/NumberField/' + assoclabel))

        if self.type == "Dirichlet" and self.isprimitive == bool_string(False):
            friendlist.append(('Primitive orbit '+self.inducing,
                url_for('characters.render_Dirichletwebpage', modulus=self.conductor, orbit_label=self.ind_orbit_label)))

        return friendlist

    @lazy_attribute
    def contents(self):
        if self._contents is None:
            self._contents = []
            self._fill_contents()
        return self._contents

    def _fill_contents(self):
        for c in self.galorbnums:
            self.add_row(c)

    def add_row(self, c):
        """
        Add a row to _contents for display on the webpage.
        Each row of content takes the form
            character_name, (header..data), (several..values)
        where `header..data` is expected to be a tuple of length the same
        size as `len(headers)`, and given in the same order as in `headers`,
        and where `several..values` are the values of the character
        on self.groupelts, in order.
        """
        mod = self.modulus
        num = c
        valuepairs = db.char_dir_values.lookup(
            "{}.{}".format(mod, num),
            projection='values'
        )
        prim = self.isprimitive == bool_string(True)
        self._contents.append((
            self._char_desc(num, mod=mod, prim=prim),
            self._determine_values(valuepairs, self.order)
        ))

    def symbol_numerator(self):
        """
        chi is equal to a kronecker symbol if and only if it is real
        """
        if self.order != 2:
            return None
        if self.parity == parity_string(-1):
            return symbol_numerator(self.conductor, True)
        return symbol_numerator(self.conductor, False)

    @lazy_attribute
    def symbol(self):
        return kronecker_symbol(self.symbol_numerator())

    @lazy_attribute
    def codesymbol(self):
        m = self.symbol_numerator()
        if m:
            return { 'sage': 'kronecker_character(%i)'%m,
                     'pari': 'znchartokronecker(g,chi)'
                     }
        return None

    def _determine_values(self, valuepairs, order):
        """
        Translate the db's values into the actual values.
        """
        raw_values = [int(v) for g, v in valuepairs]
        values = [
            self._tex_value(v, order, texify=True) for v in raw_values
        ]
        return values

    def _set_groupelts(self):
        if self.modulus == 1:
            self.groupelts = [1]
        else:
            db_data = db.char_dir_values.lookup(
                "{}.{}".format(self.modulus, 1)
            )
            valuepairs = db_data['values']
            self.groupelts = [int(g) for g, v in valuepairs]
            self.groupelts[0] = -1

    @lazy_attribute
    def codeinit(self):
        self.exnum = self.galorbnums[0]
        self.exchi = ConreyCharacter(self.modulus, self.exnum)

        values_gens = db.char_dir_values.lookup(
            "{}.{}".format(self.modulus, self.exnum),
            projection='values_gens'
        )

        vals = [int(v) for g, v in values_gens]
        sage_zeta_order = self.exchi.sage_zeta_order(self.order)
        self._genvalues_for_code = get_sage_genvalues(self.modulus,
                                    self.order, vals, sage_zeta_order)

        return {
            'sage': [
                'from sage.modular.dirichlet import DirichletCharacter',
                'H = DirichletGroup({}, base_ring=CyclotomicField({}))'.format(
                    self.modulus, sage_zeta_order),
                'M = H._module',
                'chi = DirichletCharacter(H, M([{}]))'.format(
                    ','.join(str(val) for val in self._genvalues_for_code)
                ),
                'chi.galois_orbit()'
            ],
            'pari': [
                '[g,chi] = znchar(Mod(%i,%i))' % (self.exnum, self.modulus),
                'order = charorder(g,chi)',
                '[ charpow(g,chi, k % order) | k <-[1..order-1], gcd(k,order)==1 ]'
            ]
        }

    @lazy_attribute
    def codeisprimitive(self):
        return { 'sage': 'chi.is_primitive()',
                 'pari': '#znconreyconductor(g,chi)==1' }

    @lazy_attribute
    def codecond(self):
        return { 'sage': 'chi.conductor()',
                 'pari': 'znconreyconductor(g,chi)' }

    @lazy_attribute
    def codeparity(self):
        return { 'sage': 'chi.is_odd()',
                 'pari': 'zncharisodd(g,chi)' }