@@ -92,11 +92,11 @@ def HyperellipticCurve(f, h=0, names=None, PP=None, check_squarefree=True):
92
92
sage: HyperellipticCurve(x^8 + 1, x)
93
93
Traceback (most recent call last):
94
94
...
95
- ValueError: Not a hyperelliptic curve: highly singular at infinity.
95
+ ValueError: not a hyperelliptic curve: highly singular at infinity
96
96
sage: HyperellipticCurve(x^8 + x^7 + 1, x^4)
97
97
Traceback (most recent call last):
98
98
...
99
- ValueError: Not a hyperelliptic curve: singularity in the provided affine patch.
99
+ ValueError: not a hyperelliptic curve: singularity in the provided affine patch
100
100
101
101
sage: F.<t> = PowerSeriesRing(FiniteField(2))
102
102
sage: P.<x> = PolynomialRing(FractionField(F))
@@ -128,7 +128,7 @@ def HyperellipticCurve(f, h=0, names=None, PP=None, check_squarefree=True):
128
128
sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1))
129
129
Traceback (most recent call last):
130
130
...
131
- ValueError: Not a hyperelliptic curve: singularity in the provided affine patch.
131
+ ValueError: not a hyperelliptic curve: singularity in the provided affine patch
132
132
133
133
sage: HyperellipticCurve((x^3-x+2)^2*(x^6-1), check_squarefree=False)
134
134
Hyperelliptic Curve over Finite Field of size 7 defined by
@@ -147,7 +147,7 @@ def HyperellipticCurve(f, h=0, names=None, PP=None, check_squarefree=True):
147
147
sage: HyperellipticCurve(f, h)
148
148
Traceback (most recent call last):
149
149
...
150
- ValueError: Not a hyperelliptic curve: highly singular at infinity.
150
+ ValueError: not a hyperelliptic curve: highly singular at infinity
151
151
152
152
sage: HyperellipticCurve(F)
153
153
Hyperelliptic Curve over Rational Field defined by y^2 = x^6 + 1
@@ -160,7 +160,7 @@ def HyperellipticCurve(f, h=0, names=None, PP=None, check_squarefree=True):
160
160
sage: HyperellipticCurve(x^5 + t)
161
161
Traceback (most recent call last):
162
162
...
163
- ValueError: Not a hyperelliptic curve: singularity in the provided affine patch.
163
+ ValueError: not a hyperelliptic curve: singularity in the provided affine patch
164
164
165
165
Input with integer coefficients creates objects with the integers
166
166
as base ring, but only checks smoothness over `\QQ`, not over Spec(`\ZZ`).
@@ -203,59 +203,73 @@ def HyperellipticCurve(f, h=0, names=None, PP=None, check_squarefree=True):
203
203
"""
204
204
# F is the discriminant; use this for the type check
205
205
# rather than f and h, one of which might be constant.
206
- F = h ** 2 + 4 * f
206
+ F = h ** 2 + 4 * f
207
207
if not isinstance (F , Polynomial ):
208
- raise TypeError ("Arguments f (= %s) and h (= %s) must be polynomials" % ( f , h ) )
208
+ raise TypeError (f "Arguments { f = } and { h = } must be polynomials" )
209
209
P = F .parent ()
210
210
f = P (f )
211
211
h = P (h )
212
212
df = f .degree ()
213
- dh_2 = 2 * h .degree ()
213
+ dh_2 = 2 * h .degree ()
214
214
if dh_2 < df :
215
- g = (df - 1 ) // 2
215
+ g = (df - 1 ) // 2
216
216
else :
217
- g = (dh_2 - 1 ) // 2
217
+ g = (dh_2 - 1 ) // 2
218
218
if check_squarefree :
219
219
# Assuming we are working over a field, this checks that after
220
220
# resolving the singularity at infinity, we get a smooth double cover
221
221
# of P^1.
222
222
if P (2 ) == 0 :
223
223
# characteristic 2
224
224
if h == 0 :
225
- raise ValueError ("In characteristic 2, argument h (= %s) must be non-zero." % h )
226
- if h [g + 1 ] == 0 and f [2 * g + 1 ]** 2 == f [2 * g + 2 ]* h [g ]** 2 :
227
- raise ValueError ("Not a hyperelliptic curve: "
228
- "highly singular at infinity." )
229
- should_be_coprime = [h , f * h .derivative ()** 2 + f .derivative ()** 2 ]
225
+ raise ValueError (
226
+ f"for characteristic 2, argument { h = } must be non-zero"
227
+ )
228
+ if h [g + 1 ] == 0 and f [2 * g + 1 ] ** 2 == f [2 * g + 2 ] * h [g ] ** 2 :
229
+ raise ValueError (
230
+ "not a hyperelliptic curve: highly singular at infinity"
231
+ )
232
+ should_be_coprime = [h , f * h .derivative () ** 2 + f .derivative () ** 2 ]
230
233
else :
231
234
# characteristic not 2
232
- if F .degree () not in [2 * g + 1 , 2 * g + 2 ]:
233
- raise ValueError ("Not a hyperelliptic curve: "
234
- "highly singular at infinity." )
235
+ if F .degree () not in [2 * g + 1 , 2 * g + 2 ]:
236
+ raise ValueError (
237
+ "not a hyperelliptic curve: highly singular at infinity"
238
+ )
235
239
should_be_coprime = [F , F .derivative ()]
236
240
try :
237
241
smooth = should_be_coprime [0 ].gcd (should_be_coprime [1 ]).degree () == 0
238
242
except (AttributeError , NotImplementedError , TypeError ):
239
243
try :
240
244
smooth = should_be_coprime [0 ].resultant (should_be_coprime [1 ]) != 0
241
245
except (AttributeError , NotImplementedError , TypeError ):
242
- raise NotImplementedError ("Cannot determine whether "
243
- "polynomials %s have a common root. Use "
244
- "check_squarefree=False to skip this check." %
245
- should_be_coprime )
246
+ raise NotImplementedError (
247
+ "cannot determine whether "
248
+ f"polynomials { should_be_coprime } have a common root, use "
249
+ "check_squarefree=False to skip this check"
250
+ )
246
251
if not smooth :
247
- raise ValueError ("Not a hyperelliptic curve: "
248
- "singularity in the provided affine patch." )
252
+ raise ValueError (
253
+ "not a hyperelliptic curve: "
254
+ "singularity in the provided affine patch"
255
+ )
249
256
R = P .base_ring ()
250
257
PP = ProjectiveSpace (2 , R )
251
258
if names is None :
252
259
names = ["x" , "y" ]
253
260
254
- superclass = []
261
+ bases = []
255
262
cls_name = ["HyperellipticCurve" ]
256
263
264
+ # For certain genus we specialise to child classes with
265
+ # optimised methods
257
266
genus_classes = {2 : HyperellipticCurve_g2 }
267
+ if g in genus_classes :
268
+ bases .append (genus_classes [g ])
269
+ cls_name .append ("g%s" % g )
258
270
271
+ # For certain base fields, we specialise to child classes
272
+ # with special case methods
259
273
def is_FiniteField (x ):
260
274
return isinstance (x , FiniteField )
261
275
@@ -265,25 +279,22 @@ def is_pAdicField(x):
265
279
fields = [
266
280
("FiniteField" , is_FiniteField , HyperellipticCurve_finite_field ),
267
281
("RationalField" , is_RationalField , HyperellipticCurve_rational_field ),
268
- ("pAdicField" , is_pAdicField , HyperellipticCurve_padic_field )]
269
-
270
- if g in genus_classes :
271
- superclass .append (genus_classes [g ])
272
- cls_name .append ("g%s" % g )
282
+ ("pAdicField" , is_pAdicField , HyperellipticCurve_padic_field ),
283
+ ]
273
284
274
285
for name , test , cls in fields :
275
286
if test (R ):
276
- superclass .append (cls )
287
+ bases .append (cls )
277
288
cls_name .append (name )
278
289
break
279
290
280
- base_cls = None
281
- if len (superclass ) == 0 :
282
- base_cls = HyperellipticCurve_generic
291
+ # If no specialised child class was found, we simply use the
292
+ # generic class in the class construction
293
+ if not bases :
294
+ bases = [HyperellipticCurve_generic ]
283
295
296
+ # Dynamically build a class from multiple inheritance. Note that
297
+ # all classes we slect from are children of HyperellipticCurve_generic
284
298
class_name = "_" .join (cls_name )
285
- cls = dynamic_class (class_name ,
286
- tuple (superclass ),
287
- cls = base_cls ,
288
- doccls = HyperellipticCurve )
299
+ cls = dynamic_class (class_name , tuple (bases ), doccls = HyperellipticCurve )
289
300
return cls (PP , f , h , names = names , genus = g )
0 commit comments