Skip to content

Commit 446b620

Browse files
author
Release Manager
committed
Trac #34787: streamline .set_order() methods for elliptic curves and points
Elliptic curves and points have `.set_order()` methods to supply the order to Sage's algorithms instead of computing it. However, `.set_order()` for curves currently has a `num_checks=` keyword argument instead of the usual `check=` flag, and `.set_order()` for points does not have either argument and simply runs checks unconditionally. In this patch we add `check=` arguments to both methods. Moreover, we make `.set_order()` work for points over general fields, where order- computation algorithms are not available at the moment. URL: https://trac.sagemath.org/34787 Reported by: lorenz Ticket author(s): Lorenz Panny Reviewer(s): Kwankyu Lee
2 parents 59cbf53 + 12d13b3 commit 446b620

File tree

2 files changed

+48
-36
lines changed

2 files changed

+48
-36
lines changed

src/sage/schemes/elliptic_curves/ell_finite_field.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -955,25 +955,27 @@ def abelian_group(self):
955955
if len(gens) == 2:
956956

957957
P, Q = gens
958-
n = self.cardinality() # cached
959-
n1 = P.order() # cached
958+
n = self.cardinality() # cached
959+
n1 = P.order() # cached
960960
n2 = n//n1
961-
assert not n1 * Q # PARI should guarantee this
961+
assert not n1 * Q # PARI should guarantee this
962962

963963
k = n1.prime_to_m_part(n2)
964-
Q *= k # don't need; kill that part
964+
Q *= k # don't need; kill that part
965965
nQ = n2 * generic.order_from_multiple(n2*Q, n1//k//n2)
966966

967967
S = n//nQ * P
968968
T = n2 * Q
969-
S.set_order(nQ//n2) # for .discrete_log()
969+
S.set_order(nQ//n2, check=False) # for .discrete_log()
970970
x = S.discrete_log(T)
971971
Q -= x * n1//nQ * P
972972

973-
Q.set_order(n2) # verifies n2*Q == 0
973+
assert not n2 * Q # by construction
974+
Q.set_order(n2, check=False)
975+
974976
gens = P, Q
975977

976-
orders = [T.order() for T in gens] # cached
978+
orders = [T.order() for T in gens] # cached
977979

978980
self.gens.set_cache(gens)
979981
return AdditiveAbelianGroupWrapper(self.point_homset(), gens, orders)
@@ -1155,7 +1157,7 @@ def is_ordinary(self, proof=True):
11551157
"""
11561158
return not is_j_supersingular(self.j_invariant(), proof=proof)
11571159

1158-
def set_order(self, value, num_checks=8):
1160+
def set_order(self, value, *, check=True, num_checks=8):
11591161
r"""
11601162
Set the value of self._order to value.
11611163
@@ -1167,9 +1169,12 @@ def set_order(self, value, num_checks=8):
11671169
- ``value`` -- integer in the Hasse-Weil range for this
11681170
curve.
11691171
1170-
- ``num_checks`` (integer, default: 8) -- number of times to
1171-
check whether value*(a random point on this curve) is
1172-
equal to the identity.
1172+
- ``check`` (boolean, default: ``True``) -- whether or
1173+
not to run sanity checks on the input.
1174+
1175+
- ``num_checks`` (integer, default: 8) -- if ``check`` is
1176+
``True``, the number of times to check whether ``value``
1177+
times a random point on this curve equals the identity.
11731178
11741179
OUTPUT:
11751180
@@ -1267,16 +1272,17 @@ def set_order(self, value, num_checks=8):
12671272
"""
12681273
value = Integer(value)
12691274

1270-
# Is value in the Hasse range?
1271-
q = self.base_field().order()
1272-
a,b = Hasse_bounds(q,1)
1273-
if not a <= value <= b:
1274-
raise ValueError('Value %s illegal (not an integer in the Hasse range)' % value)
1275-
# Is value*random == identity?
1276-
for i in range(num_checks):
1277-
G = self.random_point()
1278-
if value * G != self(0):
1279-
raise ValueError('Value %s illegal (multiple of random point not the identity)' % value)
1275+
if check:
1276+
# Is value in the Hasse range?
1277+
q = self.base_field().order()
1278+
a,b = Hasse_bounds(q,1)
1279+
if not a <= value <= b:
1280+
raise ValueError('Value %s illegal (not an integer in the Hasse range)' % value)
1281+
# Is value*random == identity?
1282+
for i in range(num_checks):
1283+
G = self.random_point()
1284+
if value * G != self(0):
1285+
raise ValueError('Value %s illegal (multiple of random point not the identity)' % value)
12801286

12811287
# TODO: It might help some of PARI's algorithms if we
12821288
# could copy this over to the .pari_curve() as well.

src/sage/schemes/elliptic_curves/ell_point.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,13 @@ def order(self):
484484
sage: E(0).order() == 1
485485
True
486486
"""
487+
try:
488+
return self._order
489+
except AttributeError:
490+
pass
487491
if self.is_zero():
488-
return Integer(1)
492+
self._order = Integer(1)
493+
return self._order
489494
raise NotImplementedError("Computation of order of a point "
490495
"not implemented over general fields.")
491496

@@ -1173,7 +1178,7 @@ def _divide_out(self, p):
11731178
pts = Q.division_points(p)
11741179
return (Q, k)
11751180

1176-
def set_order(self, value):
1181+
def set_order(self, value, *, check=True):
11771182
r"""
11781183
Set the value of self._order to value.
11791184
@@ -1194,7 +1199,7 @@ def set_order(self, value):
11941199
11951200
::
11961201
1197-
sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 6
1202+
sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
11981203
sage: G = E(5, 0)
11991204
sage: G.set_order(2)
12001205
sage: 2*G
@@ -1222,7 +1227,7 @@ def set_order(self, value):
12221227
12231228
It is an error to pass a `value` equal to `0`::
12241229
1225-
sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 6
1230+
sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
12261231
sage: G = E.random_point()
12271232
sage: G.set_order(0)
12281233
Traceback (most recent call last):
@@ -1237,7 +1242,7 @@ def set_order(self, value):
12371242
order of this point. How unlikely is determined by the factorization of
12381243
the actual order, and the actual group structure::
12391244
1240-
sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 6
1245+
sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
12411246
sage: G = E(5, 0) # G has order 2
12421247
sage: G.set_order(11)
12431248
Traceback (most recent call last):
@@ -1248,7 +1253,7 @@ def set_order(self, value):
12481253
of interest". For instance, the order can be set to a multiple the
12491254
actual order::
12501255
1251-
sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 6
1256+
sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
12521257
sage: G = E(5, 0) # G has order 2
12531258
sage: G.set_order(8)
12541259
sage: G.order()
@@ -1260,15 +1265,16 @@ def set_order(self, value):
12601265
"""
12611266
value = Integer(value)
12621267

1263-
E = self.curve()
1264-
q = E.base_ring().order()
1265-
if value <= 0:
1266-
raise ValueError('Value %s illegal for point order' % value)
1267-
low, hi = Hasse_bounds(q)
1268-
if value > hi:
1269-
raise ValueError('Value %s illegal: outside max Hasse bound' % value)
1270-
if value * self != E(0):
1271-
raise ValueError('Value %s illegal: %s * %s is not the identity' % (value, value, self))
1268+
if check:
1269+
if value <= 0:
1270+
raise ValueError('Value %s illegal for point order' % value)
1271+
E = self.curve()
1272+
q = E.base_ring().cardinality()
1273+
low, hi = Hasse_bounds(q)
1274+
if value > hi:
1275+
raise ValueError('Value %s illegal: outside max Hasse bound' % value)
1276+
if value * self != E(0):
1277+
raise ValueError('Value %s illegal: %s * %s is not the identity' % (value, value, self))
12721278
self._order = value
12731279

12741280
# ############################# end ################################

0 commit comments

Comments
 (0)