def norm_search(p, d): md = None if (d % 4) != 1: for nn in range(1, 20000): for mm in [nn**2 * d + p, nn**2 * d - p]: if issq(mm): m2 = int(sqrt(mm)) if (gcd(nn, p) == 1) or (gcd(m2, p) == 1): md = QuadInt(d, m2, nn) break return md
def coset_reps(qq): r""" Yield coset representatives for Gamma(q) in SL(2, Z). """ zq2 = itertools.product(range(qq), range(qq)) # # this pattern matching no longer seems to work in python 3.6 # # f=lambda (cc, dd):gcd(cc, gcd(dd, qq))==1 # # so replace it with this: # def f(pair): cc, dd = pair return gcd(cc, gcd(dd, qq)) == 1 for (cc, dd) in filter(f, zq2): ii = 0 if cc == 0: if dd != 1: cc = qq while True: if gcd(cc, dd - ii * qq) == 1: dd -= ii * qq break elif gcd(cc, dd + ii * qq) == 1: dd += ii * qq break ii += 1 # cc and dd are now relatively prime. zq2 = itertools.product(range(qq), range(qq)) for (aa, bb) in zq2: quot, rem = divmod(aa * dd - bb * cc, qq) if rem == 1: # now aa*dd-bb*cc = 1 (mod qq) for (ee, ff) in [(ee, ff) for ee in range(-2 * qq, 2 * qq) for ff in range(-2 * qq, 2 * qq)]: if (aa + ee * qq) * dd - (bb + ff * qq) * cc == 1: yieldval = np.array( [[aa + ee * qq, bb + ff * qq], [cc, dd]], dtype=int) # now normalize so that the image of D under this # transformation lies between -1/2 and q-1/2. f = mat_to_fcn(yieldval) mm = int(floor(f([0.5j])[0].real)) yieldval = np.array([[1, mm % qq - mm], [0, 1]], dtype=int).dot(yieldval) yield yieldval break
def cont_frac_quad(a, b, c, d): r""" Yield the continued fraction for (a+b*sqrt(d))/c """ sqd = mpmath.sqrt(d) while True: m = int((mpmath.mpf(a) + sqd * mpmath.mpf(b)) / mpmath.mpf(c)) yield m a1p = (a - c * m) a1 = c * a1p b1 = -c * b c1 = a1p**2 - d * b**2 g = gcd(c * gcd(a1p, b), c1) a, b, c = a1 // g, b1 // g, c1 // g
def all_reduced_forms(disc): """ Return a list of all reduced forms with negative discriminant D. """ if disc >= 0: raise ValueError("discriminant must be negative") retval = [] for a in range(1, int(sqrt(-disc / 3.0) + 1.0)): for b in range(-a + 1, a + 1): c, r = divmod(b**2 - disc, 4 * a) if r == 0: if gcd(gcd(a, abs(b)), c) == 1: if a <= c and ((a != c) or (b >= 0)): retval.append((a, b, c)) return sorted(list(set(retval)))
def solve_common_factors(ciphertexts, modulos, exponents): plaintexts = [] factors_found = [] for i in range(len(modulos)): for j in range(i + 1, len(modulos)): calc_gcd = gcd(modulos[i], modulos[j]) if calc_gcd > 1: factors_found.append([i, j, calc_gcd]) for mod_pair in factors_found: # Get factors of n1 and n2 calc_gcd = mod_pair[2] q1 = modulos[mod_pair[0]] / calc_gcd q2 = modulos[mod_pair[1]] / calc_gcd # Decrypt c1 c1 = ciphertexts[mod_pair[0]] e1 = exponents[mod_pair[0]] p1 = decrypt(c1, e1, modulos[mod_pair[0]], p=calc_gcd, q=q1) # Decrypt c2 c2 = ciphertexts[mod_pair[1]] e2 = exponents[mod_pair[1]] p2 = decrypt(c2, e2, modulos[mod_pair[1]], p=calc_gcd, q=q2) plaintexts.append(p1) plaintexts.append(p2) return plaintexts
def legendre_ch(d): """ Return the mod abs(disc Q[√d]) Legendre character. This is the character ch with modulus D=abs(disc Q[√d]) such that for any odd prime p, ch(p)=(d/p) (i.e. ch(p)=0 if p|d ch(p)=1 if d is a square mod p ch(p)=-1 if d is not a square mod p """ if not squarefree(d): raise ValueError('%d is not square free' % (d, )) abs_disc = abs(discriminant(d)) vals = [0] * abs_disc for k in range(abs_disc): if gcd(abs_disc, k) == 1: n = k while True: if isprime(n) and n % 2 == 1: vals[k] = legendre(d, n) break n += abs_disc return lambda a: vals[a % abs_disc]
def ideal_class_number(dd): r""" Return the ideal class number of Q[√d], for squarefree integer dd. """ if not squarefree(dd): raise ValueError("%d is not squarefree." % (dd, )) if dd == 1: return 1 abs_disc = abs(discriminant(dd)) ch = legendre_ch(dd) z = np.exp(2.0j * np.pi / abs_disc) rho = np.abs(1.0 / np.sqrt(abs(abs_disc)) * sum( ch(k) * np.log(1 - z**(-k)) for k in range(1, abs_disc) if gcd(k, abs_disc) == 1)) k = kappa(dd) # magically rho should be an integral multiple of kappa. # make sure this is true before we return the rounded answer. assert (abs(round(rho / k) - rho / k) < 0.001) return int(round(rho / k))
def L_one_chi(ch, m): r""" Compute the value of the Dirichlet L-series L(s, ch) at s=1. """ zz = np.exp(2.0j * np.pi / m) return -(1.0 / m) * sum( gs_numerical(ch, m, k) * np.log(1 - zz**(-k)) for k in range(1, m) if gcd(k, m) == 1)
def conjugates(self): """ Yield the conjugates of the cyclotomic integer. """ nc = len(self.coefs) for k in range(nc): if gcd(k, nc) == 1: yield CyclotomicInteger( [self.coefs[ii * k % nc] for ii in range(nc)])
def genus(a, b, c): def f(xx, yy): return a * xx**2 + b * xx * yy + c * yy**2 disc = form_disc(a, b, c) val = sorted( list( set([ f(x, y) % (-disc) for x in range(-disc) for y in range(-disc) ]))) return filter(lambda xx: gcd(xx, -disc) == 1, val)
def eisenstein(k, z): """ Return the value phi_0, k(z) of the Eisenstein series of weight k at z. """ if z.imag <= 0: raise ValueError("z not in the upper half plane.") nmax = _eisenstein_bound(1e-08, k, z) retval = 0.0 for nn in range(nmax, 0, -1): for (cc, dd) in _rectangle_n_points(nn): if cc >= 0 and (cc > 0 or dd > 0) and gcd(cc, dd) == 1: vv = 1 / (cc * z + dd)**(2 * k) retval += vv return retval
def poincare(k, nu, z): """ Return the value of the Poincare series of weight k and character nu at z. """ if z.imag <= 0: raise ValueError("z not in the upper half plane.") nmax = _eisenstein_bound(1e-08, k, z) retval = 0.0 for nn in range(nmax, 0, -1): for (cc, dd) in _rectangle_n_points(nn): if cc >= 0 and (cc > 0 or dd > 0) and gcd(cc, dd) == 1: bb, aa = euclidean_algorithm(cc, dd) Tz = (aa * z - bb) / (cc * z + dd) vv = np.exp( 2.0 * np.pi * nu * 1.0j * Tz) / (cc * z + dd)**(2 * k) retval += vv return retval
def f(pair): cc, dd = pair return gcd(cc, gcd(dd, qq)) == 1
def test_gcd(self): self.assertEqual(gcd(2 * 3 * 5, 3 * 5 * 7), 3 * 5)
def generate_public_key(self): public_key = 2 while public_key < self.phi: if math.gcd(public_key, self.phi) == 1: return public_key public_key += 1
def test_euclidean_algorithm2(self): for a in range(-100, +100): for b in range(-100, +100): x, y = euclidean_algorithm(a, b) self.assertEqual(gcd(a, b), x * a + y * b, 'gcd != x*a+y*b')
def test_euclidean_algorithm(self): a = 89 b = 55 x, y = euclidean_algorithm(a, b) self.assertEqual(abs(gcd(a, b)), abs(x * a + y * b))
for y in range(x + 1, 100): num = [a for a in str(x)] den = [a for a in str(y)] if num[-1] == 0: pass elif num[-1] == den[0]: num.remove(num[-1]) num = int("".join(num)) den.remove(den[0]) den = int("".join(den)) if den == 0: pass else: check = num / den actual = x / y if check == actual: top.append(x) bottom.append(y) top = reduce(lambda x, y: x * y, top) bottom = reduce(lambda x, y: x * y, bottom) div = gcd(top, bottom) bottom /= div print(bottom)
def test_phi(self): for nn in range(1, 100): nresid = sum(1 for kk in range(1, nn+1) if gcd(nn, kk) == 1) self.assertEqual(nresid, phi(nn))