Skip to content

Commit fb10785

Browse files
committed
Make in-place operators functions, and explict
1 parent 1c88ec3 commit fb10785

File tree

3 files changed

+172
-87
lines changed

3 files changed

+172
-87
lines changed

src/flint/test/test_all.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2837,31 +2837,36 @@ def quick_poly():
28372837
for T in [int, S, flint.fmpz, lambda x: P(x, ctx=ctx)]:
28382838
p = quick_poly()
28392839
p += T(1)
2840+
q = quick_poly()
2841+
assert q.iadd(T(1)) is None
28402842
assert quick_poly() + T(1) \
2841-
== p == mpoly({(0, 0): 2, (0, 1): 2, (1, 0): 3, (2, 2): 4})
2843+
== p == q == mpoly({(0, 0): 2, (0, 1): 2, (1, 0): 3, (2, 2): 4})
28422844
assert T(1) + quick_poly() \
28432845
== mpoly({(0, 0): 2, (0, 1): 2, (1, 0): 3, (2, 2): 4})
28442846

28452847
assert raises(lambda: mpoly({(0, 0): 2, (0, 1): 2, (1, 0): 3, (2, 2): 4}) + None, TypeError)
28462848
assert raises(lambda: None + mpoly({(0, 0): 2, (0, 1): 2, (1, 0): 3, (2, 2): 4}), TypeError)
28472849
assert raises(lambda: quick_poly() + P(ctx=ctx1), IncompatibleContextError)
2848-
assert raises(lambda: quick_poly().__iadd__(P(ctx=ctx1)), IncompatibleContextError)
2849-
assert quick_poly().__iadd__(None) is NotImplemented
2850+
assert raises(lambda: quick_poly().iadd(P(ctx=ctx1)), IncompatibleContextError)
2851+
assert raises(lambda: quick_poly().iadd(None), NotImplementedError)
28502852

28512853
assert quick_poly() - mpoly({(0, 0): 5, (0, 1): 6, (1, 0): 7, (2, 2): 8}) \
28522854
== mpoly({(0, 0): -4, (0, 1): -4, (1, 0): -4, (2, 2): -4})
28532855

28542856
for T in [int, S, flint.fmpz, lambda x: P(x, ctx=ctx)]:
28552857
p = quick_poly()
28562858
p -= T(1)
2857-
assert quick_poly() - T(1) == p == mpoly({(0, 1): 2, (1, 0): 3, (2, 2): 4})
2859+
q = quick_poly()
2860+
assert q.isub(T(1)) is None
2861+
breakpoint()
2862+
assert quick_poly() - T(1) == p == q == mpoly({(0, 1): 2, (1, 0): 3, (2, 2): 4})
28582863
assert T(1) - quick_poly() == mpoly({(0, 1): -2, (1, 0): -3, (2, 2): -4})
28592864

28602865
assert raises(lambda: quick_poly() - None, TypeError)
28612866
assert raises(lambda: None - quick_poly(), TypeError)
28622867
assert raises(lambda: quick_poly() - P(ctx=ctx1), IncompatibleContextError)
2863-
assert raises(lambda: quick_poly().__isub__(P(ctx=ctx1)), IncompatibleContextError)
2864-
assert quick_poly().__isub__(None) is NotImplemented
2868+
assert raises(lambda: quick_poly().isub(P(ctx=ctx1)), IncompatibleContextError)
2869+
assert raises(lambda: quick_poly().isub(None), NotImplementedError)
28652870

28662871
assert quick_poly() * mpoly({(1, 0): 5, (0, 1): 6}) \
28672872
== mpoly({
@@ -2877,14 +2882,16 @@ def quick_poly():
28772882
for T in [int, S, flint.fmpz, lambda x: P(x, ctx=ctx)]:
28782883
p = quick_poly()
28792884
p *= T(2)
2880-
assert quick_poly() * T(2) == p == mpoly({(0, 0): 2, (0, 1): 4, (1, 0): 6, (2, 2): 8})
2885+
q = quick_poly()
2886+
assert q.imul(T(2)) is None
2887+
assert quick_poly() * T(2) == p == q == mpoly({(0, 0): 2, (0, 1): 4, (1, 0): 6, (2, 2): 8})
28812888
assert T(2) * quick_poly() == mpoly({(0, 0): 2, (0, 1): 4, (1, 0): 6, (2, 2): 8})
28822889

28832890
assert raises(lambda: quick_poly() * None, TypeError)
28842891
assert raises(lambda: None * quick_poly(), TypeError)
28852892
assert raises(lambda: quick_poly() * P(ctx=ctx1), IncompatibleContextError)
2886-
assert raises(lambda: quick_poly().__imul__(P(ctx=ctx1)), IncompatibleContextError)
2887-
assert quick_poly().__imul__(None) is NotImplemented
2893+
assert raises(lambda: quick_poly().imul(P(ctx=ctx1)), IncompatibleContextError)
2894+
assert raises(lambda: quick_poly().imul(None), NotImplementedError)
28882895

28892896
assert quick_poly() // mpoly({(1, 1): 1}) == mpoly({(1, 1): 4})
28902897
assert quick_poly() % mpoly({(1, 1): 1}) \

src/flint/types/fmpq_mpoly.pyx

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -346,19 +346,6 @@ cdef class fmpq_mpoly(flint_mpoly):
346346
return res
347347
return NotImplemented
348348

349-
def __iadd__(self, other):
350-
if typecheck(other, fmpq_mpoly):
351-
if (<fmpq_mpoly>self).ctx is not (<fmpq_mpoly>other).ctx:
352-
raise IncompatibleContextError(f"{(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}")
353-
fmpq_mpoly_add((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq_mpoly>other).val, self.ctx.val)
354-
return self
355-
else:
356-
other = any_as_fmpq(other)
357-
if other is not NotImplemented:
358-
fmpq_mpoly_add_fmpq((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq>other).val, self.ctx.val)
359-
return self
360-
return NotImplemented
361-
362349
def __sub__(self, other):
363350
cdef fmpq_mpoly res
364351
if typecheck(other, fmpq_mpoly):
@@ -384,19 +371,6 @@ cdef class fmpq_mpoly(flint_mpoly):
384371
return -res
385372
return NotImplemented
386373

387-
def __isub__(self, other):
388-
if typecheck(other, fmpq_mpoly):
389-
if (<fmpq_mpoly>self).ctx is not (<fmpq_mpoly>other).ctx:
390-
raise IncompatibleContextError(f"{(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}")
391-
fmpq_mpoly_sub((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq_mpoly>other).val, self.ctx.val)
392-
return self
393-
else:
394-
other = any_as_fmpq(other)
395-
if other is not NotImplemented:
396-
fmpq_mpoly_sub_fmpq((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq>other).val, self.ctx.val)
397-
return self
398-
return NotImplemented
399-
400374
def __mul__(self, other):
401375
cdef fmpq_mpoly res
402376
if typecheck(other, fmpq_mpoly):
@@ -422,19 +396,6 @@ cdef class fmpq_mpoly(flint_mpoly):
422396
return res
423397
return NotImplemented
424398

425-
def __imul__(self, other):
426-
if typecheck(other, fmpq_mpoly):
427-
if (<fmpq_mpoly>self).ctx is not (<fmpq_mpoly>other).ctx:
428-
raise IncompatibleContextError(f"{(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}")
429-
fmpq_mpoly_mul((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq_mpoly>other).val, self.ctx.val)
430-
return self
431-
else:
432-
other = any_as_fmpq(other)
433-
if other is not NotImplemented:
434-
fmpq_mpoly_scalar_mul_fmpq(self.val, (<fmpq_mpoly>self).val, (<fmpq>other).val, self.ctx.val)
435-
return self
436-
return NotImplemented
437-
438399
def __pow__(self, other, modulus):
439400
cdef fmpq_mpoly res
440401
if modulus is not None:
@@ -582,6 +543,84 @@ cdef class fmpq_mpoly(flint_mpoly):
582543
raise ValueError("unreasonably large polynomial") # pragma: no cover
583544
return vres
584545

546+
def iadd(self, other):
547+
"""
548+
In-place addition, mutates self.
549+
550+
>>> from flint import Ordering
551+
>>> ctx = fmpq_mpoly_ctx.get_context(2, Ordering.lex, 'x')
552+
>>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
553+
>>> f
554+
4*x0*x1 + 2*x0 + 3*x1
555+
>>> f.iadd(5)
556+
>>> f
557+
4*x0*x1 + 2*x0 + 3*x1 + 5
558+
559+
"""
560+
if typecheck(other, fmpq_mpoly):
561+
if (<fmpq_mpoly>self).ctx is not (<fmpq_mpoly>other).ctx:
562+
raise IncompatibleContextError(f"{(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}")
563+
fmpq_mpoly_add((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq_mpoly>other).val, self.ctx.val)
564+
return
565+
else:
566+
other = any_as_fmpq(other)
567+
if other is not NotImplemented:
568+
fmpq_mpoly_add_fmpq((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq>other).val, self.ctx.val)
569+
return
570+
raise NotImplementedError(f"in-place addition not implemented between {type(self)} and {type(other)}")
571+
572+
def isub(self, other):
573+
"""
574+
In-place subtraction, mutates self.
575+
576+
>>> from flint import Ordering
577+
>>> ctx = fmpq_mpoly_ctx.get_context(2, Ordering.lex, 'x')
578+
>>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
579+
>>> f
580+
4*x0*x1 + 2*x0 + 3*x1
581+
>>> f.isub(5)
582+
>>> f
583+
4*x0*x1 + 2*x0 + 3*x1 - 5
584+
585+
"""
586+
if typecheck(other, fmpq_mpoly):
587+
if (<fmpq_mpoly>self).ctx is not (<fmpq_mpoly>other).ctx:
588+
raise IncompatibleContextError(f"{(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}")
589+
fmpq_mpoly_sub((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq_mpoly>other).val, self.ctx.val)
590+
return
591+
else:
592+
other = any_as_fmpq(other)
593+
if other is not NotImplemented:
594+
fmpq_mpoly_sub_fmpq((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq>other).val, self.ctx.val)
595+
return
596+
raise NotImplementedError(f"in-place subtraction not implemented between {type(self)} and {type(other)}")
597+
598+
def imul(self, other):
599+
"""
600+
In-place multiplication, mutates self.
601+
602+
>>> from flint import Ordering
603+
>>> ctx = fmpq_mpoly_ctx.get_context(2, Ordering.lex, 'x')
604+
>>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
605+
>>> f
606+
4*x0*x1 + 2*x0 + 3*x1
607+
>>> f.imul(2)
608+
>>> f
609+
8*x0*x1 + 4*x0 + 6*x1
610+
611+
"""
612+
if typecheck(other, fmpq_mpoly):
613+
if (<fmpq_mpoly>self).ctx is not (<fmpq_mpoly>other).ctx:
614+
raise IncompatibleContextError(f"{(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}")
615+
fmpq_mpoly_mul((<fmpq_mpoly>self).val, (<fmpq_mpoly>self).val, (<fmpq_mpoly>other).val, self.ctx.val)
616+
return
617+
else:
618+
other = any_as_fmpq(other)
619+
if other is not NotImplemented:
620+
fmpq_mpoly_scalar_mul_fmpq(self.val, (<fmpq_mpoly>self).val, (<fmpq>other).val, self.ctx.val)
621+
return
622+
raise NotImplementedError(f"in-place multiplication not implemented between {type(self)} and {type(other)}")
623+
585624
def monoms(self):
586625
"""
587626
Return the exponent vectors of each term as a tuple of fmpz.

src/flint/types/fmpz_mpoly.pyx

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -326,19 +326,6 @@ cdef class fmpz_mpoly(flint_mpoly):
326326
return res
327327
return NotImplemented
328328

329-
def __iadd__(self, other):
330-
if typecheck(other, fmpz_mpoly):
331-
if (<fmpz_mpoly>self).ctx is not (<fmpz_mpoly>other).ctx:
332-
raise IncompatibleContextError(f"{(<fmpz_mpoly>self).ctx} is not {(<fmpz_mpoly>other).ctx}")
333-
fmpz_mpoly_add((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz_mpoly>other).val, self.ctx.val)
334-
return self
335-
else:
336-
zval = any_as_fmpz(other)
337-
if zval is not NotImplemented:
338-
fmpz_mpoly_add_fmpz((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz>zval).val, self.ctx.val)
339-
return self
340-
return NotImplemented
341-
342329
def __sub__(self, other):
343330
cdef fmpz_mpoly res
344331
if typecheck(other, fmpz_mpoly):
@@ -364,19 +351,6 @@ cdef class fmpz_mpoly(flint_mpoly):
364351
return -res
365352
return NotImplemented
366353

367-
def __isub__(self, other):
368-
if typecheck(other, fmpz_mpoly):
369-
if (<fmpz_mpoly>self).ctx is not (<fmpz_mpoly>other).ctx:
370-
raise IncompatibleContextError(f"{(<fmpz_mpoly>self).ctx} is not {(<fmpz_mpoly>other).ctx}")
371-
fmpz_mpoly_sub((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz_mpoly>other).val, self.ctx.val)
372-
return self
373-
else:
374-
other = any_as_fmpz(other)
375-
if other is not NotImplemented:
376-
fmpz_mpoly_sub_fmpz((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz>other).val, self.ctx.val)
377-
return self
378-
return NotImplemented
379-
380354
def __mul__(self, other):
381355
cdef fmpz_mpoly res
382356
if typecheck(other, fmpz_mpoly):
@@ -402,19 +376,6 @@ cdef class fmpz_mpoly(flint_mpoly):
402376
return res
403377
return NotImplemented
404378

405-
def __imul__(self, other):
406-
if typecheck(other, fmpz_mpoly):
407-
if (<fmpz_mpoly>self).ctx is not (<fmpz_mpoly>other).ctx:
408-
raise IncompatibleContextError(f"{(<fmpz_mpoly>self).ctx} is not {(<fmpz_mpoly>other).ctx}")
409-
fmpz_mpoly_mul((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz_mpoly>other).val, self.ctx.val)
410-
return self
411-
else:
412-
other = any_as_fmpz(other)
413-
if other is not NotImplemented:
414-
fmpz_mpoly_scalar_mul_fmpz(self.val, (<fmpz_mpoly>self).val, (<fmpz>other).val, self.ctx.val)
415-
return self
416-
return NotImplemented
417-
418379
def __pow__(self, other, modulus):
419380
cdef fmpz_mpoly res
420381
if modulus is not None:
@@ -564,6 +525,84 @@ cdef class fmpz_mpoly(flint_mpoly):
564525
raise ValueError("unreasonably large polynomial") # pragma: no cover
565526
return vres
566527

528+
def iadd(self, other):
529+
"""
530+
In-place addition, mutates self.
531+
532+
>>> from flint import Ordering
533+
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, 'x')
534+
>>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
535+
>>> f
536+
4*x0*x1 + 2*x0 + 3*x1
537+
>>> f.iadd(5)
538+
>>> f
539+
4*x0*x1 + 2*x0 + 3*x1 + 5
540+
541+
"""
542+
if typecheck(other, fmpz_mpoly):
543+
if (<fmpz_mpoly>self).ctx is not (<fmpz_mpoly>other).ctx:
544+
raise IncompatibleContextError(f"{(<fmpz_mpoly>self).ctx} is not {(<fmpz_mpoly>other).ctx}")
545+
fmpz_mpoly_add((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz_mpoly>other).val, self.ctx.val)
546+
return
547+
else:
548+
zval = any_as_fmpz(other)
549+
if zval is not NotImplemented:
550+
fmpz_mpoly_add_fmpz((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz>zval).val, self.ctx.val)
551+
return
552+
raise NotImplementedError()
553+
554+
def isub(self, other):
555+
"""
556+
In-place subtraction, mutates self.
557+
558+
>>> from flint import Ordering
559+
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, 'x')
560+
>>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
561+
>>> f
562+
4*x0*x1 + 2*x0 + 3*x1
563+
>>> f.isub(5)
564+
>>> f
565+
4*x0*x1 + 2*x0 + 3*x1 - 5
566+
567+
"""
568+
if typecheck(other, fmpz_mpoly):
569+
if (<fmpz_mpoly>self).ctx is not (<fmpz_mpoly>other).ctx:
570+
raise IncompatibleContextError(f"{(<fmpz_mpoly>self).ctx} is not {(<fmpz_mpoly>other).ctx}")
571+
fmpz_mpoly_sub((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz_mpoly>other).val, self.ctx.val)
572+
return
573+
else:
574+
other = any_as_fmpz(other)
575+
if other is not NotImplemented:
576+
fmpz_mpoly_sub_fmpz((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz>other).val, self.ctx.val)
577+
return
578+
raise NotImplementedError()
579+
580+
def imul(self, other):
581+
"""
582+
In-place multiplication, mutates self.
583+
584+
>>> from flint import Ordering
585+
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, 'x')
586+
>>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
587+
>>> f
588+
4*x0*x1 + 2*x0 + 3*x1
589+
>>> f.imul(2)
590+
>>> f
591+
8*x0*x1 + 4*x0 + 6*x1
592+
593+
"""
594+
if typecheck(other, fmpz_mpoly):
595+
if (<fmpz_mpoly>self).ctx is not (<fmpz_mpoly>other).ctx:
596+
raise IncompatibleContextError(f"{(<fmpz_mpoly>self).ctx} is not {(<fmpz_mpoly>other).ctx}")
597+
fmpz_mpoly_mul((<fmpz_mpoly>self).val, (<fmpz_mpoly>self).val, (<fmpz_mpoly>other).val, self.ctx.val)
598+
return
599+
else:
600+
other = any_as_fmpz(other)
601+
if other is not NotImplemented:
602+
fmpz_mpoly_scalar_mul_fmpz(self.val, (<fmpz_mpoly>self).val, (<fmpz>other).val, self.ctx.val)
603+
return
604+
raise NotImplementedError()
605+
567606
def monoms(self):
568607
"""
569608
Return the exponent vectors of each term as a tuple of fmpz.

0 commit comments

Comments
 (0)