90
90
from sage .categories .number_fields import NumberFields
91
91
92
92
from sage .structure .richcmp import richcmp_method
93
- from sage .libs .pari .all import pari
94
93
from sage .combinat .words .word import Word
95
94
96
95
########################################################
@@ -366,7 +365,7 @@ def create_key(self, arg0, arg1=None, arg2=None, names='i,j,k'):
366
365
K = arg0
367
366
if K not in NumberFields ():
368
367
raise ValueError ("quaternion algebra construction via ramification only works over a number field" )
369
- if not set (arg2 ).issubset (set ([0 , QQ ((1 ,2 ))])):
368
+ if not set (arg2 ).issubset (set ([0 , QQ ((1 , 2 ))])):
370
369
raise ValueError ("list of local invariants specifying ramification should contain only 0 and 1/2" )
371
370
372
371
# Check that the finite ramification is given by prime ideals
@@ -417,7 +416,7 @@ def create_key(self, arg0, arg1=None, arg2=None, names='i,j,k'):
417
416
inv_arch_pari = [arg2 [i - 1 ] for i in perm ]
418
417
419
418
# Compute the correct quaternion algebra over L in PARI
420
- A = L .__pari__ ().alginit ([2 , [fin_places_pari , [QQ ((1 ,2 ))] * len (fin_places_pari )],
419
+ A = L .__pari__ ().alginit ([2 , [fin_places_pari , [QQ ((1 , 2 ))] * len (fin_places_pari )],
421
420
inv_arch_pari ], flag = 0 )
422
421
423
422
# Obtain representation of A in terms of invariants in L
@@ -1008,7 +1007,7 @@ def maximal_order(self, take_shortcuts=True, order_basis=None):
1008
1007
# of such a form though)
1009
1008
a , b = self .invariants ()
1010
1009
if (not order_basis and take_shortcuts and d_A .is_prime ()
1011
- and a in ZZ and b in ZZ ):
1010
+ and a in ZZ and b in ZZ ):
1012
1011
a = ZZ (a )
1013
1012
b = ZZ (b )
1014
1013
i , j , k = self .gens ()
@@ -1050,7 +1049,7 @@ def maximal_order(self, take_shortcuts=True, order_basis=None):
1050
1049
d_R = R .discriminant ()
1051
1050
except (TypeError , ValueError ):
1052
1051
raise ValueError ('order_basis is not a basis of an order of the'
1053
- ' given quaternion algebra' )
1052
+ ' given quaternion algebra' )
1054
1053
1055
1054
# Since Voight's algorithm only works for a starting basis having 1 as
1056
1055
# its first vector, we derive such a basis from the given order basis
@@ -1127,7 +1126,7 @@ def maximal_order(self, take_shortcuts=True, order_basis=None):
1127
1126
e_n [3 ] = e_n [1 ]* g
1128
1127
1129
1128
else : # t.valuation(p) > 0
1130
- ( y , z , w ) = maxord_solve_aux_eq (a , b , p )
1129
+ y , z , w = maxord_solve_aux_eq (a , b , p )
1131
1130
g = 1 / p * (1 + y * e_n [1 ] + z * e_n [2 ] + w * e_n [1 ]* e_n [2 ])
1132
1131
h = (z * b )* e_n [1 ] - (y * a )* e_n [2 ]
1133
1132
e_n [1 :4 ] = [g , h , g * h ]
@@ -1564,7 +1563,8 @@ def ramified_places(self, inf=True):
1564
1563
1565
1564
# Over the number field F, first compute the finite ramified places
1566
1565
ram_fin = [p for p in set (F .primes_above (2 )).union (F .primes_above (a ),
1567
- F .primes_above (b )) if F .hilbert_symbol (a , b , p ) == - 1 ]
1566
+ F .primes_above (b ))
1567
+ if F .hilbert_symbol (a , b , p ) == - 1 ]
1568
1568
1569
1569
if not inf :
1570
1570
return ram_fin
@@ -2750,7 +2750,7 @@ def ternary_quadratic_form(self, include_basis=False):
2750
2750
Q = self .quaternion_algebra ()
2751
2751
# 2*R + ZZ
2752
2752
twoR = self .free_module ().scale (2 )
2753
- Z = twoR .span ([Q ( 1 ).coefficient_tuple ()], ZZ )
2753
+ Z = twoR .span ([Q . one ( ).coefficient_tuple ()], ZZ )
2754
2754
S = twoR + Z
2755
2755
# Now we intersect with the trace 0 submodule
2756
2756
v = [b .reduced_trace () for b in Q .basis ()]
@@ -3614,7 +3614,7 @@ def norm(self):
3614
3614
[16, 32, 32]
3615
3615
3616
3616
sage: # optional - magma
3617
- sage: (a,b) = M.quaternion_algebra().invariants()
3617
+ sage: a, b = M.quaternion_algebra().invariants()
3618
3618
sage: magma.eval('A<i,j,k> := QuaternionAlgebra<Rationals() | %s, %s>' % (a,b))
3619
3619
''
3620
3620
sage: magma.eval('O := QuaternionOrder(%s)' % str(list(C[0].right_order().basis())))
@@ -4016,24 +4016,21 @@ def pullback(self, J, side=None):
4016
4016
4017
4017
raise ValueError ('side must be "left", "right" or None' )
4018
4018
4019
- def is_equivalent (self , J , B = 10 , certificate = False , side = None ) :
4019
+ def is_left_equivalent (self , J , B = 10 , certificate = False ) -> bool | tuple :
4020
4020
r"""
4021
- Check whether ``self`` and ``J`` are equivalent as ideals.
4022
- Tests equivalence as right ideals by default. Requires the underlying
4023
- rational quaternion algebra to be definite.
4021
+ Check whether ``self`` and ``J`` are equivalent as left ideals.
4022
+
4023
+ This requires the underlying rational quaternion algebra
4024
+ to be definite.
4024
4025
4025
4026
INPUT:
4026
4027
4027
- - ``J`` -- a fractional quaternion ideal with same order as ``self``
4028
+ - ``J`` -- a fractional quaternion left ideal with same order as ``self``
4028
4029
4029
4030
- ``B`` -- a bound to compute and compare theta series before
4030
4031
doing the full equivalence test
4031
4032
4032
- - ``certificate`` -- if ``True`` returns an element alpha such that
4033
- alpha*J = I or J*alpha = I for right and left ideals respectively
4034
-
4035
- - ``side`` -- if ``'left'`` performs left equivalence test. If ``'right'
4036
- ``or ``None`` performs right ideal equivalence test
4033
+ - ``certificate`` -- if ``True`` returns an element alpha such that J*alpha=I
4037
4034
4038
4035
OUTPUT: boolean, or (boolean, alpha) if ``certificate`` is ``True``
4039
4036
@@ -4043,48 +4040,22 @@ def is_equivalent(self, J, B=10, certificate=False, side=None):
4043
4040
2
4044
4041
sage: OO = R[0].left_order()
4045
4042
sage: S = OO.right_ideal([3*a for a in R[0].basis()])
4046
- sage: R[0].is_equivalent(S)
4047
- doctest:...: DeprecationWarning: is_equivalent is deprecated,
4048
- please use is_left_equivalent or is_right_equivalent
4049
- accordingly instead
4050
- See https://github.com/sagemath/sage/issues/37100 for details.
4043
+ sage: R[0].is_left_equivalent(S)
4051
4044
True
4052
4045
"""
4053
- from sage .misc .superseded import deprecation
4054
- deprecation (37100 , 'is_equivalent is deprecated, please use is_left_equivalent'
4055
- ' or is_right_equivalent accordingly instead' )
4056
- if side == 'left' :
4057
- return self .is_left_equivalent (J , B , certificate )
4058
- # If None, assume right ideals, for backwards compatibility
4059
- return self .is_right_equivalent (J , B , certificate )
4060
-
4061
- def is_left_equivalent (self , J , B = 10 , certificate = False ):
4062
- r"""
4063
- Check whether ``self`` and ``J`` are equivalent as left ideals.
4064
- Requires the underlying rational quaternion algebra to be definite.
4065
-
4066
- INPUT:
4067
-
4068
- - ``J`` -- a fractional quaternion left ideal with same order as ``self``
4069
-
4070
- - ``B`` -- a bound to compute and compare theta series before
4071
- doing the full equivalence test
4072
-
4073
- - ``certificate`` -- if ``True`` returns an element alpha such that J*alpha=I
4074
-
4075
- OUTPUT: boolean, or (boolean, alpha) if ``certificate`` is ``True``
4076
- """
4077
4046
if certificate :
4078
4047
is_equiv , cert = self .conjugate ().is_right_equivalent (J .conjugate (), B , True )
4079
4048
if is_equiv :
4080
4049
return True , cert .conjugate ()
4081
4050
return False , None
4082
4051
return self .conjugate ().is_right_equivalent (J .conjugate (), B , False )
4083
4052
4084
- def is_right_equivalent (self , J , B = 10 , certificate = False ):
4053
+ def is_right_equivalent (self , J , B = 10 , certificate = False ) -> bool | tuple :
4085
4054
r"""
4086
4055
Check whether ``self`` and ``J`` are equivalent as right ideals.
4087
- Requires the underlying rational quaternion algebra to be definite.
4056
+
4057
+ This requires the underlying rational quaternion algebra
4058
+ to be definite.
4088
4059
4089
4060
INPUT:
4090
4061
@@ -4128,14 +4099,14 @@ def is_right_equivalent(self, J, B=10, certificate=False):
4128
4099
"""
4129
4100
if not isinstance (J , QuaternionFractionalIdeal_rational ):
4130
4101
raise TypeError ('J must be a fractional ideal'
4131
- ' in a rational quaternion algebra' )
4102
+ ' in a rational quaternion algebra' )
4132
4103
4133
4104
if self .right_order () != J .right_order ():
4134
4105
raise ValueError ('self and J must be right ideals over the same order' )
4135
4106
4136
4107
if not self .quaternion_algebra ().is_definite ():
4137
4108
raise NotImplementedError ('equivalence test of ideals not implemented'
4138
- ' for indefinite quaternion algebras' )
4109
+ ' for indefinite quaternion algebras' )
4139
4110
4140
4111
# Just test theta series first; if the theta series are
4141
4112
# different, the ideals are definitely not equivalent
@@ -4184,7 +4155,7 @@ def is_principal(self, certificate=False):
4184
4155
"""
4185
4156
if not self .quaternion_algebra ().is_definite ():
4186
4157
raise NotImplementedError ('principality test not implemented in'
4187
- ' indefinite quaternion algebras' )
4158
+ ' indefinite quaternion algebras' )
4188
4159
4189
4160
c = self .theta_series_vector (2 )[1 ]
4190
4161
if not certificate :
@@ -4414,10 +4385,12 @@ def primitive_decomposition(self):
4414
4385
4415
4386
Check that randomly generated ideals decompose as expected::
4416
4387
4417
- sage: for d in ( m for m in range(400, 750) if is_squarefree(m) ): # long time (7s)
4388
+ sage: for d in range(400, 650): # long time (7s)
4389
+ ....: if not is_squarefree(d):
4390
+ ....: continue
4418
4391
....: A = QuaternionAlgebra(d)
4419
4392
....: O = A.maximal_order()
4420
- ....: for _ in range(10 ):
4393
+ ....: for _ in range(8 ):
4421
4394
....: a = O.random_element()
4422
4395
....: if not a.is_constant(): # avoids a = 0
4423
4396
....: I = a*O + a.reduced_norm()*O
@@ -4712,7 +4685,7 @@ def maxord_solve_aux_eq(a, b, p):
4712
4685
sage: from sage.algebras.quatalg.quaternion_algebra import maxord_solve_aux_eq
4713
4686
sage: for a in [1,3]:
4714
4687
....: for b in [1,2,3]:
4715
- ....: (y,z,w) = maxord_solve_aux_eq(a, b, 2)
4688
+ ....: y, z, w = maxord_solve_aux_eq(a, b, 2)
4716
4689
....: assert mod(y, 4) == 1 or mod(y, 4) == 3
4717
4690
....: assert mod(1 - a*y^2 - b*z^2 + a*b*w^2, 4) == 0
4718
4691
"""
0 commit comments