def generate_smooth(number, factor_base): result = [] start = calculate_start(number) end = calculate_end(number) sieve = np.array([x**2-number for x in range(start,end)], copy = False, order = 'C') xs = [] ys = [] for factor in factor_base: roots = [] if 2 == factor: roots = [modsqrt(number, factor)] # ring formed by mod 2 only has one root else: first_root = modsqrt(number, factor) roots = [first_root, factor - first_root] for root in roots: s = math.ceil(start / factor) * factor - start for ind in [s-root,s+root]: index = int(ind) # for python2 while index < end - start: if 0 <= index: sieve[index] = factor_out(sieve[index], factor) if sieve[index] == 1: xs.append(index+start) ys.append((index+start)**2-number) if len(xs) > len(factor_base) + 30: return (xs, ys) index = index + factor return (xs,ys)
def roots_loop(g, deg_g, p, Fp): if deg_g == 0: return [] if deg_g == 1: return [(-g[0]/g[1]).toInteger()] elif deg_g == 2: d = g[1]*g[1]-4*g[0] e = arith1.modsqrt(d.toInteger(), p) g1 = -g[1] g2 = 2*g[2] return [((g1 - e) / g2).toInteger(), ((g1 + e) / g2).toInteger()] deg_h = 0 x = uniutil.FinitePrimeFieldPolynomial({0:-1, (p-1)//2:1}, Fp) a = 0 while deg_h == 0 or deg_h == deg_g: b = uniutil.FinitePrimeFieldPolynomial({0:-a, 1:1}, Fp) v = g(b) h = x.gcd(v) a = a + 1 deg_h = h.degree() b = uniutil.FinitePrimeFieldPolynomial({0:a-1, 1:1}, Fp) s = h(b) deg_s = deg_h t = g.exact_division(s) deg_t = t.degree() return roots_loop(s, deg_s, p, Fp) + roots_loop(t, deg_t, p, Fp)
def roots_loop(g, deg_g, p, Fp): if deg_g == 0: return [] if deg_g == 1: return [(-g[0] / g[1]).toInteger()] elif deg_g == 2: d = g[1] * g[1] - 4 * g[0] e = arith1.modsqrt(d.toInteger(), p) g1 = -g[1] g2 = 2 * g[2] return [((g1 - e) / g2).toInteger(), ((g1 + e) / g2).toInteger()] deg_h = 0 x = uniutil.FinitePrimeFieldPolynomial({0: -1, (p - 1) >> 1: 1}, Fp) a = 0 while deg_h == 0 or deg_h == deg_g: b = uniutil.FinitePrimeFieldPolynomial({0: -a, 1: 1}, Fp) v = g(b) h = x.gcd(v) a = a + 1 deg_h = h.degree() b = uniutil.FinitePrimeFieldPolynomial({0: a - 1, 1: 1}, Fp) s = h(b) deg_s = deg_h t = g.exact_division(s) deg_t = t.degree() return roots_loop(s, deg_s, p, Fp) + roots_loop(t, deg_t, p, Fp)
def cornacchia(d, p): """ Return the solution of x^2 + d * y^2 = p . p be a prime and d be an integer such that 0 < d < p. """ if (d <= 0) or (d >= p): raise ValueError("invalid input") k = arith1.legendre(-d, p) if k == -1: raise ValueError("no solution") x0 = arith1.modsqrt(-d, p) if x0 < (p / 2): x0 = p - x0 a = p b = x0 l = arith1.floorsqrt(p) while b > l: a, b = b, a % b c, r = divmod(p - b * b, d) if r: raise ValueError("no solution") t = arith1.issquare(c) if t == 0: raise ValueError("no solution") else: return (b, t)
def cornacchiamodify(d, p): """ Algorithm 26 (Modified cornacchia) Input : p be a prime and d be an integer such that d < 0 and d > -4p with d = 0, 1 (mod 4) Output : the solution of u^2 -d * v^2 = 4p. """ q = 4 * p if (d >= 0) or (d <= -q): raise ValueError("invalid input") if p == 2: b = arith1.issquare(d + 8) if b: return (b, 1) else: raise ValueError("no solution") if arith1.legendre(d, p) == -1: raise ValueError("no solution") x0 = arith1.modsqrt(d, p) if (x0 - d) & 1: x0 = p - x0 a = 2 * p b = x0 l = arith1.floorsqrt(q) while b > l: a, b = b, a % b c, r = divmod(q - b * b, -d) if r: raise ValueError("no solution") t = arith1.issquare(c) if t: return (b, t) else: raise ValueError("no solution")
def cornacchiamodify(d, p): """ Algorithm 26 (Modified cornacchia) Input : p be a prime and d be an integer such that d < 0 and d > -4p with d = 0, 1 (mod 4) Output : the solution of u^2 -d * v^2 = 4p. """ q = 4 * p if (d >= 0) or (d <= -q): raise ValueError("invalid input") if p == 2: b = arith1.issquare(d + 8) if b: return (b, 1) else: raise ValueError("no solution") if arith1.legendre(d, p) == -1: raise ValueError("no solution") x0 = arith1.modsqrt(d, p) if (x0 - d) % 2 != 0: x0 = p - x0 a = 2 * p b = x0 l = arith1.floorsqrt(q) while b > l: a, b = b, a % b c, r = divmod(q - b * b, -d) if r: raise ValueError("no solution") t = arith1.issquare(c) if t: return (b, t) else: raise ValueError("no solution")
def SquareRoot(self, element): """ Return square root if exist. """ if not element or element.n == 1: return element # trivial case if element.m == 2: return element.getRing().one return arith1.modsqrt(element.n, element.m)
def random_point(self): """ Returns: A random point on the curve. """ x = random.randrange(self.p) y_square = x**3 + self.a * x + self.b while jacobi(y_square, self.p) == -1: x = random.randrange(self.p) y_square = x**3 + self.a * x + self.b y = modsqrt(y_square, self.p) return x,
def choose_point(self): """ Choose point on E_{a,b}(Z_n) Algorithm 27 (Atkin-morain ECPP) Step5 """ n, f = self.modulus, self.f x = bigrandom.randrange(n) Q = f(x) while arith1.legendre(Q, n) == -1: x = bigrandom.randrange(n) Q = f(x) y = arith1.modsqrt(Q, n) return [intresidue.IntegerResidueClass(t, n) for t in (x, y)]
def root_Fp(g, p, flag=True): """ Return a root over F_p of nonzero polynomial g. p must be prime. If flag = False, return a root randomly """ if isinstance(g, list): if not isinstance(g[0], tuple): g = zip(range(len(g)), g) Fp = finitefield.FinitePrimeField(p) g = uniutil.FinitePrimeFieldPolynomial(g, Fp) h = uniutil.FinitePrimeFieldPolynomial({1: -1, p: 1}, Fp) g = g.gcd(h) deg_g = g.degree() if g[0] == 0: deg_g = deg_g - 1 g = g.shift_degree_to(deg_g) while True: if deg_g == 0: return None if deg_g == 1: return (-g[0] / g[1]).toInteger() elif deg_g == 2: d = g[1] * g[1] - 4 * g[0] e = arith1.modsqrt(d.toInteger(), p) return ((-g[1] - e) / (2 * g[2])).toInteger() deg_h = 0 x = uniutil.FinitePrimeFieldPolynomial({0: -1, (p - 1) >> 1: 1}, Fp) if flag: a = 0 while deg_h == 0 or deg_h == deg_g: b = uniutil.FinitePrimeFieldPolynomial({0: -a, 1: 1}, Fp) v = g(b) h = x.gcd(v) a = a + 1 deg_h = h.degree() b = uniutil.FinitePrimeFieldPolynomial({0: a - 1, 1: 1}, Fp) else: while deg_h == 0 or deg_h == deg_g: a = bigrandom.randrange(p) b = uniutil.FinitePrimeFieldPolynomial({0: -a, 1: 1}, Fp) v = g(b) h = x.gcd(v) deg_h = h.degree() b = uniutil.FinitePrimeFieldPolynomial({0: a, 1: 1}, Fp) g = h(b) deg_g = deg_h
def root_Fp(g, p, flag=True): """ Return a root over F_p of nonzero polynomial g. p must be prime. If flag = False, return a root randomly """ if isinstance(g, list): if not isinstance(g[0], tuple): g = zip(range(len(g)), g) Fp = finitefield.FinitePrimeField(p) g = uniutil.FinitePrimeFieldPolynomial(g, Fp) h = uniutil.FinitePrimeFieldPolynomial({1:-1, p:1}, Fp) g = g.gcd(h) deg_g = g.degree() if g[0] == 0: deg_g = deg_g - 1 g = g.shift_degree_to(deg_g) while True: if deg_g == 0: return None if deg_g == 1: return (-g[0]/g[1]).toInteger() elif deg_g == 2: d = g[1]*g[1] - 4*g[0] e = arith1.modsqrt(d.toInteger(), p) return ((-g[1]-e)/(2*g[2])).toInteger() deg_h = 0 x = uniutil.FinitePrimeFieldPolynomial({0:-1, (p-1)//2:1}, Fp) if flag: a = 0 while deg_h == 0 or deg_h == deg_g: b = uniutil.FinitePrimeFieldPolynomial({0:-a, 1:1}, Fp) v = g(b) h = x.gcd(v) a = a + 1 deg_h = h.degree() b = uniutil.FinitePrimeFieldPolynomial({0:a-1, 1:1}, Fp) else: while deg_h == 0 or deg_h == deg_g: a = bigrandom.randrange(p) b = uniutil.FinitePrimeFieldPolynomial({0:-a, 1:1}, Fp) v = g(b) h = x.gcd(v) deg_h = h.degree() b = uniutil.FinitePrimeFieldPolynomial({0:a, 1:1}, Fp) g = h(b) deg_g = deg_h
def cornacchia_smith(p, d): ''' modified Cornacchia's Algorithm to solve a^2 + b^2 |D| = 4p for a and b Args: p: d: Returns: a, b such that a^2 + b^2 |D| = 4p ''' # check input if not -4 * p < d < 0: raise ValueError(" -4p < D < 0 not true.") elif not (d % 4 in {0, 1}): raise ValueError(" D = 0, 1 (mod 4) not true.") # case where p=2 if p == 2: r = sqrt(d + 8) if r != -1: return r, 1 else: return None # test for solvability if jacobi(d % p, p) < 1: return None x = modsqrt(d, p) if (x % 2) != (d % 2): x = p - x # euclid chain a, b = (2 * p, x) c = floorsqrt(4 * p) while b > c: a, b = b, a % b t = 4 * p - b * b if t % (-d) != 0: return None if not issquare(t / (-d)): return None return b, int(mpmath.sqrt(t / -d))
def choose_point(ec): """ Choose a random point on EC. Adapted from random_point function. With the additional check for modsqrt. Args: ec: an elliptic curve by the equation y^2 = x^3 + a * x + b Returns: a valid point on the curve. """ x = random.randrange(ec.p) y_square = (x**3 + ec.a * x + ec.b) % ec.p while jacobi(y_square, ec.p) == -1: x = random.randrange(ec.p) y_square = (x**3 + ec.a * x + ec.b) % ec.p y = modsqrt(y_square, ec.p) if (y**2 % ec.p) != y_square: raise ValueError("Error computing square root.") return x, y
def sqroot_power(a, p, n): """ return squareroot of a mod p^k for k = 2,3,...,n """ r = arith1.modsqrt(a, p) x = (r, p-r) i = 2 answer = [x] ppower = p while i <= n: b_1 = (x[0]**2-a) // ppower b_2 = (x[1]**2-a) // ppower x_1 = -b_1 * arith1.inverse(2*x[0], p) x_2 = -b_2 * arith1.inverse(2*x[1], p) X_1 = x[0] + x_1*ppower % (p*ppower) X_2 = x[1] + x_2*ppower % (p*ppower) x = [X_1, X_2] answer.append(x) i += 1 ppower *= p return answer
def sqroot(disc, p): """ Return a reduced quadratic form with the given discriminant. 'disc' is a quadratic residue mod 'p'. """ if p == 2: # if 8 | disc => (disc / 8) = 0, 8 not | disc but 4 | disc => 2 if (disc % 8) == 0: bp = disc elif (disc % 4) == 0: # 4 - 4 * odd % 8 => 0 bp = 2 elif (disc % 8) == 1: # disc is odd and disc % 8 is 1 bp = disc else: # disc is odd and disc % 4 is 1 => impossible (-5 / 2) = -1 raise ValueError("disc is odd and disc % 4 is 1 => impossible (-5 / 2) = -1") else: bpf1 = arith1.modsqrt(disc, p) bpf2 = disc bp = crt([(bpf1, p), (bpf2, 4)]) if bp > p: bp = 2 * p - bp fpt = reducePDF((p, bp, ((bp ** 2) - disc) // (4 * p))) return fpt
def e2_Fp(x, p): """ p is prime f = x[0] + x[1]*t + x[2]*t**2 """ c, b, a = [_x % p for _x in x] if a == 0: return [e1_ZnZ([c, b], p)] if p == 2: solutions = [] if x[0] & 1 == 0: solutions.append(0) if (x[0] + x[1] + x[2]) & 1 == 0: solutions.append(1) if len(solutions) == 1: return solutions * 2 return solutions d = b**2 - 4 * a * c if arith1.legendre(d, p) == -1: return [] sqrtd = arith1.modsqrt(d, p) a = arith1.inverse(2 * a, p) return [((-b + sqrtd) * a) % p, ((-b - sqrtd) * a) % p]
def e2_Fp(x, p): """ p is prime f = x[0] + x[1]*t + x[2]*t**2 """ c, b, a = [_x % p for _x in x] if a == 0: return [e1_ZnZ([c, b], p)] if p == 2: solutions = [] if x[0] % 2 == 0: solutions.append(0) if (x[0] + x[1] + x[2]) % 2 == 0: solutions.append(1) if len(solutions) == 1: return solutions * 2 return solutions d = b**2 - 4*a*c if arith1.legendre(d, p) == -1: return [] sqrtd = arith1.modsqrt(d, p) a = arith1.inverse(2*a, p) return [((-b+sqrtd)*a)%p, ((-b-sqrtd)*a)%p]
def sqroot(disc, p): """ Return a reduced quadratic form with the given discriminant. 'disc' is a quadratic residue mod 'p'. """ if p == 2: # if 8 | disc => (disc / 8) = 0, 8 not | disc but 4 | disc => 2 if (disc & 7) == 0: bp = disc elif (disc & 3) == 0: # 4 - 4 * odd % 8 => 0 bp = 2 elif (disc & 7) == 1: # disc is odd and disc % 8 is 1 bp = disc else: # disc is odd and disc & 3 is 1 => impossible (-5 / 2) = -1 raise ValueError( "disc is odd and disc & 3 is 1 => impossible (-5 / 2) = -1") else: bpf1 = arith1.modsqrt(disc, p) bpf2 = disc bp = crt([(bpf1, p), (bpf2, 4)]) if bp > p: bp = 2 * p - bp fpt = reducePDF((p, bp, ((bp**2) - disc) // (4 * p))) return fpt
def testModsqrt(self): self.assertTrue(arith1.modsqrt(2, 17) in (6, 11)) self.assertTrue(arith1.modsqrt(124413, 2**17 - 1) in (3998, 127073)) self.assertEqual(1, arith1.modsqrt(1, 2**13 - 1)) self.assertTrue(arith1.modsqrt(2, 7, 2) in (10, 39)) self.assertTrue(arith1.modsqrt(12, 97, 3) in (448799, 463874))