def dc_calc_kloosterman(modulus, number): arg = request.args.get("val", []) if not arg: return flask.abort(404) try: a, b = map(int, arg.split(',')) if modulus == 1: # there is a bug in sage for modulus = 1 return r""" \( \displaystyle K(%s,%s,\chi_{1}(1,·)) = \sum_{r \in \mathbb{Z}/\mathbb{Z}} \chi_{1}(1,r) 1^{%s r + %s r^{-1}} = 1 \) """ % (a, b, a, b) from dirichlet_conrey import DirichletGroup_conrey chi = DirichletGroup_conrey(modulus)[number] chi = chi.sage_character() k = chi.kloosterman_sum_numerical(100, a, b) real = round(k.real(), 5) imag = round(k.imag(), 5) if imag == 0: k = str(real) elif real == 0: k = str(imag) + "i" else: k = latex(k) return r""" \( \displaystyle K(%s,%s,\chi_{%s}(%s,·)) = \sum_{r \in \mathbb{Z}/%s\mathbb{Z}} \chi_{%s}(%s,r) e\left(\frac{%s r + %s r^{-1}}{%s}\right) = %s. \)""" % (a, b, modulus, number, modulus, modulus, number, a, b, modulus, k) except Exception, e: return "<span style='color:red;'>ERROR: %s</span>" % e
def dc_calc_gauss(modulus, number): arg = request.args.get("val", []) if not arg: return flask.abort(404) try: if modulus == 1: # there is a bug in sage for modulus = 1 return r"""\(\displaystyle \tau_{%s}(\chi_{1}(1,·)) = \sum_{r\in \mathbb{Z}/\mathbb{Z}} \chi_{1}(1,r) 1^{%s}= 1. \)""" % ( int(arg), int(arg)) from dirichlet_conrey import DirichletGroup_conrey chi = DirichletGroup_conrey(modulus)[number] chi = chi.sage_character() g = chi.gauss_sum_numerical(100, int(arg)) real = round(g.real(), 10) imag = round(g.imag(), 10) if imag == 0.: g = str(real) elif real == 0.: g = str(imag) + "i" else: g = latex(g) from sage.rings.rational import Rational x = Rational('%s/%s' % (int(arg), modulus)) n = x.numerator() n = str(n) + "r" if not n == 1 else "r" d = x.denominator() return r"\(\displaystyle \tau_{%s}(\chi_{%s}(%s,·)) = \sum_{r\in \mathbb{Z}/%s\mathbb{Z}} \chi_{%s}(%s,r) e\left(\frac{%s}{%s}\right) = %s. \)" % ( int(arg), modulus, number, modulus, modulus, number, n, d, g) except Exception, e: return "<span style='color:red;'>ERROR: %s</span>" % e
def dc_calc_gauss(modulus, number): arg = request.args.get("val", []) if not arg: return flask.abort(404) try: if modulus == 1: # there is a bug in sage for modulus = 1 return r"""\(\displaystyle \tau_{%s}(\chi_{1}(1,·)) = \sum_{r\in \mathbb{Z}/\mathbb{Z}} \chi_{1}(1,r) 1^{%s}= 1. \)""" % (int(arg), int(arg)) from dirichlet_conrey import DirichletGroup_conrey chi = DirichletGroup_conrey(modulus)[number] chi = chi.sage_character() g = chi.gauss_sum_numerical(100, int(arg)) real = round(g.real(), 10) imag = round(g.imag(), 10) if imag == 0.: g = str(real) elif real == 0.: g = str(imag) + "i" else: g = latex(g) from sage.rings.rational import Rational x = Rational('%s/%s' % (int(arg), modulus)) n = x.numerator() n = str(n) + "r" if not n == 1 else "r" d = x.denominator() return r"\(\displaystyle \tau_{%s}(\chi_{%s}(%s,·)) = \sum_{r\in \mathbb{Z}/%s\mathbb{Z}} \chi_{%s}(%s,r) e\left(\frac{%s}{%s}\right) = %s. \)" % (int(arg), modulus, number, modulus, modulus, number, n, d, g) except Exception, e: return "<span style='color:red;'>ERROR: %s</span>" % e
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 = DirichletGroup_conrey(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
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
def dc_calc_jacobi(modulus, number): arg = request.args.get("val", []) if not arg: return flask.abort(404) arg = map(int, arg.split('.')) try: num = arg[0] from dirichlet_conrey import DirichletGroup_conrey chi = DirichletGroup_conrey(modulus)[number] psi = DirichletGroup_conrey(modulus)[num] chi = chi.sage_character() psi = psi.sage_character() jacobi_sum = chi.jacobi_sum(psi) return r"\( \displaystyle J(\chi_{%s}(%s,·),\chi_{%s}(%s,·)) = \sum_{r\in \mathbb{Z}/%s\mathbb{Z}} \chi_{%s}(%s,r) \chi_{%s}(%s,1-r) = %s.\)" % (modulus, number, modulus, num, modulus, modulus, number, modulus, num, latex(jacobi_sum)) except Exception, e: return "<span style='color:red;'>ERROR: %s</span>" % e
def nextprimchar(m, n): if m < 3: return 3, 2 if n < m - 1: Gm = DirichletGroup_conrey(m) while 1: n += 1 if n >= m: m, n = m + 1, 2 Gm = DirichletGroup_conrey(m) if gcd(m, n) != 1: continue # we have a character, test if it is primitive chi = Gm[n] if chi.is_primitive(): return m, n
def dirichlet_group(self): from dirichlet_conrey import DirichletGroup_conrey f = self.conductor() if f == 1: # To make the trivial case work correctly return [1] G = DirichletGroup_conrey(f) pram = f.prime_factors() P = Primes() p = P.first() K = self.K() while p in pram: p = P.next(p) fres = K.factor(p)[0][0].residue_class_degree() a = p**fres S = set(G[a].kernel()) timeout = 10000 while len(S) != self.degree(): timeout -= 1 p = P.next(p) if p not in pram: fres = K.factor(p)[0][0].residue_class_degree() a = p**fres S = S.intersection(G[a].kernel()) if timeout == 0: raise Exception('timeout in dirichlet group') return [b for b in S]
def charisprimitive(self, mod, num): if isinstance(self.H, DirichletGroup_conrey) and self.H.modulus() == mod: H = self.H else: H = DirichletGroup_conrey(mod) return H[num].is_primitive()
def dim_and_orbit(n,k,number): G = DirichletGroup_conrey(n) char = G[number] go = char.galois_orbit() indexes = [elt.number() for elt in go] dim = sum([dimension_new_cusp_forms(char.sage_character(),k) for elt in go]) return dim, indexes
def doline(inputs, line, lfun_dir, check_for_lpdata = True, check_for_lfunction = True): linesplit = line.rstrip('\n').split(':') hoc, label, conrey_label, embedding_index, embedding_m, ap_txt = linesplit lpfilename = os.path.join(lfun_dir, label + ".lpdata") lfunctionfilename = os.path.join(lfun_dir, label + ".lpdata.lfunction") level, weight, char_orbit, hecke_orbit, conrey_label_again, embedding = label.split('.') assert conrey_label_again == conrey_label level = int(level) weight = int(weight) conrey_label = int(conrey_label) ap_list = None G = DirichletGroup_conrey(level, CCC) char = DirichletCharacter_conrey(G, conrey_label) if not os.path.exists(lpfilename) or not check_for_lpdata: ap_list = read_aps(ap_txt) euler_factors = [[elt[0], euler_factor(level, weight, char, elt[0], elt[1])] for elt in ap_list] with open(lpfilename, 'w') as LPDATA: for p, ep in euler_factors: LPDATA.write("%d, [ %s ]\n" % (p, ", ".join(map(print_CCC, ep)))) if not os.path.exists(lfunctionfilename) or not check_for_lfunction: if weight not in inputs: inputs[weight] = [] sd = self_dual_by_char(char) if sd is None: if ap_list is None: ap_list = read_aps(ap_txt) sd = self_dual(char, ap_list) inputs[weight].append("%d %d %d %s %s" % (weight, sd, level, label, lpfilename))
def init_dynamic_properties(self, embeddings=False): if self.number is not None: emf_logger.debug('number: {0}'.format(self.number)) self.character = DirichletCharacter_conrey( DirichletGroup_conrey(self.modulus), self.number) if not self.number == 1: self.sage_character = self.character.sage_character() else: self.sage_character = trivial_character(self.modulus) self.name = "Character nr. {0} of modulus {1}".format( self.number, self.modulus) if embeddings: from lmfdb.modular_forms.elliptic_modular_forms.backend.emf_utils import dirichlet_character_conrey_galois_orbit_embeddings emb = dirichlet_character_conrey_galois_orbit_embeddings( self.modulus, self.number) self.set_embeddings(emb) c = self.character if self.conductor == 0: self.conductor = c.conductor() if self.order == 0: self.order = c.multiplicative_order() if self.modulus_euler_phi == 0: self.modulus_euler_phi = euler_phi(self.modulus) if self.latex_name == '': self.latex_name = "\chi_{" + str(self.modulus) + "}(" + str( self.number) + ", \cdot)"
def check_all_files(filename, linecount, chunk = 100): k = 0 base_dir = os.path.dirname(os.path.abspath(filename)) lfun_dir = os.path.join(base_dir, 'lfun') inputs_dir = os.path.join(base_dir, 'inputs') inputs = {} with open(filename, 'r') as F: for line in F: linesplit = line[:-1].split(':') hoc, label, conrey_label_tmp, embedding_index_tmp, embedding_m, ap_txt = linesplit lpdatafilename = os.path.join(lfun_dir, label + ".lpdata") lfunfilename = os.path.join(lfun_dir, label + ".lpdata.lfunction") if not os.path.exists(lpdatafilename): print "%s\tMissing lpdata file: %s" % (label, lpdatafilename) print "Use generate_lpdata_and_inputs.py to generate those files" sys.exit(1) if not os.path.exists(lfunfilename): print "%s\tMissing lfunction file: for %s" % (label, lfunfilename) # reading the line level, weight, char_orbit, hecke_orbit, conrey_label, embedding_index = label.split(".") level, weight, conrey_label, embedding_index = map(int, [level, weight, conrey_label, embedding_index]) ap_list = [ toCCC(*elt.split(',')) for elt in ap_txt[2:-2].split('],[')] ap_list = zip(primes_first_n(len(ap_list)),ap_list) G = DirichletGroup_conrey(level, CCC) char = DirichletCharacter_conrey(G, conrey_label) if weight not in inputs: inputs[weight] = [] inputs[weight].append("%d %d %d %s %s" % (weight, self_dual(char, ap_list) , level, label, lpdatafilename)) k += 1 if linecount > 10: if (k % (linecount//10)) == 0: print "check_all_files %.2f%% done" % (k*100./linecount) if len(inputs) > 0: real_filename = os.path.abspath(filename).split('/')[-1] parallel_inputs = os.path.join(base_dir, real_filename + '.tsv.missing') with open(parallel_inputs, 'w') as I: for weight, lines in inputs.iteritems(): if chunk is None: chunked_lines = [lines] else: chunked_lines = [ lines[i:i+chunk] for i in range(0, len(lines), chunk)] assert sum(map(len, chunked_lines)) == len(lines), "%d != %d" % (sum(map(len, chunked_lines)), len(lines)) for i, line_block in enumerate(chunked_lines): inputsfilename = os.path.join(inputs_dir, real_filename + '_wt%d_%d.missing.input' % (weight, i)) with open(inputsfilename , 'w') as W: W.write('\n'.join(line_block) + '\n') #print "wrote %d lines to %s" % (len(line_block), inputsfilename) I.write("%d\t%s\n" % (weight, inputsfilename)) print "There were some missing lfunction files!" print "please set LFUNCTIONS and run:" print r"""parallel -a %s --colsep '\t' --progress ${LFUNCTIONS}/euler_factors 11 200 ${LFUNCTIONS}/gamma_files/mf.{1} {2} 100""" % (parallel_inputs,) sys.exit(1) print "check_all_files done" return None
def dirichlet_l_iterator(min_conductor=2, max_conductor=10**5): from dirichlet_conrey import DirichletGroup_conrey for modulus in filter(lambda _: _ % 4 != 2, xrange(min_conductor, max_conductor)): print(modulus) for c in DirichletGroup_conrey(modulus).primitive_characters(): L_dirichlet = Lfunction_Dirichlet(charactermodulus=modulus, characternumber=c.number()) yield L_dirichlet
def prevprimchar(m, n): if m <= 3: return 1, 1 if n > 2: Gm = DirichletGroup_conrey(m) while True: n -= 1 if n <= 1: # (m,1) is never primitive for m>1 m, n = m - 1, m - 1 Gm = DirichletGroup_conrey(m) if m <= 2: return 1, 1 if gcd(m, n) != 1: continue # we have a character, test if it is primitive chi = Gm[n] if chi.is_primitive(): return m, n
def sage_character_to_conrey_index(chi, N): r""" For Dirichlet character chi, we return the corresponding Conrey Index n, so that x(m)=chi_N(n,m). """ Dc = DirichletGroup_conrey(N) for c in Dc: if c.sage_character() == chi: return c.number() return -1
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
def get_entries(modulus): from dirichlet_conrey import DirichletGroup_conrey from sage.all import Integer from WebCharacter import log_value G = DirichletGroup_conrey(modulus) headers = range(1, modulus + 1) e = euler_phi(modulus) rows = [] for chi in G: is_prim = chi.is_primitive() number = chi.number() rows.append((number, is_prim, log_value(modulus, number))) return headers, rows
def check_Skchi_dim_formula(self, rec, verbose=False): """ for k > 1 check that dim is the Q-dimension of S_k^new(N,chi) (using sage dimension formula) """ # sample: dimension_new_cusp_forms(DirichletGroup(100).1^2,4) # Work around a bug in sage for Dirichlet characters in level 1 and 2 if rec['level'] < 3: dirchar = rec['level'] else: dirchar = DirichletGroup_conrey( rec['level'])[rec['conrey_indexes'][0]].sage_character() return self._test_equality( rec['relative_dim'], dimension_new_cusp_forms(dirchar, rec['weight']), verbose)
def line(N): l = [] count = 0 for modulus in range(N, 250): G = DirichletGroup_conrey(modulus) for j, chi in enumerate(G): if count == 8: break elif chi.multiplicative_order() == N: count += 1 l.append((modulus, chi.number(), chi.is_primitive(), chi.multiplicative_order(), k(chi))) if count == 8: break return l
def line(N): l = [] count = 0 for modulus in range(N, 250): G = DirichletGroup_conrey(modulus) for j, chi in enumerate(G): c = WebDirichletCharacter(modulus = chi.modulus(),number = chi.number()) if count == 8: break elif chi.multiplicative_order() == N: count += 1 l.append((modulus, chi.number(), chi.is_primitive(), chi.multiplicative_order(), c.symbol)) if count == 8: break return l
def results_by_modulus(self, mmin, mmax, start, limit): res = [] ticks = 0 if mmin > mmax or self.cmin > self.cmax or self.omin > self.omax: return res, True if self.omax == 1 and self.cmin > 1: return res, True step = 1 if self.conductor and self.cmin == self.cmax: step = self.cmin if mmin % step: mmin = mmin + step - (mmin % step) count = 0 for q in xrange(mmin, mmax + 1, step): # if we have not found any results of modululs q <= cmax we are never going to find any (unless only imprimitive results are sought) if q > self.cmax and not res and self.start == 0 and ( not self.primitive or self.is_primitive): return res, True if self.conductor and not divisors_in_interval( q, self.cmin, self.cmax): continue if self.order and not divisors_in_interval(modn_exponent(q), self.omin, self.omax): continue G = DirichletGroup_conrey(q) for chi in G: ticks += 1 c, o, p = chi.conductor(), chi.multiplicative_order( ), chi.is_odd() if c < self.cmin or c > self.cmax or o < self.omin or o > self.omax: continue if self.primitive and self.is_primitive != (True if q == c else False): continue if self.parity and self.is_odd != p: continue if count >= start: if len(res) == limit: return res, False res.append(charinfo(chi)) count += 1 if ticks > 100000: flash( Markup( "Error: Unable to complete query within timeout (showing results up to modulus %d). Try narrowing your search." % q), "error") return res, False return res, True
def row(N): ret = [] G = DirichletGroup_conrey(N) for chi in G: j = chi.number() add = True add &= not conductor or chi.conductor() == conductor add &= not order or chi.multiplicative_order() == order if add: if chi.multiplicative_order() == 2 and kronecker_symbol(chi) is not None: ret.append([(j, kronecker_symbol(chi), chi.modulus( ), chi.conductor(), chi.multiplicative_order(), chi.is_primitive(), chi.is_even())]) else: ret.append([(j, chi, chi.modulus( ), chi.conductor(), chi.multiplicative_order(), chi.is_primitive(), chi.is_even())]) return ret
def dirichlet_group(self): from dirichlet_conrey import DirichletGroup_conrey f = self.conductor() if f == 1: # To make the trivial case work correctly return [1] if euler_phi(f) > dir_group_size_bound: return [] # Can do quadratic fields directly if self.degree() == 2: if is_odd(f): return [1, f-1] f1 = f/4 if is_odd(f1): return [1, f-1] # we now want f with all powers of 2 removed f1 = f1/2 if is_even(f1): raise Exception('Invalid conductor') if (self.disc()/8) % 4 == 3: return [1, 4*f1-1] # Finally we want congruent to 5 mod 8 and -1 mod f1 if (f1 % 4) == 3: return [1, 2*f1-1] return [1, 6*f1-1] G = DirichletGroup_conrey(f) pram = f.prime_factors() P = Primes() p = P.first() K = self.K() while p in pram: p = P.next(p) fres = K.factor(p)[0][0].residue_class_degree() a = p ** fres S = set(G[a].kernel()) timeout = 10000 while len(S) != self.degree(): timeout -= 1 p = P.next(p) if p not in pram: fres = K.factor(p)[0][0].residue_class_degree() a = p ** fres S = S.intersection(G[a].kernel()) if timeout == 0: raise Exception('timeout in dirichlet group') return [b for b in S]
def line(n): l = [] count = 0 q = n while count < limit: if modn_exponent(q) % n == 0: G = DirichletGroup_conrey(q) for chi in G: j = chi.number() c = WebDirichletCharacter(modulus = q, number = j) if chi.multiplicative_order() == n: l.append((q, j, chi.is_primitive(), chi.multiplicative_order(), c.symbol)) count += 1 if count == limit: break q += 1 return l
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 = DirichletGroup_conrey(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
def line(N): l = [] if N%4 == 2: return l count = 0 q = N while count < limit: if q % N == 0: G = DirichletGroup_conrey(q) for chi in G: j = chi.number() c = WebDirichletCharacter(modulus = q, number = j) if chi.conductor() == q: l.append((q, j, chi.is_primitive(), chi.multiplicative_order(), c.symbol)) count += 1 if count == limit: break q += N return l
def line(N): l = [] count = 0 modulus = N while count < 7: if modulus % N == 0: G = DirichletGroup_conrey(modulus) for chi in G: j = chi.number() c = WebDirichletCharacter(modulus = chi.modulus(),number = chi.number()) if count == 7: break elif chi.conductor() == N: count += 1 l.append((modulus, j, chi.is_primitive(), chi.multiplicative_order(), c.symbol)) modulus += N if count == 0: break return l
def line(N): l = [] count = 0 modulus = N while count < 7: if modulus % N == 0: G = DirichletGroup_conrey(modulus) for chi in G: j = chi.number() print chi.conductor(), j, N if count == 7: break elif chi.conductor() == N: count += 1 l.append((modulus, j, chi.is_primitive(), chi.multiplicative_order(), k(chi))) modulus += N if count == 0: break return l
def check_dims(self, rec, verbose=False): """ for k > 1 check each of eis_dim, eis_new_dim, cusp_dim, mf_dim, mf_new_dim using Sage dimension formulas (when applicable) """ # Work around a bug in sage for Dirichlet characters in level 1 if rec['level'] < 3: dirchar = rec['level'] else: dirchar = DirichletGroup_conrey( rec['level'])[rec['conrey_indexes'][0]].sage_character() k = rec['weight'] m = rec['char_degree'] for func, key in [(dimension_eis, 'eis_dim'), (dimension_cusp_forms, 'cusp_dim'), (dimension_modular_forms, 'mf_dim')]: if not self._test_equality(rec[key], func(dirchar, k) * m, verbose): return False return True
def dc_calc_jacobi(modulus, number): arg = request.args.get("val", []) if not arg: return flask.abort(404) arg = map(int, arg.split('.')) try: num = arg[0] from dirichlet_conrey import DirichletGroup_conrey chi = DirichletGroup_conrey(modulus)[number] psi = DirichletGroup_conrey(modulus)[num] chi = chi.sage_character() psi = psi.sage_character() jacobi_sum = chi.jacobi_sum(psi) return r"\( \displaystyle J(\chi_{%s}(%s,·),\chi_{%s}(%s,·)) = \sum_{r\in \mathbb{Z}/%s\mathbb{Z}} \chi_{%s}(%s,r) \chi_{%s}(%s,1-r) = %s.\)" % ( modulus, number, modulus, num, modulus, modulus, number, modulus, num, latex(jacobi_sum)) except Exception, e: return "<span style='color:red;'>ERROR: %s</span>" % e
def dirichlet_character_conrey_galois_orbits_reps(N): """ Return list of representatives for the Galois orbits of Conrey Dirichlet characters of level N. We always take the one that has the smallest index. """ D = DirichletGroup_conrey(N) if N == 1: return [D[1]] Dl = list(D) reps = [] for x in D: if x not in Dl: continue orbit_of_x = sorted(x.galois_orbit()) reps.append(orbit_of_x[0]) for xx in orbit_of_x: if xx not in Dl: continue Dl.remove(xx) return reps
def row(N): ret = [] G = DirichletGroup_conrey(N) for chi in G: j = chi.number() c = WebDirichletCharacter(modulus=chi.modulus(), number=chi.number()) add = True add &= not conductor or chi.conductor() == conductor add &= not order or chi.multiplicative_order() == order if add: if chi.multiplicative_order() == 2 and c.symbol is not None: ret.append([(j, c.symbol, chi.modulus(), chi.conductor(), chi.multiplicative_order(), chi.is_primitive(), chi.is_even())]) else: ret.append([(j, chi, chi.modulus(), chi.conductor(), chi.multiplicative_order(), chi.is_primitive(), chi.is_even())]) return ret
def _compute(self): if self.modlabel: self.modulus = m = int(self.modlabel) self.H = DirichletGroup_conrey(m) self.credit = 'SageMath' self.codelangs = ('pari', 'sage')
class WebDirichlet(WebCharObject): """ For some applications (orbits, enumeration), Dirichlet characters may be represented by a couple (modulus, number) without computing the Dirichlet group. """ def _compute(self): if self.modlabel: self.modulus = m = int(self.modlabel) self.H = DirichletGroup_conrey(m) self.credit = 'SageMath' self.codelangs = ('pari', 'sage') def _char_desc(self, c, mod=None, prim=None): """ usually num is the number, but can be a character """ if isinstance(c, DirichletCharacter_conrey): if prim == None: prim = c.is_primitive() mod = c.modulus() num = c.number() elif mod == None: mod = self.modulus num = c if prim == None: prim = self.charisprimitive(mod,num) return ( mod, num, self.char2tex(mod,num), prim) def charisprimitive(self,mod,num): if isinstance(self.H, DirichletGroup_conrey) and self.H.modulus()==mod: H = self.H else: H = DirichletGroup_conrey(mod) return H[num].is_primitive() @property def gens(self): return map(int, self.H.gens()) @property def generators(self): #import pdb; pdb.set_trace() #assert self.H.gens() is not None return self.textuple(map(str, self.H.gens())) """ for Dirichlet over Z, everything is described using integers """ @staticmethod def char2tex(modulus, number, val='\cdot', tag=True): c = r'\chi_{%s}(%s,%s)'%(modulus,number,val) if tag: return '\(%s\)'%c else: return c group2tex = int group2label = int label2group = int ideal2tex = int ideal2label = int label2ideal = int """ numbering characters """ number2label = int label2number = int @property def groupelts(self): return map(self.group2tex, self.Gelts()) @cached_method def Gelts(self): res = [] m,n,k = self.modulus, 1, 1 while k < m and n <= self.maxcols: if gcd(k,m) == 1: res.append(k) n += 1 k += 1 if n > self.maxcols: self.coltruncate = True return res @staticmethod def nextchar(m, n, onlyprimitive=False): """ we know that the characters chi_m(1,.) and chi_m(m-1,.) always exist for m>1. They are extremal for a given m. """ if onlyprimitive: return WebDirichlet.nextprimchar(m, n) if m == 1: return 2, 1 if n == m - 1: return m + 1, 1 k = n+1 while k < m: if gcd(m, k) == 1: return m, k k += 1 raise Exception("nextchar") @staticmethod def prevchar(m, n, onlyprimitive=False): """ Assume m>1 """ if onlyprimitive: return WebDirichlet.prevprimchar(m, n) if n == 1: m, n = m - 1, m if m <= 2: return m, 1 # important : 2,2 is not a character k = n-1 while k > 0: if gcd(m, k) == 1: return m, k k -= 1 raise Exception("prevchar") @staticmethod def prevprimchar(m, n): if m <= 3: return 1, 1 if n > 2: Gm = DirichletGroup_conrey(m) while True: n -= 1 if n <= 1: # (m,1) is never primitive for m>1 m, n = m - 1, m - 1 Gm = DirichletGroup_conrey(m) if m <= 2: return 1, 1 if gcd(m, n) != 1: continue # we have a character, test if it is primitive chi = Gm[n] if chi.is_primitive(): return m, n @staticmethod def nextprimchar(m, n): if m < 3: return 3, 2 if n < m - 1: Gm = DirichletGroup_conrey(m) while 1: n += 1 if n >= m: m, n = m + 1, 2 Gm = DirichletGroup_conrey(m) if gcd(m, n) != 1: continue # we have a character, test if it is primitive chi = Gm[n] if chi.is_primitive(): return m, n