Skip to content

Commit d4d93de

Browse files
authored
Merge pull request #6841 from LMFDB/copilot/fix-signature-display-number-fields
Change number field signature display from [r1, r2] to (r1, r2)
2 parents 8fae6da + 1f2c5ed commit d4d93de

File tree

4 files changed

+30
-16
lines changed

4 files changed

+30
-16
lines changed

lmfdb/number_fields/number_field.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ def statistics():
326326
for r2 in range(12)]
327327
nsig = [[{'cnt': comma(nsig[nn][r2]),
328328
'prop': format_percentage(nsig[nn][r2], n[nn]),
329-
'query': url_for(".number_field_render_webpage")+'?degree=%d&signature=[%d,%d]' % (nn+1,nn+1-2*r2,r2)} for r2 in range(len(nsig[nn]))] for nn in range(len(nsig))]
329+
'query': url_for(".number_field_render_webpage")+'?degree=%d&signature=(%d,%d)' % (nn+1,nn+1-2*r2,r2)} for r2 in range(len(nsig[nn]))] for nn in range(len(nsig))]
330330
h = [{'cnt': comma(h[j]),
331331
'prop': format_percentage(h[j], has_h),
332332
'label': '$10^{' + str(j - 1) + r'}<h\leq 10^{' + str(j) + '}$',
@@ -342,7 +342,7 @@ def statistics():
342342
sigclass1 = [[{'cnt': comma(sigclass1.get((nn+1,r2),0)),
343343
'prop': format_percentage(sigclass1.get((nn+1,r2),0), sighasclass.get((nn+1,r2),0)) if sighasclass.get((nn+1,r2),0) > 0 else 0,
344344
'show': sighasclass.get((nn+1,r2),0) > 0,
345-
'query': url_for(".number_field_render_webpage")+'?degree=%d&signature=[%d,%d]&class_number=1' % (nn + 1, nn + 1 - 2*r2, r2)}
345+
'query': url_for(".number_field_render_webpage")+'?degree=%d&signature=(%d,%d)&class_number=1' % (nn + 1, nn + 1 - 2*r2, r2)}
346346
for r2 in range(len(nsig[nn]))] for nn in range(len(nsig))]
347347

348348
n = [{'cnt': comma(n[nn]),
@@ -373,8 +373,8 @@ def statistics():
373373
@nf_page.route("/")
374374
def number_field_render_webpage():
375375
info = to_dict(request.args, search_array=NFSearchArray())
376-
sig_list = sum([[[d - 2 * r2, r2] for r2 in range(
377-
1 + (d // 2))] for d in range(1, 11)], []) + sum([[[d, 0]] for d in range(11, 21)], [])
376+
sig_list = sum([[(d - 2 * r2, r2) for r2 in range(
377+
1 + (d // 2))] for d in range(1, 11)], []) + sum([[(d, 0)] for d in range(11, 21)], [])
378378
sig_list = [str(s).replace(' ','') for s in sig_list[:16]]
379379
if not request.args:
380380
init_nf_count()
@@ -465,7 +465,7 @@ def render_field_webpage(args):
465465
data['class_group'] = nf.class_group()
466466
data['narrow_class_group'] = nf.narrow_class_group()
467467
data['class_group_invs'] = nf.class_group_invariants()
468-
data['signature'] = nf.signature()
468+
data['signature'] = nf.signature_display()
469469
data['coefficients'] = nf.coeffs()
470470
nf.make_code_snippets()
471471
D = nf.disc()
@@ -850,7 +850,7 @@ def number_field_jump(info):
850850
lambda label: '<a href="%s">%s</a>' % (url_for_label(label), nf_label_pretty(label))),
851851
PolynomialCol("coeffs", "nf.defining_polynomial", "Polynomial"),
852852
MathCol("degree", "nf.degree", "Degree", align="center", default=False),
853-
MultiProcessedCol("signature", "nf.signature", "Signature", ["r2", "degree"], lambda r2, degree: '[%s,%s]' % (degree - 2*r2, r2 ), apply_download=lambda r2, degree: [degree - 2*r2, r2], align="center", default=False),
853+
MultiProcessedCol("signature", "nf.signature", "Signature", ["r2", "degree"], lambda r2, degree: '(%s, %s)' % (degree - 2*r2, r2 ), apply_download=lambda r2, degree: [degree - 2*r2, r2], align="center", default=False),
854854
DiscriminantCol("disc", "nf.discriminant", "Discriminant", ['disc_sign', 'disc_abs'], func=None, align="left"),
855855
MathCol("num_ram", "nf.ramified_primes", "Ram. prime count", short_title="ramified prime count", default=False),
856856
MathCol("rd", "nf.root_discriminant", "Root discriminant", default=False),
@@ -1185,7 +1185,7 @@ def __init__(self):
11851185
name="signature",
11861186
label="Signature",
11871187
knowl="nf.signature",
1188-
example="[1,1]")
1188+
example="(1,1)")
11891189
discriminant = TextBox(
11901190
name="discriminant",
11911191
label="Discriminant",

lmfdb/number_fields/test_numberfield.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,17 @@ def test_statistics(self):
7474
self.check_args('/NumberField/stats', 'Class number')
7575

7676
def test_signature_search(self):
77+
# Square brackets
7778
self.check_args('/NumberField/?start=0&degree=6&signature=%5B0%2C3%5D&count=100', '6.0.61131.1')
7879
self.check_args('/NumberField/?start=0&degree=7&signature=%5B3%2C2%5D&count=100', '7.3.1420409.1')
80+
# Round brackets
81+
self.check_args('/NumberField/?start=0&degree=6&signature=%280%2C3%29&count=100', '6.0.61131.1')
82+
self.check_args('/NumberField/?start=0&degree=7&signature=%283%2C2%29&count=100', '7.3.1420409.1')
83+
84+
def test_signature_display(self):
85+
# Verify that signatures are displayed with parentheses, not square brackets
86+
self.check_args('/NumberField/6.0.61131.1', '(0, 3)') # degree 6 field with signature (0, 3)
87+
self.check_args('/NumberField/7.3.1420409.1', '(3, 2)') # degree 7 field with signature (3, 2)
7988

8089
def test_relative_class_number(self):
8190
self.check_args('/NumberField/4.0.1327873600.2', '2108')

lmfdb/number_fields/web_number_field.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,11 @@ def signature(self):
559559
n = self._data['degree']
560560
return [n-2*r2, r2]
561561

562+
def signature_display(self):
563+
"""Return signature formatted for display with parentheses."""
564+
r1, r2 = self.signature()
565+
return '(%s, %s)' % (r1, r2)
566+
562567
def degree(self):
563568
return self._data['degree']
564569

lmfdb/utils/search_parsing.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
LIST_RE = re.compile(r"^(\d+|(\d*-(\d+)?))(,(\d+|(\d*-(\d+)?)))*$")
1919
FLOAT_STR = r"(-?(((\d+([.]\d*)?)|([.]\d+))(e[-+]?\d+)?)|(-?\d+/\d+))"
2020
LIST_FLOAT_RE = re.compile(r"^({0}|{0}-|{0}-{0})(,({0}|{0}-|{0}-{0}))*$".format(FLOAT_STR))
21-
BRACKETED_POSINT_RE = re.compile(r"^\[\]|\[0*[1-9]\d*(,0*[1-9]\d*)*\]$")
22-
BRACKETED_NN_RE = re.compile(r"^\[\]|\[\d+(,\d+)*\]$")
23-
BRACKETED_RAT_RE = re.compile(r"^\[\]|\[-?(\d+|\d+/\d+)(,-?(\d+|\d+/\d+))*\]$")
21+
BRACKETED_POSINT_RE = re.compile(r"^[\[(][\])]|[\[(]0*[1-9]\d*(,0*[1-9]\d*)*[\])]$")
22+
BRACKETED_NN_RE = re.compile(r"^[\[(][\])]|[\[(]\d+(,\d+)*[\])]$")
23+
BRACKETED_RAT_RE = re.compile(r"^[\[(][\])]|[\[(]-?(\d+|\d+/\d+)(,-?(\d+|\d+/\d+))*[\])]$")
2424
QQ_RE = re.compile(r"^-?\d+(/\d+)?$")
2525
QQ_LIST_RE = re.compile(r"^-?\d+(/\d+)?(,-?\d+(/\d+)?)*$")
2626
# Single non-negative rational, allowing decimals, used in parse_range2rat
@@ -896,7 +896,7 @@ def parse_bracketed_posints(
896896
not myregex.match(inp)
897897
or (maxlength is not None and inp.count(",") > maxlength - 1)
898898
or (exactlength is not None and inp.count(",") != exactlength - 1)
899-
or (exactlength is not None and inp == "[]" and exactlength > 0)
899+
or (exactlength is not None and inp in ("[]", "()") and exactlength > 0)
900900
):
901901
if exactlength == 2:
902902
lstr = "pair of positive integers"
@@ -921,9 +921,9 @@ def parse_bracketed_posints(
921921
else:
922922
lstr = "list of positive integers"
923923
example = "[1,2,3] or [5,6]"
924-
raise SearchParsingError("It needs to be a %s in square brackets, such as %s." % (lstr, example))
924+
raise SearchParsingError("It needs to be a %s in square or round brackets, such as %s." % (lstr, example))
925925
else:
926-
if (inp == "[]"): # fixes bug in the code below (split never returns an empty list)
926+
if inp in ("[]", "()"): # fixes bug in the code below (split never returns an empty list)
927927
if split:
928928
query[qfield] = []
929929
else:
@@ -995,7 +995,7 @@ def parse_bracketed_rats(
995995
or (maxlength is not None and inp.count(",") > maxlength - 1)
996996
or (minlength is not None and inp.count(",") < minlength - 1)
997997
or (exactlength is not None and inp.count(",") != exactlength - 1)
998-
or (exactlength is not None and inp == "[]" and exactlength > 0)
998+
or (exactlength is not None and inp in ("[]", "()") and exactlength > 0)
999999
):
10001000
if exactlength == 2:
10011001
lstr = "pair of rational numbers"
@@ -1034,9 +1034,9 @@ def parse_bracketed_rats(
10341034
else:
10351035
lstr = "list of rational numbers"
10361036
example = "[1/7,2,3] or [5,6/71]"
1037-
raise SearchParsingError("It needs to be a %s in square brackets, such as %s." % (lstr, example))
1037+
raise SearchParsingError("It needs to be a %s in square or round brackets, such as %s." % (lstr, example))
10381038
else:
1039-
if inp == "[]": # fixes bug in the code below (split never returns an empty list)
1039+
if inp in ("[]", "()"): # fixes bug in the code below (split never returns an empty list)
10401040
if split:
10411041
query[qfield] = []
10421042
else:

0 commit comments

Comments
 (0)