def te_s_t(a, b): g, s, t = gmpy.gcdext(a, b) if abs(a) == abs(b): test_s = s == 0 elif b == 0 or abs(b) == 2 * g: test_s = s == bool(a > 0) - bool(a < 0) # sign of a else: test_s = abs(s) < abs(b) / (2 * g) if abs(a) == abs(b) or a == 0 or abs(a) == 2 * g: test_t = t == bool(b > 0) - bool(b < 0) # sign of b else: test_t = abs(t) < abs(a) / (2 * g) return g == a * s + b * t and test_s and test_t
def operation2(cls, f, /): # Cohen: Algorithm 5.4.8 (NUDUPL) a, b, c = f d1, u, _ = gcdext(b, a) assert d1 == 1 # because -discriminant is prime A = a // d1 B = b // d1 C = (-c * u) % A C1 = A - C if C1 < C: C = -C1 d, v3 = A, C v2, v = 1, 0 z = 0 L = iroot(-cls.discriminant // 4, 4)[0] while abs(v3) > L: # partial Euclid d, (q, v3) = v3, divmod(d, v3) v, v2, = v2, v - q * v2 z += 1 if z % 2: v2, v3 = -v2, -v3 if z == 0: g = (B * v3 + c) // d a2 = d**2 b2 = b + 2 * d * v3 c2 = v3**2 + g * d1 else: e = (c * v + B * d) // A h = e * v2 g = (h - B) // v a2 = d**2 + d1 * e * v b2 = d1 * (h + v * g) + 2 * d * v3 c2 = v3**2 + d1 * g * v2 f2 = int(a2), int(b2), int( c2) # NB: convert from gmpy2.mpz, if gmpy2 is used for gcdext() return cls(cls._reduce(f2), check=False)
def operation(cls, f1, f2): # Cohen: Algorithm 5.4.9 (NUCOMP) if f1[0] < f2[0]: f1, f2 = f2, f1 a1, b1, c1 = f1 a2, b2, c2 = f2 s = (b1 + b2) // 2 n = b2 - s d, u, v = gcdext(a2, a1) if d == 1: A = -u * n d1 = d elif s % d == 0: A = -u * n d1 = d a1 //= d1 a2 //= d1 s //= d1 else: d1, u1, _ = gcdext(s, d) if d1 > 1: a1 //= d1 a2 //= d1 s //= d1 d //= d1 l = (-u1 * (u * (c1 % d) + v * (c2 % d))) % d A = -u * (n // d) + l * (a1 // d) A = A % a1 A1 = a1 - A if A1 < A: A = - A1 d, v3 = a1, A v2, v = 1, 0 z = 0 L = iroot(-cls.discriminant//4, 4)[0] while abs(v3) > L: # partial Euclid d, (q, v3) = v3, divmod(d, v3) v, v2, = v2, v - q * v2 z += 1 if z%2: v2, v3 = -v2, -v3 if z == 0: Q1 = a2 * v3 f = (Q1 + n) // d g = (v3 * s + c2) // d a3 = d * a2 b3 = 2*Q1 + b2 c3 = v3 * f + g * d1 # erratum Cohen (step 6) else: b = (a2 * d + n * v) // a1 Q1 = b * v3 Q2 = Q1 + n f = Q2 // d e = (s * d + c2 * v) // a1 Q3 = e * v2 Q4 = Q3 - s g = Q4 // v a3 = d * b + d1 * e * v b3 = Q1 + Q2 + d1 * (Q3 + Q4) c3 = v3 * f + d1 * g * v2 f3 = int(a3), int(b3), int(c3) # NB: convert from gmpy2.mpz, if gmpy2 is used for gcdext() return cls(cls._reduce(f3), check=False)
def test_basic(self): self.assertFalse(gmpy.is_prime(1)) self.assertTrue(gmpy.is_prime(2)) self.assertTrue(gmpy.is_prime(101)) self.assertFalse(gmpy.is_prime(561)) self.assertTrue(gmpy.is_prime(2**16 + 1)) self.assertFalse(gmpy.is_prime(41041)) self.assertEqual(gmpy.next_prime(1), 2) self.assertEqual(gmpy.next_prime(2), 3) self.assertEqual(gmpy.next_prime(256), 257) self.assertEqual(gmpy.powmod(3, 256, 257), 1) self.assertEqual(gmpy.gcdext(3, 257), (1, 86, -1)) self.assertEqual(gmpy.gcdext(1234, 257), (1, -126, 605)) self.assertEqual(gmpy.gcdext(-1234 * 3, -257 * 3), (3, 126, -605)) def te_s_t(a, b): g, s, t = gmpy.gcdext(a, b) if abs(a) == abs(b): test_s = s == 0 elif b == 0 or abs(b) == 2 * g: test_s = s == bool(a > 0) - bool(a < 0) # sign of a else: test_s = abs(s) < abs(b) / (2 * g) if abs(a) == abs(b) or a == 0 or abs(a) == 2 * g: test_t = t == bool(b > 0) - bool(b < 0) # sign of b else: test_t = abs(t) < abs(a) / (2 * g) return g == a * s + b * t and test_s and test_t self.assertTrue( all((te_s_t(0, 0), te_s_t(0, -1), te_s_t(1, 0), te_s_t(-1, 1)))) self.assertTrue(te_s_t(-1234, 257)) self.assertTrue(te_s_t(-12537, -257)) self.assertTrue(te_s_t(-11 * 1234, -11 * 2567)) self.assertTrue(te_s_t(1234, -2 * 1234)) self.assertTrue(te_s_t(-2 * 12364, 12364)) # self.assertEqual(gmpy.invert(3, -1), 0) # pending gmpy2 issue if modulus is 1 or -1 self.assertEqual(gmpy.invert(3, 257), 86) self.assertRaises(ZeroDivisionError, gmpy.invert, 2, 0) self.assertRaises(ZeroDivisionError, gmpy.invert, 2, 4) self.assertEqual(gmpy.legendre(0, 101), 0) self.assertEqual(gmpy.legendre(42, 101), -1) self.assertEqual(gmpy.legendre(54, 101), 1) self.assertRaises(ValueError, gmpy.legendre, 1, 2) self.assertEqual(gmpy.jacobi(9, 99), 0) self.assertEqual(gmpy.jacobi(43, 99), -1) self.assertEqual(gmpy.jacobi(53, 99), 1) self.assertRaises(ValueError, gmpy.jacobi, 1, 20) self.assertEqual(gmpy.kronecker(0, 0), 0) self.assertEqual(gmpy.kronecker(-1, 0), 1) self.assertEqual(gmpy.kronecker(43, -98), -1) self.assertEqual(gmpy.kronecker(-53, -98), 1) self.assertEqual(gmpy.kronecker(-54, -98), 0) self.assertTrue(gmpy.is_square(625)) self.assertFalse(gmpy.is_square(652)) self.assertEqual(gmpy.isqrt(0), 0) self.assertEqual(gmpy.isqrt(1225), 35) self.assertTrue(gmpy.iroot(0, 10)[1]) self.assertFalse(gmpy.iroot(1226, 2)[1]) self.assertEqual(gmpy.iroot(1226, 2)[0], 35) self.assertEqual(gmpy.iroot(3**10 + 42, 10)[0], 3)