diff --git a/lmfdb/groups/abstract/code.yaml b/lmfdb/groups/abstract/code.yaml index 419415d455..6977858bcd 100644 --- a/lmfdb/groups/abstract/code.yaml +++ b/lmfdb/groups/abstract/code.yaml @@ -41,8 +41,7 @@ GLZ: GLFp: comment: Define the group as a matrix group with coefficients in GLFp magma: G := MatrixGroup< {nFp}, GF({Fp}) | {LFp} >; - gap: G := not yet implemented -# gap: G := Group({LFpsplit}); + gap: G := Group({LFpsplit}); GLZN: comment: Define the group as a matrix group with coefficients in GLZN @@ -55,10 +54,10 @@ GLZq: gap: G := Group({LZqsplit}); -#GLFq: -# comment: Define the group as a matrix group with coefficients in GLFq -# magma: G := MatrixGroup< {nFq}, GL({Fq}) | {LFq} >; -# gap: G := Group({LFqsplit}); +GLFq: + comment: Define the group as a matrix group with coefficients in GLFq + magma: F:=GF({Fq}); al:=PrimitiveElement(F); G := MatrixGroup< {nFq}, F | {LFq} >; + gap: G := Group({LFqsplit}); transitive: comment: Define the group from the transitive group database diff --git a/lmfdb/groups/abstract/web_groups.py b/lmfdb/groups/abstract/web_groups.py index 9be86487bd..075206c2ba 100644 --- a/lmfdb/groups/abstract/web_groups.py +++ b/lmfdb/groups/abstract/web_groups.py @@ -134,12 +134,24 @@ def split_matrix_list_ZN(longList,d, Znfld): longList = [f"ZmodnZObj({x},{Znfld})" for x in longList] return str([longList[i:i+d] for i in range(0,d**2,d)]).replace("'", "") -#not currently in use. Should work if elements of Fp and Fq are given as -#power of mult. generator + + +def split_matrix_list_Fp(longList,d,e): + return [longList[i:i+d]*e for i in range(0,d**2,d)] + + def split_matrix_list_Fq(longList,d, Fqfld): - longList = [f"0*Z({Fqfld})" if x == 0 else "Z({Fqfld})^{x-1}" for x in longList] +# for gap definition of Fq + longList = [f"0*Z({Fqfld})" if x == -1 else f"Z({Fqfld})^{x}" for x in longList] #-1 distinguishes 0 from z^0 return str([longList[i:i+d] for i in range(0,d**2,d)]).replace("'", "") + +def split_matrix_Fq_add_al(longList,d): +# for magma definition of Fq + longList = [0 if x == -1 else 1 if x ==0 else f"al^{x}" for x in longList] + return str([longList[i:i+d] for i in range(0,d**2,d)]).replace("'", "") + + # Functions below are for conjugacy class searches def gp_label_to_cc_data(gp): gp_ord, gp_counter = gp.split(".") @@ -1903,7 +1915,11 @@ def _matrix_coefficient_data(self, rep_type, as_str=False): q = ZZ(rep_data["q"]) if sq_flag: q = q**2 - R = rf"\F_{{{q}}}" if as_str else GF(q) + if as_str: + R = rf"\F_{{{q}}}" + else: + R = GF(q, modulus = "primitive", names=('a',)) + (a,) = R._first_ngens(1) N, k = q.is_prime_power(get_data=True) if k == 1: # Might happen for Lie @@ -1922,6 +1938,10 @@ def decode_as_matrix(self, code, rep_type, as_str=False, LieType=False, ListForm d = rep_data["d"] else: R, N, k, d, rep_type = self._matrix_coefficient_data(rep_type) + if rep_type == "GLFq": + q=N**k + R = GF(q, modulus = "primitive", names=('a',)) + (a,) = R._first_ngens(1) #need a for powers L = ZZ(code).digits(N) def pad(X, m): @@ -1929,16 +1949,37 @@ def pad(X, m): L = pad(L, k * d**2) if rep_type == "GLFq": L = [R(L[i:i+k]) for i in range(0, k*d**2, k)] + L = [l.log(a) if l!= 0 else -1 for l in L] #-1 represents 0, to distinguish from a^0 elif rep_type == "GLZ": shift = (N - 1) // 2 L = [c - shift for c in L] if ListForm: - return L - x = matrix(R, d, d, L) + return L #as ints representing powers of primitive element if GLFq + if rep_type == "GLFq": + x = matrix(ZZ,d,d,L) #giving powers of alpha (primitive element) + else: + x = matrix(R, d, d, L) if as_str: # for projective families, we add "[ ]" if LieType and self.representations["Lie"][0]["family"][0] == "P": return r"\left[" + latex(x) + "\\right]" + if rep_type == "GLFq": #need to customize latex command for GLFq + rs = 'r'*d + st_latex = '\left(\\begin{array}{'+rs+'}' + for i in range(d): + for j in range(d): + if j0: + st_latex =st_latex + '\\alpha^{' +str(L[d*i+j]) + '}' + endstr + elif L[d*i+j] == 0: + st_latex = st_latex+ str(1)+ endstr + else: + st_latex = st_latex+ str(0)+ endstr + st_latex=st_latex +'\end{array}\\right)' + return st_latex return latex(x) return x @@ -2196,10 +2237,7 @@ def representation_line(self, rep_type, skip_head=False): R, N, k, d, _ = self._matrix_coefficient_data(rep_type, as_str=True) gens = ", ".join(self.decode_as_matrix(g, rep_type, as_str=True) for g in rdata["gens"]) gens = fr"$\left\langle {gens} \right\rangle \subseteq \GL_{{{d}}}({R})$" - if rep_type == "GLFq": - code_cmd = "" - else: - code_cmd = self.create_snippet(rep_type) + code_cmd = self.create_snippet(rep_type) if skip_head: return f'{gens}{code_cmd}' else: @@ -2639,10 +2677,20 @@ def create_snippet(self,item): else: # not currrently used in groups lines = code[item][L] prompt = code['prompt'][L] if 'prompt' in code and L in code['prompt'] else L - class_str = " ".join([L,'nodisplay','code','codebox']) + class_str = " ".join([L,'nodisplay','codebox']) col_span_val = '"6"' for line in lines: - snippet_str = snippet_str + f'
{prompt}: {line}
 
' + snippet_str += f""" + + +
+ Copy content + {prompt}: {line} +
 
+
+ + +""" return snippet_str @cached_method @@ -2679,10 +2727,10 @@ def code_snippets(self): nFp = self.representations["GLFp"]["d"] Fp = self.representations["GLFp"]["p"] LFp = [self.decode_as_matrix(g, "GLFp", ListForm=True) for g in self.representations["GLFp"]["gens"]] -# LFpsplit = "[" + ",".join([split_matrix_list_Fq(self.decode_as_matrix(g, "GLFp", ListForm=True), nFp, Fp) for g in self.representations["GLFp"]["gens"]]) +"]" + e = libgap.One(GF(Fp)) + LFpsplit = [split_matrix_list_Fp(A,nFp,e) for A in LFp] else: - nFp, Fp, LFp = None, None, None - #nFp, Fp, LFp, LFpsplit = None, None, None, None + nFp, Fp, LFp, LFpsplit = None, None, None, None if "GLZN" in self.representations: nZN = self.representations["GLZN"]["d"] N = self.representations["GLZN"]["p"] @@ -2698,22 +2746,22 @@ def code_snippets(self): else: nZq, Zq, LZq, LZqsplit = None, None, None, None # add below for GLFq implementation -# if "GLFq" in self.representations: -# nFq = self.representations["GLFq"]["d"] -# Fq = self.representations["GLFq"]["q"] -# LFq = [self.decode_as_matrix(g, "GLFq", ListForm=True) for g in self.representations["GLFq"]["gens"]] -# LFqsplit = "[" + ",".join([split_matrix_list_Fq(self.decode_as_matrix(g, "GLFq", ListForm=True), nFq, Fq) for g in self.representations["GLFq"]["gens"]]) +"]" -# else: -# nFq, Fq, LFq, LFqsplit = None, None, None, None + if "GLFq" in self.representations: + nFq = self.representations["GLFq"]["d"] + Fq = self.representations["GLFq"]["q"] + LFq = ",".join([split_matrix_Fq_add_al(self.decode_as_matrix(g, "GLFq", ListForm=True), nFq ) for g in self.representations["GLFq"]["gens"]]) + LFqsplit = "[" + ",".join([split_matrix_list_Fq(self.decode_as_matrix(g, "GLFq", ListForm=True), nFq, Fq) for g in self.representations["GLFq"]["gens"]]) +"]" + else: + nFq, Fq, LFq, LFqsplit = None, None, None, None data = {'gens' : gens, 'pccodelist': pccodelist, 'pccode': pccode, 'ordgp': ordgp, 'used_gens': used_gens, 'gap_assign': gap_assign, 'magma_assign': magma_assign, 'deg': deg, 'perms' : perms, - 'nZ': nZ, 'nFp': nFp, 'nZN': nZN, 'nZq': nZq, #'nFq': nFq, - 'Fp': Fp, 'N': N, 'Zq': Zq, #'Fq': Fq, - 'LZ': LZ, 'LFp': LFp, 'LZN': LZN, 'LZq': LZq, #'LFq': LFq, + 'nZ': nZ, 'nFp': nFp, 'nZN': nZN, 'nZq': nZq, 'nFq': nFq, + 'Fp': Fp, 'N': N, 'Zq': Zq, 'Fq': Fq, + 'LZ': LZ, 'LFp': LFp, 'LZN': LZN, 'LZq': LZq, 'LFq': LFq, 'LZsplit': LZsplit, 'LZNsplit': LZNsplit, 'LZqsplit': LZqsplit, - # 'LFpsplit': LFpsplit, 'LFqsplit': LFqsplit, # add for GLFq GAP + 'LFpsplit': LFpsplit, 'LFqsplit': LFqsplit, # add for GLFq GAP } for prop in code: for lang in code['prompt']: diff --git a/lmfdb/static/raw_typeset.js b/lmfdb/static/raw_typeset.js index d9da0f6c6e..63b6a31b93 100644 --- a/lmfdb/static/raw_typeset.js +++ b/lmfdb/static/raw_typeset.js @@ -86,8 +86,15 @@ function copyTextOf(elt) { ); } +function copySibling(elt, filter) { + copyTextOf($(elt).parent().children(filter).first()); +} + function copyrawcontainer(elt) { - copyTextOf($(elt).parent().children("textarea.raw-container").first()); + copySibling(elt, "textarea.raw-container"); +} +function copycode(elt) { + copySibling(elt, "span.code"); } diff --git a/lmfdb/templates/style.css b/lmfdb/templates/style.css index e3df793574..df0d33d011 100644 --- a/lmfdb/templates/style.css +++ b/lmfdb/templates/style.css @@ -528,12 +528,23 @@ body.intro #sidebar a.intro { background: {{ color.sidebar_bkg_highlight }}; } height: 0px; } -.code { +.code, .prompt { font-family: monospace; + white-space: pre; +} + +.code { margin: 2px; margin-right: 20px; + margin-left: 0px; } +.prompt { + margin: 2px; + margin-right: 0px; +} + + .nodisplay { display: None; } @@ -1569,7 +1580,6 @@ div.codebox { border-radius: 5px; background-color: {{color.knowl_background}}; box-shadow: 3px 3px 3px {{color.knowl_shadow}}; - white-space: pre; }