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
@@ -1015,7 +1014,7 @@ def maximal_order(self, take_shortcuts=True, order_basis=None):
1015
1014
# of such a form though)
1016
1015
a , b = self .invariants ()
1017
1016
if (not order_basis and take_shortcuts and d_A .is_prime ()
1018
- and a in ZZ and b in ZZ ):
1017
+ and a in ZZ and b in ZZ ):
1019
1018
a = ZZ (a )
1020
1019
b = ZZ (b )
1021
1020
i , j , k = self .gens ()
@@ -1057,7 +1056,7 @@ def maximal_order(self, take_shortcuts=True, order_basis=None):
1057
1056
d_R = R .discriminant ()
1058
1057
except (TypeError , ValueError ):
1059
1058
raise ValueError ('order_basis is not a basis of an order of the'
1060
- ' given quaternion algebra' )
1059
+ ' given quaternion algebra' )
1061
1060
1062
1061
# Since Voight's algorithm only works for a starting basis having 1 as
1063
1062
# its first vector, we derive such a basis from the given order basis
@@ -1134,7 +1133,7 @@ def maximal_order(self, take_shortcuts=True, order_basis=None):
1134
1133
e_n [3 ] = e_n [1 ]* g
1135
1134
1136
1135
else : # t.valuation(p) > 0
1137
- ( y , z , w ) = maxord_solve_aux_eq (a , b , p )
1136
+ y , z , w = maxord_solve_aux_eq (a , b , p )
1138
1137
g = 1 / p * (1 + y * e_n [1 ] + z * e_n [2 ] + w * e_n [1 ]* e_n [2 ])
1139
1138
h = (z * b )* e_n [1 ] - (y * a )* e_n [2 ]
1140
1139
e_n [1 :4 ] = [g , h , g * h ]
@@ -1571,7 +1570,8 @@ def ramified_places(self, inf=True):
1571
1570
1572
1571
# Over the number field F, first compute the finite ramified places
1573
1572
ram_fin = [p for p in set (F .primes_above (2 )).union (F .primes_above (a ),
1574
- F .primes_above (b )) if F .hilbert_symbol (a , b , p ) == - 1 ]
1573
+ F .primes_above (b ))
1574
+ if F .hilbert_symbol (a , b , p ) == - 1 ]
1575
1575
1576
1576
if not inf :
1577
1577
return ram_fin
@@ -2757,7 +2757,7 @@ def ternary_quadratic_form(self, include_basis=False):
2757
2757
Q = self .quaternion_algebra ()
2758
2758
# 2*R + ZZ
2759
2759
twoR = self .free_module ().scale (2 )
2760
- Z = twoR .span ([Q ( 1 ).coefficient_tuple ()], ZZ )
2760
+ Z = twoR .span ([Q . one ( ).coefficient_tuple ()], ZZ )
2761
2761
S = twoR + Z
2762
2762
# Now we intersect with the trace 0 submodule
2763
2763
v = [b .reduced_trace () for b in Q .basis ()]
@@ -3621,7 +3621,7 @@ def norm(self):
3621
3621
[16, 32, 32]
3622
3622
3623
3623
sage: # optional - magma
3624
- sage: (a,b) = M.quaternion_algebra().invariants()
3624
+ sage: a, b = M.quaternion_algebra().invariants()
3625
3625
sage: magma.eval('A<i,j,k> := QuaternionAlgebra<Rationals() | %s, %s>' % (a,b))
3626
3626
''
3627
3627
sage: magma.eval('O := QuaternionOrder(%s)' % str(list(C[0].right_order().basis())))
@@ -4023,24 +4023,21 @@ def pullback(self, J, side=None):
4023
4023
4024
4024
raise ValueError ('side must be "left", "right" or None' )
4025
4025
4026
- def is_equivalent (self , J , B = 10 , certificate = False , side = None ) :
4026
+ def is_left_equivalent (self , J , B = 10 , certificate = False ) -> bool | tuple :
4027
4027
r"""
4028
- Check whether ``self`` and ``J`` are equivalent as ideals.
4029
- Tests equivalence as right ideals by default. Requires the underlying
4030
- rational quaternion algebra to be definite.
4028
+ Check whether ``self`` and ``J`` are equivalent as left ideals.
4029
+
4030
+ This requires the underlying rational quaternion algebra
4031
+ to be definite.
4031
4032
4032
4033
INPUT:
4033
4034
4034
- - ``J`` -- a fractional quaternion ideal with same order as ``self``
4035
+ - ``J`` -- a fractional quaternion left ideal with same order as ``self``
4035
4036
4036
4037
- ``B`` -- a bound to compute and compare theta series before
4037
4038
doing the full equivalence test
4038
4039
4039
- - ``certificate`` -- if ``True`` returns an element alpha such that
4040
- alpha*J = I or J*alpha = I for right and left ideals respectively
4041
-
4042
- - ``side`` -- if ``'left'`` performs left equivalence test. If ``'right'
4043
- ``or ``None`` performs right ideal equivalence test
4040
+ - ``certificate`` -- if ``True`` returns an element alpha such that J*alpha=I
4044
4041
4045
4042
OUTPUT: boolean, or (boolean, alpha) if ``certificate`` is ``True``
4046
4043
@@ -4050,48 +4047,22 @@ def is_equivalent(self, J, B=10, certificate=False, side=None):
4050
4047
2
4051
4048
sage: OO = R[0].left_order()
4052
4049
sage: S = OO.right_ideal([3*a for a in R[0].basis()])
4053
- sage: R[0].is_equivalent(S)
4054
- doctest:...: DeprecationWarning: is_equivalent is deprecated,
4055
- please use is_left_equivalent or is_right_equivalent
4056
- accordingly instead
4057
- See https://github.com/sagemath/sage/issues/37100 for details.
4050
+ sage: R[0].is_left_equivalent(S)
4058
4051
True
4059
4052
"""
4060
- from sage .misc .superseded import deprecation
4061
- deprecation (37100 , 'is_equivalent is deprecated, please use is_left_equivalent'
4062
- ' or is_right_equivalent accordingly instead' )
4063
- if side == 'left' :
4064
- return self .is_left_equivalent (J , B , certificate )
4065
- # If None, assume right ideals, for backwards compatibility
4066
- return self .is_right_equivalent (J , B , certificate )
4067
-
4068
- def is_left_equivalent (self , J , B = 10 , certificate = False ):
4069
- r"""
4070
- Check whether ``self`` and ``J`` are equivalent as left ideals.
4071
- Requires the underlying rational quaternion algebra to be definite.
4072
-
4073
- INPUT:
4074
-
4075
- - ``J`` -- a fractional quaternion left ideal with same order as ``self``
4076
-
4077
- - ``B`` -- a bound to compute and compare theta series before
4078
- doing the full equivalence test
4079
-
4080
- - ``certificate`` -- if ``True`` returns an element alpha such that J*alpha=I
4081
-
4082
- OUTPUT: boolean, or (boolean, alpha) if ``certificate`` is ``True``
4083
- """
4084
4053
if certificate :
4085
4054
is_equiv , cert = self .conjugate ().is_right_equivalent (J .conjugate (), B , True )
4086
4055
if is_equiv :
4087
4056
return True , cert .conjugate ()
4088
4057
return False , None
4089
4058
return self .conjugate ().is_right_equivalent (J .conjugate (), B , False )
4090
4059
4091
- def is_right_equivalent (self , J , B = 10 , certificate = False ):
4060
+ def is_right_equivalent (self , J , B = 10 , certificate = False ) -> bool | tuple :
4092
4061
r"""
4093
4062
Check whether ``self`` and ``J`` are equivalent as right ideals.
4094
- Requires the underlying rational quaternion algebra to be definite.
4063
+
4064
+ This requires the underlying rational quaternion algebra
4065
+ to be definite.
4095
4066
4096
4067
INPUT:
4097
4068
@@ -4135,14 +4106,14 @@ def is_right_equivalent(self, J, B=10, certificate=False):
4135
4106
"""
4136
4107
if not isinstance (J , QuaternionFractionalIdeal_rational ):
4137
4108
raise TypeError ('J must be a fractional ideal'
4138
- ' in a rational quaternion algebra' )
4109
+ ' in a rational quaternion algebra' )
4139
4110
4140
4111
if self .right_order () != J .right_order ():
4141
4112
raise ValueError ('self and J must be right ideals over the same order' )
4142
4113
4143
4114
if not self .quaternion_algebra ().is_definite ():
4144
4115
raise NotImplementedError ('equivalence test of ideals not implemented'
4145
- ' for indefinite quaternion algebras' )
4116
+ ' for indefinite quaternion algebras' )
4146
4117
4147
4118
# Just test theta series first; if the theta series are
4148
4119
# different, the ideals are definitely not equivalent
@@ -4191,7 +4162,7 @@ def is_principal(self, certificate=False):
4191
4162
"""
4192
4163
if not self .quaternion_algebra ().is_definite ():
4193
4164
raise NotImplementedError ('principality test not implemented in'
4194
- ' indefinite quaternion algebras' )
4165
+ ' indefinite quaternion algebras' )
4195
4166
4196
4167
c = self .theta_series_vector (2 )[1 ]
4197
4168
if not certificate :
@@ -4421,10 +4392,12 @@ def primitive_decomposition(self):
4421
4392
4422
4393
Check that randomly generated ideals decompose as expected::
4423
4394
4424
- sage: for d in ( m for m in range(400, 750) if is_squarefree(m) ): # long time (7s)
4395
+ sage: for d in range(400, 650): # long time (7s)
4396
+ ....: if not is_squarefree(d):
4397
+ ....: continue
4425
4398
....: A = QuaternionAlgebra(d)
4426
4399
....: O = A.maximal_order()
4427
- ....: for _ in range(10 ):
4400
+ ....: for _ in range(8 ):
4428
4401
....: a = O.random_element()
4429
4402
....: if not a.is_constant(): # avoids a = 0
4430
4403
....: I = a*O + a.reduced_norm()*O
@@ -4719,7 +4692,7 @@ def maxord_solve_aux_eq(a, b, p):
4719
4692
sage: from sage.algebras.quatalg.quaternion_algebra import maxord_solve_aux_eq
4720
4693
sage: for a in [1,3]:
4721
4694
....: for b in [1,2,3]:
4722
- ....: (y,z,w) = maxord_solve_aux_eq(a, b, 2)
4695
+ ....: y, z, w = maxord_solve_aux_eq(a, b, 2)
4723
4696
....: assert mod(y, 4) == 1 or mod(y, 4) == 3
4724
4697
....: assert mod(1 - a*y^2 - b*z^2 + a*b*w^2, 4) == 0
4725
4698
"""
0 commit comments