3
3
4
4
AUTHORS:
5
5
6
- - Jon Bobber -- 2009 rewrite
6
+ - Jon Bobber ( 2009): rewrite
7
7
8
- - William Stein -- 2009 rewrite
8
+ - William Stein (2009): rewrite
9
+
10
+ - Julian Rueth (2014-03-02): use UniqueFactory for caching
9
11
10
12
This code is partly based on Sage code by David Kohel from 2005.
11
13
21
23
########################################################################
22
24
# Copyright (C) 2009 William Stein <[email protected] >
23
25
# Copyright (C) 2009 Jonathon Bober <[email protected] >
26
+ # Copyright (C) 2014 Julian Rueth <[email protected] >
24
27
#
25
28
# Distributed under the terms of the GNU General Public License (GPL)
26
29
#
53
56
from sage .matrix .constructor import diagonal_matrix , matrix
54
57
from sage .structure .sequence import Sequence
55
58
from sage .structure .element import is_RingElement
59
+ from sage .structure .factory import UniqueFactory
56
60
from sage .modules .free_module import VectorSpace , FreeModule
57
61
from sage .modules .free_module_element import vector
58
62
72
76
# Constructor
73
77
########################################################
74
78
75
- _cache = {}
76
-
77
- def QuaternionAlgebra (arg0 , arg1 = None , arg2 = None , names = 'i,j,k' ):
79
+ class QuaternionAlgebraFactory (UniqueFactory ):
78
80
"""
79
81
There are three input formats:
80
82
@@ -192,60 +194,76 @@ def QuaternionAlgebra(arg0, arg1=None, arg2=None, names='i,j,k'):
192
194
sage: parent(Q._b)
193
195
Rational Field
194
196
"""
197
+ def create_key (self , arg0 , arg1 = None , arg2 = None , names = 'i,j,k' ):
198
+ """
199
+ Create a key that uniquely determines a quaternion algebra.
195
200
196
- # QuaternionAlgebra(D)
197
- if arg1 is None and arg2 is None :
198
- K = QQ
199
- D = Integer (arg0 )
200
- a , b = hilbert_conductor_inverse (D )
201
- a = Rational (a ); b = Rational (b )
201
+ TESTS::
202
202
203
- elif arg2 is None :
204
- # If arg0 or arg1 are Python data types, coerce them
205
- # to the relevant Sage types. This is a bit inelegant.
206
- L = []
207
- for a in [arg0 ,arg1 ]:
208
- if is_RingElement (a ):
209
- L .append (a )
210
- elif isinstance (a , int ) or isinstance (a , long ):
211
- L .append (Integer (a ))
212
- elif isinstance (a , float ):
213
- L .append (RR (a ))
214
- else :
215
- raise ValueError ("a and b must be elements of a ring with characteristic not 2" )
203
+ sage: QuaternionAlgebra.create_key(-1,-1)
204
+ (Rational Field, -1, -1, ('i', 'j', 'k'))
205
+
206
+ """
207
+ # QuaternionAlgebra(D)
208
+ if arg1 is None and arg2 is None :
209
+ K = QQ
210
+ D = Integer (arg0 )
211
+ a , b = hilbert_conductor_inverse (D )
212
+ a = Rational (a ); b = Rational (b )
213
+
214
+ elif arg2 is None :
215
+ # If arg0 or arg1 are Python data types, coerce them
216
+ # to the relevant Sage types. This is a bit inelegant.
217
+ L = []
218
+ for a in [arg0 ,arg1 ]:
219
+ if is_RingElement (a ):
220
+ L .append (a )
221
+ elif isinstance (a , int ) or isinstance (a , long ):
222
+ L .append (Integer (a ))
223
+ elif isinstance (a , float ):
224
+ L .append (RR (a ))
225
+ else :
226
+ raise ValueError ("a and b must be elements of a ring with characteristic not 2" )
216
227
217
- # QuaternionAlgebra(a, b)
218
- v = Sequence (L )
219
- K = v .universe ().fraction_field ()
220
- a = K (v [0 ])
221
- b = K (v [1 ])
228
+ # QuaternionAlgebra(a, b)
229
+ v = Sequence (L )
230
+ K = v .universe ().fraction_field ()
231
+ a = K (v [0 ])
232
+ b = K (v [1 ])
222
233
223
- # QuaternionAlgebra(K, a, b)
224
- else :
225
- K = arg0
226
- if K not in _Fields :
227
- raise TypeError ("base ring of quaternion algebra must be a field" )
228
- a = K (arg1 )
229
- b = K (arg2 )
234
+ # QuaternionAlgebra(K, a, b)
235
+ else :
236
+ K = arg0
237
+ if K not in _Fields :
238
+ raise TypeError ("base ring of quaternion algebra must be a field" )
239
+ a = K (arg1 )
240
+ b = K (arg2 )
230
241
231
- if K .characteristic () == 2 :
232
- # Lameness!
233
- raise ValueError ("a and b must be elements of a ring with characteristic not 2" )
234
- if a == 0 or b == 0 :
235
- raise ValueError ("a and b must be nonzero" )
242
+ if K .characteristic () == 2 :
243
+ # Lameness!
244
+ raise ValueError ("a and b must be elements of a ring with characteristic not 2" )
245
+ if a == 0 or b == 0 :
246
+ raise ValueError ("a and b must be nonzero" )
236
247
237
- global _cache
238
- names = normalize_names (3 , names )
239
- key = (K , a , b , names )
240
- if key in _cache :
241
- return _cache [key ]
242
- A = QuaternionAlgebra_ab (K , a , b , names = names )
243
- A ._key = key
244
- _cache [key ] = A
245
- return A
248
+ names = normalize_names (3 , names )
249
+ return (K , a , b , names )
246
250
247
251
252
+ def create_object (self , version , key , ** extra_args ):
253
+ """
254
+ Create the object from the key (extra arguments are ignored). This is
255
+ only called if the object was not found in the cache.
248
256
257
+ TESTS::
258
+
259
+ sage: QuaternionAlgebra.create_object("6.0", (QQ, -1, -1, ('i', 'j', 'k')))
260
+ Quaternion Algebra (-1, -1) with base ring Rational Field
261
+
262
+ """
263
+ K , a , b , names = key
264
+ return QuaternionAlgebra_ab (K , a , b , names = names )
265
+
266
+ QuaternionAlgebra = QuaternionAlgebraFactory ("QuaternionAlgebra" )
249
267
250
268
########################################################
251
269
# Classes
@@ -872,23 +890,6 @@ def __cmp__(self, other):
872
890
if c : return c
873
891
return cmp ((self ._a , self ._b ), (other ._a , other ._b ))
874
892
875
- def __reduce__ (self ):
876
- """
877
- Internal method used for pickling.
878
-
879
- TESTS::
880
-
881
- sage: QuaternionAlgebra(QQ,-1,-2).__reduce__()
882
- (<function unpickle_QuaternionAlgebra_v0 at ...>, (Rational Field, -1, -2, ('i', 'j', 'k')))
883
-
884
- Test uniqueness of parent::
885
-
886
- sage: Q = QuaternionAlgebra(QQ,-1,-2)
887
- sage: loads(dumps(Q)) is Q
888
- True
889
- """
890
- return unpickle_QuaternionAlgebra_v0 , self ._key
891
-
892
893
def gen (self , i = 0 ):
893
894
"""
894
895
Return the `i^{th}` generator of ``self``.
@@ -1238,7 +1239,7 @@ def unpickle_QuaternionAlgebra_v0(*key):
1238
1239
EXAMPLES::
1239
1240
1240
1241
sage: Q = QuaternionAlgebra(-5,-19)
1241
- sage: f, t = Q.__reduce__( )
1242
+ sage: t = (QQ, -5, -19, ('i', 'j', 'k') )
1242
1243
sage: sage.algebras.quatalg.quaternion_algebra.unpickle_QuaternionAlgebra_v0(*t)
1243
1244
Quaternion Algebra (-5, -19) with base ring Rational Field
1244
1245
sage: loads(dumps(Q)) == Q
@@ -1248,7 +1249,6 @@ def unpickle_QuaternionAlgebra_v0(*key):
1248
1249
"""
1249
1250
return QuaternionAlgebra (* key )
1250
1251
1251
-
1252
1252
class QuaternionOrder (Algebra ):
1253
1253
"""
1254
1254
An order in a quaternion algebra.
0 commit comments