Merge #113: Upstream PRs #849 #851

f4fa8d226a95e42b252c07edb425c446370e01c0 forbid a test iteration of 0 or less (Andrew Poelstra)
0ce45548813709d828cb3abcc7db4c9ce6e26907 make test count iteration configurable by environment variable (Andrew Poelstra)
13c88efed0005eb6745a222963ee74564054eafb Convert Sage code to Python 3 (as used by Sage >= 9) (Frédéric Chapoton)

Pull request description:

Top commit has no ACKs.

Tree-SHA512: b17847a02843a36630a3c05065e0bda6895e042bbfd045feb2ad64e278a02842a80d66b6416eb3a6768f4b2f6c8f639fb293a537dff90a353624aff737058b8f
This commit is contained in:
Jonas Nick 2020-12-04 13:48:51 +00:00
commit 0129b77767
No known key found for this signature in database
GPG Key ID: 4861DBF262123605
3 changed files with 38 additions and 24 deletions

View File

@ -65,7 +65,7 @@ class fastfrac:
return self.top in I and self.bot not in I return self.top in I and self.bot not in I
def reduce(self,assumeZero): def reduce(self,assumeZero):
zero = self.R.ideal(map(numerator, assumeZero)) zero = self.R.ideal(list(map(numerator, assumeZero)))
return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot)) return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot))
def __add__(self,other): def __add__(self,other):
@ -100,7 +100,7 @@ class fastfrac:
"""Multiply something else with a fraction.""" """Multiply something else with a fraction."""
return self.__mul__(other) return self.__mul__(other)
def __div__(self,other): def __truediv__(self,other):
"""Divide two fractions.""" """Divide two fractions."""
if parent(other) == ZZ: if parent(other) == ZZ:
return fastfrac(self.R,self.top,self.bot * other) return fastfrac(self.R,self.top,self.bot * other)
@ -108,6 +108,11 @@ class fastfrac:
return fastfrac(self.R,self.top * other.bot,self.bot * other.top) return fastfrac(self.R,self.top * other.bot,self.bot * other.top)
return NotImplemented return NotImplemented
# Compatibility wrapper for Sage versions based on Python 2
def __div__(self,other):
"""Divide two fractions."""
return self.__truediv__(other)
def __pow__(self,other): def __pow__(self,other):
"""Compute a power of a fraction.""" """Compute a power of a fraction."""
if parent(other) == ZZ: if parent(other) == ZZ:
@ -175,7 +180,7 @@ class constraints:
def conflicts(R, con): def conflicts(R, con):
"""Check whether any of the passed non-zero assumptions is implied by the zero assumptions""" """Check whether any of the passed non-zero assumptions is implied by the zero assumptions"""
zero = R.ideal(map(numerator, con.zero)) zero = R.ideal(list(map(numerator, con.zero)))
if 1 in zero: if 1 in zero:
return True return True
# First a cheap check whether any of the individual nonzero terms conflict on # First a cheap check whether any of the individual nonzero terms conflict on
@ -195,7 +200,7 @@ def conflicts(R, con):
def get_nonzero_set(R, assume): def get_nonzero_set(R, assume):
"""Calculate a simple set of nonzero expressions""" """Calculate a simple set of nonzero expressions"""
zero = R.ideal(map(numerator, assume.zero)) zero = R.ideal(list(map(numerator, assume.zero)))
nonzero = set() nonzero = set()
for nz in map(numerator, assume.nonzero): for nz in map(numerator, assume.nonzero):
for (f,n) in nz.factor(): for (f,n) in nz.factor():
@ -208,7 +213,7 @@ def get_nonzero_set(R, assume):
def prove_nonzero(R, exprs, assume): def prove_nonzero(R, exprs, assume):
"""Check whether an expression is provably nonzero, given assumptions""" """Check whether an expression is provably nonzero, given assumptions"""
zero = R.ideal(map(numerator, assume.zero)) zero = R.ideal(list(map(numerator, assume.zero)))
nonzero = get_nonzero_set(R, assume) nonzero = get_nonzero_set(R, assume)
expl = set() expl = set()
ok = True ok = True
@ -250,7 +255,7 @@ def prove_zero(R, exprs, assume):
r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume) r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume)
if not r: if not r:
return (False, map(lambda x: "Possibly zero denominator: %s" % x, e)) return (False, map(lambda x: "Possibly zero denominator: %s" % x, e))
zero = R.ideal(map(numerator, assume.zero)) zero = R.ideal(list(map(numerator, assume.zero)))
nonzero = prod(x for x in assume.nonzero) nonzero = prod(x for x in assume.nonzero)
expl = [] expl = []
for expr in exprs: for expr in exprs:
@ -265,8 +270,8 @@ def describe_extra(R, assume, assumeExtra):
"""Describe what assumptions are added, given existing assumptions""" """Describe what assumptions are added, given existing assumptions"""
zerox = assume.zero.copy() zerox = assume.zero.copy()
zerox.update(assumeExtra.zero) zerox.update(assumeExtra.zero)
zero = R.ideal(map(numerator, assume.zero)) zero = R.ideal(list(map(numerator, assume.zero)))
zeroextra = R.ideal(map(numerator, zerox)) zeroextra = R.ideal(list(map(numerator, zerox)))
nonzero = get_nonzero_set(R, assume) nonzero = get_nonzero_set(R, assume)
ret = set() ret = set()
# Iterate over the extra zero expressions # Iterate over the extra zero expressions

View File

@ -175,24 +175,24 @@ laws_jacobian_weierstrass = {
def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p): def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p):
"""Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field""" """Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field"""
F = Integers(p) F = Integers(p)
print "Formula %s on Z%i:" % (name, p) print("Formula %s on Z%i:" % (name, p))
points = [] points = []
for x in xrange(0, p): for x in range(0, p):
for y in xrange(0, p): for y in range(0, p):
point = affinepoint(F(x), F(y)) point = affinepoint(F(x), F(y))
r, e = concrete_verify(on_weierstrass_curve(A, B, point)) r, e = concrete_verify(on_weierstrass_curve(A, B, point))
if r: if r:
points.append(point) points.append(point)
for za in xrange(1, p): for za in range(1, p):
for zb in xrange(1, p): for zb in range(1, p):
for pa in points: for pa in points:
for pb in points: for pb in points:
for ia in xrange(2): for ia in range(2):
for ib in xrange(2): for ib in range(2):
pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia) pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia)
pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib) pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib)
for branch in xrange(0, branches): for branch in range(0, branches):
assumeAssert, assumeBranch, pC = formula(branch, pA, pB) assumeAssert, assumeBranch, pC = formula(branch, pA, pB)
pC.X = F(pC.X) pC.X = F(pC.X)
pC.Y = F(pC.Y) pC.Y = F(pC.Y)
@ -206,13 +206,13 @@ def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p):
r, e = concrete_verify(assumeLaw) r, e = concrete_verify(assumeLaw)
if r: if r:
if match: if match:
print " multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity) print(" multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity))
else: else:
match = True match = True
r, e = concrete_verify(require) r, e = concrete_verify(require)
if not r: if not r:
print " failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e) print(" failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e))
print print()
def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC): def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC):
@ -242,9 +242,9 @@ def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula):
for key in laws_jacobian_weierstrass: for key in laws_jacobian_weierstrass:
res[key] = [] res[key] = []
print ("Formula " + name + ":") print("Formula " + name + ":")
count = 0 count = 0
for branch in xrange(branches): for branch in range(branches):
assumeFormula, assumeBranch, pC = formula(branch, pA, pB) assumeFormula, assumeBranch, pC = formula(branch, pA, pB)
pC.X = lift(pC.X) pC.X = lift(pC.X)
pC.Y = lift(pC.Y) pC.Y = lift(pC.Y)
@ -255,10 +255,10 @@ def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula):
res[key].append((check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC), branch)) res[key].append((check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC), branch))
for key in res: for key in res:
print " %s:" % key print(" %s:" % key)
val = res[key] val = res[key]
for x in val: for x in val:
if x[0] is not None: if x[0] is not None:
print " branch %i: %s" % (x[1], x[0]) print(" branch %i: %s" % (x[1], x[0]))
print print()

View File

@ -5802,6 +5802,15 @@ int main(int argc, char **argv) {
/* find iteration count */ /* find iteration count */
if (argc > 1) { if (argc > 1) {
count = strtol(argv[1], NULL, 0); count = strtol(argv[1], NULL, 0);
} else {
const char* env = getenv("SECP256K1_TEST_ITERS");
if (env) {
count = strtol(env, NULL, 0);
}
}
if (count <= 0) {
fputs("An iteration count of 0 or less is not allowed.\n", stderr);
return EXIT_FAILURE;
} }
printf("test count = %i\n", count); printf("test count = %i\n", count);