def __init__(self, level, weight): data = db.mf_gamma1.lucky({'level': level, 'weight': weight}) if data is None: raise ValueError("Space not in database") self.__dict__.update(data) self.weight_parity = -1 if (self.weight % 2) == 1 else 1 self.factored_level = web_latex_factored_integer(self.level, equals=True) self.has_projective_image_types = all(typ + '_dim' in data for typ in ('dihedral', 'a4', 's4', 'a5')) # The following can be removed once we change the behavior of lucky to include Nones self.num_forms = data.get('num_forms') self.num_spaces = data.get('num_spaces') self.trace_bound = data.get('trace_bound') self.has_trace_form = (data.get('traces') is not None) # by default we sort on char_orbit_index newspaces = list( db.mf_newspaces.search({ 'level': level, 'weight': weight, 'char_parity': self.weight_parity })) oldspaces = db.mf_gamma1_subspaces.search( { 'level': level, 'sub_level': { '$ne': level }, 'weight': weight }, ['sub_level', 'sub_mult']) self.oldspaces = [(old['sub_level'], old['sub_mult']) for old in oldspaces] self.dim_grid = sum( DimGrid.from_db(space) for space in newspaces) if newspaces else DimGrid() #self.mf_dim = sum(space['mf_dim'] for space in newspaces) #self.eis_dim = sum(space['eis_dim'] for space in newspaces) #self.eis_new_dim = sum(space['eis_new_dim'] for space in newspaces) #self.eis_old_dim = self.eis_dim - self.eis_new_dim #self.cusp_dim = sum(space['cusp_dim'] for space in newspaces) self.new_dim = sum(space['dim'] for space in newspaces) self.old_dim = sum( (space['cusp_dim'] - space['dim']) for space in newspaces) self.decomp = [] newforms = list( db.mf_newforms.search({ 'level': level, 'weight': weight }, [ 'label', 'space_label', 'dim', 'level', 'char_orbit_label', 'hecke_orbit', 'char_degree' ])) self.has_uncomputed_char = False for space in newspaces: if space.get('num_forms') is None: self.decomp.append((space, None)) self.has_uncomputed_char = True else: self.decomp.append((space, [ form for form in newforms if form['space_label'] == space['label'] ])) self.plot = db.mf_gamma1_portraits.lookup(self.label, projection="portrait") self.properties = [ ('Label', self.label), ] if self.plot is not None and self.new_dim > 0: self.properties += [ (None, '<a href="{0}"><img src="{0}" width="200" height="200"/></a>'. format(self.plot)) ] self.properties += [('Level', str(self.level)), ('Weight', str(self.weight)), ('Dimension', str(self.new_dim))] if self.num_spaces is not None: self.properties.append(('Nonzero newspaces', str(self.num_spaces))) if self.num_forms is not None: self.properties.append(('Newform subspaces', str(self.num_forms))) self.properties.append(('Sturm bound', str(self.sturm_bound))) if self.trace_bound is not None: self.properties.append(('Trace bound', str(self.trace_bound))) self.bread = get_bread(level=self.level, weight=self.weight) # Downloads self.downloads = [('Trace form to text', url_for('cmf.download_traces', label=self.label)), ('All stored data to text', url_for('cmf.download_full_space', label=self.label))] self.title = r"Space of modular forms of level %s and weight %s" % ( self.level, self.weight) self.friends = []
def __init__(self, data): # Need to set mf_dim, eis_dim, cusp_dim, new_dim, old_dim self.__dict__.update(data) self.factored_level = web_latex_factored_integer(self.level, equals=True) self.has_projective_image_types = all(typ + '_dim' in data for typ in ('dihedral', 'a4', 's4', 'a5')) # The following can be removed once we change the behavior of lucky to include Nones self.num_forms = data.get('num_forms') self.trace_bound = data.get('trace_bound') self.has_trace_form = (data.get('traces') is not None) self.char_conrey = self.conrey_indexes[0] self.char_conrey_str = r'\chi_{%s}(%s,\cdot)' % (self.level, self.char_conrey) self.newforms = list( db.mf_newforms.search({'space_label': self.label}, projection=2)) oldspaces = db.mf_subspaces.search( { 'label': self.label, 'sub_level': { '$ne': self.level } }, [ 'sub_level', 'sub_char_orbit_index', 'sub_conrey_indexes', 'sub_mult' ]) self.oldspaces = [(old['sub_level'], old['sub_char_orbit_index'], old['sub_conrey_indexes'][0], old['sub_mult']) for old in oldspaces] self.dim_grid = DimGrid.from_db(data) self.plot = db.mf_newspace_portraits.lookup(self.label, projection="portrait") # Properties self.properties = [('Label', self.label)] if self.plot is not None and self.dim > 0: self.properties += [ (None, '<img src="{0}" width="200" height="200"/>'.format(self.plot)) ] self.properties += [ ('Level', prop_int_pretty(self.level)), ('Weight', prop_int_pretty(self.weight)), ('Character orbit', '%s.%s' % (self.level, self.char_orbit_label)), ('Rep. character', '$%s$' % self.char_conrey_str), ('Character field', r'$\Q%s$' % ('' if self.char_degree == 1 else r'(\zeta_{%s})' % self.char_order)), ('Dimension', prop_int_pretty(self.dim)), ] if self.num_forms is not None: self.properties.append( ('Newform subspaces', prop_int_pretty(self.num_forms))) self.properties.append( ('Sturm bound', prop_int_pretty(self.sturm_bound))) if data.get('trace_bound') is not None: self.properties.append( ('Trace bound', prop_int_pretty(self.trace_bound))) # Work around search results not including None if data.get('num_forms') is None: self.num_forms = None # Breadcrumbs self.bread = get_bread(level=self.level, weight=self.weight, char_orbit_label=self.char_orbit_label) # Downloads self.downloads = [ ('Trace form to text', url_for('cmf.download_traces', label=self.label)), ('All stored data to text', url_for('.download_newspace', label=self.label)), ] if self.conrey_indexes[0] == 1: self.trivial_character = True character_str = "trivial character" if self.dim == 0: self.dim_str = r"\(%s\)" % (self.dim) else: self.minus_dim = self.dim - self.plus_dim self.dim_str = r"\(%s + %s\)" % (self.plus_dim, self.minus_dim) else: self.trivial_character = False character_str = r"Character {level}.{orbit_label}".format( level=self.level, orbit_label=self.char_orbit_label) # character_str = r"Character \(\chi_{{{level}}}({conrey}, \cdot)\)".format(level=self.level, conrey=self.conrey_indexes[0]) self.dim_str = r"\(%s\)" % (self.dim) self.title = r"Space of modular forms of level %s, weight %s, and %s" % ( self.level, self.weight, character_str) gamma1_link = '/ModularForm/GL2/Q/holomorphic/%d/%d' % (self.level, self.weight) self.friends = [('Newspace %d.%d' % (self.level, self.weight), gamma1_link)]
def factored_level(self): return web_latex_factored_integer(self.level, equals=True)
def make_object(self, curve, endo, tama, ratpts, clus, is_curve): from lmfdb.genus2_curves.main import url_for_curve_label # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} data['label'] = curve['label'] if is_curve else curve['class'] data['slabel'] = data['label'].split('.') # set attributes common to curves and isogeny classes here data['Lhash'] = str(curve['Lhash']) data['cond'] = ZZ(curve['cond']) data['cond_factor_latex'] = web_latex_factored_integer(data['cond']) data['analytic_rank'] = ZZ(curve['analytic_rank']) data['mw_rank'] = ZZ(0) if curve.get('mw_rank') is None else ZZ(curve['mw_rank']) # 0 will be marked as a lower bound data['mw_rank_proved'] = curve['mw_rank_proved'] data['analytic_rank_proved'] = curve['analytic_rank_proved'] data['hasse_weil_proved'] = curve['hasse_weil_proved'] data['st_group'] = curve['st_group'] data['st_group_link'] = st_link_by_name(1,4,data['st_group']) data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg']) data['is_gl2_type'] = curve['is_gl2_type'] data['root_number'] = ZZ(curve['root_number']) data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1]) data['bad_lfactors'] = literal_eval(curve['bad_lfactors']) data['bad_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']] if is_curve: # invariants specific to curve data['class'] = curve['class'] data['abs_disc'] = ZZ(curve['abs_disc']) data['disc'] = curve['disc_sign'] * data['abs_disc'] data['min_eqn'] = literal_eval(curve['eqn']) data['min_eqn_display'] = min_eqns_pretty(data['min_eqn']) data['disc_factor_latex'] = web_latex_factored_integer(data['disc']) data['igusa_clebsch'] = [ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv'])] data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])] data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])] data['igusa_clebsch_factor_latex'] = [web_latex_factored_integer(i) for i in data['igusa_clebsch']] data['igusa_factor_latex'] = [ web_latex_factored_integer(j) for j in data['igusa'] ] data['aut_grp'] = small_group_label_display_knowl('%d.%d' % tuple(literal_eval(curve['aut_grp_id']))) data['geom_aut_grp'] = small_group_label_display_knowl('%d.%d' % tuple(literal_eval(curve['geom_aut_grp_id']))) data['num_rat_wpts'] = ZZ(curve['num_rat_wpts']) data['has_square_sha'] = "square" if curve['has_square_sha'] else "twice a square" P = curve['non_solvable_places'] if len(P): sz = "except over " sz += ", ".join([QpName(p) for p in P]) last = " and" if len(P) > 2: last = ", and" sz = last.join(sz.rsplit(",",1)) else: sz = "everywhere" data['non_solvable_places'] = sz data['two_selmer_rank'] = ZZ(curve['two_selmer_rank']) data['torsion_order'] = curve['torsion_order'] data['end_ring_base'] = endo['ring_base'] data['end_ring_geom'] = endo['ring_geom'] data['real_period'] = decimal_pretty(str(curve['real_period'])) data['regulator'] = decimal_pretty(str(curve['regulator'])) if curve['regulator'] > -0.5 else 'unknown' if data['mw_rank'] == 0 and data['mw_rank_proved']: data['regulator'] = '1' # display an exact 1 when we know this data['tamagawa_product'] = ZZ(curve['tamagawa_product']) if curve.get('tamagawa_product') else 0 data['analytic_sha'] = ZZ(curve['analytic_sha']) if curve.get('analytic_sha') else 0 data['leading_coeff'] = decimal_pretty(str(curve['leading_coeff'])) if curve['leading_coeff'] else 'unknown' data['rat_pts'] = ratpts['rat_pts'] data['rat_pts_v'] = ratpts['rat_pts_v'] data['rat_pts_table'] = ratpts_table(ratpts['rat_pts'],ratpts['rat_pts_v']) data['rat_pts_simple_table'] = ratpts_simpletable(ratpts['rat_pts'],ratpts['rat_pts_v'],data['min_eqn']) data['mw_gens_v'] = ratpts['mw_gens_v'] lower = len([n for n in ratpts['mw_invs'] if n == 0]) upper = data['analytic_rank'] invs = ratpts['mw_invs'] if data['mw_gens_v'] or lower >= upper else [0 for n in range(upper-lower)] + ratpts['mw_invs'] if len(invs) == 0: data['mw_group'] = 'trivial' else: data['mw_group'] = r'\(' + r' \times '.join([ (r'\Z' if n == 0 else r'\Z/{%s}\Z' % n) for n in invs]) + r'\)' if lower >= upper: data['mw_gens_table'] = mw_gens_table (ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts']) data['mw_gens_simple_table'] = mw_gens_simple_table (ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts'], data['min_eqn']) if curve['two_torsion_field'][0]: data['two_torsion_field_knowl'] = nf_display_knowl (curve['two_torsion_field'][0], field_pretty(curve['two_torsion_field'][0])) else: t = curve['two_torsion_field'] data['two_torsion_field_knowl'] = r"splitting field of \(%s\) with Galois group %s" % (intlist_to_poly(t[1]),group_display_knowl(t[2][0],t[2][1])) tamalist = [[item['p'],item['tamagawa_number']] for item in tama] data['local_table'] = local_table (data['cond'],data['abs_disc'],tamalist,data['bad_lfactors_pretty'],clus) else: # invariants specific to isogeny class curves_data = list(db.g2c_curves.search({"class" : curve['class']}, ['label','eqn'])) if not curves_data: raise KeyError("No curves found in database for isogeny class %s of genus 2 curve %s." %(curve['class'],curve['label'])) data['curves'] = [ {"label" : c['label'], "equation_formatted" : min_eqn_pretty(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label'])} for c in curves_data ] lfunc_data = db.lfunc_lfunctions.lucky({'Lhash':str(curve['Lhash'])}) if not lfunc_data: raise KeyError("No Lfunction found in database for isogeny class of genus 2 curve %s." %curve['label']) if lfunc_data and lfunc_data.get('euler_factors'): data['good_lfactors'] = [[nth_prime(n+1),lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n+1) < 30 and (data['cond'] % nth_prime(n+1))] data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors']] # Endomorphism data over QQ: data['gl2_statement_base'] = gl2_statement_base(endo['factorsRR_base'], r'\(\Q\)') data['factorsQQ_base'] = endo['factorsQQ_base'] data['factorsRR_base'] = endo['factorsRR_base'] data['end_statement_base'] = (r"Endomorphism %s over \(\Q\):<br>" %("ring" if is_curve else "algebra") + end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None)) # Field over which all endomorphisms are defined data['end_field_label'] = endo['fod_label'] data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs']) data['end_field_statement'] = end_field_statement(data['end_field_label'], data['end_field_poly']) # Endomorphism data over QQbar: data['factorsQQ_geom'] = endo['factorsQQ_geom'] data['factorsRR_geom'] = endo['factorsRR_geom'] if data['end_field_label'] != '1.1.1.1': data['gl2_statement_geom'] = gl2_statement_base(data['factorsRR_geom'], r'\(\overline{\Q}\)') data['end_statement_geom'] = (r"Endomorphism %s over \(\overline{\Q}\):" %("ring" if is_curve else "algebra") + end_statement(data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None)) data['real_geom_end_alg_name'] = real_geom_end_alg_name(curve['real_geom_end_alg']) data['geom_end_alg_name'] = geom_end_alg_name(curve['geom_end_alg']) data['end_alg_name'] = end_alg_name(curve['end_alg']) # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant): if is_curve: data['end_lattice'] = (endo['lattice'])[1:-1] if data['end_lattice']: data['end_lattice_statement'] = end_lattice_statement(data['end_lattice']) # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple) data['is_simple_geom'] = endo['is_simple_geom'] data['split_field_label'] = endo['spl_fod_label'] data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs']) data['split_field_statement'] = split_field_statement(data['is_simple_geom'], data['split_field_label'], data['split_field_poly']) # Elliptic curve factors for non-simple Jacobians if not data['is_simple_geom']: data['split_coeffs'] = endo['spl_facs_coeffs'] if 'spl_facs_labels' in endo and len(endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']): data['split_labels'] = endo['spl_facs_labels'] data['split_condnorms'] = endo['spl_facs_condnorms'] data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms']) # Properties self.properties = properties = [('Label', data['label'])] if is_curve: plot_from_db = db.g2c_plots.lucky({"label": curve['label']}) if (plot_from_db is None): self.plot = encode_plot(eqn_list_to_curve_plot(data['min_eqn'], ratpts['rat_pts'] if ratpts else [])) else: self.plot = plot_from_db['plot'] plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(self.plot) properties += [ (None, plot_link), ('Conductor', prop_int_pretty(data['cond'])), ('Discriminant', prop_int_pretty(data['disc'])), ] if data['mw_rank_proved']: properties += [('Mordell-Weil group', data['mw_group'])] else: properties += [('Conductor', prop_int_pretty(data['cond']))] properties += [ ('Sato-Tate group', data['st_group_link']), (r'\(\End(J_{\overline{\Q}}) \otimes \R\)', r'\(%s\)' % data['real_geom_end_alg_name']), (r'\(\End(J_{\overline{\Q}}) \otimes \Q\)', r'\(%s\)' % data['geom_end_alg_name']), (r'\(\End(J) \otimes \Q\)', r'\(%s\)' % data['end_alg_name']), (r'\(\overline{\Q}\)-simple', bool_pretty(data['is_simple_geom'])), (r'\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])), ] # Friends self.friends = friends = [] if is_curve: friends.append(('Genus 2 curve %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))) # first deal with ECs and MFs ecs = [] mfs = [] if 'split_labels' in data: for friend_label in data['split_labels']: if is_curve: ecs.append(("Elliptic curve " + friend_label, url_for_ec(friend_label))) else: ecs.append(("Elliptic curve " + ec_label_class(friend_label), url_for_ec_class(friend_label))) try: cond, iso = ec_label_class(friend_label).split(".") newform_label = ".".join([cond, str(2), 'a', iso]) mfs.append(("Modular form " + newform_label, url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso))) except ValueError: # means the friend isn't an elliptic curve over Q; adding Hilbert/Bianchi modular forms # is dealt with via the L-functions instances below pass ecs.sort(key=lambda x: key_for_numerically_sort(x[0])) mfs.sort(key=lambda x: key_for_numerically_sort(x[0])) # then again EC from lfun instances = [] for elt in db.lfunc_instances.search({'Lhash':data['Lhash'], 'type' : 'ECQP'}, 'url'): instances.extend(elt.split('|')) # and then the other isogeny friends instances.extend([ elt['url'] for elt in get_instances_by_Lhash_and_trace_hash(data["Lhash"], 4, int(data["Lhash"]) ) ]) exclude = {elt[1].rstrip('/').lstrip('/') for elt in self.friends if elt[1]} exclude.add(data['lfunc_url'].lstrip('/L/').rstrip('/')) for elt in ecs + mfs + names_and_urls(instances, exclude=exclude): # because of the splitting we must use G2C specific code add_friend(friends, elt) if is_curve: friends.append(('Twists', url_for(".index_Q", g20=str(data['g2'][0]), g21=str(data['g2'][1]), g22=str(data['g2'][2])))) friends.append(('L-function', data['lfunc_url'])) # Breadcrumbs self.bread = bread = [ ('Genus 2 curves', url_for(".index")), (r'$\Q$', url_for(".index_Q")), ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])), ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1])) ] if is_curve: bread += [ ('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])), ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3])) ] # Title self.title = "Genus 2 " + ("curve " if is_curve else "isogeny class ") + data['label'] # Code snippets (only for curves) if not is_curve: return self.code = code = {} code['show'] = {'sage':'','magma':''} # use default show names f,h = fh = data['min_eqn'] g = simplify_hyperelliptic(fh) code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s));'%(f,h), 'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(f,h) } code['simple_curve'] = {'sage':'X = HyperellipticCurve(R(%s))'%(g), 'magma':'X,pi:= SimplifiedModel(C);' } if data['abs_disc'] % 4096 == 0: ind2 = [a[0] for a in data['bad_lfactors']].index(2) bad2 = data['bad_lfactors'][ind2][1] magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(data['cond'])+',2),R!'+str(bad2)+'>*]' else: magma_cond_option = '' code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);'% magma_cond_option} code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'} code['geom_inv'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]', 'magma':'IgusaClebschInvariants(C); IgusaInvariants(C); G2Invariants(C);'} code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'} code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'} code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'} if ratpts: code['rat_pts'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in ratpts['rat_pts']]) + ']; // minimal model'} code['rat_pts_simp'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in [simplify_hyperelliptic_point(data['min_eqn'], pt) for pt in ratpts['rat_pts']]]) + ']; // simplified model'} code['mw_group'] = {'magma':'MordellWeilGroupGenus2(Jacobian(C));'} code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'} code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'} code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'} code['torsion_subgroup'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}
ec_columns = SearchColumns([ LinkCol("lmfdb_label", "ec.q.lmfdb_label", "Label", lambda label: url_for(".by_ec_label", label=label), default=True, align="center", short_title="LMFDB curve label"), MultiProcessedCol("cremona_label", "ec.q.cremona_label", "Cremona label", ["Clabel", "conductor"], lambda label, conductor: '<a href="%s">%s</a>' % (url_for(".by_ec_label", label=label), label) if conductor < CREMONA_BOUND else " - ", align="center", short_title="Cremona curve label"), LinkCol("lmfdb_iso", "ec.q.lmfdb_label", "Class", lambda label: url_for(".by_ec_label", label=label), default=True, align="center", short_title="LMFDB class label"), MultiProcessedCol("cremona_iso", "ec.q.cremona_label", "Cremona class", ["Ciso", "conductor"], lambda label, conductor: '<a href="%s">%s</a>' % (url_for(".by_ec_label", label=label), label) if conductor < CREMONA_BOUND else " - ", align="center", short_title="Cremona class label"), MathCol("class_size", "ec.isogeny_class", "Class size", align="center", default=lambda info: info.get("class_size") or info.get("optimal") == "on"), MathCol("class_deg", "ec.isogeny_class_degree", "Class degree", align="center", default=lambda info: info.get("class_deg")), ProcessedCol("conductor", "ec.q.conductor", "Conductor", lambda v: web_latex_factored_integer(ZZ(v)), default=True, align="center"), MultiProcessedCol("disc", "ec.discriminant", "Discriminant", ["signD", "absD"], lambda s, a: web_latex_factored_integer(s*ZZ(a)), default=lambda info: info.get("discriminant"), align="center"), MathCol("rank", "ec.rank", "Rank", default=True), ProcessedCol("torsion_structure", "ec.torsion_subgroup", "Torsion", lambda tors: r"\oplus".join([r"\Z/%s\Z"%n for n in tors]) if tors else r"\mathsf{trivial}", default=True, mathmode=True, align="center"), ProcessedCol("geom_end_alg", "ag.endomorphism_algebra", r"$\textrm{End}^0(E_{\overline\Q})$", lambda v: r"$\Q$" if not v else r"$\Q(\sqrt{%d})$"%(integer_squarefree_part(v)), short_title="Qbar-end algebra", align="center", orig="cm"), ProcessedCol("cm_discriminant", "ec.complex_multiplication", "CM", lambda v: "" if v == 0 else v, short_title="CM discriminant", mathmode=True, align="center", default=True, orig="cm"), ProcessedCol("sato_tate_group", "st_group.definition", "Sato-Tate", lambda v: st_display_knowl('1.2.A.1.1a' if v==0 else '1.2.B.2.1a'), short_title="Sato-Tate group", align="center", orig="cm"), CheckCol("semistable", "ec.reduction", "Semistable"), CheckCol("potential_good_reduction", "ec.reduction", "Potentially good"), ProcessedCol("nonmax_primes", "ec.maximal_elladic_galois_rep", r"Nonmax $\ell$", lambda primes: ", ".join([str(p) for p in primes]),
"magma": [ "R<x>:=PolynomialRing(Rationals());", "return [HyperellipticCurve(R![c:c in r[1]],R![c:c in r[2]]):r in data];", ], "sage": [ "R.<x>=PolynomialRing(QQ)", "return [HyperellipticCurve(R(r[0]),R(r[1])) for r in data]", ], "gp": ["[apply(Polrev,c)|c<-data];"], } g2c_columns = SearchColumns([ LinkCol("label", "g2c.label", "Label", url_for_curve_label, default=True), ProcessedLinkCol("class", "g2c.isogeny_class", "Class", lambda v: url_for_isogeny_class_label(class_from_curve_label(v)), class_from_curve_label, default=True, orig="label"), ProcessedCol("cond", "g2c.conductor", "Conductor", lambda v: web_latex(factor(v)), align="center", default=True), MultiProcessedCol("disc", "ec.discriminant", "Discriminant", ["disc_sign", "abs_disc"], lambda s, a: web_latex_factored_integer(s*ZZ(a)), default=lambda info: info.get("abs_disc"), align="center"), MathCol("analytic_rank", "g2c.analytic_rank", "Rank*", default=True), MathCol("two_selmer_rank", "g2c.two_selmer_rank", "2-Selmer rank"), ProcessedCol("torsion_subgroup", "g2c.torsion", "Torsion", lambda tors: r"\oplus".join([r"\Z/%s\Z"%n for n in literal_eval(tors)]) if tors != "[]" else r"\mathsf{trivial}", default=True, mathmode=True, align="center"), ProcessedCol("geom_end_alg", "g2c.geom_end_alg", r"$\textrm{End}^0(J_{\overline\Q})$", lambda v: r"\(%s\)"%geom_end_alg_name(v), short_title="Qbar-end algebra", default=True, align="center"), ProcessedCol("end_alg", "g2c.end_alg", r"$\textrm{End}^0(J)$", lambda v: r"\(%s\)"%end_alg_name(v), short_title="Q-end algebra", align="center"), CheckCol("is_gl2_type", "g2c.gl2type", r"$\GL_2\textsf{-type}$", short_title="GL2-type"), ProcessedCol("st_label", "g2c.st_group", "Sato-Tate", st_display_knowl, short_title='Sato-Tate group', align="center"), CheckCol("is_simple_base", "ag.simple", r"$\Q$-simple", short_title="Q-simple"), CheckCol("is_simple_geom", "ag.geom_simple", r"\(\overline{\Q}\)-simple", short_title="Qbar-simple"), MathCol("aut_grp_tex", "g2c.aut_grp", r"\(\Aut(X)\)", short_title="Q-automorphisms"),