|
3 | 3 |
|
4 | 4 | AUTHORS: |
5 | 5 |
|
| 6 | +This code is partly based on Sage code by David Kohel from 2005. |
| 7 | +
|
6 | 8 | - Jon Bobber (2009): rewrite |
7 | 9 |
|
8 | 10 | - William Stein (2009): rewrite |
|
19 | 21 |
|
20 | 22 | - Eloi Torrents (2024): construct quaternion algebras over number fields from ramification |
21 | 23 |
|
22 | | -This code is partly based on Sage code by David Kohel from 2005. |
| 24 | +- Lorenz Panny (2025): :meth:`QuaternionOrder.represent_integer` |
23 | 25 |
|
24 | 26 | TESTS: |
25 | 27 |
|
@@ -2972,6 +2974,78 @@ def attempt_isomorphism(self, other): |
2972 | 2974 | # Otherwise, there might be other unknown alpha's giving isomorphism. If so we can't find them. |
2973 | 2975 | raise NotImplementedError("isomorphism_to was not able to recognize the given orders as isomorphic") |
2974 | 2976 |
|
| 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 | + |
2975 | 3049 |
|
2976 | 3050 | class QuaternionFractionalIdeal(Ideal_fractional): |
2977 | 3051 | pass |
|
0 commit comments