Skip to content

Commit d82cfd3

Browse files
committed
Avoid mutate Integer.value at a few more places
1 parent 4cdd703 commit d82cfd3

File tree

1 file changed

+99
-78
lines changed

1 file changed

+99
-78
lines changed

src/sage/rings/integer.pyx

Lines changed: 99 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1982,14 +1982,15 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
19821982
sage: Integer(10^100) * int(4)
19831983
40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
19841984
"""
1985-
cdef Integer x = <Integer>PY_NEW(Integer)
1985+
cdef mpz_t x
1986+
mpz_init(x)
19861987
if mpz_size(self.value) > 100000:
19871988
sig_on()
1988-
mpz_mul_si(x.value, self.value, n)
1989+
mpz_mul_si(x, self.value, n)
19891990
sig_off()
19901991
else:
1991-
mpz_mul_si(x.value, self.value, n)
1992-
return x
1992+
mpz_mul_si(x, self.value, n)
1993+
return move_integer_from_mpz(x)
19931994

19941995
def __mul__(left, right):
19951996
r"""
@@ -2031,16 +2032,17 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
20312032
True
20322033
"""
20332034
# self and right are guaranteed to be Integers
2034-
cdef Integer x = <Integer>PY_NEW(Integer)
2035+
cdef mpz_t x
2036+
mpz_init(x)
20352037
if mpz_size(self.value) + mpz_size((<Integer>right).value) > 100000:
20362038
# We only use the signal handler (to enable ctrl-c out) when the
20372039
# product might take a while to compute
20382040
sig_on()
2039-
mpz_mul(x.value, self.value, (<Integer>right).value)
2041+
mpz_mul(x, self.value, (<Integer>right).value)
20402042
sig_off()
20412043
else:
2042-
mpz_mul(x.value, self.value, (<Integer>right).value)
2043-
return x
2044+
mpz_mul(x, self.value, (<Integer>right).value)
2045+
return move_integer_from_mpz(x)
20442046

20452047
def __truediv__(left, right):
20462048
r"""
@@ -2147,14 +2149,15 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
21472149
if not mpz_sgn((<Integer>right).value):
21482150
raise ZeroDivisionError("Integer division by zero")
21492151

2150-
cdef Integer z = <Integer>PY_NEW(Integer)
2152+
cdef mpz_t z
2153+
mpz_init(z)
21512154
if mpz_size(self.value) > 1000:
21522155
sig_on()
2153-
mpz_fdiv_q(z.value, self.value, (<Integer>right).value)
2156+
mpz_fdiv_q(z, self.value, (<Integer>right).value)
21542157
sig_off()
21552158
else:
2156-
mpz_fdiv_q(z.value, self.value, (<Integer>right).value)
2157-
return z
2159+
mpz_fdiv_q(z, self.value, (<Integer>right).value)
2160+
return move_integer_from_mpz(z)
21582161

21592162
def __pow__(left, right, modulus):
21602163
r"""
@@ -2472,18 +2475,19 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
24722475
raise ValueError("n (=%s) must be positive" % n)
24732476
if (mpz_sgn(self.value) < 0) and not (n & 1):
24742477
raise ValueError("cannot take even root of negative number")
2475-
cdef Integer x
2478+
cdef mpz_t x
24762479
cdef bint is_exact
2477-
x = PY_NEW(Integer)
2480+
mpz_init(x)
24782481
sig_on()
2479-
is_exact = mpz_root(x.value, self.value, n)
2482+
is_exact = mpz_root(x, self.value, n)
24802483
sig_off()
2484+
x_int = move_integer_from_mpz(x)
24812485

24822486
if truncate_mode:
2483-
return x, is_exact
2487+
return x_int, is_exact
24842488
else:
24852489
if is_exact:
2486-
return x
2490+
return x_int
24872491
else:
24882492
raise ValueError("%s is not a %s power" % (self,
24892493
integer_ring.ZZ(n).ordinal_str()))
@@ -3001,22 +3005,25 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
30013005
...
30023006
ArithmeticError: self must be nonzero
30033007
"""
3004-
cdef Integer mm = Integer(m)
3005-
30063008
if not self:
30073009
raise ArithmeticError("self must be nonzero")
3008-
if not mm:
3010+
if not isinstance(m, Integer):
3011+
m = Integer(m)
3012+
if not m:
30093013
return one
30103014

3011-
cdef Integer n = Integer(self) # need a copy as it is modified below
3012-
3015+
cdef mpz_t mm, n
3016+
mpz_init(mm)
3017+
mpz_init(n)
3018+
mpz_set(n, self.value)
3019+
mpz_set(mm, (<Integer>m).value)
30133020
sig_on()
3014-
while mpz_cmp_ui(mm.value, 1):
3015-
mpz_gcd(mm.value, n.value, mm.value)
3016-
mpz_divexact(n.value, n.value, mm.value)
3021+
while mpz_cmp_ui(mm, 1):
3022+
mpz_gcd(mm, n, mm)
3023+
mpz_divexact(n, n, mm)
30173024
sig_off()
3018-
3019-
return n
3025+
mpz_clear(mm)
3026+
return move_integer_from_mpz(n)
30203027

30213028
def prime_divisors(self, *args, **kwds):
30223029
"""
@@ -3419,18 +3426,20 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
34193426
"""
34203427
cdef Integer z
34213428

3429+
cdef mpz_t zz
3430+
34223431
# First case: Integer % Integer
34233432
if type(x) is type(y):
34243433
if not mpz_sgn((<Integer>y).value):
34253434
raise ZeroDivisionError("Integer modulo by zero")
3426-
z = <Integer>PY_NEW(Integer)
3435+
mpz_init(zz)
34273436
if mpz_size((<Integer>x).value) > 100000:
34283437
sig_on()
3429-
mpz_fdiv_r(z.value, (<Integer>x).value, (<Integer>y).value)
3438+
mpz_fdiv_r(zz, (<Integer>x).value, (<Integer>y).value)
34303439
sig_off()
34313440
else:
3432-
mpz_fdiv_r(z.value, (<Integer>x).value, (<Integer>y).value)
3433-
return z
3441+
mpz_fdiv_r(zz, (<Integer>x).value, (<Integer>y).value)
3442+
return move_integer_from_mpz(zz)
34343443

34353444
# Next: Integer % C long
34363445
cdef long yy = 0
@@ -3516,39 +3525,42 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
35163525
sage: len(str(root))
35173526
301
35183527
"""
3519-
cdef Integer q = PY_NEW(Integer)
3520-
cdef Integer r = PY_NEW(Integer)
35213528
cdef long d, res
3529+
cdef mpz_t q, r
35223530

35233531
if is_small_python_int(other):
35243532
d = PyLong_AsLong(other)
3533+
mpz_init(q)
3534+
mpz_init(r)
35253535
if d > 0:
3526-
mpz_fdiv_qr_ui(q.value, r.value, self.value, d)
3536+
mpz_fdiv_qr_ui(q, r, self.value, d)
35273537
elif d == 0:
35283538
raise ZeroDivisionError("Integer division by zero")
35293539
else:
3530-
res = mpz_fdiv_qr_ui(q.value, r.value, self.value, -d)
3531-
mpz_neg(q.value, q.value)
3540+
res = mpz_fdiv_qr_ui(q, r, self.value, -d)
3541+
mpz_neg(q, q)
35323542
if res:
3533-
mpz_sub_ui(q.value, q.value, 1)
3534-
mpz_sub_ui(r.value, r.value, -d)
3543+
mpz_sub_ui(q, q, 1)
3544+
mpz_sub_ui(r, r, -d)
3545+
return move_integer_from_mpz(q), move_integer_from_mpz(r)
35353546

35363547
elif type(other) is Integer:
35373548
if mpz_sgn((<Integer>other).value) == 0:
35383549
raise ZeroDivisionError("Integer division by zero")
3550+
mpz_init(q)
3551+
mpz_init(r)
35393552
if mpz_size(self.value) > 100000:
35403553
sig_on()
3541-
mpz_fdiv_qr(q.value, r.value, self.value, (<Integer>other).value)
3554+
mpz_fdiv_qr(q, r, self.value, (<Integer>other).value)
35423555
sig_off()
35433556
else:
3544-
mpz_fdiv_qr(q.value, r.value, self.value, (<Integer>other).value)
3557+
mpz_fdiv_qr(q, r, self.value, (<Integer>other).value)
3558+
return move_integer_from_mpz(q), move_integer_from_mpz(r)
35453559

35463560
else:
35473561
left, right = coercion_model.canonical_coercion(self, other)
35483562
return left.quo_rem(right)
35493563

3550-
return q, r
3551-
35523564
def powermod(self, exp, mod):
35533565
r"""
35543566
Compute ``self**exp`` modulo ``mod``.
@@ -3576,13 +3588,14 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
35763588
if mpz_cmp_si(_mod.value,0) == 0:
35773589
raise ZeroDivisionError("cannot raise to a power modulo 0")
35783590

3579-
x = PY_NEW(Integer)
3591+
cdef mpz_t res
3592+
mpz_init(res)
35803593

35813594
sig_on()
3582-
mpz_powm(x.value, self.value, _exp.value, _mod.value)
3595+
mpz_powm(res, self.value, _exp.value, _mod.value)
35833596
sig_off()
35843597

3585-
return x
3598+
return move_integer_from_mpz(res)
35863599

35873600
def rational_reconstruction(self, Integer m):
35883601
r"""
@@ -4498,11 +4511,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
44984511
sage: n._lcm(150)
44994512
300
45004513
"""
4501-
cdef Integer z = PY_NEW(Integer)
4514+
cdef mpz_t z
4515+
mpz_init(z)
45024516
sig_on()
4503-
mpz_lcm(z.value, self.value, n.value)
4517+
mpz_lcm(z, self.value, n.value)
45044518
sig_off()
4505-
return z
4519+
return move_integer_from_mpz(z)
45064520

45074521
def _gcd(self, Integer n):
45084522
"""
@@ -4521,11 +4535,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
45214535
sage: 21._gcd(2^6)
45224536
1
45234537
"""
4524-
cdef Integer z = PY_NEW(Integer)
4538+
cdef mpz_t z
4539+
mpz_init(z)
45254540
sig_on()
4526-
mpz_gcd(z.value, self.value, n.value)
4541+
mpz_gcd(z, self.value, n.value)
45274542
sig_off()
4528-
return z
4543+
return move_integer_from_mpz(z)
45294544

45304545
def denominator(self):
45314546
"""
@@ -4613,13 +4628,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
46134628
if not mpz_fits_ulong_p(self.value):
46144629
raise OverflowError("argument too large for factorial")
46154630

4616-
cdef Integer z = PY_NEW(Integer)
4617-
4631+
cdef mpz_t tmp
4632+
mpz_init(tmp)
46184633
sig_on()
4619-
mpz_fac_ui(z.value, mpz_get_ui(self.value))
4634+
mpz_fac_ui(tmp, mpz_get_ui(self.value))
46204635
sig_off()
4621-
4622-
return z
4636+
return move_integer_from_mpz(tmp)
46234637

46244638
def multifactorial(self, long k):
46254639
r"""
@@ -6449,13 +6463,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
64496463
if mpz_sgn(self.value) < 0:
64506464
raise ValueError("square root of negative integer not defined")
64516465

6452-
cdef Integer x = PY_NEW(Integer)
6453-
6466+
cdef mpz_t x
6467+
mpz_init(x)
64546468
sig_on()
6455-
mpz_sqrt(x.value, self.value)
6469+
mpz_sqrt(x, self.value)
64566470
sig_off()
6457-
6458-
return x
6471+
return move_integer_from_mpz(x)
64596472

64606473
def sqrt(self, prec=None, extend=True, all=False):
64616474
"""
@@ -6534,17 +6547,22 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
65346547
return [self] if all else self
65356548

65366549
cdef bint is_square
6550+
cdef mpz_t sqrt_val, rem
65376551
cdef Integer z
6538-
cdef mpz_t tmp
6552+
65396553
if mpz_sgn(self.value) < 0:
65406554
is_square = False
65416555
else:
65426556
sig_on()
6543-
mpz_init(tmp)
6544-
z = PY_NEW(Integer)
6545-
mpz_sqrtrem(z.value, tmp, self.value)
6546-
is_square = (mpz_sgn(tmp) == 0)
6547-
mpz_clear(tmp)
6557+
mpz_init(sqrt_val)
6558+
mpz_init(rem)
6559+
mpz_sqrtrem(sqrt_val, rem, self.value)
6560+
is_square = (mpz_sgn(rem) == 0)
6561+
if is_square:
6562+
z = move_integer_from_mpz(sqrt_val)
6563+
else:
6564+
mpz_clear(sqrt_val)
6565+
mpz_clear(rem)
65486566
sig_off()
65496567

65506568
if not is_square:
@@ -6677,13 +6695,16 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
66776695
66786696
- David Harvey (2007-12-26): added minimality option
66796697
"""
6680-
cdef Integer g = PY_NEW(Integer)
6681-
cdef Integer s = PY_NEW(Integer)
6682-
cdef Integer t = PY_NEW(Integer)
6683-
6698+
cdef mpz_t g_tmp, s_tmp, t_tmp
6699+
mpz_init(g_tmp)
6700+
mpz_init(s_tmp)
6701+
mpz_init(t_tmp)
66846702
sig_on()
6685-
mpz_gcdext(g.value, s.value, t.value, self.value, n.value)
6703+
mpz_gcdext(g_tmp, s_tmp, t_tmp, self.value, n.value)
66866704
sig_off()
6705+
cdef Integer g = move_integer_from_mpz(g_tmp)
6706+
cdef Integer s = move_integer_from_mpz(s_tmp)
6707+
cdef Integer t = move_integer_from_mpz(t_tmp)
66876708

66886709
# Note: the GMP documentation for mpz_gcdext (or mpn_gcdext for that
66896710
# matter) makes absolutely no claims about any minimality conditions
@@ -7457,7 +7478,6 @@ def GCD_list(v):
74577478
0
74587479
"""
74597480
cdef int i, n = len(v)
7460-
cdef Integer z = <Integer>PY_NEW(Integer)
74617481

74627482
for i in range(n):
74637483
if not isinstance(v[i], Integer):
@@ -7470,15 +7490,16 @@ def GCD_list(v):
74707490
elif n == 1:
74717491
return v[0].abs()
74727492

7493+
cdef mpz_t tmp
7494+
mpz_init(tmp)
74737495
sig_on()
7474-
mpz_gcd(z.value, (<Integer>v[0]).value, (<Integer>v[1]).value)
7496+
mpz_gcd(tmp, (<Integer>v[0]).value, (<Integer>v[1]).value)
74757497
for i in range(2, n):
7476-
if mpz_cmp_ui(z.value, 1) == 0:
7498+
if mpz_cmp_ui(tmp, 1) == 0:
74777499
break
7478-
mpz_gcd(z.value, z.value, (<Integer>v[i]).value)
7500+
mpz_gcd(tmp, tmp, (<Integer>v[i]).value)
74797501
sig_off()
7480-
7481-
return z
7502+
return move_integer_from_mpz(tmp)
74827503

74837504

74847505
@cython.binding(True)

0 commit comments

Comments
 (0)