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