Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement EllipticCurve_with_order #37119

Merged
merged 20 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5522,6 +5522,10 @@ REFERENCES:
imaginary quadratic fields. Invent. Math. 103 (1991),
no. 1, 25--68.

.. [RS2010] RUBIN, K., & SILVERBERG, A. (2010). CHOOSING THE CORRECT ELLIPTIC
CURVE IN THE CM METHOD. Mathematics of Computation, 79(269),
545–561. :doi:`10.1090/S0025-5718-09-02266-2`

.. [Rud1958] \M. E. Rudin. *An unshellable triangulation of a
tetrahedron*. Bull. Amer. Math. Soc. 64 (1958), 90-91.

Expand Down
54 changes: 43 additions & 11 deletions src/sage/quadratic_forms/binary_qf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1596,17 +1596,21 @@
raise ValueError("Unable to find a prime value of %s" % self)
B += 10

def solve_integer(self, n, *, algorithm="general"):
def solve_integer(self, n, *, algorithm="general", _flag=2):
r"""
Solve `Q(x, y) = n` in integers `x` and `y` where `Q` is this
quadratic form.

INPUT:

- ``n`` -- a positive integer
- ``n`` -- a positive integer or a
`:sage:`~sage.structure.factorization.Factorization` object

- ``algorithm`` -- ``"general"`` (default) or ``"cornacchia"``

- ``_flag`` -- ``1``, ``2`` (default) or ``3``; passed onto the pari
function``qfbsolve``. For internal use only.

To use the Cornacchia algorithm, the quadratic form must have
`a=1` and `b=0` and `c>0`, and ``n`` must be a prime or four
times a prime (but this is not checked).
Expand All @@ -1618,6 +1622,8 @@

ALGORITHM: :pari:`qfbsolve` or :pari:`qfbcornacchia`

TODO:: Replace `_flag` with human-readable parameters c.f. :issue:`37119`

EXAMPLES::

sage: Q = BinaryQF([1, 0, 419])
Expand Down Expand Up @@ -1653,6 +1659,14 @@
sage: [Q.solve_integer(6) for Q in Qs]
[(1, -1), (1, -1), (-1, -1)]

::

sage: # needs sage.libs.pari
sage: n = factor(126)
sage: Q = BinaryQF([1, 0, 5])
sage: Q.solve_integer(n)
(11, -1)

TESTS:

The returned solutions are correct (random inputs)::
Expand Down Expand Up @@ -1702,22 +1716,39 @@
sage: Q = Q.matrix_action_right(U)
sage: Q.discriminant().is_square()
True
sage: xy = Q.solve_integer(n) # needs sage.libs.pari
sage: Q(*xy) == n # needs sage.libs.pari
sage: # needs sage.libs.pari
sage: xy = Q.solve_integer(n)
sage: Q(*xy) == n
True

Also test the `n=0` special case separately::

sage: xy = Q.solve_integer(0) # needs sage.libs.pari
sage: Q(*xy) # needs sage.libs.pari
sage: # needs sage.libs.pari
sage: xy = Q.solve_integer(0)
sage: Q(*xy)
0
"""
n = ZZ(n)

Test for different `_flag` values::

sage: # needs sage.libs.pari
sage: Q = BinaryQF([1, 0, 5])
sage: Q.solve_integer(126, _flag=1)
[(11, -1), (-1, -5), (-1, 5), (-11, -1)]
sage: Q.solve_integer(126, _flag=2)
(11, -1)
sage: Q.solve_integer(126, _flag=3)
[(11, -1), (-1, -5), (-1, 5), (-11, -1), (-9, -3), (9, -3)]
"""
if self.is_negative_definite(): # not supported by PARI
return (-self).solve_integer(-n)

if self.is_reducible(): # square discriminant; not supported by PARI
from sage.structure.factorization import Factorization
if isinstance(n, Factorization):
n = ZZ(n.value())

Check warning on line 1748 in src/sage/quadratic_forms/binary_qf.py

View check run for this annotation

Codecov / codecov/patch

src/sage/quadratic_forms/binary_qf.py#L1748

Added line #L1748 was not covered by tests
else:
n = ZZ(n)

if self._a:
# https://math.stackexchange.com/a/980075
w = self.discriminant().sqrt()
Expand Down Expand Up @@ -1760,9 +1791,10 @@
if algorithm != 'general':
raise ValueError(f'algorithm {algorithm!r} is not a valid algorithm')

flag = 2 # single solution, possibly imprimitive
sol = self.__pari__().qfbsolve(n, flag)
return tuple(map(ZZ, sol)) if sol else None
sol = self.__pari__().qfbsolve(n, _flag)
if _flag == 2:
return tuple(map(ZZ, sol)) if sol else None
return list(map(lambda tup: tuple(map(ZZ, tup)), sol))

def form_class(self):
r"""
Expand Down
Loading
Loading