@@ -1135,7 +1135,8 @@ def isogeny_degrees_cm(E, verbose=False):
1135
1135
1136
1136
A finite list of primes `\ell` such that every curve isogenous to
1137
1137
this curve can be obtained by a finite sequence of isogenies of
1138
- degree one of the primes in the list.
1138
+ degree one of the primes in the list. This list is not
1139
+ necessarily minimal.
1139
1140
1140
1141
ALGORITHM:
1141
1142
@@ -1188,8 +1189,20 @@ def isogeny_degrees_cm(E, verbose=False):
1188
1189
downward split primes: {2, 3}
1189
1190
downward inert primes: {5}
1190
1191
primes generating the class group: [2]
1191
- Complete set of primes: {2, 3, 5}
1192
- [2, 3, 5]
1192
+ Set of primes before filtering: {2, 3, 5}
1193
+ List of primes after filtering: [2, 3]
1194
+ [2, 3]
1195
+
1196
+ TESTS:
1197
+
1198
+ Check that :issue:`36780` is fixed::
1199
+
1200
+ sage: L5.<r5> = NumberField(x^2-5)
1201
+ sage: E = EllipticCurve(L5,[0,-4325477943600 *r5-4195572876000])
1202
+ sage: from sage.schemes.elliptic_curves.isogeny_class import isogeny_degrees_cm
1203
+ sage: isogeny_degrees_cm(E)
1204
+ [3, 5]
1205
+
1193
1206
"""
1194
1207
if not E .has_cm ():
1195
1208
raise ValueError ("possible_isogeny_degrees_cm(E) requires E to be an elliptic curve with CM" )
@@ -1205,6 +1218,11 @@ def isogeny_degrees_cm(E, verbose=False):
1205
1218
n = E .base_field ().absolute_degree ()
1206
1219
if not E .has_rational_cm ():
1207
1220
n *= 2
1221
+ # For discriminants with extra units there's an extra factor in the class number formula:
1222
+ if d == - 4 :
1223
+ n *= 2
1224
+ if d == - 3 :
1225
+ n *= 3
1208
1226
divs = n .divisors ()
1209
1227
1210
1228
data = pari (d ).quadclassunit ()
@@ -1232,7 +1250,7 @@ def isogeny_degrees_cm(E, verbose=False):
1232
1250
# of the order O of discriminant d. The latter case can only
1233
1251
# happen when l^2 divides d.
1234
1252
1235
- # Compute the ramified primes
1253
+ # (a) ramified primes
1236
1254
1237
1255
ram_l = d .odd_part ().prime_factors ()
1238
1256
@@ -1247,25 +1265,22 @@ def isogeny_degrees_cm(E, verbose=False):
1247
1265
1248
1266
else :
1249
1267
1250
- # Find the "upward " primes (index divided by l):
1268
+ # "Upward " primes (index divided by l):
1251
1269
1252
1270
L1 = Set ([l for l in ram_l if d .valuation (l ) > 1 ])
1253
1271
L += L1
1254
1272
if verbose :
1255
1273
print ("upward primes: %s" % L1 )
1256
1274
1257
- # Find the "downward" primes (index multiplied by l, class
1258
- # number multiplied by l-kronecker_symbol(d,l)):
1259
-
1260
- # (a) ramified primes; the suborder has class number l*h, so l
1261
- # must divide n/2h:
1275
+ # "Downward" ramified primes; index multiplied by l, class
1276
+ # number multiplied by l, so l must divide n/2h:
1262
1277
1263
1278
L1 = Set ([l for l in ram_l if l .divides (n_over_2h )])
1264
1279
L += L1
1265
1280
if verbose :
1266
1281
print ("downward ramified primes: %s" % L1 )
1267
1282
1268
- # (b) split primes; the suborder has class number (l-1)*h, so
1283
+ # (b) Downward split primes; the suborder has class number (l-1)*h, so
1269
1284
# l-1 must divide n/2h:
1270
1285
1271
1286
L1 = Set ([lm1 + 1 for lm1 in divs
@@ -1274,7 +1289,7 @@ def isogeny_degrees_cm(E, verbose=False):
1274
1289
if verbose :
1275
1290
print ("downward split primes: %s" % L1 )
1276
1291
1277
- # (c) inert primes; the suborder has class number (l+1)*h, so
1292
+ # (c) Downward inert primes; the suborder has class number (l+1)*h, so
1278
1293
# l+1 must divide n/2h:
1279
1294
1280
1295
L1 = Set ([lp1 - 1 for lp1 in divs
@@ -1283,10 +1298,9 @@ def isogeny_degrees_cm(E, verbose=False):
1283
1298
if verbose :
1284
1299
print ("downward inert primes: %s" % L1 )
1285
1300
1286
- # Now find primes represented by each form of discriminant d.
1287
- # In the rational CM case, we use all forms associated to
1288
- # generators of the class group, otherwise only forms of order
1289
- # 2:
1301
+ # Horizontal primes (rational CM only): same order, degrees are
1302
+ # all integers represented by some binary quadratic form of
1303
+ # discriminant d, so we find a prime represented by each form.
1290
1304
1291
1305
if E .has_rational_cm ():
1292
1306
from sage .quadratic_forms .binary_qf import BinaryQF
@@ -1300,10 +1314,14 @@ def isogeny_degrees_cm(E, verbose=False):
1300
1314
# Return sorted list
1301
1315
1302
1316
if verbose :
1303
- print ("Complete set of primes: %s" % L )
1304
-
1305
- return sorted (L )
1317
+ print ("Set of primes before filtering: %s" % L )
1306
1318
1319
+ # This filter will quickly eliminate most false entries in the set
1320
+ from .gal_reps_number_field import Frobenius_filter
1321
+ L = Frobenius_filter (E , sorted (L ))
1322
+ if verbose :
1323
+ print ("List of primes after filtering: %s" % L )
1324
+ return L
1307
1325
1308
1326
def possible_isogeny_degrees (E , algorithm = 'Billerey' , max_l = None ,
1309
1327
num_l = None , exact = True , verbose = False ):
@@ -1434,8 +1452,9 @@ def possible_isogeny_degrees(E, algorithm='Billerey', max_l=None,
1434
1452
downward split primes: {2, 3}
1435
1453
downward inert primes: {5}
1436
1454
primes generating the class group: [2]
1437
- Complete set of primes: {2, 3, 5}
1438
- [2, 3, 5]
1455
+ Set of primes before filtering: {2, 3, 5}
1456
+ List of primes after filtering: [2, 3]
1457
+ [2, 3]
1439
1458
"""
1440
1459
if E .has_cm ():
1441
1460
return isogeny_degrees_cm (E , verbose )
0 commit comments