We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Dirichlet character server error
The page https://www.lmfdb.org/Character/Dirichlet/68800/66667 is throwing a server error

--- 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,
2                       DirichletGroup, CyclotomicField, euler_phi, lcm)
3 from sage.misc.cachefunc import cached_method
4 from sage.modular.dirichlet import DirichletCharacter
5 from lmfdb.logger import make_logger
6 logger = make_logger("TinyConrey")
7 
8 def symbol_numerator(cond, parity):
9     # Reference: Sect. 9.3, Montgomery, Hugh L; Vaughan, Robert C. (2007).
10     # Multiplicative number theory. I. Classical theory. Cambridge Studies in
11     # Advanced Mathematics 97
12     #
13     # Let F = Q(\sqrt(d)) with d a non zero squarefree integer then a real
14     # Dirichlet character \chi(n) can be represented as a Kronecker symbol
15     # (m / n) where { m  = d if # d = 1 mod 4 else m = 4d if d = 2,3 (mod) 4 }
16     # and m is the discriminant of F. The conductor of \chi is |m|.
17     #
18     # symbol_numerator returns the appropriate Kronecker symbol depending on
19     # the conductor of \chi.
20     m = cond
21     if cond % 2 == 1:
22         if cond % 4 == 3:
23             m = -cond
24     elif cond % 8 == 4:
25         # Fixed cond % 16 == 4 and cond % 16 == 12 were switched in the
26         # previous version of the code.
27         #
28         # Let d be a non zero squarefree integer. If d  = 2,3 (mod) 4 and if
29         # cond = 4d = 4 ( 4n + 2) or 4 (4n + 3) = 16 n + 8 or 16n + 12 then we
30         # set m = cond.  On the other hand if d = 1 (mod) 4 and cond = 4d = 4
31         # (4n +1) = 16n + 4 then we set m = -cond.
32         if cond % 16 == 4:
33             m = -cond
34     elif cond % 16 == 8:
35         if parity == 1:
36             m = -cond
37     else:
38         return None
39     return m
40 
41 
42 def kronecker_symbol(m):
43     if m:
44         return r'\(\displaystyle\left(\frac{%s}{\bullet}\right)\)' % (m)
45     else:
46         return None
47 
48 ###############################################################################
49 # Conrey character with no call to Jonathan's code
50 # in order to handle big moduli
51 
52 
53 def get_sage_genvalues(modulus, order, genvalues, zeta_order):
54     """
55     Helper method for computing correct genvalues when constructing
56     the sage character
57     """
58     phi_mod = euler_phi(modulus)
59     exponent_factor = phi_mod / order
60     genvalues_exponent = (x * exponent_factor for x in genvalues)
61     return [x * zeta_order / phi_mod for x in genvalues_exponent]
62 
63 
64 class PariConreyGroup():
65 
66     def __init__(self, modulus):
67         self.modulus = int(modulus)
68         self.G = pari(f"znstar({modulus},1)")
69 
70     def gens(self):
71         return Integers(self.modulus).unit_gens()
72 
73     def invariants(self):
74         return pari(f"{self.G}.cyc")
75 
76     @cached_method
77     def first_chars(self, limit=31):
78         if self.modulus == 1:
79             return [1]
80         r = []
81         for i,c in enumerate(Integers(self.modulus).list_of_elements_of_multiplicative_group()):
82             r.append(c)
83             if i > limit:
84                 self.rowtruncate = True
85                 break
86         return r
87 
88     @cached_method
89     def first_chars_with_orbit(self, limit=31):
90         """ would be nice to compute those directly
91             instead of querying each to db
92         """
93         pass
94 
95 
96 class ConreyCharacter():
97     """
98     minimal implementation of character from its Conrey index
99     use Pari/GP functions when available
100     """
101 
102     def __init__(self, modulus, number):
103         assert gcd(modulus, number)==1
104         self.modulus = Integer(modulus)
105         self.number = Integer(number)
106         self.conrey = Mod(number,modulus)
107         self.G = pari("znstar({},1)".format(modulus))
108         self.G_gens = Integers(self.modulus).unit_gens() # use sage generators
109         self.chi_pari = self.G.znconreylog(self.number)
110         self.chi_0 = None
111         self.indlabel = None
112 
113     @property
114     def texname(self):
115         from lmfdb.characters.web_character import WebDirichlet
116         return WebDirichlet.char2tex(self.modulus, self.number)
117 
118     @cached_method
119     def modfactor(self):
120         return self.modulus.factor()
121 
122     @cached_method
123     def conductor(self):
124         B = pari(f"znconreyconductor({self.G},{self.chi_pari},&chi0)")
125         if B.type() == 't_INT':
126             # means chi is primitive
127             self.chi_0 = self.chi_pari
128             self.indlabel = self.number
129             return int(B)
130         else:
131             self.chi_0 = pari("chi0")
132             G_0 = pari(f"znstar({B},1)")
133             self.indlabel = int(G_0.znconreyexp(self.chi_0))
134             return int(B[0])
135 
136     @cached_method
137     def is_primitive(self):
138         return self.conductor() == self.modulus
139 
140     @cached_method
141     def parity(self):
142         return self.G.zncharisodd(self.chi_pari)
143 
144     def is_odd(self):
145         return self.parity() == 1
146 
147     def is_even(self):
148         return self.parity() == 0
149 
150     @property
151     def order(self):
152         return self.conrey.multiplicative_order()
153 
154     @property
155     def genvalues(self):
156         # This assumes that the generators are ordered in the way
157         # that Sage returns
158         return [self.conreyangle(k) * self.order for k in self.G_gens]
159 
160     @property
161     def values_gens(self):
162         # This may be considered the full version of genvalues;
163         # that is, it returns both the generators as well as the values
164         # at those generators
165         return [[k, self.conreyangle(k) * self.order] for k in self.G_gens]
166 
167     @cached_method
168     def kronecker_symbol(self):
169         c = self.conductor()
170         p = self.parity()
171         return kronecker_symbol(symbol_numerator(c, p))
172 
173     def conreyangle(self,x):
174         return Rational(self.G.chareval(self.chi_pari,x))
175 
176     def gauss_sum_numerical(self, a):
177         # There seems to be a bug in pari when a is a multiple of the modulus,
178         # so we deal with that separately
179         if self.modulus.divides(a):
180             if self.conductor() == 1:
181                 return euler_phi(self.modulus)
182             else:
183                 return Integer(0)
184         else:
185             return self.G.znchargauss(self.chi_pari,a)
186 
187     def sage_zeta_order(self, order):
188         return 1 if self.modulus <= 2 else lcm(2,order)
189 
190     def sage_character(self, order=None, genvalues=None):
191 
192         if order is None:
193             order = self.order
194 
195         if genvalues is None:
196             genvalues = self.genvalues
197 
198         H = DirichletGroup(self.modulus, base_ring=CyclotomicField(self.sage_zeta_order(order)))
199         M = H._module
200         order_corrected_genvalues = get_sage_genvalues(self.modulus, order, genvalues, self.sage_zeta_order(order))
201         return DirichletCharacter(H,M(order_corrected_genvalues))
202 
203     @cached_method
204     def galois_orbit(self, limit=31):
205         """
206         orbit under Galois of the value field,
207         can be used to find first conjugate or list of first conjugates
208         """
209         logger.debug(f"## galois_orbit({limit})")
210         order = self.order
211         if order == 1:
212             return [1]
213         elif order < limit or order * order < limit * self.modulus:
214             logger.debug(f"compute all conjugate characters and return first {limit}")
215             return self.galois_orbit_all(limit)
216         elif limit == 1 or self.modulus < 30 * order:
217             logger.debug(f"compute {limit} first conjugate characters")
218             return self.galois_orbit_search(limit)
219         else:
220             logger.debug(f"galois orbit of size {order} too expansive, give up")
221             return []
222 
223     def galois_orbit_all(self, limit=31):
224         # construct all Galois orbit, assume not too large
225         order = self.order
226         chik = self.conrey
227         output = []
228         for k in range(1,order):
229             if gcd(k,order) == 1:
230                 output.append(Integer(chik))
231             chik *= self.conrey
232         output.sort()
233         return output[:limit]
234 
235     def galois_orbit_search(self, limit=31):
236         # fishing strategy, assume orbit relatively dense
237         order = self.order
238         num = self.number
239         mod = self.modulus
240         kmin = 1
241         width = kmax = min(mod,limit * 50)
242         while True:
243             cmd = f"a=Mod({num},{mod});my(valid(k)=my(l=znlog(k,a,{order}));l&&gcd(l,{order})==1);[ k | k <- [{kmin}..{kmax}], gcd(k,{mod})==1 && valid(k) ]"
244             ans = [Integer(m) for m in pari(cmd)[:limit]]
245             if ans:
246                 return ans
247             kmin += width
248             kmax += width
249 
250     @property
251     def min_conrey_conj(self):
252         return self.galois_orbit(1)[0]
253 
254     @cached_method
255     def kernel_field_poly(self):
256         pol = self.G.galoissubcyclo(self.G.charker(self.chi_pari))
257         if self.order <= 12:
258             pol = pol.polredabs()
259         return pol
260
```
--- 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
@@ -213,7 +213,7 @@
         elif order < limit or order * order < limit * self.modulus:
             logger.debug(f"compute all conjugate characters and return first {limit}")
             return self.galois_orbit_all(limit)
-        elif limit == 1 or self.modulus < 30 * order:
+        elif limit == 1 or self.modulus <= 1000000:
             logger.debug(f"compute {limit} first conjugate characters")
             return self.galois_orbit_search(limit)
         else:

{"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@@ -213,7 +213,7 @@\n         elif order < limit or order * order < limit * self.modulus:\n             logger.debug(f\"compute all conjugate characters and return first {limit}\")\n             return self.galois_orbit_all(limit)\n-        elif limit == 1 or self.modulus < 30 * order:\n+        elif limit == 1 or self.modulus <= 1000000:\n             logger.debug(f\"compute {limit} first conjugate characters\")\n             return self.galois_orbit_search(limit)\n         else:\n", "issue": "Dirichlet character server error\nThe page https://www.lmfdb.org/Character/Dirichlet/68800/66667 is throwing a server error\n", "before_files": [{"content": "from sage.all import (gcd, Mod, Integer, Integers, Rational, pari,\n                      DirichletGroup, CyclotomicField, euler_phi, lcm)\nfrom sage.misc.cachefunc import cached_method\nfrom sage.modular.dirichlet import DirichletCharacter\nfrom lmfdb.logger import make_logger\nlogger = make_logger(\"TinyConrey\")\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():\n\n    def __init__(self, modulus):\n        self.modulus = int(modulus)\n        self.G = pari(f\"znstar({modulus},1)\")\n\n    def gens(self):\n        return Integers(self.modulus).unit_gens()\n\n    def invariants(self):\n        return pari(f\"{self.G}.cyc\")\n\n    @cached_method\n    def first_chars(self, limit=31):\n        if self.modulus == 1:\n            return [1]\n        r = []\n        for i,c in enumerate(Integers(self.modulus).list_of_elements_of_multiplicative_group()):\n            r.append(c)\n            if i > limit:\n                self.rowtruncate = True\n                break\n        return r\n\n    @cached_method\n    def first_chars_with_orbit(self, limit=31):\n        \"\"\" would be nice to compute those directly\n            instead of querying each to db\n        \"\"\"\n        pass\n\n\nclass ConreyCharacter():\n    \"\"\"\n    minimal implementation of character from its Conrey index\n    use Pari/GP functions when available\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.conrey = Mod(number,modulus)\n        self.G = pari(\"znstar({},1)\".format(modulus))\n        self.G_gens = Integers(self.modulus).unit_gens() # use sage generators\n        self.chi_pari = self.G.znconreylog(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(f\"znconreyconductor({self.G},{self.chi_pari},&chi0)\")\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(f\"znstar({B},1)\")\n            self.indlabel = int(G_0.znconreyexp(self.chi_0))\n            return int(B[0])\n\n    @cached_method\n    def is_primitive(self):\n        return self.conductor() == self.modulus\n\n    @cached_method\n    def parity(self):\n        return self.G.zncharisodd(self.chi_pari)\n\n    def is_odd(self):\n        return self.parity() == 1\n\n    def is_even(self):\n        return self.parity() == 0\n\n    @property\n    def order(self):\n        return self.conrey.multiplicative_order()\n\n    @property\n    def genvalues(self):\n        # This assumes that the generators are ordered in the way\n        # that Sage returns\n        return [self.conreyangle(k) * self.order for k in self.G_gens]\n\n    @property\n    def values_gens(self):\n        # This may be considered the full version of genvalues;\n        # that is, it returns both the generators as well as the values\n        # at those generators\n        return [[k, self.conreyangle(k) * self.order] for k in self.G_gens]\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(self.G.chareval(self.chi_pari,x))\n\n    def gauss_sum_numerical(self, a):\n        # There seems to be a bug in pari when a is a multiple of the modulus,\n        # so we deal with that separately\n        if self.modulus.divides(a):\n            if self.conductor() == 1:\n                return euler_phi(self.modulus)\n            else:\n                return Integer(0)\n        else:\n            return self.G.znchargauss(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=None, genvalues=None):\n\n        if order is None:\n            order = self.order\n\n        if genvalues is None:\n            genvalues = self.genvalues\n\n        H = DirichletGroup(self.modulus, base_ring=CyclotomicField(self.sage_zeta_order(order)))\n        M = H._module\n        order_corrected_genvalues = get_sage_genvalues(self.modulus, order, genvalues, self.sage_zeta_order(order))\n        return DirichletCharacter(H,M(order_corrected_genvalues))\n\n    @cached_method\n    def galois_orbit(self, limit=31):\n        \"\"\"\n        orbit under Galois of the value field,\n        can be used to find first conjugate or list of first conjugates\n        \"\"\"\n        logger.debug(f\"## galois_orbit({limit})\")\n        order = self.order\n        if order == 1:\n            return [1]\n        elif order < limit or order * order < limit * self.modulus:\n            logger.debug(f\"compute all conjugate characters and return first {limit}\")\n            return self.galois_orbit_all(limit)\n        elif limit == 1 or self.modulus < 30 * order:\n            logger.debug(f\"compute {limit} first conjugate characters\")\n            return self.galois_orbit_search(limit)\n        else:\n            logger.debug(f\"galois orbit of size {order} too expansive, give up\")\n            return []\n\n    def galois_orbit_all(self, limit=31):\n        # construct all Galois orbit, assume not too large\n        order = self.order\n        chik = self.conrey\n        output = []\n        for k in range(1,order):\n            if gcd(k,order) == 1:\n                output.append(Integer(chik))\n            chik *= self.conrey\n        output.sort()\n        return output[:limit]\n\n    def galois_orbit_search(self, limit=31):\n        # fishing strategy, assume orbit relatively dense\n        order = self.order\n        num = self.number\n        mod = self.modulus\n        kmin = 1\n        width = kmax = min(mod,limit * 50)\n        while True:\n            cmd = f\"a=Mod({num},{mod});my(valid(k)=my(l=znlog(k,a,{order}));l&&gcd(l,{order})==1);[ k | k <- [{kmin}..{kmax}], gcd(k,{mod})==1 && valid(k) ]\"\n            ans = [Integer(m) for m in pari(cmd)[:limit]]\n            if ans:\n                return ans\n            kmin += width\n            kmax += width\n\n    @property\n    def min_conrey_conj(self):\n        return self.galois_orbit(1)[0]\n\n    @cached_method\n    def kernel_field_poly(self):\n        pol = self.G.galoissubcyclo(self.G.charker(self.chi_pari))\n        if self.order <= 12:\n            pol = pol.polredabs()\n        return pol\n", "path": "lmfdb/characters/TinyConrey.py"}], "after_files": [{"content": "from sage.all import (gcd, Mod, Integer, Integers, Rational, pari,\n                      DirichletGroup, CyclotomicField, euler_phi, lcm)\nfrom sage.misc.cachefunc import cached_method\nfrom sage.modular.dirichlet import DirichletCharacter\nfrom lmfdb.logger import make_logger\nlogger = make_logger(\"TinyConrey\")\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():\n\n    def __init__(self, modulus):\n        self.modulus = int(modulus)\n        self.G = pari(f\"znstar({modulus},1)\")\n\n    def gens(self):\n        return Integers(self.modulus).unit_gens()\n\n    def invariants(self):\n        return pari(f\"{self.G}.cyc\")\n\n    @cached_method\n    def first_chars(self, limit=31):\n        if self.modulus == 1:\n            return [1]\n        r = []\n        for i,c in enumerate(Integers(self.modulus).list_of_elements_of_multiplicative_group()):\n            r.append(c)\n            if i > limit:\n                self.rowtruncate = True\n                break\n        return r\n\n    @cached_method\n    def first_chars_with_orbit(self, limit=31):\n        \"\"\" would be nice to compute those directly\n            instead of querying each to db\n        \"\"\"\n        pass\n\n\nclass ConreyCharacter():\n    \"\"\"\n    minimal implementation of character from its Conrey index\n    use Pari/GP functions when available\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.conrey = Mod(number,modulus)\n        self.G = pari(\"znstar({},1)\".format(modulus))\n        self.G_gens = Integers(self.modulus).unit_gens() # use sage generators\n        self.chi_pari = self.G.znconreylog(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(f\"znconreyconductor({self.G},{self.chi_pari},&chi0)\")\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(f\"znstar({B},1)\")\n            self.indlabel = int(G_0.znconreyexp(self.chi_0))\n            return int(B[0])\n\n    @cached_method\n    def is_primitive(self):\n        return self.conductor() == self.modulus\n\n    @cached_method\n    def parity(self):\n        return self.G.zncharisodd(self.chi_pari)\n\n    def is_odd(self):\n        return self.parity() == 1\n\n    def is_even(self):\n        return self.parity() == 0\n\n    @property\n    def order(self):\n        return self.conrey.multiplicative_order()\n\n    @property\n    def genvalues(self):\n        # This assumes that the generators are ordered in the way\n        # that Sage returns\n        return [self.conreyangle(k) * self.order for k in self.G_gens]\n\n    @property\n    def values_gens(self):\n        # This may be considered the full version of genvalues;\n        # that is, it returns both the generators as well as the values\n        # at those generators\n        return [[k, self.conreyangle(k) * self.order] for k in self.G_gens]\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(self.G.chareval(self.chi_pari,x))\n\n    def gauss_sum_numerical(self, a):\n        # There seems to be a bug in pari when a is a multiple of the modulus,\n        # so we deal with that separately\n        if self.modulus.divides(a):\n            if self.conductor() == 1:\n                return euler_phi(self.modulus)\n            else:\n                return Integer(0)\n        else:\n            return self.G.znchargauss(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=None, genvalues=None):\n\n        if order is None:\n            order = self.order\n\n        if genvalues is None:\n            genvalues = self.genvalues\n\n        H = DirichletGroup(self.modulus, base_ring=CyclotomicField(self.sage_zeta_order(order)))\n        M = H._module\n        order_corrected_genvalues = get_sage_genvalues(self.modulus, order, genvalues, self.sage_zeta_order(order))\n        return DirichletCharacter(H,M(order_corrected_genvalues))\n\n    @cached_method\n    def galois_orbit(self, limit=31):\n        \"\"\"\n        orbit under Galois of the value field,\n        can be used to find first conjugate or list of first conjugates\n        \"\"\"\n        logger.debug(f\"## galois_orbit({limit})\")\n        order = self.order\n        if order == 1:\n            return [1]\n        elif order < limit or order * order < limit * self.modulus:\n            logger.debug(f\"compute all conjugate characters and return first {limit}\")\n            return self.galois_orbit_all(limit)\n        elif limit == 1 or self.modulus <= 1000000:\n            logger.debug(f\"compute {limit} first conjugate characters\")\n            return self.galois_orbit_search(limit)\n        else:\n            logger.debug(f\"galois orbit of size {order} too expansive, give up\")\n            return []\n\n    def galois_orbit_all(self, limit=31):\n        # construct all Galois orbit, assume not too large\n        order = self.order\n        chik = self.conrey\n        output = []\n        for k in range(1,order):\n            if gcd(k,order) == 1:\n                output.append(Integer(chik))\n            chik *= self.conrey\n        output.sort()\n        return output[:limit]\n\n    def galois_orbit_search(self, limit=31):\n        # fishing strategy, assume orbit relatively dense\n        order = self.order\n        num = self.number\n        mod = self.modulus\n        kmin = 1\n        width = kmax = min(mod,limit * 50)\n        while True:\n            cmd = f\"a=Mod({num},{mod});my(valid(k)=my(l=znlog(k,a,{order}));l&&gcd(l,{order})==1);[ k | k <- [{kmin}..{kmax}], gcd(k,{mod})==1 && valid(k) ]\"\n            ans = [Integer(m) for m in pari(cmd)[:limit]]\n            if ans:\n                return ans\n            kmin += width\n            kmax += width\n\n    @property\n    def min_conrey_conj(self):\n        return self.galois_orbit(1)[0]\n\n    @cached_method\n    def kernel_field_poly(self):\n        pol = self.G.galoissubcyclo(self.G.charker(self.chi_pari))\n        if self.order <= 12:\n            pol = pol.polredabs()\n        return pol\n", "path": "lmfdb/characters/TinyConrey.py"}]}