Skip to content

Commit

Permalink
Trac #32726: quaternion ideals' .scale() incorrectly copies cached le…
Browse files Browse the repository at this point in the history
…ft and right orders

The method `QuaternionFractionalIdeal_rational.scale()` always copies
over the existing left and right orders of `self` to the scaled ideal.
This is incorrect when the scaling factor does not lie in the center of
the algebra, as demonstrated by this example:

{{{#!sage
sage: Quat.<i,j,k> = QuaternionAlgebra(-1,-19)
sage: a = 1+2*i+3*j+4*k
sage: I = Quat.maximal_order().unit_ideal()
sage: I.right_order()
Order of Quaternion Algebra (-1, -19) with base ring Rational Field with
basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k)
sage: I.scale(a).right_order()
Order of Quaternion Algebra (-1, -19) with base ring Rational Field with
basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k)
sage: J = Quat.ideal(I.scale(a).basis(), check=False)
sage: J == I.scale(a)
True
sage: J.right_order()
Order of Quaternion Algebra (-1, -19) with base ring Rational Field with
basis (1/2 + 1/10*j + 109/5*k, 1/48*i + 1/120*j + 8411/240*k, 1/5*j +
218/5*k, 120*k)
}}}

The patch fixes this by only copying over the cached orders when scaling
on the other side, or when scaling by an element of `QQ`.

URL: https://trac.sagemath.org/32726
Reported by: lorenz
Ticket author(s): Lorenz Panny
Reviewer(s): Michael Orlitzky
  • Loading branch information
Release Manager committed Jan 30, 2022
2 parents 468797c + 4310b6c commit 06f45f2
Showing 1 changed file with 20 additions and 2 deletions.
22 changes: 20 additions & 2 deletions src/sage/algebras/quatalg/quaternion_algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -1923,15 +1923,33 @@ def scale(self, alpha, left=False):
sage: I.scale(1) == I
True
Check that :trac:`32726` is fixed::
sage: Q.<i,j,k> = QuaternionAlgebra(-1,-19)
sage: I = Q.ideal([1,i,j,k])
sage: _ = I.left_order(), I.right_order() # cache
sage: span = lambda L: L.basis_matrix().row_module(ZZ)
sage: for left in (True,False):
....: J = I.scale(1+i+j+k, left=left)
....: Ol, Or = J.left_order(), J.right_order()
....: [
....: span(Ol.unit_ideal() * J) <= span(J),
....: span(J * Or.unit_ideal()) <= span(J),
....: ]
[True, True]
[True, True]
"""
Q = self.quaternion_algebra()
alpha = Q(alpha)
if left:
gens = [alpha * b for b in self.basis()]
else:
gens = [b * alpha for b in self.basis()]
return Q.ideal(gens, left_order=self.__left_order,
right_order=self.__right_order, check=False)
left_order = self.__left_order if alpha in QQ or not left else None
right_order = self.__right_order if alpha in QQ or left else None
return Q.ideal(gens, check=False,
left_order=left_order, right_order=right_order)

def quaternion_algebra(self):
"""
Expand Down

0 comments on commit 06f45f2

Please sign in to comment.