Skip to content

Commit

Permalink
Trac #32775: Mostly fix slow down by #30022
Browse files Browse the repository at this point in the history
We avoid multiple imports caused by #30022:

Before (and with #30022):

{{{
sage: a = 1/1000
sage: %timeit a.__pari__()
810 ns ± 2.33 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: p = a.__pari__()
sage: %timeit QQ(p)
1.52 µs ± 1.37 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: a = 12314
sage: %timeit a.__pari__()
723 ns ± 0.804 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: p = a.__pari__()
sage: %timeit ZZ(p)
715 ns ± 1.32 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: %timeit a.divisors(method='pari')
1.23 µs ± 1.51 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: %timeit a.is_prime_power()
647 ns ± 0.164 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: %timeit a.is_prime()
604 ns ± 0.486 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: %timeit a.factor()
3.6 µs ± 13.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops
each)
}}}

Reverting #30022:

{{{
sage: a = 1/1000
sage: %timeit a.__pari__()
221 ns ± 0.289 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: p = a.__pari__()
sage: %timeit QQ(p)
810 ns ± 0.852 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: a = 12314
sage: %timeit a.__pari__()
176 ns ± 0.217 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops
each)
sage: p = a.__pari__()
sage: %timeit ZZ(p)
150 ns ± 0.104 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops
each)
sage: %timeit a.divisors(method='pari')
643 ns ± 1.38 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: %timeit a.is_prime_power()
53.9 ns ± 0.336 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops
each)
sage: %timeit a.is_prime()
58 ns ± 0.174 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops
each)
sage: %timeit a.factor()
2.99 µs ± 4.62 ns per loop (mean ± std. dev. of 7 runs, 100000 loops
each)
}}}

With this ticket:

{{{
sage: a = 1/1000
sage: %timeit a.__pari__()
274 ns ± 0.344 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: p = a.__pari__()
sage: %timeit QQ(p)
867 ns ± 0.999 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: a = 12314
sage: %timeit a.__pari__()
200 ns ± 0.0656 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops
each)
sage: p = a.__pari__()
sage: %timeit ZZ(p)
183 ns ± 0.179 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops
each)
sage: %timeit a.divisors(method='pari')
673 ns ± 0.928 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops
each)
sage: %timeit a.is_prime_power()
88.4 ns ± 0.075 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops
each)
sage: %timeit a.is_prime()
68.9 ns ± 0.0878 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops
each)
sage: %timeit a.factor()
3.19 µs ± 10.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops
each)
}}}

URL: https://trac.sagemath.org/32775
Reported by: gh-kliem
Ticket author(s): Jonathan Kliem
Reviewer(s): Matthias Koeppe, Samuel Lelièvre
  • Loading branch information
Release Manager committed Oct 29, 2021
2 parents 1277457 + 4d7ac2f commit 32cfd6f
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 26 deletions.
71 changes: 47 additions & 24 deletions src/sage/rings/integer.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,15 @@ except ImportError:
pari_gen = ()


set_integer_from_gen = None
pari_divisors_small = None
n_factor_to_list = None
pari_is_prime_power = None
pari_is_prime = None
objtogen = None
new_gen_from_integer = None


cdef extern from *:
int unlikely(int) nogil # Defined by Cython

Expand Down Expand Up @@ -637,7 +646,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
raise TypeError("Cannot convert non-integral float to integer")

elif isinstance(x, pari_gen):
from sage.libs.pari.convert_sage import set_integer_from_gen
global set_integer_from_gen
if set_integer_from_gen is None:
from sage.libs.pari.convert_sage import set_integer_from_gen
set_integer_from_gen(self, x)

else:
Expand Down Expand Up @@ -3046,12 +3057,14 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
raise ValueError("n must be nonzero")

if (method is None or method == 'pari') and mpz_fits_slong_p(self.value):
try:
from sage.libs.pari.convert_sage import pari_divisors_small
except ImportError:
if method == 'pari':
raise ImportError("method `pari` requested, but cypari2 not present")
else:
global pari_divisors_small
if pari_divisors_small is None:
try:
from sage.libs.pari.convert_sage import pari_divisors_small
except ImportError:
if method == 'pari':
raise ImportError("method `pari` requested, but cypari2 not present")
if pari_divisors_small is not None:
if mpz_sgn(self.value) > 0:
return pari_divisors_small(self)
else:
Expand Down Expand Up @@ -3909,11 +3922,13 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
return factor_trial_division(self, limit)

if mpz_fits_slong_p(n.value):
try:
from sage.libs.flint.ulong_extras import n_factor_to_list
except ImportError:
pass
else:
global n_factor_to_list
if n_factor_to_list is None:
try:
from sage.libs.flint.ulong_extras import n_factor_to_list
except ImportError:
pass
if n_factor_to_list is not None:
if proof is None:
from sage.structure.proof.proof import get_flag
proof = get_flag(proof, "arithmetic")
Expand Down Expand Up @@ -5108,11 +5123,13 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
return (self, zero) if get_data else False

if mpz_fits_slong_p(self.value):
try:
from sage.libs.pari.convert_sage import pari_is_prime_power
except ImportError:
pass
else:
global pari_is_prime_power
if pari_is_prime_power is None:
try:
from sage.libs.pari.convert_sage import pari_is_prime_power
except ImportError:
pass
if pari_is_prime_power is not None:
return pari_is_prime_power(self, get_data)

cdef long n
Expand Down Expand Up @@ -5194,11 +5211,13 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
return False

if mpz_fits_ulong_p(self.value):
try:
from sage.libs.pari.convert_sage import pari_is_prime
except ImportError:
pass
else:
global pari_is_prime
if pari_is_prime is None:
try:
from sage.libs.pari.convert_sage import pari_is_prime
except ImportError:
pass
if pari_is_prime is not None:
return pari_is_prime(self)

if proof is None:
Expand Down Expand Up @@ -5550,7 +5569,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
"""
from cypari2.gen import objtogen
global objtogen
if objtogen is None:
from cypari2.gen import objtogen
if self.is_square():
raise ValueError("class_number not defined for square integers")
if not self%4 in [0,1]:
Expand Down Expand Up @@ -5958,7 +5979,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
1041334
"""
from sage.libs.pari.convert_sage import new_gen_from_integer
global new_gen_from_integer
if new_gen_from_integer is None:
from sage.libs.pari.convert_sage import new_gen_from_integer
return new_gen_from_integer(self)

def _interface_init_(self, I=None):
Expand Down
12 changes: 10 additions & 2 deletions src/sage/rings/rational.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ except ImportError:
pari_gen = ()


set_rational_from_gen = None
new_gen_from_rational = None


cdef sage.rings.fast_arith.arith_int ai
ai = sage.rings.fast_arith.arith_int()

Expand Down Expand Up @@ -650,7 +654,9 @@ cdef class Rational(sage.structure.element.FieldElement):
mpq_canonicalize(self.value)

elif isinstance(x, pari_gen):
from sage.libs.pari.convert_sage import set_rational_from_gen
global set_rational_from_gen
if set_rational_from_gen is None:
from sage.libs.pari.convert_sage import set_rational_from_gen
set_rational_from_gen(self, x)

elif isinstance(x, list) and len(x) == 1:
Expand Down Expand Up @@ -3777,7 +3783,9 @@ cdef class Rational(sage.structure.element.FieldElement):
sage: m.type()
't_FRAC'
"""
from sage.libs.pari.convert_sage import new_gen_from_rational
global new_gen_from_rational
if new_gen_from_rational is None:
from sage.libs.pari.convert_sage import new_gen_from_rational
return new_gen_from_rational(self)

def _interface_init_(self, I=None):
Expand Down

0 comments on commit 32cfd6f

Please sign in to comment.