You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I think the nextprime() function in sympy/ntheory/generate.py is a very low level basic function that could be a bottleneck in many applications. Some apparent easy-to-fix inefficiencies hop into my eye:
if n < 2: # this should be inside the next 'if' to avoid 2 checks which are useless in 99.9% of all cases
return 2
if n < 7:
return {2: 3, 3: 5, 4: 5, 5: 7, 6: 7}[n] # this should be simply: (n+1)|1 which is ~20x faster
Indeed, (n+1)|1 is obviously the next larger odd number: it yields n+1 if this is odd (then the bitwise or with 1 does nothing), or else n+2 (when the binary or with 1 adds one more when n+1 is even).
I guess that the lookup in the "literal dict" is most probably optimized to a cascade of if n==2:... elif n==3:... elif n==4... or similar, but why rely on this when there's such a simple and highly efficient formula?
(Update: I did check the timings and found that the dict lookup is about 20x slower than (n+1)|1.)
BTW, that formula is correct up to n=18 except when it gives 9 or 15; it might be even more efficient to use a toplevel "if n<19" instead of "n<7" to deal with all these small n in one single if clause. For example:
if n < 19:
if n < 2: return 2
# next larger odd number except for n=7, 8, 13, 14 where we must add 2 more:
return (n+1)|1 if n < 7 or n > 14 or (n-1)%6<2 else (n+3)|1
Equivalently, instead of (n-1)%6<2 one could use n%6 not in (1,2) which is maybe as fast and easier to read.
Since the last expression yields the correct result also for n=19,20 one could also use
if n < 23:
if n < 2: return 2
# next larger odd number except for n in {7, 8, 13, 14, 19, 20} <=> n==1 or 2 (mod 6).
return (n+1)|1 if n < 7 or (n-1)%6<2 else (n+3)|1
where "...n<7 or..." could also be omitted; it is only left in order to avoid the division/modulo operation for n<7, i.e., to ensure that in ths case, the new code does not anything more than the current code, but only gives a faster result.
In addition to that benefit, the case of 7 <= n < 23 (which might occur quite frequently) is also dealt with much more efficiently.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I think the
nextprime()
function in sympy/ntheory/generate.py is a very low level basic function that could be a bottleneck in many applications. Some apparent easy-to-fix inefficiencies hop into my eye:Indeed, (n+1)|1 is obviously the next larger odd number: it yields n+1 if this is odd (then the bitwise or with 1 does nothing), or else n+2 (when the binary or with 1 adds one more when n+1 is even).
I guess that the lookup in the "literal dict" is most probably optimized to a cascade of
if n==2:... elif n==3:... elif n==4...
or similar, but why rely on this when there's such a simple and highly efficient formula?(Update: I did check the timings and found that the dict lookup is about 20x slower than (n+1)|1.)
BTW, that formula is correct up to n=18 except when it gives 9 or 15; it might be even more efficient to use a toplevel "if n<19" instead of "n<7" to deal with all these small n in one single if clause. For example:
Equivalently, instead of
(n-1)%6<2
one could usen%6 not in (1,2)
which is maybe as fast and easier to read.Since the last expression yields the correct result also for n=19,20 one could also use
where "...n<7 or..." could also be omitted; it is only left in order to avoid the division/modulo operation for n<7, i.e., to ensure that in ths case, the new code does not anything more than the current code, but only gives a faster result.
In addition to that benefit, the case of 7 <= n < 23 (which might occur quite frequently) is also dealt with much more efficiently.
Beta Was this translation helpful? Give feedback.
All reactions