Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 47 additions & 6 deletions src/sage/rings/integer.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -4812,23 +4812,44 @@ 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)
sage: (-243).perfect_power() # optional - sage.libs.pari
(-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
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), smallInteger(mpz_sizeinbase(self.value, 2) - 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer sanity tests for this.
It's so easy to get this wrong by +-1....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Added tests in d2c9c5e

if n < 1000:
if _small_primes_table[n >> 1]:
return self, one

parians = self.__pari__().ispower()
return Integer(parians[1]), Integer(parians[0])

Expand Down Expand Up @@ -5164,11 +5185,32 @@ 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

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), 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

global pari_is_prime_power
if pari_is_prime_power is None:
try:
Expand All @@ -5178,7 +5220,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")
Expand Down Expand Up @@ -5362,7 +5403,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
True
"""
cdef Integer n = self if self >= 0 else -self
return n.__pari__().isprime()
return n.is_prime(proof=True)

def is_pseudoprime(self):
r"""
Expand Down