From 94ef4f6b9bc1d6243cfa6d208383373cfe28c638 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Jun 2023 09:41:56 -0700 Subject: [PATCH 1/5] Integer.{perfect_power,is_prime_power}: Check easy cases first before calling PARI --- src/sage/rings/integer.pyx | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 7473969a6ac..ea3e59040e8 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -4829,6 +4829,20 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: (-64).perfect_power() # optional - sage.libs.pari (-4, 3) """ + cdef long n + # Fast PARI-free path + if mpz_fits_slong_p(self.value): + n = mpz_get_si(self.value) + if -8 < n < 4: + return self, one + if n >= 4: + if not (n & 1): + if mpz_popcount(self.value) == 1: + return smallInteger(2), mpz_sizeinbase(self.value, 2) - 1 + if n < 1000: + if _small_primes_table[n >> 1]: + return self, one + parians = self.__pari__().ispower() return Integer(parians[1]), Integer(parians[0]) @@ -5165,10 +5179,22 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: n.is_prime_power() # optional - sage.libs.pari True """ + cdef long n + if mpz_sgn(self.value) <= 0: return (self, zero) if get_data else False if mpz_fits_slong_p(self.value): + # Fast PARI-free path + n = mpz_get_si(self.value) + if not (n & 1): + if mpz_popcount(self.value) != 1: + return (self, zero) if get_data else False + return (smallInteger(2), mpz_sizeinbase(self.value, 2) - 1) if get_data else True + if n < 1000: + if _small_primes_table[n >> 1]: + return (self, one) if get_data else True + global pari_is_prime_power if pari_is_prime_power is None: try: @@ -5178,7 +5204,6 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): if pari_is_prime_power is not None: return pari_is_prime_power(self, get_data) - cdef long n if proof is None: from sage.structure.proof.proof import get_flag proof = get_flag(proof, "arithmetic") From f01b0c2f8664862506338ec9f0ab9119e6ea304a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Jun 2023 12:31:43 -0700 Subject: [PATCH 2/5] Integer.{perfect_power,is_prime_power}: Fix up return type --- src/sage/rings/integer.pyx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index ea3e59040e8..3421cdd3612 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -4812,15 +4812,15 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: 144.perfect_power() # optional - sage.libs.pari (12, 2) - sage: 1.perfect_power() # optional - sage.libs.pari + sage: 1.perfect_power() (1, 1) - sage: 0.perfect_power() # optional - sage.libs.pari + sage: 0.perfect_power() (0, 1) - sage: (-1).perfect_power() # optional - sage.libs.pari + sage: (-1).perfect_power() (-1, 1) sage: (-8).perfect_power() # optional - sage.libs.pari (-2, 3) - sage: (-4).perfect_power() # optional - sage.libs.pari + sage: (-4).perfect_power() (-4, 1) sage: (101^29).perfect_power() # optional - sage.libs.pari (101, 29) @@ -4838,7 +4838,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): if n >= 4: if not (n & 1): if mpz_popcount(self.value) == 1: - return smallInteger(2), mpz_sizeinbase(self.value, 2) - 1 + return smallInteger(2), smallInteger(mpz_sizeinbase(self.value, 2) - 1) if n < 1000: if _small_primes_table[n >> 1]: return self, one @@ -5190,7 +5190,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): if not (n & 1): if mpz_popcount(self.value) != 1: return (self, zero) if get_data else False - return (smallInteger(2), mpz_sizeinbase(self.value, 2) - 1) if get_data else True + return (smallInteger(2), smallInteger(mpz_sizeinbase(self.value, 2) - 1)) if get_data else True if n < 1000: if _small_primes_table[n >> 1]: return (self, one) if get_data else True From ab81af050c9075b3ba2ee8c961ffc76e5705c2f3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 30 Jun 2023 17:43:16 -0700 Subject: [PATCH 3/5] Integer.is_irreducible: Delegate to is_prime, so that easy cases are done without PARI --- src/sage/rings/integer.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 3421cdd3612..024ff87c9a9 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -5387,7 +5387,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): True """ cdef Integer n = self if self >= 0 else -self - return n.__pari__().isprime() + return self.is_prime(proof=True) def is_pseudoprime(self): r""" From 053f1a2fc197e03c10c270517cd0c9c6ddef165b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 30 Jun 2023 21:27:42 -0700 Subject: [PATCH 4/5] Integer.is_irreducible: Delegate to is_prime, so that easy cases are done without PARI (fixup) --- src/sage/rings/integer.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 024ff87c9a9..4ff89eb1702 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -5387,7 +5387,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): True """ cdef Integer n = self if self >= 0 else -self - return self.is_prime(proof=True) + return n.is_prime(proof=True) def is_pseudoprime(self): r""" From d2c9c5efd2c1a8b4a41623452781ad66922eee82 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 2 Jul 2023 11:13:21 -0700 Subject: [PATCH 5/5] src/sage/rings/integer.pyx (is_prime_power, perfect_power): Add doctests for powers of 2 --- src/sage/rings/integer.pyx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 4ff89eb1702..3fcc7a9960c 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -4828,6 +4828,13 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): (-3, 5) sage: (-64).perfect_power() # optional - sage.libs.pari (-4, 3) + + TESTS:: + + sage: 4.perfect_power() + (2, 2) + sage: 256.perfect_power() + (2, 8) """ cdef long n # Fast PARI-free path @@ -5178,6 +5185,15 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: n = 150607571^14 sage: n.is_prime_power() # optional - sage.libs.pari True + + TESTS:: + + sage: 2.is_prime_power(get_data=True) + (2, 1) + sage: 4.is_prime_power(get_data=True) + (2, 2) + sage: 512.is_prime_power(get_data=True) + (2, 9) """ cdef long n