Skip to content

Commit 25553ab

Browse files
committed
implement QuaternionOrder.represent_integer()
1 parent 28a7d04 commit 25553ab

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

src/doc/en/reference/references/index.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4215,6 +4215,11 @@ REFERENCES:
42154215
Dimensional Analogues. Available at
42164216
https://www.i2m.univ-amu.fr/perso/david.kohel/dbs/index.html
42174217
4218+
.. [KLPT2014] David Kohel, Kristin Lauter, Christophe Petit, and Jean-Pierre Tignol:
4219+
*On the quaternion `\ell`-isogeny path problem*.
4220+
LMS Journal of Computation and Mathematics 17, pp. 418-432, 2014.
4221+
https://ia.cr/2014/505
4222+
42184223
.. [Koh2007] \A. Kohnert, *Constructing two-weight codes with prescribed
42194224
groups of automorphisms*, Discrete applied mathematics 155,
42204225
no. 11 (2007):

src/sage/algebras/quatalg/quaternion_algebra.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
44
AUTHORS:
55
6+
This code is partly based on Sage code by David Kohel from 2005.
7+
68
- Jon Bobber (2009): rewrite
79
810
- William Stein (2009): rewrite
@@ -19,7 +21,7 @@
1921
2022
- Eloi Torrents (2024): construct quaternion algebras over number fields from ramification
2123
22-
This code is partly based on Sage code by David Kohel from 2005.
24+
- Lorenz Panny (2025): :meth:`QuaternionOrder.represent_integer`
2325
2426
TESTS:
2527
@@ -2972,6 +2974,78 @@ def attempt_isomorphism(self, other):
29722974
# Otherwise, there might be other unknown alpha's giving isomorphism. If so we can't find them.
29732975
raise NotImplementedError("isomorphism_to was not able to recognize the given orders as isomorphic")
29742976

2977+
def represent_integer(self, n):
2978+
r"""
2979+
Given a positive integer `n`, attempt to compute a quaternion in this order
2980+
whose (reduced) norm equals `n`.
2981+
2982+
.. WARNING::
2983+
2984+
This method does not guarantee success: If it does not *find* a solution,
2985+
that does **not** imply that there does not *exist* a solution.
2986+
2987+
.. NOTE::
2988+
2989+
This method currently only works for orders containing `1,i,j,k`
2990+
in definite quaternion algebras.
2991+
2992+
.. NOTE::
2993+
2994+
This method requires `q = -i^2` to be "small" in order to have
2995+
any chance at succeeding before the heat death of the universe.
2996+
(The complexity scales approximately linearly with the class
2997+
number of `\ZZ[\sqrt{-q}]`.)
2998+
2999+
EXAMPLES::
3000+
3001+
sage: B.<i,j,k> = QuaternionAlgebra(-1, -419)
3002+
sage: O = B.maximal_order(); O
3003+
Order of Quaternion Algebra (-1, -419) with base ring Rational Field with basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k)
3004+
sage: O.represent_integer(5)
3005+
2 + i
3006+
sage: O.represent_integer(1019)
3007+
10 + 9*i + j + k
3008+
3009+
ALGORITHM: [KLPT2014]_, §3.2
3010+
"""
3011+
n = ZZ(n)
3012+
3013+
B = self.quaternion_algebra()
3014+
ii, jj, kk = B.gens()
3015+
if ii not in self or jj not in self:
3016+
raise NotImplementedError('only implemented for orders containing 1,i,j,k')
3017+
3018+
from sage.quadratic_forms.binary_qf import BinaryQF
3019+
if not all(v in ZZ for v in B.invariants()):
3020+
raise NotImplementedError('only implemented for integral algebra invariants')
3021+
q, p = (-ZZ(v) for v in B.invariants())
3022+
if q <= 0 or p <= 0:
3023+
raise NotImplementedError('only implemented for definite quaternion algebras')
3024+
nf = BinaryQF(1, 0, q)
3025+
3026+
from sage.misc.functional import isqrt
3027+
cbnd = isqrt(n / 2 / p)
3028+
dbnd = isqrt(n / 2 / p / q)
3029+
3030+
from sage.misc.mrange import cantor_product
3031+
3032+
for c,d in cantor_product(range(cbnd + 1), range(dbnd + 1)):
3033+
n1 = n - p * nf(c,d)
3034+
if not n1.is_pseudoprime(): # or otherwise "Cornacchia-friendly"
3035+
continue
3036+
3037+
sol = nf.solve_integer(n1, algorithm='cornacchia')
3038+
if sol is not None:
3039+
a, b = sol
3040+
break
3041+
else:
3042+
return
3043+
3044+
elt = B([a, b, c, d])
3045+
assert elt in self
3046+
assert elt.reduced_norm() == n
3047+
return elt
3048+
29753049

29763050
class QuaternionFractionalIdeal(Ideal_fractional):
29773051
pass

0 commit comments

Comments
 (0)