Skip to content

Commit 9070ab6

Browse files
committed
Assorted code improvements
1 parent fd0234c commit 9070ab6

File tree

3 files changed

+86
-74
lines changed

3 files changed

+86
-74
lines changed

cypari2/gen.pyx

Lines changed: 69 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ from .convert cimport PyObject_AsGEN, gen_to_integer
7272
from .pari_instance cimport (prec_bits_to_words, prec_words_to_bits,
7373
default_bitprec, get_var)
7474
from .stack cimport (new_gen, new_gen_noclear,
75-
clone_gen, clone_gen_noclear,
76-
clear_stack, reset_avma,
75+
clone_gen, clear_stack, reset_avma,
7776
remove_from_pari_stack, move_gens_to_heap)
7877
from .closure cimport objtoclosure
7978

@@ -1465,9 +1464,9 @@ cdef class Gen(Gen_base):
14651464
def __len__(self):
14661465
return glength(self.g)
14671466

1468-
def __richcmp__(left, right, int op):
1467+
def __richcmp__(self, right, int op):
14691468
"""
1470-
Compare ``left`` and ``right`` using ``op``.
1469+
Compare ``self`` and ``right`` using ``op``.
14711470
14721471
Examples:
14731472
@@ -1528,14 +1527,13 @@ cdef class Gen(Gen_base):
15281527
>>> pari('O(2)') == 0
15291528
True
15301529
"""
1531-
cdef Gen t0, t1
1530+
cdef Gen t1
15321531
try:
1533-
t0 = objtogen(left)
15341532
t1 = objtogen(right)
15351533
except Exception:
15361534
return NotImplemented
15371535
cdef bint r
1538-
cdef GEN x = t0.g
1536+
cdef GEN x = self.g
15391537
cdef GEN y = t1.g
15401538
sig_on()
15411539
if op == Py_EQ:
@@ -1605,7 +1603,8 @@ cdef class Gen(Gen_base):
16051603
return r
16061604

16071605
def __copy__(self):
1608-
return clone_gen_noclear(self.g)
1606+
sig_on()
1607+
return clone_gen(self.g)
16091608

16101609
def __oct__(self):
16111610
"""
@@ -1821,6 +1820,7 @@ cdef class Gen(Gen_base):
18211820
>>> pari("[1,2,3]~").python_list()
18221821
[1, 2, 3]
18231822
"""
1823+
# TODO: deprecate
18241824
cdef long n
18251825
cdef Gen t
18261826

@@ -2574,7 +2574,7 @@ cdef class Gen(Gen_base):
25742574
sig_on()
25752575
return new_gen(precision0(x.g, n))
25762576

2577-
def round(x, estimate=False):
2577+
def round(x, bint estimate=False):
25782578
"""
25792579
round(x,estimate=False): If x is a real number, returns x rounded
25802580
to the nearest integer (rounding up). If the optional argument
@@ -2695,7 +2695,7 @@ cdef class Gen(Gen_base):
26952695
"""
26962696
return gsizebyte(x.g)
26972697

2698-
def truncate(x, estimate=False):
2698+
def truncate(x, bint estimate=False):
26992699
"""
27002700
truncate(x,estimate=False): Return the truncation of x. If estimate
27012701
is True, also return the number of error bits.
@@ -3192,13 +3192,10 @@ cdef class Gen(Gen_base):
31923192
<... 'int'>
31933193
"""
31943194
sig_on()
3195-
cdef GEN g = ellan(self.g, n)
3196-
if python_ints:
3197-
v = [gtolong(gel(g, i+1)) for i in range(glength(g))]
3198-
clear_stack()
3199-
return v
3200-
else:
3201-
return new_gen(g)
3195+
cdef Gen g = new_gen(ellan(self.g, n))
3196+
if not python_ints:
3197+
return g
3198+
return [gtolong(gel(g.g, i+1)) for i in range(glength(g.g))]
32023199

32033200
def ellaplist(self, long n, python_ints=False):
32043201
r"""
@@ -3932,56 +3929,7 @@ cdef class Gen(Gen_base):
39323929
>>> nf(x='y')
39333930
[y^2 + 1, [0, 1], -4, 1, [Mat([1, 0.E-38 + 1.00000000000000*I]), [1, 1.00000000000000; 1, -1.00000000000000], [1, 1; 1, -1], [2, 0; 0, -2], [2, 0; 0, 2], [1, 0; 0, -1], [1, [0, -1; 1, 0]], [2]], [0.E-38 + 1.00000000000000*I], [1, y], [1, 0; 0, 1], [1, 0, 0, -1; 0, 1, 1, 0]]
39343931
"""
3935-
cdef long t = typ(self.g)
3936-
cdef Gen t0
3937-
cdef GEN result
3938-
cdef long arity
3939-
cdef long nargs = len(args)
3940-
cdef long nkwds = len(kwds)
3941-
3942-
# Closure must be evaluated using *args
3943-
if t == t_CLOSURE:
3944-
if nkwds > 0:
3945-
raise TypeError("cannot evaluate a PARI closure using keyword arguments")
3946-
if closure_is_variadic(self.g):
3947-
arity = closure_arity(self.g) - 1
3948-
args = list(args[:arity]) + [0]*(arity-nargs) + [args[arity:]]
3949-
t0 = objtogen(args)
3950-
sig_on()
3951-
result = closure_callgenvec(self.g, t0.g)
3952-
if result == gnil:
3953-
clear_stack()
3954-
return None
3955-
return new_gen(result)
3956-
3957-
# Evaluate univariate polynomials, rational functions and
3958-
# series using *args
3959-
if nargs > 0:
3960-
if nkwds > 0:
3961-
raise TypeError("mixing unnamed and keyword arguments not allowed when evaluating a PARI object")
3962-
if not (t == t_POL or t == t_RFRAC or t == t_SER):
3963-
raise TypeError("cannot evaluate PARI %s using unnamed arguments" % self.type())
3964-
if nargs != 1:
3965-
raise TypeError("evaluating PARI %s takes exactly 1 argument (%d given)"
3966-
% (self.type(), nargs))
3967-
3968-
t0 = objtogen(args[0])
3969-
sig_on()
3970-
if t == t_POL or t == t_RFRAC:
3971-
return new_gen(poleval(self.g, t0.g))
3972-
else: # t == t_SER
3973-
return new_gen(gsubst(self.g, varn(self.g), t0.g))
3974-
3975-
# Call substvec() using **kwds
3976-
vstr = iter(kwds.iterkeys()) # Variables as Python strings
3977-
t0 = objtogen(kwds.values()) # Replacements
3978-
3979-
sig_on()
3980-
cdef GEN v = cgetg(nkwds+1, t_VEC) # Variables as PARI polynomials
3981-
cdef long i
3982-
for i in range(nkwds):
3983-
set_gel(v, i+1, pol_x(get_var(next(vstr))))
3984-
return new_gen(gsubstvec(self.g, v, t0.g))
3932+
return self(*args, **kwds)
39853933

39863934
def __call__(self, *args, **kwds):
39873935
"""
@@ -4026,7 +3974,57 @@ cdef class Gen(Gen_base):
40263974
...
40273975
TypeError: cannot evaluate PARI t_INT using unnamed arguments
40283976
"""
4029-
return self.eval(*args, **kwds)
3977+
cdef long t = typ(self.g)
3978+
cdef Gen t0
3979+
cdef GEN result
3980+
cdef long arity
3981+
cdef long nargs = len(args)
3982+
cdef long nkwds = len(kwds)
3983+
3984+
# Closure must be evaluated using *args
3985+
if t == t_CLOSURE:
3986+
if nkwds:
3987+
raise TypeError("cannot evaluate a PARI closure using keyword arguments")
3988+
if closure_is_variadic(self.g):
3989+
arity = closure_arity(self.g) - 1
3990+
args = list(args[:arity]) + [0]*(arity-nargs) + [args[arity:]]
3991+
t0 = objtogen(args)
3992+
sig_on()
3993+
result = closure_callgenvec(self.g, t0.g)
3994+
if result is gnil:
3995+
clear_stack()
3996+
return None
3997+
return new_gen(result)
3998+
3999+
# Evaluate univariate polynomials, rational functions and
4000+
# series using *args
4001+
if nargs:
4002+
if nkwds:
4003+
raise TypeError("mixing unnamed and keyword arguments not allowed when evaluating a PARI object")
4004+
if not (t == t_POL or t == t_RFRAC or t == t_SER):
4005+
raise TypeError("cannot evaluate PARI %s using unnamed arguments" % self.type())
4006+
if nargs != 1:
4007+
raise TypeError("evaluating PARI %s takes exactly 1 argument (%d given)"
4008+
% (self.type(), nargs))
4009+
4010+
t0 = objtogen(args[0])
4011+
sig_on()
4012+
if t == t_POL or t == t_RFRAC:
4013+
return new_gen(poleval(self.g, t0.g))
4014+
else: # t == t_SER
4015+
return new_gen(gsubst(self.g, varn(self.g), t0.g))
4016+
4017+
# Call substvec() using **kwds
4018+
cdef list V = [to_bytes(k) for k in kwds] # Variables as Python byte strings
4019+
t0 = objtogen(kwds.values()) # Replacements
4020+
4021+
sig_on()
4022+
cdef GEN v = cgetg(nkwds+1, t_VEC) # Variables as PARI polynomials
4023+
cdef long i
4024+
for i in range(nkwds):
4025+
varname = <bytes>V[i]
4026+
set_gel(v, i+1, pol_x(fetch_user_var(varname)))
4027+
return new_gen(gsubstvec(self.g, v, t0.g))
40304028

40314029
def factorpadic(self, p, long r=20):
40324030
"""
@@ -4275,7 +4273,7 @@ cdef class Gen(Gen_base):
42754273
def __abs__(self):
42764274
return self.abs()
42774275

4278-
def nextprime(self, bint add_one=0):
4276+
def nextprime(self, bint add_one=False):
42794277
"""
42804278
nextprime(x): smallest pseudoprime greater than or equal to `x`.
42814279
If ``add_one`` is non-zero, return the smallest pseudoprime
@@ -4345,7 +4343,8 @@ cdef class Gen(Gen_base):
43454343
if typ(self.g) != t_POL and typ(self.g) != t_SER:
43464344
raise TypeError("set_variable() only works for polynomials or power series")
43474345
# Copy self and then change the variable in place
4348-
newg = clone_gen_noclear(self.g)
4346+
sig_on()
4347+
newg = clone_gen(self.g)
43494348
setvarn(newg.g, n)
43504349
return newg
43514350

cypari2/pari_instance.pyx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ def prec_bits_to_dec(long prec_in_bits):
315315
"""
316316
return nbits2ndec(prec_in_bits)
317317

318+
318319
def prec_dec_to_bits(long prec_in_dec):
319320
r"""
320321
Convert from precision expressed in decimal to precision expressed
@@ -331,6 +332,7 @@ def prec_dec_to_bits(long prec_in_dec):
331332
cdef double log_10 = 3.32192809488736
332333
return int(prec_in_dec*log_10 + 1.0) # Add one to round up
333334

335+
334336
cpdef long prec_bits_to_words(unsigned long prec_in_bits):
335337
r"""
336338
Convert from precision expressed in bits to pari real precision
@@ -358,6 +360,7 @@ cpdef long prec_bits_to_words(unsigned long prec_in_bits):
358360
# This equals ceil(prec_in_bits/wordsize) + 2
359361
return (prec_in_bits - 1)//wordsize + 3
360362

363+
361364
cpdef long prec_words_to_bits(long prec_in_words):
362365
r"""
363366
Convert from pari real precision expressed in words to precision
@@ -380,6 +383,7 @@ cpdef long prec_words_to_bits(long prec_in_words):
380383
# see user's guide to the pari library, page 10
381384
return (prec_in_words - 2) * BITS_IN_LONG
382385

386+
383387
cpdef long default_bitprec():
384388
r"""
385389
Return the default precision in bits.
@@ -392,6 +396,7 @@ cpdef long default_bitprec():
392396
"""
393397
return (prec - 2) * BITS_IN_LONG
394398

399+
395400
def prec_dec_to_words(long prec_in_dec):
396401
r"""
397402
Convert from precision expressed in decimal to precision expressed
@@ -413,6 +418,7 @@ def prec_dec_to_words(long prec_in_dec):
413418
"""
414419
return prec_bits_to_words(prec_dec_to_bits(prec_in_dec))
415420

421+
416422
def prec_words_to_dec(long prec_in_words):
417423
r"""
418424
Convert from precision expressed in words to precision expressed in
@@ -844,6 +850,7 @@ cdef class Pari(Pari_auto):
844850
pari.new_with_bits_prec(self, s, precision) creates s as a PARI
845851
Gen with (at most) precision *bits* of precision.
846852
"""
853+
# TODO: deprecate
847854
cdef unsigned long old_prec
848855
old_prec = GP_DATA.fmt.sigd
849856
precision = prec_bits_to_dec(precision)
@@ -1243,7 +1250,8 @@ cdef class Pari(Pari_auto):
12431250
...
12441251
IndexError: length of entries (=3) must equal n (=2)
12451252
"""
1246-
cdef Gen v = self._empty_vector(n)
1253+
# TODO: deprecate
1254+
v = self._empty_vector(n)
12471255
if entries is not None:
12481256
if len(entries) != n:
12491257
raise IndexError("length of entries (=%s) must equal n (=%s)"%\

cypari2/stack.pyx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ cimport cython
1919

2020
from cpython.ref cimport PyObject, Py_XINCREF, Py_XDECREF
2121

22-
from cysignals.signals cimport sig_on, sig_off
22+
from cysignals.signals cimport sig_on, sig_off, sig_block, sig_unblock
2323
from cysignals.memory cimport check_malloc, sig_free
2424

2525
from .gen cimport Gen, Gen_new
@@ -32,6 +32,7 @@ from warnings import warn
3232

3333
cdef extern from *:
3434
int sig_on_count "cysigs.sig_on_count"
35+
int block_sigint "cysigs.block_sigint"
3536

3637

3738
# Singleton object to denote the top of the PARI stack
@@ -59,6 +60,8 @@ cdef void remove_from_pari_stack(Gen self):
5960
else:
6061
warn(f"cypari2 leaked {self.sp() - avma} bytes on the PARI stack",
6162
RuntimeWarning, stacklevel=2)
63+
if sig_on_count and not block_sigint:
64+
print(f"ERROR: sig_on_count = {sig_on_count} during remove_from_pari_stack()")
6265
n = self.next
6366
stackbottom = <PyObject*>n
6467
self.next = None
@@ -121,8 +124,10 @@ cdef int move_gens_to_heap(pari_sp lim) except -1:
121124
current = <Gen>stackbottom
122125
sig_on()
123126
current.g = gclone(current.g)
124-
sig_off()
127+
sig_block()
125128
remove_from_pari_stack(current)
129+
sig_unblock()
130+
sig_off()
126131
# The .address attribute can only be updated now because it is
127132
# needed in remove_from_pari_stack(). This means that the object
128133
# is temporarily in an inconsistent state but this does not
@@ -159,7 +164,7 @@ cdef Gen new_gen_noclear(GEN x):
159164
elif isclone(x):
160165
gclone_refc(x)
161166
return Gen_new(x, x)
162-
raise RuntimeError("new_gen() argument not on PARI stack, not on PARI heap and not a universal constant")
167+
raise SystemError("new_gen() argument not on PARI stack, not on PARI heap and not a universal constant")
163168

164169
z = Gen_stack_new(x)
165170

0 commit comments

Comments
 (0)