We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Some Dirichlet character pages are failing to load
The page https://www.lmfdb.org/Character/Dirichlet/947/934 is timing out.  Some similar pages such as https://www.lmfdb.org/Character/Dirichlet/947/933 and https://www.lmfdb.org/Character/Dirichlet/947/935 work but are slow too load and the knowl for the fixed field does not work.  I believe this is due to some of the recent changes that were made #4231 -- @BarinderBanwait can you take a look at this?

Below is the trace back from the page that is failing to load.  the failure is inside the call to "zeta_order" on line 156 of https://github.com/LMFDB/lmfdb/blob/master/lmfdb/characters/TinyConrey.py.  I don't think that call should be taking any time, but if Sage is doing something silly we should just compute zeta_order directly.  I confess it's not clear to me why we are using Sage DirichletGroup and Sage characters at all (it appears they are being used in just 2 places).

```
Traceback (most recent call last):
  File "/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/lmfdb/lmfdb-git-web/lmfdb/characters/main.py", line 367, in render_Dirichletwebpage
    webchar = make_webchar(args)
  File "/home/lmfdb/lmfdb-git-web/lmfdb/characters/main.py", line 313, in make_webchar
    return WebDBDirichletCharacter(**args)
  File "/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py", line 925, in __init__
    WebDBDirichlet.__init__(self, **kwargs)
  File "/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py", line 568, in __init__
    self._compute()
  File "/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py", line 575, in _compute
    self._populate_from_db()
  File "/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py", line 589, in _populate_from_db
    self._set_generators_and_genvalues(values_data)
  File "/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py", line 615, in _set_generators_and_genvalues
    self._genvalues_for_code = get_sage_genvalues(self.modulus, self.order, vals, self.chi.sage_zeta_order(self.order))
  File "/home/lmfdb/lmfdb-git-web/lmfdb/characters/TinyConrey.py", line 156, in sage_zeta_order
    return DirichletGroup(self.modulus, base_ring=CyclotomicField(order)).zeta_order()
  File "sage/misc/cachefunc.pyx", line 2310, in sage.misc.cachefunc.CachedMethodCallerNoArgs.__call__ (build/cythonized/sage/misc/cachefunc.c:12712)
    self.cache = f(self._instance)
  File "/home/sage/sage-9.1/local/lib/python3.7/site-packages/sage/modular/dirichlet.py", line 2880, in zeta_order
    order = self.zeta().multiplicative_order()
  File "sage/rings/number_field/number_field_element.pyx", line 3229, in sage.rings.number_field.number_field_element.NumberFieldElement.multiplicative_order (build/cythonized/sage/rings/number_field/number_field_element.cpp:27976)
    elif not (self.is_integral() and self.norm().is_one()):
  File "sage/rings/number_field/number_field_element.pyx", line 3576, in sage.rings.number_field.number_field_element.NumberFieldElement.is_integral (build/cythonized/sage/rings/number_field/number_field_element.cpp:30234)
    return all(a in ZZ for a in self.absolute_minpoly())
  File "sage/rings/number_field/number_field_element.pyx", line 3576, in genexpr (build/cythonized/sage/rings/number_field/number_field_element.cpp:30109)
    return all(a in ZZ for a in self.absolute_minpoly())
  File "sage/rings/number_field/number_field_element.pyx", line 4488, in sage.rings.number_field.number_field_element.NumberFieldElement_absolute.absolute_minpoly (build/cythonized/sage/rings/number_field/number_field_element.cpp:37507)
    return self.minpoly(var)
  File "sage/rings/number_field/number_field_element.pyx", line 4576, in sage.rings.number_field.number_field_element.NumberFieldElement_absolute.minpoly (build/cythonized/sage/rings/number_field/number_field_element.cpp:38144)
    return self.charpoly(var, algorithm).radical() # square free part of charpoly
  File "sage/rings/number_field/number_field_element.pyx", line 4543, in sage.rings.number_field.number_field_element.NumberFieldElement_absolute.charpoly (build/cythonized/sage/rings/number_field/number_field_element.cpp:37945)
    return R(self.matrix().charpoly())
  File "sage/matrix/matrix_rational_dense.pyx", line 1034, in sage.matrix.matrix_rational_dense.Matrix_rational_dense.charpoly (build/cythonized/sage/matrix/matrix_rational_dense.c:10660)
    f = A.charpoly(var, algorithm=algorithm)
  File "sage/matrix/matrix_integer_dense.pyx", line 1336, in sage.matrix.matrix_integer_dense.Matrix_integer_dense.charpoly (build/cythonized/sage/matrix/matrix_integer_dense.c:12941)
    sig_on()
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lmfdb/characters/TinyConrey.py`
Content:
```
1 from sage.all import (gcd, Mod, Integer, Integers, Rational, pari, Pari,
2                       DirichletGroup, CyclotomicField, euler_phi)
3 from sage.misc.cachefunc import cached_method
4 from sage.modular.dirichlet import DirichletCharacter
5 
6 def symbol_numerator(cond, parity):
7     # Reference: Sect. 9.3, Montgomery, Hugh L; Vaughan, Robert C. (2007).
8     # Multiplicative number theory. I. Classical theory. Cambridge Studies in
9     # Advanced Mathematics 97
10     #
11     # Let F = Q(\sqrt(d)) with d a non zero squarefree integer then a real
12     # Dirichlet character \chi(n) can be represented as a Kronecker symbol
13     # (m / n) where { m  = d if # d = 1 mod 4 else m = 4d if d = 2,3 (mod) 4 }
14     # and m is the discriminant of F. The conductor of \chi is |m|.
15     #
16     # symbol_numerator returns the appropriate Kronecker symbol depending on
17     # the conductor of \chi.
18     m = cond
19     if cond % 2 == 1:
20         if cond % 4 == 3:
21             m = -cond
22     elif cond % 8 == 4:
23         # Fixed cond % 16 == 4 and cond % 16 == 12 were switched in the
24         # previous version of the code.
25         #
26         # Let d be a non zero squarefree integer. If d  = 2,3 (mod) 4 and if
27         # cond = 4d = 4 ( 4n + 2) or 4 (4n + 3) = 16 n + 8 or 16n + 12 then we
28         # set m = cond.  On the other hand if d = 1 (mod) 4 and cond = 4d = 4
29         # (4n +1) = 16n + 4 then we set m = -cond.
30         if cond % 16 == 4:
31             m = -cond
32     elif cond % 16 == 8:
33         if parity == 1:
34             m = -cond
35     else:
36         return None
37     return m
38 
39 
40 def kronecker_symbol(m):
41     if m:
42         return r'\(\displaystyle\left(\frac{%s}{\bullet}\right)\)' % (m)
43     else:
44         return None
45 
46 ###############################################################################
47 ## Conrey character with no call to Jonathan's code
48 ## in order to handle big moduli
49 ##
50 
51 def get_sage_genvalues(modulus, order, genvalues, zeta_order):
52         """
53         Helper method for computing correct genvalues when constructing
54         the sage character
55         """
56         phi_mod = euler_phi(modulus)
57         exponent_factor = phi_mod / order
58         genvalues_exponent = [x * exponent_factor for x in genvalues]
59         return [x * zeta_order / phi_mod for x in genvalues_exponent]
60 
61 
62 class PariConreyGroup(object):
63 
64     def __init__(self, modulus):
65         self.modulus = int(modulus)
66         self.G = Pari("znstar({},1)".format(modulus))
67 
68     def gens(self):
69         return Integers(self.modulus).unit_gens()
70 
71     def invariants(self):
72         return pari("znstar({},1).cyc".format(self.modulus))
73 
74 
75 class ConreyCharacter(object):
76     """
77     tiny implementation on Conrey index only
78     """
79 
80     def __init__(self, modulus, number):
81         assert gcd(modulus, number)==1
82         self.modulus = Integer(modulus)
83         self.number = Integer(number)
84         self.G = Pari("znstar({},1)".format(modulus))
85         self.chi_pari = pari("znconreylog(%s,%d)"%(self.G,self.number))
86         self.chi_0 = None
87         self.indlabel = None
88 
89     @property
90     def texname(self):
91         from lmfdb.characters.web_character import WebDirichlet
92         return WebDirichlet.char2tex(self.modulus, self.number)
93 
94     @cached_method
95     def modfactor(self):
96         return self.modulus.factor()
97 
98     @cached_method
99     def conductor(self):
100         B = pari("znconreyconductor(%s,%s,&chi0)"%(self.G, self.chi_pari))
101         if B.type() == 't_INT':
102             # means chi is primitive
103             self.chi_0 = self.chi_pari
104             self.indlabel = self.number
105             return int(B)
106         else:
107             self.chi_0 = pari("chi0")
108             G_0 = Pari("znstar({},1)".format(B))
109             self.indlabel = int(pari("znconreyexp(%s,%s)"%(G_0,self.chi_0)))
110             return int(B[0])
111 
112     def is_primitive(self):
113         return self.conductor() == self.modulus
114 
115     @cached_method
116     def parity(self):
117         number = self.number
118         par = 0
119         for p,e in self.modfactor():
120             if p == 2:
121                 if number % 4 == 3:
122                     par = 1 - par
123             else:
124                 phi2 = (p-1)/Integer(2) * p **(e-1)
125                 if Mod(number, p ** e)**phi2 != 1:
126                     par = 1 - par
127         return par
128 
129     def is_odd(self):
130         return self.parity() == 1
131 
132     def is_even(self):
133         return self.parity() == 0
134 
135     @cached_method
136     def multiplicative_order(self):
137         return Mod(self.number, self.modulus).multiplicative_order()
138 
139     @property
140     def order(self):
141         return self.multiplicative_order()
142 
143     @cached_method
144     def kronecker_symbol(self):
145         c = self.conductor()
146         p = self.parity()
147         return kronecker_symbol(symbol_numerator(c, p))
148 
149     def conreyangle(self,x):
150         return Rational(pari("chareval(%s,znconreylog(%s,%d),%d)"%(self.G,self.G,self.number,x)))
151 
152     def gauss_sum_numerical(self, a):
153         return pari("znchargauss(%s,%s,a=%d)"%(self.G,self.chi_pari,a))
154 
155     def sage_zeta_order(self, order):
156         return DirichletGroup(self.modulus, base_ring=CyclotomicField(order)).zeta_order()
157 
158     def sage_character(self, order, genvalues):
159         H = DirichletGroup(self.modulus, base_ring=CyclotomicField(order))
160         M = H._module
161         order_corrected_genvalues = get_sage_genvalues(self.modulus, order, genvalues, H.zeta_order())
162         return DirichletCharacter(H,M(order_corrected_genvalues))
163
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lmfdb/characters/TinyConrey.py b/lmfdb/characters/TinyConrey.py
--- a/lmfdb/characters/TinyConrey.py
+++ b/lmfdb/characters/TinyConrey.py
@@ -1,5 +1,5 @@
 from sage.all import (gcd, Mod, Integer, Integers, Rational, pari, Pari,
-                      DirichletGroup, CyclotomicField, euler_phi)
+                      DirichletGroup, CyclotomicField, euler_phi, lcm)
 from sage.misc.cachefunc import cached_method
 from sage.modular.dirichlet import DirichletCharacter
 
@@ -153,7 +153,7 @@
         return pari("znchargauss(%s,%s,a=%d)"%(self.G,self.chi_pari,a))
 
     def sage_zeta_order(self, order):
-        return DirichletGroup(self.modulus, base_ring=CyclotomicField(order)).zeta_order()
+        return 1 if self.modulus <= 2 else lcm(2,order)
 
     def sage_character(self, order, genvalues):
         H = DirichletGroup(self.modulus, base_ring=CyclotomicField(order))

{"golden_diff": "diff --git a/lmfdb/characters/TinyConrey.py b/lmfdb/characters/TinyConrey.py\n--- a/lmfdb/characters/TinyConrey.py\n+++ b/lmfdb/characters/TinyConrey.py\n@@ -1,5 +1,5 @@\n from sage.all import (gcd, Mod, Integer, Integers, Rational, pari, Pari,\n-                      DirichletGroup, CyclotomicField, euler_phi)\n+                      DirichletGroup, CyclotomicField, euler_phi, lcm)\n from sage.misc.cachefunc import cached_method\n from sage.modular.dirichlet import DirichletCharacter\n \n@@ -153,7 +153,7 @@\n         return pari(\"znchargauss(%s,%s,a=%d)\"%(self.G,self.chi_pari,a))\n \n     def sage_zeta_order(self, order):\n-        return DirichletGroup(self.modulus, base_ring=CyclotomicField(order)).zeta_order()\n+        return 1 if self.modulus <= 2 else lcm(2,order)\n \n     def sage_character(self, order, genvalues):\n         H = DirichletGroup(self.modulus, base_ring=CyclotomicField(order))\n", "issue": "Some Dirichlet character pages are failing to load\nThe page https://www.lmfdb.org/Character/Dirichlet/947/934 is timing out.  Some similar pages such as https://www.lmfdb.org/Character/Dirichlet/947/933 and https://www.lmfdb.org/Character/Dirichlet/947/935 work but are slow too load and the knowl for the fixed field does not work.  I believe this is due to some of the recent changes that were made #4231 -- @BarinderBanwait can you take a look at this?\r\n\r\nBelow is the trace back from the page that is failing to load.  the failure is inside the call to \"zeta_order\" on line 156 of https://github.com/LMFDB/lmfdb/blob/master/lmfdb/characters/TinyConrey.py.  I don't think that call should be taking any time, but if Sage is doing something silly we should just compute zeta_order directly.  I confess it's not clear to me why we are using Sage DirichletGroup and Sage characters at all (it appears they are being used in just 2 places).\r\n\r\n```\r\nTraceback (most recent call last):\r\n  File \"/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py\", line 2447, in wsgi_app\r\n    response = self.full_dispatch_request()\r\n  File \"/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py\", line 1952, in full_dispatch_request\r\n    rv = self.handle_user_exception(e)\r\n  File \"/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py\", line 1821, in handle_user_exception\r\n    reraise(exc_type, exc_value, tb)\r\n  File \"/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/_compat.py\", line 39, in reraise\r\n    raise value\r\n  File \"/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py\", line 1950, in full_dispatch_request\r\n    rv = self.dispatch_request()\r\n  File \"/home/sage/sage-9.1/local/lib/python3.7/site-packages/flask/app.py\", line 1936, in dispatch_request\r\n    return self.view_functions[rule.endpoint](**req.view_args)\r\n  File \"/home/lmfdb/lmfdb-git-web/lmfdb/characters/main.py\", line 367, in render_Dirichletwebpage\r\n    webchar = make_webchar(args)\r\n  File \"/home/lmfdb/lmfdb-git-web/lmfdb/characters/main.py\", line 313, in make_webchar\r\n    return WebDBDirichletCharacter(**args)\r\n  File \"/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py\", line 925, in __init__\r\n    WebDBDirichlet.__init__(self, **kwargs)\r\n  File \"/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py\", line 568, in __init__\r\n    self._compute()\r\n  File \"/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py\", line 575, in _compute\r\n    self._populate_from_db()\r\n  File \"/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py\", line 589, in _populate_from_db\r\n    self._set_generators_and_genvalues(values_data)\r\n  File \"/home/lmfdb/lmfdb-git-web/lmfdb/characters/web_character.py\", line 615, in _set_generators_and_genvalues\r\n    self._genvalues_for_code = get_sage_genvalues(self.modulus, self.order, vals, self.chi.sage_zeta_order(self.order))\r\n  File \"/home/lmfdb/lmfdb-git-web/lmfdb/characters/TinyConrey.py\", line 156, in sage_zeta_order\r\n    return DirichletGroup(self.modulus, base_ring=CyclotomicField(order)).zeta_order()\r\n  File \"sage/misc/cachefunc.pyx\", line 2310, in sage.misc.cachefunc.CachedMethodCallerNoArgs.__call__ (build/cythonized/sage/misc/cachefunc.c:12712)\r\n    self.cache = f(self._instance)\r\n  File \"/home/sage/sage-9.1/local/lib/python3.7/site-packages/sage/modular/dirichlet.py\", line 2880, in zeta_order\r\n    order = self.zeta().multiplicative_order()\r\n  File \"sage/rings/number_field/number_field_element.pyx\", line 3229, in sage.rings.number_field.number_field_element.NumberFieldElement.multiplicative_order (build/cythonized/sage/rings/number_field/number_field_element.cpp:27976)\r\n    elif not (self.is_integral() and self.norm().is_one()):\r\n  File \"sage/rings/number_field/number_field_element.pyx\", line 3576, in sage.rings.number_field.number_field_element.NumberFieldElement.is_integral (build/cythonized/sage/rings/number_field/number_field_element.cpp:30234)\r\n    return all(a in ZZ for a in self.absolute_minpoly())\r\n  File \"sage/rings/number_field/number_field_element.pyx\", line 3576, in genexpr (build/cythonized/sage/rings/number_field/number_field_element.cpp:30109)\r\n    return all(a in ZZ for a in self.absolute_minpoly())\r\n  File \"sage/rings/number_field/number_field_element.pyx\", line 4488, in sage.rings.number_field.number_field_element.NumberFieldElement_absolute.absolute_minpoly (build/cythonized/sage/rings/number_field/number_field_element.cpp:37507)\r\n    return self.minpoly(var)\r\n  File \"sage/rings/number_field/number_field_element.pyx\", line 4576, in sage.rings.number_field.number_field_element.NumberFieldElement_absolute.minpoly (build/cythonized/sage/rings/number_field/number_field_element.cpp:38144)\r\n    return self.charpoly(var, algorithm).radical() # square free part of charpoly\r\n  File \"sage/rings/number_field/number_field_element.pyx\", line 4543, in sage.rings.number_field.number_field_element.NumberFieldElement_absolute.charpoly (build/cythonized/sage/rings/number_field/number_field_element.cpp:37945)\r\n    return R(self.matrix().charpoly())\r\n  File \"sage/matrix/matrix_rational_dense.pyx\", line 1034, in sage.matrix.matrix_rational_dense.Matrix_rational_dense.charpoly (build/cythonized/sage/matrix/matrix_rational_dense.c:10660)\r\n    f = A.charpoly(var, algorithm=algorithm)\r\n  File \"sage/matrix/matrix_integer_dense.pyx\", line 1336, in sage.matrix.matrix_integer_dense.Matrix_integer_dense.charpoly (build/cythonized/sage/matrix/matrix_integer_dense.c:12941)\r\n    sig_on()\r\n```\n", "before_files": [{"content": "from sage.all import (gcd, Mod, Integer, Integers, Rational, pari, Pari,\n                      DirichletGroup, CyclotomicField, euler_phi)\nfrom sage.misc.cachefunc import cached_method\nfrom sage.modular.dirichlet import DirichletCharacter\n\ndef symbol_numerator(cond, parity):\n    # Reference: Sect. 9.3, Montgomery, Hugh L; Vaughan, Robert C. (2007).\n    # Multiplicative number theory. I. Classical theory. Cambridge Studies in\n    # Advanced Mathematics 97\n    #\n    # Let F = Q(\\sqrt(d)) with d a non zero squarefree integer then a real\n    # Dirichlet character \\chi(n) can be represented as a Kronecker symbol\n    # (m / n) where { m  = d if # d = 1 mod 4 else m = 4d if d = 2,3 (mod) 4 }\n    # and m is the discriminant of F. The conductor of \\chi is |m|.\n    #\n    # symbol_numerator returns the appropriate Kronecker symbol depending on\n    # the conductor of \\chi.\n    m = cond\n    if cond % 2 == 1:\n        if cond % 4 == 3:\n            m = -cond\n    elif cond % 8 == 4:\n        # Fixed cond % 16 == 4 and cond % 16 == 12 were switched in the\n        # previous version of the code.\n        #\n        # Let d be a non zero squarefree integer. If d  = 2,3 (mod) 4 and if\n        # cond = 4d = 4 ( 4n + 2) or 4 (4n + 3) = 16 n + 8 or 16n + 12 then we\n        # set m = cond.  On the other hand if d = 1 (mod) 4 and cond = 4d = 4\n        # (4n +1) = 16n + 4 then we set m = -cond.\n        if cond % 16 == 4:\n            m = -cond\n    elif cond % 16 == 8:\n        if parity == 1:\n            m = -cond\n    else:\n        return None\n    return m\n\n\ndef kronecker_symbol(m):\n    if m:\n        return r'\\(\\displaystyle\\left(\\frac{%s}{\\bullet}\\right)\\)' % (m)\n    else:\n        return None\n\n###############################################################################\n## Conrey character with no call to Jonathan's code\n## in order to handle big moduli\n##\n\ndef get_sage_genvalues(modulus, order, genvalues, zeta_order):\n        \"\"\"\n        Helper method for computing correct genvalues when constructing\n        the sage character\n        \"\"\"\n        phi_mod = euler_phi(modulus)\n        exponent_factor = phi_mod / order\n        genvalues_exponent = [x * exponent_factor for x in genvalues]\n        return [x * zeta_order / phi_mod for x in genvalues_exponent]\n\n\nclass PariConreyGroup(object):\n\n    def __init__(self, modulus):\n        self.modulus = int(modulus)\n        self.G = Pari(\"znstar({},1)\".format(modulus))\n\n    def gens(self):\n        return Integers(self.modulus).unit_gens()\n\n    def invariants(self):\n        return pari(\"znstar({},1).cyc\".format(self.modulus))\n\n\nclass ConreyCharacter(object):\n    \"\"\"\n    tiny implementation on Conrey index only\n    \"\"\"\n\n    def __init__(self, modulus, number):\n        assert gcd(modulus, number)==1\n        self.modulus = Integer(modulus)\n        self.number = Integer(number)\n        self.G = Pari(\"znstar({},1)\".format(modulus))\n        self.chi_pari = pari(\"znconreylog(%s,%d)\"%(self.G,self.number))\n        self.chi_0 = None\n        self.indlabel = None\n\n    @property\n    def texname(self):\n        from lmfdb.characters.web_character import WebDirichlet\n        return WebDirichlet.char2tex(self.modulus, self.number)\n\n    @cached_method\n    def modfactor(self):\n        return self.modulus.factor()\n\n    @cached_method\n    def conductor(self):\n        B = pari(\"znconreyconductor(%s,%s,&chi0)\"%(self.G, self.chi_pari))\n        if B.type() == 't_INT':\n            # means chi is primitive\n            self.chi_0 = self.chi_pari\n            self.indlabel = self.number\n            return int(B)\n        else:\n            self.chi_0 = pari(\"chi0\")\n            G_0 = Pari(\"znstar({},1)\".format(B))\n            self.indlabel = int(pari(\"znconreyexp(%s,%s)\"%(G_0,self.chi_0)))\n            return int(B[0])\n\n    def is_primitive(self):\n        return self.conductor() == self.modulus\n\n    @cached_method\n    def parity(self):\n        number = self.number\n        par = 0\n        for p,e in self.modfactor():\n            if p == 2:\n                if number % 4 == 3:\n                    par = 1 - par\n            else:\n                phi2 = (p-1)/Integer(2) * p **(e-1)\n                if Mod(number, p ** e)**phi2 != 1:\n                    par = 1 - par\n        return par\n\n    def is_odd(self):\n        return self.parity() == 1\n\n    def is_even(self):\n        return self.parity() == 0\n\n    @cached_method\n    def multiplicative_order(self):\n        return Mod(self.number, self.modulus).multiplicative_order()\n\n    @property\n    def order(self):\n        return self.multiplicative_order()\n\n    @cached_method\n    def kronecker_symbol(self):\n        c = self.conductor()\n        p = self.parity()\n        return kronecker_symbol(symbol_numerator(c, p))\n\n    def conreyangle(self,x):\n        return Rational(pari(\"chareval(%s,znconreylog(%s,%d),%d)\"%(self.G,self.G,self.number,x)))\n\n    def gauss_sum_numerical(self, a):\n        return pari(\"znchargauss(%s,%s,a=%d)\"%(self.G,self.chi_pari,a))\n\n    def sage_zeta_order(self, order):\n        return DirichletGroup(self.modulus, base_ring=CyclotomicField(order)).zeta_order()\n\n    def sage_character(self, order, genvalues):\n        H = DirichletGroup(self.modulus, base_ring=CyclotomicField(order))\n        M = H._module\n        order_corrected_genvalues = get_sage_genvalues(self.modulus, order, genvalues, H.zeta_order())\n        return DirichletCharacter(H,M(order_corrected_genvalues))\n", "path": "lmfdb/characters/TinyConrey.py"}], "after_files": [{"content": "from sage.all import (gcd, Mod, Integer, Integers, Rational, pari, Pari,\n                      DirichletGroup, CyclotomicField, euler_phi, lcm)\nfrom sage.misc.cachefunc import cached_method\nfrom sage.modular.dirichlet import DirichletCharacter\n\ndef symbol_numerator(cond, parity):\n    # Reference: Sect. 9.3, Montgomery, Hugh L; Vaughan, Robert C. (2007).\n    # Multiplicative number theory. I. Classical theory. Cambridge Studies in\n    # Advanced Mathematics 97\n    #\n    # Let F = Q(\\sqrt(d)) with d a non zero squarefree integer then a real\n    # Dirichlet character \\chi(n) can be represented as a Kronecker symbol\n    # (m / n) where { m  = d if # d = 1 mod 4 else m = 4d if d = 2,3 (mod) 4 }\n    # and m is the discriminant of F. The conductor of \\chi is |m|.\n    #\n    # symbol_numerator returns the appropriate Kronecker symbol depending on\n    # the conductor of \\chi.\n    m = cond\n    if cond % 2 == 1:\n        if cond % 4 == 3:\n            m = -cond\n    elif cond % 8 == 4:\n        # Fixed cond % 16 == 4 and cond % 16 == 12 were switched in the\n        # previous version of the code.\n        #\n        # Let d be a non zero squarefree integer. If d  = 2,3 (mod) 4 and if\n        # cond = 4d = 4 ( 4n + 2) or 4 (4n + 3) = 16 n + 8 or 16n + 12 then we\n        # set m = cond.  On the other hand if d = 1 (mod) 4 and cond = 4d = 4\n        # (4n +1) = 16n + 4 then we set m = -cond.\n        if cond % 16 == 4:\n            m = -cond\n    elif cond % 16 == 8:\n        if parity == 1:\n            m = -cond\n    else:\n        return None\n    return m\n\n\ndef kronecker_symbol(m):\n    if m:\n        return r'\\(\\displaystyle\\left(\\frac{%s}{\\bullet}\\right)\\)' % (m)\n    else:\n        return None\n\n###############################################################################\n## Conrey character with no call to Jonathan's code\n## in order to handle big moduli\n##\n\ndef get_sage_genvalues(modulus, order, genvalues, zeta_order):\n        \"\"\"\n        Helper method for computing correct genvalues when constructing\n        the sage character\n        \"\"\"\n        phi_mod = euler_phi(modulus)\n        exponent_factor = phi_mod / order\n        genvalues_exponent = [x * exponent_factor for x in genvalues]\n        return [x * zeta_order / phi_mod for x in genvalues_exponent]\n\n\nclass PariConreyGroup(object):\n\n    def __init__(self, modulus):\n        self.modulus = int(modulus)\n        self.G = Pari(\"znstar({},1)\".format(modulus))\n\n    def gens(self):\n        return Integers(self.modulus).unit_gens()\n\n    def invariants(self):\n        return pari(\"znstar({},1).cyc\".format(self.modulus))\n\n\nclass ConreyCharacter(object):\n    \"\"\"\n    tiny implementation on Conrey index only\n    \"\"\"\n\n    def __init__(self, modulus, number):\n        assert gcd(modulus, number)==1\n        self.modulus = Integer(modulus)\n        self.number = Integer(number)\n        self.G = Pari(\"znstar({},1)\".format(modulus))\n        self.chi_pari = pari(\"znconreylog(%s,%d)\"%(self.G,self.number))\n        self.chi_0 = None\n        self.indlabel = None\n\n    @property\n    def texname(self):\n        from lmfdb.characters.web_character import WebDirichlet\n        return WebDirichlet.char2tex(self.modulus, self.number)\n\n    @cached_method\n    def modfactor(self):\n        return self.modulus.factor()\n\n    @cached_method\n    def conductor(self):\n        B = pari(\"znconreyconductor(%s,%s,&chi0)\"%(self.G, self.chi_pari))\n        if B.type() == 't_INT':\n            # means chi is primitive\n            self.chi_0 = self.chi_pari\n            self.indlabel = self.number\n            return int(B)\n        else:\n            self.chi_0 = pari(\"chi0\")\n            G_0 = Pari(\"znstar({},1)\".format(B))\n            self.indlabel = int(pari(\"znconreyexp(%s,%s)\"%(G_0,self.chi_0)))\n            return int(B[0])\n\n    def is_primitive(self):\n        return self.conductor() == self.modulus\n\n    @cached_method\n    def parity(self):\n        number = self.number\n        par = 0\n        for p,e in self.modfactor():\n            if p == 2:\n                if number % 4 == 3:\n                    par = 1 - par\n            else:\n                phi2 = (p-1)/Integer(2) * p **(e-1)\n                if Mod(number, p ** e)**phi2 != 1:\n                    par = 1 - par\n        return par\n\n    def is_odd(self):\n        return self.parity() == 1\n\n    def is_even(self):\n        return self.parity() == 0\n\n    @cached_method\n    def multiplicative_order(self):\n        return Mod(self.number, self.modulus).multiplicative_order()\n\n    @property\n    def order(self):\n        return self.multiplicative_order()\n\n    @cached_method\n    def kronecker_symbol(self):\n        c = self.conductor()\n        p = self.parity()\n        return kronecker_symbol(symbol_numerator(c, p))\n\n    def conreyangle(self,x):\n        return Rational(pari(\"chareval(%s,znconreylog(%s,%d),%d)\"%(self.G,self.G,self.number,x)))\n\n    def gauss_sum_numerical(self, a):\n        return pari(\"znchargauss(%s,%s,a=%d)\"%(self.G,self.chi_pari,a))\n\n    def sage_zeta_order(self, order):\n        return 1 if self.modulus <= 2 else lcm(2,order)\n\n    def sage_character(self, order, genvalues):\n        H = DirichletGroup(self.modulus, base_ring=CyclotomicField(order))\n        M = H._module\n        order_corrected_genvalues = get_sage_genvalues(self.modulus, order, genvalues, H.zeta_order())\n        return DirichletCharacter(H,M(order_corrected_genvalues))\n", "path": "lmfdb/characters/TinyConrey.py"}]}