Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/databases/cremona.py
6915 views
1
"""
2
Cremona's tables of elliptic curves
3
4
Sage includes John Cremona's tables of elliptic curves in an
5
easy-to-use format. An instance of the class CremonaDatabase()
6
gives access to the database.
7
8
If the optional full CremonaDatabase is not installed, a mini-version
9
is included by default with Sage. It contains Weierstrass equations,
10
rank, and torsion for curves up to conductor 10000.
11
12
The large database includes all curves of conductor up to 240,000. It
13
also includes data related to the BSD conjecture and modular degrees
14
for all of these curves, and generators for the Mordell-Weil
15
groups. To install it type the following in Sage::
16
17
!sage -i database_cremona_ellcurve
18
19
This causes the latest version of the database to be downloaded from
20
the internet. You can also install it from a local copy of the
21
database spkg file, using a command of the form::
22
23
!sage -i database_cremona_ellcurve-*.spkg
24
25
Both the mini and full versions of John Cremona's tables are stored in
26
SAGE_DATA/cremona as SQLite databases. The mini version has the layout::
27
28
CREATE TABLE t_class(conductor INTEGER, class TEXT PRIMARY KEY, rank INTEGER);
29
CREATE TABLE t_curve(class TEXT, curve TEXT PRIMARY KEY, eqn TEXT UNIQUE, tors INTEGER);
30
CREATE INDEX i_t_class_conductor ON t_class(conductor);
31
CREATE INDEX i_t_curve_class ON t_curve(class);
32
33
while the full version has the layout::
34
35
CREATE TABLE t_class(conductor INTEGER, class TEXT PRIMARY KEY, rank INTEGER, L REAL, deg INTEGER);
36
CREATE TABLE t_curve(class TEXT, curve TEXT PRIMARY KEY, eqn TEXT UNIQUE, gens TEXT, tors INTEGER, cp INTEGER, om REAL, reg REAL, sha);
37
CREATE INDEX i_t_class_conductor ON t_class(conductor);
38
CREATE INDEX i_t_curve_class ON t_curve(class);
39
"""
40
#*****************************************************************************
41
# Copyright (C) 2011 R. Andrew Ohana <[email protected]>
42
# Copyright (C) 2005 William Stein <[email protected]>
43
#
44
# Distributed under the terms of the GNU General Public License (GPL)
45
# as published by the Free Software Foundation; either version 2 of
46
# the License, or (at your option) any later version.
47
# http://www.gnu.org/licenses/
48
#*****************************************************************************
49
50
import os
51
from sage.misc.prandom import randint
52
53
import sage.schemes.elliptic_curves.constructor as elliptic
54
from sql_db import SQLDatabase, verify_column
55
from sage.misc.package import optional_packages
56
from sage.misc.misc import SAGE_DATA, walltime
57
58
import re
59
import string
60
61
_cremonaSkeleton = {
62
't_class': {
63
'conductor': {'sql':'INTEGER', 'index':True},
64
'class': {'sql':'TEXT', 'primary_key':True},
65
'rank': {'sql':'INTEGER'},
66
'L': {'sql':'REAL'},
67
'deg': {'sql':'INTEGER'}
68
},
69
't_curve': {
70
'class': {'sql':'TEXT', 'index':True},
71
'curve': {'sql':'TEXT', 'primary_key':True},
72
'eqn': {'sql':'TEXT', 'unique':True},
73
'gens': {'sql':'TEXT'},
74
'tors': {'sql':'INTEGER'},
75
'cp': {'sql':'INTEGER'},
76
'om': {'sql':'REAL'},
77
'reg': {'sql':'REAL'},
78
'sha': {'sql':'NOTYPE'}
79
}
80
}
81
_miniCremonaSkeleton = {
82
't_class': {
83
'conductor': {'sql':'INTEGER', 'index':True},
84
'class': {'sql':'TEXT', 'primary_key':True},
85
'rank': {'sql':'INTEGER'}
86
},
87
't_curve': {
88
'class': {'sql':'TEXT', 'index':True},
89
'curve': {'sql':'TEXT', 'primary_key':True},
90
'eqn': {'sql':'TEXT', 'unique':True},
91
'tors': {'sql':'INTEGER'}
92
}
93
}
94
95
for t in _cremonaSkeleton:
96
for c in _cremonaSkeleton[t]:
97
_cremonaSkeleton[t][c] = verify_column(_cremonaSkeleton[t][c])
98
for c in _miniCremonaSkeleton[t]:
99
_miniCremonaSkeleton[t][c] = verify_column(_miniCremonaSkeleton[t][c])
100
101
def build(name, data_tgz, largest_conductor=0, mini=False, decompress=True):
102
"""
103
Build the CremonaDatabase with given name from scratch
104
using the data_tgz tarball.
105
106
... note::
107
108
For data up to level 240000, this function takes about 3
109
minutes on a AMD Opteron(tm) Processor 6174. The resulting database
110
occupies 309MB disk space.
111
112
To create the large Cremona database from Cremona's data_tgz tarball,
113
run the following command::
114
115
sage: d = sage.databases.cremona.build('cremona','ecdata.tgz') # not tested
116
"""
117
t = name.replace(' ','_')
118
if os.path.exists("%s/cremona/%s.db"%(SAGE_DATA, t)):
119
raise RuntimeError("Please (re)move %s/cremona/%s.db"%(SAGE_DATA, t)
120
+ " before rebuilding database.")
121
if not os.path.exists(data_tgz):
122
raise IOError, "The data file is not at %s"%data_tgz
123
t = walltime()
124
125
if decompress:
126
cmd = "tar zxvf %s"%data_tgz
127
n = os.system(cmd)
128
if n:
129
raise RuntimeError, "Error extracting tarball."
130
if mini:
131
c = MiniCremonaDatabase(name,False,True)
132
else:
133
c = LargeCremonaDatabase(name,False,True)
134
c._init_from_ftpdata('ecdata', largest_conductor)
135
print "Total time: ", walltime(t)
136
137
def is_optimal_id(id):
138
"""
139
Returns true if the Cremona id refers to an optimal curve, and
140
false otherwise. The curve is optimal if the id, which is of the
141
form [letter code][number] has number 1.
142
143
.. note::
144
145
990h3 is the optimal curve in that class, so doesn't obey
146
this rule.
147
148
INPUT:
149
150
- ``id`` - str of form letter code followed by an
151
integer, e.g., a3, bb5, etc.
152
153
OUTPUT: bool
154
155
EXAMPLES::
156
157
sage: from sage.databases.cremona import is_optimal_id
158
sage: is_optimal_id('b1')
159
True
160
sage: is_optimal_id('bb1')
161
True
162
sage: is_optimal_id('c1')
163
True
164
sage: is_optimal_id('c2')
165
False
166
"""
167
return id[-1] == '1' and not id[-2].isdigit()
168
169
def cremona_letter_code(n):
170
"""
171
Returns the Cremona letter code corresponding to an integer. For
172
example, 0 - a 25 - z 26 - ba 51 - bz 52 - ca 53 - cb etc.
173
174
.. note::
175
176
This is just the base 26 representation of n, where a=0, b=1,
177
..., z=25. This extends the old Cremona notation (counting from
178
0) for the first 26 classes, and is different for classes above
179
26.
180
181
INPUT:
182
183
- ``n`` (int) -- a non-negative integer
184
185
OUTPUT: str
186
187
EXAMPLES::
188
189
sage: from sage.databases.cremona import cremona_letter_code
190
sage: cremona_letter_code(0)
191
'a'
192
sage: cremona_letter_code(26)
193
'ba'
194
sage: cremona_letter_code(27)
195
'bb'
196
sage: cremona_letter_code(521)
197
'ub'
198
sage: cremona_letter_code(53)
199
'cb'
200
sage: cremona_letter_code(2005)
201
'czd'
202
203
TESTS::
204
205
sage: cremona_letter_code(QQ)
206
Traceback (most recent call last):
207
...
208
ValueError: Cremona letter codes are only defined for non-negative integers
209
sage: cremona_letter_code(x)
210
Traceback (most recent call last):
211
...
212
ValueError: Cremona letter codes are only defined for non-negative integers
213
sage: cremona_letter_code(-1)
214
Traceback (most recent call last):
215
...
216
ValueError: Cremona letter codes are only defined for non-negative integers
217
sage: cremona_letter_code(3.14159)
218
Traceback (most recent call last):
219
...
220
ValueError: Cremona letter codes are only defined for non-negative integers
221
"""
222
try:
223
m = int(n)
224
if n == m:
225
n = m
226
else:
227
n = -1
228
except (ValueError, TypeError):
229
n = -1
230
231
if n<0:
232
raise ValueError, "Cremona letter codes are only defined for non-negative integers"
233
234
if n == 0:
235
return "a"
236
s = ""
237
while n != 0:
238
s = chr(n%26+97) + s
239
n //= 26
240
return s
241
242
def old_cremona_letter_code(n):
243
r"""
244
Returns the *old* Cremona letter code corresponding to an integer.
245
integer.
246
247
For example::
248
249
1 --> A
250
26 --> Z
251
27 --> AA
252
52 --> ZZ
253
53 --> AAA
254
etc.
255
256
INPUT:
257
258
- ``n`` - int
259
260
OUTPUT: str
261
262
EXAMPLES::
263
264
sage: from sage.databases.cremona import old_cremona_letter_code
265
sage: old_cremona_letter_code(1)
266
'A'
267
sage: old_cremona_letter_code(26)
268
'Z'
269
sage: old_cremona_letter_code(27)
270
'AA'
271
sage: old_cremona_letter_code(521)
272
'AAAAAAAAAAAAAAAAAAAAA'
273
sage: old_cremona_letter_code(53)
274
'AAA'
275
sage: old_cremona_letter_code(2005)
276
'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC'
277
"""
278
n -= 1
279
k = n%26 + 65
280
label = chr(k)*int(n//26 + 1)
281
return label
282
283
def parse_cremona_label(label):
284
"""
285
Given a Cremona label that defines an elliptic
286
curve, e.g., 11A1 or 37B3, parse the label and return the
287
conductor, isogeny class label, and number.
288
289
The isogeny number may be omitted, in which case it defaults to 1.
290
If the isogeny number and letter are both omitted, so label is just
291
a string representing a conductor, then the label defaults to 'A'
292
and the number to 1.
293
294
INPUT:
295
296
- ``label`` - str
297
298
OUTPUT:
299
300
- ``int`` - the conductor
301
- ``str`` - the isogeny class label
302
- ``int`` - the number
303
304
EXAMPLES::
305
306
sage: from sage.databases.cremona import parse_cremona_label
307
sage: parse_cremona_label('37a2')
308
(37, 'a', 2)
309
sage: parse_cremona_label('37b1')
310
(37, 'b', 1)
311
sage: parse_cremona_label('10bb2')
312
(10, 'bb', 2)
313
"""
314
if not isinstance(label, str):
315
label = str(label)
316
i=0
317
while i<len(label) and label[i]>='0' and label[i]<='9':
318
i += 1
319
j=i+1
320
if j>len(label):
321
label += "a"
322
while j<len(label) and not (label[j]>='0' and label[j]<='9'):
323
j += 1
324
if j>=len(label):
325
label += "1"
326
conductor, iso, num = int(label[:i]), label[i:j], int(label[j:])
327
return conductor, iso, num
328
329
def split_code(key):
330
"""
331
Splits class+curve id string into its two parts.
332
333
EXAMPLES::
334
335
sage: import sage.databases.cremona as cremona
336
sage: cremona.split_code('ba2')
337
('ba', '2')
338
"""
339
cu = re.split("[a-z]*",key)[1]
340
cl = re.split("[0-9]*",key)[0]
341
return (cl,cu)
342
343
def class_to_int(k):
344
"""
345
Converts class id string into an integer. Note that this is the
346
inverse of cremona_letter_code.
347
348
EXAMPLES::
349
350
sage: import sage.databases.cremona as cremona
351
sage: cremona.class_to_int('ba')
352
26
353
sage: cremona.class_to_int('cremona')
354
821863562
355
sage: cremona.cremona_letter_code(821863562)
356
'cremona'
357
"""
358
kk = [string.ascii_lowercase.index(ch) for ch in list(k)]
359
kk.reverse()
360
return sum([kk[i]*26**i for i in range(len(kk))])
361
362
def cmp_code(key1,key2):
363
"""
364
Comparison function for curve id strings.
365
366
.. note::
367
368
Not the same as standard lexicographic order!
369
370
EXAMPLES::
371
372
sage: import sage.databases.cremona as cremona
373
sage: cremona.cmp_code('ba1','z1')
374
1
375
376
By contrast::
377
378
sage: cmp('ba1','z1')
379
-1
380
"""
381
cl1,cu1 = split_code(key1)
382
cl2,cu2 = split_code(key2)
383
d = class_to_int(cl1)-class_to_int(cl2)
384
if d!=0: return d
385
return cmp(cu1,cu2)
386
387
class MiniCremonaDatabase(SQLDatabase):
388
"""
389
The Cremona database of elliptic curves.
390
391
EXAMPLES::
392
393
sage: c = CremonaDatabase()
394
sage: c.allcurves(11)
395
{'a1': [[0, -1, 1, -10, -20], 0, 5], 'a3': [[0, -1, 1, 0, 0], 0, 5],
396
'a2': [[0, -1, 1, -7820, -263580], 0, 1]}
397
"""
398
def __init__(self, name, read_only=True, build=False):
399
"""
400
Initialize the database.
401
402
TESTS::
403
404
sage: c = CremonaDatabase('cremona mini')
405
sage: c.name
406
'cremona mini'
407
"""
408
if build:
409
if name is None:
410
raise RuntimeError('The database must have a name.')
411
if read_only:
412
raise RuntimeError('The database must not be read_only.')
413
self.name = name
414
name = name.replace(' ','_')
415
SQLDatabase.__init__(self, '%s/cremona/%s.db'%(SAGE_DATA, name), \
416
read_only=read_only, skeleton=_miniCremonaSkeleton)
417
return
418
self.name = name
419
name = name.replace(' ','_')
420
SQLDatabase.__init__(self, '%s/cremona/%s.db'%(SAGE_DATA, name), \
421
read_only=read_only)
422
if self.get_skeleton() != _miniCremonaSkeleton:
423
raise RuntimeError('Database at %s does '%(self.__dblocation__) \
424
+ 'not appear to be a valid SQL Cremona database.')
425
426
def __iter__(self):
427
"""
428
Returns an iterator through all EllipticCurve objects in the
429
Cremona database.
430
431
TESTS::
432
433
sage: it = CremonaDatabase().__iter__()
434
sage: it.next().label()
435
'11a1'
436
sage: it.next().label()
437
'11a2'
438
sage: it.next().label()
439
'11a3'
440
sage: it.next().label()
441
'14a1'
442
sage: skip = [it.next() for _ in range(100)]
443
sage: it.next().label()
444
'45a3'
445
"""
446
for c in self.__connection__.cursor().execute('SELECT curve FROM ' \
447
+ 't_curve'):
448
yield self.elliptic_curve(c[0])
449
450
def __getitem__(self, N):
451
"""
452
If N is an integer, return all data about level N in the database.
453
If N is a string it must be a Cremona label, in which case return
454
the corresponding elliptic curve, if it is in the database.
455
456
INPUT:
457
458
- ``N`` - int or str
459
460
OUTPUT: dict (if N is an int) or EllipticCurve (if N is a str)
461
462
TESTS::
463
464
sage: c = CremonaDatabase()
465
sage: c[11]['allcurves']['a2']
466
[[0, -1, 1, -7820, -263580], 0, 1]
467
sage: c['11a2']
468
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field
469
"""
470
if isinstance(N, str):
471
return self.elliptic_curve(N)
472
473
try:
474
N = int(N)
475
except ValueError:
476
raise KeyError("N (=%s) must be a string or positive integer."%N)
477
478
if N <= 0:
479
raise KeyError("N (=%s) must be a string or positive integer."%N)
480
481
ret = {'allcurves': self.allcurves(N)}
482
if hasattr(self, 'allbsd'):
483
ret['allbsd'] = self.allbsd(N)
484
if hasattr(self, 'degphi'):
485
ret['degphi'] = self.degphi(N)
486
if hasattr(self, 'allgens'):
487
ret['allgens'] = self.allgens(N)
488
return ret
489
490
def __repr__(self):
491
"""
492
String representation of this database.
493
494
TESTS::
495
496
sage: c = CremonaDatabase('cremona mini')
497
sage: c.__repr__()
498
"Cremona's database of elliptic curves with conductor at most 9999"
499
"""
500
return "Cremona's database of elliptic curves with conductor at most "\
501
+ str(self.largest_conductor())
502
503
def allcurves(self, N):
504
"""
505
Returns the allcurves table of curves of conductor N.
506
507
INPUT:
508
509
- ``N`` - int, the conductor
510
511
OUTPUT:
512
513
- ``dict`` - id:[ainvs, rank, tor], ...
514
515
EXAMPLES::
516
517
sage: c = CremonaDatabase()
518
sage: c.allcurves(11)['a3']
519
[[0, -1, 1, 0, 0], 0, 5]
520
sage: c.allcurves(12)
521
{}
522
sage: c.allcurves(12001)['a1'] # optional - database_cremona_ellcurve
523
[[1, 0, 0, -101, 382], 1, 1]
524
"""
525
ret = {}
526
for c in self.__connection__.cursor().execute('SELECT curve,eqn,' \
527
+ 'rank,tors FROM t_curve,t_class USING(class) WHERE ' \
528
+ 'conductor=?',(int(N),)):
529
N,iso,num = parse_cremona_label(c[0])
530
ret[iso+str(num)] = [eval(c[1]),c[2],c[3]]
531
return ret
532
533
def curves(self, N):
534
"""
535
Returns the curves table of all *optimal* curves of conductor N.
536
537
INPUT:
538
539
- ``N`` - int, the conductor
540
541
OUTPUT:
542
543
- ``dict`` - id:[ainvs, rank, tor], ...
544
545
EXAMPLES:
546
547
Optimal curves of conductor 37::
548
549
sage: CremonaDatabase().curves(37)
550
{'a1': [[0, 0, 1, -1, 0], 1, 1], 'b1': [[0, 1, 1, -23, -50], 0, 3]}
551
552
Note the 'h3', which is the unique case in the tables where
553
the optimal curve doesn't have label ending in 1::
554
555
sage: list(sorted(CremonaDatabase().curves(990).keys()))
556
['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h3', 'i1', 'j1', 'k1', 'l1']
557
558
TESTS::
559
560
sage: c = CremonaDatabase()
561
sage: c.curves(12001)['a1'] # optional - database_cremona_ellcurve
562
[[1, 0, 0, -101, 382], 1, 1]
563
"""
564
ret = {}
565
for c in self.__connection__.cursor().execute('SELECT curve,eqn,' \
566
+ 'rank,tors FROM t_curve,t_class USING(class) WHERE ' \
567
+ 'curve=class||1 AND conductor=?',(int(N),)):
568
N,iso,num = parse_cremona_label(c[0])
569
ret[iso+str(num)] = [eval(c[1]),c[2],c[3]]
570
if N == 990:
571
del ret['h1']
572
ret['h3'] = [[1,-1,1,-1568,-4669],int(1),int(6)]
573
return ret
574
575
def elliptic_curve_from_ainvs(self, ainvs):
576
"""
577
Returns the elliptic curve in the database of with minimal
578
ainvs, if it exists, or raises a RuntimeError exception
579
otherwise.
580
581
INPUT:
582
583
- ``ainvs`` - list (5-tuple of int's); the minimal
584
Weierstrass model for an elliptic curve
585
586
OUTPUT: EllipticCurve
587
588
EXAMPLES::
589
590
sage: c = CremonaDatabase()
591
sage: c.elliptic_curve_from_ainvs([0, -1, 1, -10, -20])
592
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
593
sage: c.elliptic_curve_from_ainvs([1, 0, 0, -101, 382]) # optional - database_cremona_ellcurve
594
Elliptic Curve defined by y^2 + x*y = x^3 - 101*x + 382 over Rational Field
595
"""
596
q = self.__connection__.cursor().execute("SELECT curve FROM t_curve " \
597
+ "WHERE eqn=?",(str(ainvs).replace(' ',''),))
598
try:
599
return self.elliptic_curve(q.next()[0])
600
except StopIteration:
601
raise RuntimeError("No elliptic curve with ainvs (=%s) "%ainvs \
602
+ "in the database.")
603
604
def elliptic_curve(self, label):
605
"""
606
Return an elliptic curve with given label with some data about it
607
from the database pre-filled in.
608
609
INPUT:
610
611
- ``label`` - str (Cremona label)
612
613
OUTPUT: EllipticCurve
614
615
EXAMPLES::
616
617
sage: c = CremonaDatabase()
618
sage: c.elliptic_curve('11a1')
619
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
620
sage: c.elliptic_curve('12001a1') # optional - database_cremona_ellcurve
621
Elliptic Curve defined by y^2 + x*y = x^3 - 101*x + 382 over Rational Field
622
sage: c.elliptic_curve('48c1')
623
Traceback (most recent call last):
624
...
625
ValueError: There is no elliptic curve with label 48c1 in the database (note: use lower case letters!)
626
"""
627
N, iso, num = parse_cremona_label(label)
628
label = str(N)+iso+str(num)
629
if self.get_skeleton() == _miniCremonaSkeleton:
630
q = self.__connection__.cursor().execute("SELECT eqn,rank,tors " \
631
+ 'FROM t_curve,t_class USING(class) WHERE curve=?', (label,))
632
else:
633
q = self.__connection__.cursor().execute("SELECT eqn,rank,tors," \
634
+ "deg,gens,cp,om,L,reg,sha FROM t_curve,t_class " \
635
+ "USING(class) WHERE curve=?",(label,))
636
try:
637
c = q.next()
638
F = elliptic.EllipticCurve(eval(c[0]))
639
F._set_cremona_label(label)
640
F._set_rank(c[1])
641
F._set_torsion_order(c[2])
642
F._set_conductor(N)
643
if len(c) > 3:
644
if num == 1:
645
F._set_modular_degree(c[3])
646
F._set_gens(eval(c[4]))
647
F.db_extra = list(c[5:])
648
elif c[1] == 0:
649
# we know the rank is 0, so the gens are empty
650
F._set_gens([])
651
return F
652
except StopIteration:
653
if N < self.largest_conductor():
654
message = "There is no elliptic curve with label " + label \
655
+ " in the database (note: use lower case letters!)"
656
elif 'database_cremona_ellcurve' in \
657
[s.split('-')[0] for s in optional_packages()[0]]:
658
message = "There is no elliptic curve with label " + label \
659
+ " in the currently available databases"
660
else:
661
message = "There is no elliptic curve with label " \
662
+ label + " in the default database; try installing " \
663
+ "the optional package database_cremona_ellcurve which " \
664
+ "contains the complete Cremona database"
665
raise ValueError(message)
666
667
def iter(self, conductors):
668
"""
669
Return an iterator through all curves in the database with given
670
conductors.
671
672
INPUT:
673
674
- ``conductors`` - list or generator of ints
675
676
OUTPUT: generator that iterates over EllipticCurve objects.
677
678
EXAMPLES::
679
680
sage: [e.cremona_label() for e in CremonaDatabase().iter([11..15])]
681
['11a1', '11a2', '11a3', '14a1', '14a2', '14a3', '14a4', '14a5',
682
'14a6', '15a1', '15a2', '15a3', '15a4', '15a5', '15a6', '15a7', '15a8']
683
"""
684
for N in conductors:
685
for c in self.__connection__.cursor().execute('SELECT curve ' \
686
+ 'FROM t_curve,t_class USING(class) WHERE conductor=?', \
687
(int(N),)):
688
yield self.elliptic_curve(c[0])
689
690
def isogeny_classes(self, conductor):
691
"""
692
Return the allcurves data (ainvariants, rank and torsion) for the
693
elliptic curves in the database of given conductor as a list of
694
lists, one for each isogeny class. The curve with number 1 is
695
always listed first.
696
697
EXAMPLES::
698
699
sage: c = CremonaDatabase()
700
sage: c.isogeny_classes(11)
701
[[[[0, -1, 1, -10, -20], 0, 5],
702
[[0, -1, 1, -7820, -263580], 0, 1],
703
[[0, -1, 1, 0, 0], 0, 5]]]
704
sage: c.isogeny_classes(12001) # optional - database_cremona_ellcurve
705
[[[[1, 0, 0, -101, 382], 1, 1]],
706
[[[0, 0, 1, -247, 1494], 1, 1]],
707
[[[0, 0, 1, -4, -18], 1, 1]],
708
[[[0, 1, 1, -10, 18], 1, 1]]]
709
"""
710
conductor=int(conductor)
711
classes = []
712
A = self.allcurves(conductor)
713
K = A.keys()
714
K.sort(cmp_code)
715
for k in K:
716
v = A[k]
717
# test if not first curve in class
718
if not (k[-1] == '1' and k[-2].isalpha()):
719
classes[len(classes)-1].append(v)
720
else:
721
classes.append([v])
722
return classes
723
724
def isogeny_class(self, label):
725
"""
726
Returns the isogeny class of elliptic curves that are
727
isogenous to the curve with given Cremona label.
728
729
INPUT:
730
731
- ``label`` - string
732
733
OUTPUT:
734
735
- ``list`` - list of EllipticCurve objects.
736
737
EXAMPLES::
738
739
sage: c = CremonaDatabase()
740
sage: c.isogeny_class('11a1')
741
[Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field,
742
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field,
743
Elliptic Curve defined by y^2 + y = x^3 - x^2 over Rational Field]
744
sage: c.isogeny_class('12001a1') # optional - database_cremona_ellcurve
745
[Elliptic Curve defined by y^2 + x*y = x^3 - 101*x + 382 over Rational Field]
746
"""
747
conductor,iso,num=parse_cremona_label(label)
748
q = self.__connection__.cursor().execute("SELECT curve FROM t_curve " \
749
+ "WHERE class=?",(str(conductor)+iso,))
750
return [self.elliptic_curve(c[0]) for c in q]
751
752
def iter_optimal(self, conductors):
753
"""
754
Return an iterator through all optimal curves in the database with given conductors.
755
756
INPUT:
757
758
- ``conductors`` - list or generator of ints
759
760
OUTPUT:
761
762
generator that iterates over EllipticCurve objects.
763
764
EXAMPLES:
765
766
We list optimal curves with conductor up to 20::
767
768
sage: [e.cremona_label() for e in CremonaDatabase().iter_optimal([11..20])]
769
['11a1', '14a1', '15a1', '17a1', '19a1', '20a1']
770
771
Note the unfortunate 990h3 special case::
772
773
sage: [e.cremona_label() for e in CremonaDatabase().iter_optimal([990])]
774
['990a1', '990b1', '990c1', '990d1', '990e1', '990f1', '990g1', '990h3', '990i1', '990j1', '990k1', '990l1']
775
"""
776
for N in conductors:
777
if N == 990:
778
for c in self.__connection__.cursor().execute('SELECT class ' \
779
+ 'FROM t_class WHERE conductor=990'):
780
if c[0][-1] == u'h':
781
yield self.elliptic_curve(c[0]+u'3')
782
else:
783
yield self.elliptic_curve(c[0]+u'1')
784
continue
785
for c in self.__connection__.cursor().execute('SELECT curve ' \
786
+ 'FROM t_curve,t_class USING(class) WHERE curve=class||1 ' \
787
+ 'AND conductor=?',(int(N),)):
788
yield self.elliptic_curve(c[0])
789
790
def list(self, conductors):
791
"""
792
Returns a list of all curves with given conductors.
793
794
INPUT:
795
796
- ``conductors`` - list or generator of ints
797
798
OUTPUT:
799
800
- list of EllipticCurve objects.
801
802
EXAMPLES::
803
804
sage: CremonaDatabase().list([37])
805
[Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field,
806
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 23*x - 50 over Rational Field,
807
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field,
808
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 3*x + 1 over Rational Field]
809
"""
810
return list(self.iter(conductors))
811
812
def list_optimal(self, conductors):
813
"""
814
Returns a list of all optimal curves with given conductors.
815
816
INPUT:
817
818
- ``conductors`` - list or generator of ints
819
list of EllipticCurve objects.
820
821
OUTPUT:
822
823
list of EllipticCurve objects.
824
825
EXAMPLES::
826
827
sage: CremonaDatabase().list_optimal([37])
828
[Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field,
829
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 23*x - 50 over Rational Field]
830
"""
831
return list(self.iter_optimal(conductors))
832
833
def largest_conductor(self):
834
"""
835
The largest conductor for which the database is complete.
836
837
OUTPUT:
838
839
- ``int`` - largest conductor
840
841
EXAMPLES::
842
843
sage: c = CremonaDatabase('cremona mini')
844
sage: c.largest_conductor()
845
9999
846
"""
847
if hasattr(self, '__largest_conductor__'):
848
return self.__largest_conductor__
849
#print "Computing largest conductor."
850
q = self.__connection__.cursor().execute('SELECT conductor FROM ' \
851
+ 't_class ORDER BY conductor DESC LIMIT 1')
852
self.__largest_conductor__ = q.next()[0]
853
return self.__largest_conductor__
854
855
def smallest_conductor(self):
856
"""
857
The smallest conductor for which the database is complete: always 1.
858
859
OUTPUT:
860
861
- ``int`` - smallest conductor
862
863
.. note::
864
865
This always returns the integer 1, since that is the
866
smallest conductor for which the database is complete,
867
although there are no elliptic curves of conductor 1. The
868
smallest conductor of a curve in the database is 11.
869
870
EXAMPLES::
871
872
sage: CremonaDatabase().smallest_conductor()
873
1
874
"""
875
return 1
876
877
def conductor_range(self):
878
"""
879
Return the range of conductors that are covered by the database.
880
881
OUTPUT: tuple of ints (N1,N2+1) where N1 is the smallest and
882
N2 the largest conductor for which the database is complete.
883
884
EXAMPLES::
885
886
sage: c = CremonaDatabase('cremona mini')
887
sage: c.conductor_range()
888
(1, 10000)
889
"""
890
return 1, self.largest_conductor()+1
891
892
def number_of_curves(self, N=0, i=0):
893
"""
894
Returns the number of curves stored in the database with conductor
895
N. If N = 0, returns the total number of curves in the database.
896
897
If i is nonzero, returns the number of curves in the i-th isogeny
898
class. If i is a Cremona letter code, e.g., 'a' or 'bc', it is
899
converted to the corresponding number.
900
901
INPUT:
902
903
- ``N`` - int
904
- ``i`` - int or str
905
906
OUTPUT: int
907
908
EXAMPLES::
909
910
sage: c = CremonaDatabase()
911
sage: c.number_of_curves(11)
912
3
913
sage: c.number_of_curves(37)
914
4
915
sage: c.number_of_curves(990)
916
42
917
sage: num = c.number_of_curves()
918
"""
919
if N == 0:
920
if hasattr(self, '__number_of_curves__'):
921
return self.__number_of_curves__
922
q = self.__connection__.cursor().execute('SELECT COUNT(curve) ' \
923
+ 'FROM t_curve')
924
self.__number_of_curves__ = q.next()[0]
925
return self.__number_of_curves__
926
if i == 0:
927
q = self.__connection__.cursor().execute('SELECT COUNT(curve) ' \
928
+ 'FROM t_curve,t_class USING(class) WHERE conductor=?', \
929
(int(N),))
930
return q.next()[0]
931
if not isinstance(i, str):
932
i = cremona_letter_code(i)
933
q = self.__connection__.cursor().execute('SELECT COUNT(curve) FROM ' \
934
+ 't_curve WHERE class=?',(str(N)+i,))
935
return q.next()[0]
936
937
def number_of_isogeny_classes(self, N=0):
938
"""
939
Returns the number of isogeny classes of curves in the database of
940
conductor N. If N is 0, return the total number of isogeny classes
941
of curves in the database.
942
943
INPUT:
944
945
- ``N`` - int
946
947
OUTPUT: int
948
949
EXAMPLES::
950
951
sage: c = CremonaDatabase()
952
sage: c.number_of_isogeny_classes(11)
953
1
954
sage: c.number_of_isogeny_classes(37)
955
2
956
sage: num = c.number_of_isogeny_classes()
957
"""
958
if N == 0:
959
if hasattr(self, '__number_of_isogeny_classes__'):
960
return self.__number_of_isogeny_classes__
961
q = self.__connection__.cursor().execute('SELECT COUNT(class) ' \
962
+ 'FROM t_class')
963
self.__number_of_isogeny_classes__ = q.next()[0]
964
return self.__number_of_isogeny_classes__
965
q = self.__connection__.cursor().execute('SELECT COUNT(class) FROM ' \
966
+ 't_class WHERE conductor=?',(int(N),))
967
return q.next()[0]
968
969
def random(self):
970
"""
971
Returns a random curve from the database.
972
973
EXAMPLES::
974
975
sage: CremonaDatabase().random() # random -- depends on database installed
976
Elliptic Curve defined by y^2 + x*y = x^3 - x^2 - 224*x + 3072 over Rational Field
977
"""
978
N = randint(11, self.largest_conductor())
979
q = self.__connection__.cursor().execute('SELECT conductor FROM ' \
980
+ 't_class WHERE conductor>=? ORDER BY conductor',(int(N),))
981
try:
982
N = q.next()[0]
983
except StopIteration:
984
N = 11
985
iso = randint(0, self.number_of_isogeny_classes(N)-1)
986
iso = cremona_letter_code(iso)
987
num = randint(1, self.number_of_curves(N,iso))
988
return self.elliptic_curve(str(N)+iso+str(num))
989
990
###############################################################################
991
# Functions for loading data from Cremona's ftpdata directory.
992
###############################################################################
993
def _init_from_ftpdata(self, ftpdata, largest_conductor=0):
994
"""
995
Create the SQL Cremona Database from the Cremona data directory,
996
which is available from Cremona's website. I.e., just wget
997
Cremona's database to a local directory.
998
999
To create the large database from Cremona's text files, see
1000
sage.databases.cremona.build, do NOT run this method directly.
1001
1002
EXAMPLES::
1003
1004
sage: d = sage.databases.cremona.MiniCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1005
sage: d._init_from_ftpdata('.') # not tested
1006
"""
1007
if self.__read_only__:
1008
raise RuntimeError("The database must not be read_only.")
1009
1010
if not os.path.exists(ftpdata):
1011
raise RuntimeError("The cremona ftpdata directory '" + ftpdata \
1012
+ "' does not exist.")
1013
1014
if largest_conductor:
1015
print "largest conductor =", largest_conductor
1016
self.__largest_conductor__ = largest_conductor
1017
1018
num_curves, num_iso_classes = self._init_allcurves(ftpdata, largest_conductor)
1019
self.__number_of_curves__ = num_curves
1020
self.__number_of_isogeny_classes__ = num_iso_classes
1021
if hasattr(self, 'degphi'):
1022
self._init_degphi(ftpdata, largest_conductor)
1023
if hasattr(self, 'allbsd'):
1024
self._init_allbsd(ftpdata, largest_conductor)
1025
if hasattr(self, 'allgens'):
1026
self._init_allgens(ftpdata, largest_conductor)
1027
self.vacuum()
1028
1029
def _init_allcurves(self, ftpdata, largest_conductor=0):
1030
"""
1031
Initialize the allcurves table by reading the corresponding ftpdata
1032
files and importing them into the database.
1033
1034
To create the large database from Cremona's text files, see
1035
sage.databases.cremona.build, do NOT run this method directly.
1036
1037
INPUT:
1038
1039
- ``largest_conductor`` - int (default: 0), if 0,
1040
then only include data up to that conductor.
1041
1042
OUTPUT:
1043
1044
- ``int`` - number_of_curves
1045
- ``int`` - number_of_isogeny_classes
1046
1047
EXAMPLES::
1048
1049
sage: d = sage.databases.cremona.MiniCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1050
sage: d._init_allcurves('.', 11) # not tested
1051
(3, 1)
1052
"""
1053
if self.__read_only__:
1054
raise RuntimeError("The database must not be read_only.")
1055
files = os.listdir(ftpdata)
1056
files.sort()
1057
name = 'allcurves'
1058
num_curves = 0
1059
num_iso_classes = 0
1060
con = self.get_connection()
1061
for F in files:
1062
if not F[:len(name)] == name:
1063
continue
1064
print "Inserting", F
1065
class_data = []
1066
curve_data = []
1067
for L in file(ftpdata + "/" + F).readlines():
1068
N, iso, num, ainvs, r, tor = L.split()
1069
if largest_conductor and int(N) > largest_conductor: break
1070
cls = N+iso
1071
cur = cls+num
1072
if num == "1":
1073
class_data.append((N,cls,r))
1074
num_iso_classes += 1
1075
curve_data.append((cur,cls,ainvs,tor))
1076
num_curves += 1
1077
con.executemany('INSERT INTO t_class (conductor,class,rank) ' \
1078
+ 'VALUES (?,?,?)', class_data)
1079
con.executemany('INSERT INTO t_curve (curve,class,eqn,tors) ' \
1080
+ 'VALUES (?,?,?,?)', curve_data)
1081
print "Committing..."
1082
print "num_iso_classes =", num_iso_classes
1083
self.commit()
1084
if largest_conductor and int(N) > largest_conductor: break
1085
return num_curves, num_iso_classes
1086
1087
class LargeCremonaDatabase(MiniCremonaDatabase):
1088
"""
1089
The Cremona database of elliptic curves.
1090
1091
EXAMPLES::
1092
1093
sage: c = CremonaDatabase('cremona') # optional - database_cremona_ellcurve
1094
sage: c.allcurves(11) # optional - database_cremona_ellcurve
1095
{'a1': [[0, -1, 1, -10, -20], 0, 5], 'a3': [[0, -1, 1, 0, 0], 0, 5],
1096
'a2': [[0, -1, 1, -7820, -263580], 0, 1]}
1097
"""
1098
def __init__(self, name, read_only=True, build=False):
1099
"""
1100
Initialize the database.
1101
1102
TESTS::
1103
1104
sage: c = CremonaDatabase('cremona') # optional - database_cremona_ellcurve
1105
sage: c.name # optional - database_cremona_ellcurve
1106
'cremona'
1107
"""
1108
if build:
1109
if name is None:
1110
raise RuntimeError('The database must have a name.')
1111
if read_only:
1112
raise RuntimeError('The database must not be read_only.')
1113
self.name = name
1114
name = name.replace(' ','_')
1115
SQLDatabase.__init__(self, '%s/cremona/%s.db'%(SAGE_DATA, name), \
1116
read_only=read_only, skeleton=_cremonaSkeleton)
1117
return
1118
self.name = name
1119
name = name.replace(' ','_')
1120
SQLDatabase.__init__(self, '%s/cremona/%s.db'%(SAGE_DATA, name), \
1121
read_only=read_only)
1122
if self.get_skeleton() != _cremonaSkeleton:
1123
raise RuntimeError('Database at %s does '%(self.__dblocation__) \
1124
+ 'not appear to be a valid SQL Cremona database.')
1125
1126
def allbsd(self, N):
1127
r"""
1128
Return the allbsd table for conductor N. The entries are::
1129
1130
[id, tamagawa_product, Omega_E, L, Reg_E, Sha_an(E)]
1131
1132
where id is the isogeny class (letter) followed by a number, e.g.,
1133
b3, and L is `L^r(E,1)/r!`, where E has rank r.
1134
1135
INPUT:
1136
1137
- ``N`` - int, the conductor
1138
1139
OUTPUT: dict containing the allbsd table for each isogeny class
1140
in conductor N
1141
1142
EXAMPLES::
1143
1144
sage: c = CremonaDatabase()
1145
sage: c.allbsd(12) # optional - database_cremona_ellcurve
1146
{}
1147
sage: c.allbsd(19)['a3'] # optional - database_cremona_ellcurve
1148
[1, 4.079279200464932, 0.4532532444961036, 1.0, 1]
1149
sage: c.allbsd(12001)['a1'] # optional - database_cremona_ellcurve
1150
[2, 3.2760813524872185, 1.5491014309050595, 0.23642597118795194, 1]
1151
"""
1152
ret = {}
1153
for c in self.__connection__.cursor().execute('SELECT curve,cp,om,L,' \
1154
+ 'reg,sha FROM t_curve,t_class USING(class) WHERE conductor=?', \
1155
(int(N),)):
1156
N,iso,num = parse_cremona_label(c[0])
1157
ret[iso+str(num)] = list(c[1:])
1158
return ret
1159
1160
def allgens(self, N):
1161
"""
1162
Return the allgens table for conductor N.
1163
1164
INPUT:
1165
1166
- ``N`` - int, the conductor
1167
1168
OUTPUT:
1169
1170
- ``dict`` - id:[points, ...], ...
1171
1172
EXAMPLES::
1173
1174
sage: c = CremonaDatabase()
1175
sage: c.allgens(12) # optional - database_cremona_ellcurve
1176
{}
1177
sage: c.allgens(1001)['a1'] # optional - database_cremona_ellcurve
1178
[[61, 181, 1]]
1179
sage: c.allgens(12001)['a1'] # optional - database_cremona_ellcurve
1180
[[7, 2, 1]]
1181
"""
1182
ret = {}
1183
for c in self.__connection__.cursor().execute('SELECT curve,gens ' \
1184
+ 'FROM t_curve,t_class USING(class) WHERE conductor=?',(int(N),)):
1185
N,iso,num = parse_cremona_label(c[0])
1186
ret[iso+str(num)] = eval(c[1])
1187
return ret
1188
1189
def degphi(self, N):
1190
"""
1191
Return the degphi table for conductor N.
1192
1193
INPUT:
1194
1195
- ``N`` - int, the conductor
1196
1197
OUTPUT:
1198
1199
- ``dict`` - id:degphi, ...
1200
1201
EXAMPLES::
1202
1203
sage: c = CremonaDatabase()
1204
sage: c.degphi(11) # optional - database_cremona_ellcurve
1205
{'a1': 1}
1206
sage: c.degphi(12001)['c1'] # optional - database_cremona_ellcurve
1207
1640
1208
"""
1209
ret = {}
1210
for c in self.__connection__.cursor().execute('SELECT curve,deg FROM' \
1211
+ ' t_curve,t_class USING(class) WHERE curve=class||1 AND ' \
1212
+ 'conductor=?', (int(N),)):
1213
N,iso,num = parse_cremona_label(c[0])
1214
ret[iso+str(num)] = c[1]
1215
return ret
1216
1217
def _init_degphi(self, ftpdata, largest_conductor=0):
1218
"""
1219
Initialize the degphi table by reading the corresponding ftpdata
1220
files and importing them into the database.
1221
1222
To create the large database from Cremona's text files, see
1223
sage.databases.cremona.build, do NOT run this method directly.
1224
1225
EXAMPLES::
1226
1227
sage: d = sage.databases.cremona.LargeCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1228
sage: d._init_degphi('.') # not tested
1229
"""
1230
if self.__read_only__:
1231
raise RuntimeError, "The database must not be read_only."
1232
files = os.listdir(ftpdata)
1233
files.sort()
1234
name = "degphi"
1235
con = self.get_connection()
1236
for F in files:
1237
if not F[:len(name)] == name:
1238
continue
1239
print "Inserting", F
1240
class_data = []
1241
for L in file(ftpdata + "/" + F).readlines():
1242
N, iso, num, degree, primes, curve = L.split()
1243
if largest_conductor and int(N) > largest_conductor: break
1244
class_data.append((degree,N+iso))
1245
con.executemany('UPDATE t_class SET deg=? WHERE class=?', \
1246
class_data)
1247
print "Committing..."
1248
self.commit()
1249
if largest_conductor and int(N) > largest_conductor: break
1250
1251
def _init_allbsd(self, ftpdata, largest_conductor=0):
1252
"""
1253
Initialize the allbsd table by reading the corresponding ftpdata
1254
files and importing them into the database.
1255
1256
To create the large database from Cremona's text files, see
1257
sage.databases.cremona.build, do NOT run this method directly.
1258
1259
EXAMPLES::
1260
1261
sage: d = sage.databases.cremona.LargeCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1262
sage: d._init_allbsd('.') # not tested
1263
"""
1264
if self.__read_only__:
1265
raise RuntimeError, "The database must not be read_only."
1266
files = os.listdir(ftpdata)
1267
files.sort()
1268
name = "allbsd"
1269
con = self.get_connection()
1270
for F in files:
1271
if not F[:len(name)] == name:
1272
continue
1273
print "Inserting", F
1274
curve_data = []
1275
class_data = []
1276
for L in file(ftpdata + "/" + F).readlines():
1277
N, iso, num, eqn, rank, tor, cp, om, L, reg, sha = L.split()
1278
if largest_conductor and int(N) > largest_conductor: break
1279
cls = N+iso
1280
if num == "1":
1281
class_data.append((L,cls))
1282
curve_data.append((cp,om,reg,eval(sha),cls+num))
1283
con.executemany("UPDATE t_class SET L=? WHERE class=?", class_data)
1284
con.executemany("UPDATE t_curve SET cp=?,om=?,reg=?,sha=? WHERE " \
1285
+ "curve=?", curve_data)
1286
print "Committing..."
1287
self.commit()
1288
if largest_conductor and int(N) > largest_conductor: break
1289
1290
def _init_allgens(self, ftpdata, largest_conductor=0):
1291
"""
1292
Initialize the allgens table by reading the corresponding ftpdata
1293
files and importing them into the database.
1294
1295
To create the large database from Cremona's text files, see
1296
sage.databases.cremona.build, do NOT run this method directly.
1297
1298
EXAMPLES::
1299
1300
sage: d = sage.databases.cremona.LargeCremonaDatabase(name='cremona', read_only=False, rebuild=True) # not tested
1301
sage: d._init_allgens('.') # not tested
1302
"""
1303
if self.__read_only__:
1304
raise RuntimeError, "The database must not be read_only."
1305
files = os.listdir(ftpdata)
1306
files.sort()
1307
name = "allgens"
1308
con = self.get_connection()
1309
for F in files:
1310
if not F[:len(name)] == name:
1311
continue
1312
print "Inserting", F
1313
curve_data = []
1314
for L in file(ftpdata + "/" + F).readlines():
1315
v = L.split()
1316
if largest_conductor and int(v[0]) > largest_conductor: break
1317
gens = '['+','.join(v[6:6+int(v[4])]).replace(':',',')+']'
1318
curve_data.append((gens,''.join(v[:3])))
1319
con.executemany("UPDATE t_curve SET gens=? WHERE curve=?", \
1320
curve_data)
1321
print "Committing..."
1322
if largest_conductor and int(v[0]) > largest_conductor: break
1323
1324
_db = None
1325
def CremonaDatabase(name=None,mini=None,set_global=None):
1326
"""
1327
Initializes the Cremona database with name ``name``. If ``name`` is
1328
``None`` it instead initializes large Cremona database (named 'cremona'),
1329
if available or default mini Cremona database (named 'cremona mini').
1330
1331
If the Cremona database in question is in the format of the mini database,
1332
you must set ``mini=True``, otherwise it must be set to ``False``.
1333
1334
If you would like other components of Sage to use this database, mark
1335
``set_global=True``.
1336
1337
TESTS::
1338
1339
sage: c = CremonaDatabase()
1340
sage: isinstance(c, sage.databases.cremona.MiniCremonaDatabase)
1341
True
1342
sage: isinstance(c, sage.databases.cremona.LargeCremonaDatabase) # optional - database_cremona_ellcurve
1343
True
1344
"""
1345
global _db
1346
if set_global is None:
1347
set_global = _db is None and name is None
1348
if name is None and not set_global:
1349
return _db
1350
if set_global and name is None:
1351
if os.path.isfile('%s/cremona/cremona.db'%SAGE_DATA):
1352
name = 'cremona'
1353
elif os.path.isfile('%s/cremona/cremona_mini.db'%SAGE_DATA):
1354
name = 'cremona mini'
1355
else:
1356
raise RuntimeError('Could not find valid cremona database. ' \
1357
+ 'Please make sure SAGE_DATA is set correctly.')
1358
if name == 'cremona':
1359
mini = False
1360
elif name == 'cremona mini':
1361
mini = True
1362
if mini is None:
1363
raise ValueError('mini must be set as either True or False')
1364
if set_global:
1365
if mini:
1366
_db = MiniCremonaDatabase(name)
1367
else:
1368
_db = LargeCremonaDatabase(name)
1369
return _db
1370
if mini:
1371
return MiniCremonaDatabase(name)
1372
return LargeCremonaDatabase(name)
1373
1374