Skip to content

Commit e2b6369

Browse files
author
Jake Moss
committed
Significantly clean up nmod_mpoly type conversion
Other types will come later
1 parent 9abc8d2 commit e2b6369

File tree

2 files changed

+293
-551
lines changed

2 files changed

+293
-551
lines changed

src/flint/flint_base/flint_base.pyx

+230
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ cimport libc.stdlib
1313
from typing import Optional
1414
from flint.utils.flint_exceptions import IncompatibleContextError
1515

16+
from flint.types.fmpz cimport fmpz, any_as_fmpz
17+
1618

1719
FLINT_BITS = _FLINT_BITS
1820
FLINT_VERSION = _FLINT_VERSION.decode("ascii")
@@ -404,6 +406,48 @@ cdef class flint_mpoly(flint_elem):
404406
def _add_mpoly_(self, other):
405407
return NotImplemented
406408

409+
def _iadd_scalar_(self, other):
410+
return NotImplemented
411+
412+
def _iadd_mpoly_(self, other):
413+
return NotImplemented
414+
415+
def _sub_scalar_(self, other):
416+
return NotImplemented
417+
418+
def _sub_mpoly_(self, other):
419+
return NotImplemented
420+
421+
def _isub_scalar_(self, other):
422+
return NotImplemented
423+
424+
def _isub_mpoly_(self, other):
425+
return NotImplemented
426+
427+
def _mul_scalar_(self, other):
428+
return NotImplemented
429+
430+
def _imul_mpoly_(self, other):
431+
return NotImplemented
432+
433+
def _imul_scalar_(self, other):
434+
return NotImplemented
435+
436+
def _mul_mpoly_(self, other):
437+
return NotImplemented
438+
439+
def _pow_(self, other):
440+
return NotImplemented
441+
442+
def _divmod_mpoly_(self, other):
443+
return NotImplemented
444+
445+
def _floordiv_mpoly_(self, other):
446+
return NotImplemented
447+
448+
def _truediv_mpoly_(self, other):
449+
return NotImplemented
450+
407451
def __add__(self, other):
408452
if typecheck(other, type(self)):
409453
self.context().compatible_context_check(other.context())
@@ -418,6 +462,123 @@ cdef class flint_mpoly(flint_elem):
418462
def __radd__(self, other):
419463
return self.__add__(other)
420464

465+
def iadd(self, other):
466+
"""
467+
In-place addition, mutates self.
468+
469+
>>> from flint import Ordering, fmpz_mpoly_ctx
470+
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, 'x')
471+
>>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
472+
>>> f
473+
4*x0*x1 + 2*x0 + 3*x1
474+
>>> f.iadd(5)
475+
>>> f
476+
4*x0*x1 + 2*x0 + 3*x1 + 5
477+
478+
"""
479+
if typecheck(other, type(self)):
480+
self.context().compatible_context_check(other.context())
481+
self._iadd_mpoly_(other)
482+
return
483+
484+
other_scalar = self.context().any_as_scalar(other)
485+
if other_scalar is NotImplemented:
486+
raise NotImplementedError(f"cannot add {type(self)} and {type(other)}")
487+
488+
self._iadd_scalar_(other_scalar)
489+
490+
def __sub__(self, other):
491+
if typecheck(other, type(self)):
492+
self.context().compatible_context_check(other.context())
493+
return self._sub_mpoly_(other)
494+
495+
other = self.context().any_as_scalar(other)
496+
if other is NotImplemented:
497+
return NotImplemented
498+
499+
return self._sub_scalar_(other)
500+
501+
def __rsub__(self, other):
502+
return -self.__sub__(other)
503+
504+
def isub(self, other):
505+
"""
506+
In-place subtraction, mutates self.
507+
508+
>>> from flint import Ordering, fmpz_mpoly_ctx
509+
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, 'x')
510+
>>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
511+
>>> f
512+
4*x0*x1 + 2*x0 + 3*x1
513+
>>> f.isub(5)
514+
>>> f
515+
4*x0*x1 + 2*x0 + 3*x1 - 5
516+
517+
"""
518+
if typecheck(other, type(self)):
519+
self.context().compatible_context_check(other.context())
520+
self._isub_mpoly_(other)
521+
return
522+
523+
other_scalar = self.context().any_as_scalar(other)
524+
if other_scalar is NotImplemented:
525+
raise NotImplementedError(f"cannot subtract {type(self)} and {type(other)}")
526+
527+
self._isub_scalar_(other_scalar)
528+
529+
def __mul__(self, other):
530+
if typecheck(other, type(self)):
531+
self.context().compatible_context_check(other.context())
532+
return self._mul_mpoly_(other)
533+
534+
other = self.context().any_as_scalar(other)
535+
if other is NotImplemented:
536+
return NotImplemented
537+
538+
return self._mul_scalar_(other)
539+
540+
def __rmul__(self, other):
541+
return self.__mul__(other)
542+
543+
def imul(self, other):
544+
"""
545+
In-place multiplication, mutates self.
546+
547+
>>> from flint import Ordering, fmpz_mpoly_ctx
548+
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, 'x')
549+
>>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
550+
>>> f
551+
4*x0*x1 + 2*x0 + 3*x1
552+
>>> f.imul(2)
553+
>>> f
554+
8*x0*x1 + 4*x0 + 6*x1
555+
556+
"""
557+
if typecheck(other, type(self)):
558+
self.context().compatible_context_check(other.context())
559+
self._imul_mpoly_(other)
560+
return
561+
562+
other_scalar = self.context().any_as_scalar(other)
563+
if other_scalar is NotImplemented:
564+
raise NotImplementedError(f"cannot multiply {type(self)} and {type(other)}")
565+
566+
self._imul_scalar_(other_scalar)
567+
568+
def __pow__(self, other, modulus):
569+
if modulus is not None:
570+
raise NotImplementedError("cannot specify modulus outside of the context")
571+
elif typecheck(other, fmpz):
572+
return self._pow_(other)
573+
574+
other = any_as_fmpz(other)
575+
if other is NotImplemented:
576+
return NotImplemented
577+
elif other < 0:
578+
raise ValueError("cannot raise to a negative power")
579+
580+
return self._pow_(other)
581+
421582
def __divmod__(self, other):
422583
if typecheck(other, type(self)):
423584
self._division_check(other)
@@ -441,6 +602,75 @@ cdef class flint_mpoly(flint_elem):
441602
other = self.context().scalar_as_mpoly(other)
442603
return other._divmod_mpoly_(self)
443604

605+
def __truediv__(self, other):
606+
if typecheck(other, type(self)):
607+
self._division_check(other)
608+
self.context().compatible_context_check(other.context())
609+
return self._truediv_mpoly_(other)
610+
611+
other = self.context().any_as_scalar(other)
612+
if other is NotImplemented:
613+
return NotImplemented
614+
615+
self._division_check(other)
616+
other = self.context().scalar_as_mpoly(other)
617+
return self._truediv_mpoly_(other)
618+
619+
def __rtruediv__(self, other):
620+
other = self.context().any_as_scalar(other)
621+
if other is NotImplemented:
622+
return NotImplemented
623+
624+
self._division_check(self)
625+
other = self.context().scalar_as_mpoly(other)
626+
return other._truediv_mpoly_(self)
627+
628+
def __floordiv__(self, other):
629+
if typecheck(other, type(self)):
630+
self._division_check(other)
631+
self.context().compatible_context_check(other.context())
632+
return self._floordiv_mpoly_(other)
633+
634+
other = self.context().any_as_scalar(other)
635+
if other is NotImplemented:
636+
return NotImplemented
637+
638+
self._division_check(other)
639+
other = self.context().scalar_as_mpoly(other)
640+
return self._floordiv_mpoly_(other)
641+
642+
def __rfloordiv__(self, other):
643+
other = self.context().any_as_scalar(other)
644+
if other is NotImplemented:
645+
return NotImplemented
646+
647+
self._division_check(self)
648+
other = self.context().scalar_as_mpoly(other)
649+
return other._floordiv_mpoly_(self)
650+
651+
def __mod__(self, other):
652+
if typecheck(other, type(self)):
653+
self._division_check(other)
654+
self.context().compatible_context_check(other.context())
655+
return self._mod_mpoly_(other)
656+
657+
other = self.context().any_as_scalar(other)
658+
if other is NotImplemented:
659+
return NotImplemented
660+
661+
self._division_check(other)
662+
other = self.context().scalar_as_mpoly(other)
663+
return self._mod_mpoly_(other)
664+
665+
def __rmod__(self, other):
666+
other = self.context().any_as_scalar(other)
667+
if other is NotImplemented:
668+
return NotImplemented
669+
670+
self._division_check(self)
671+
other = self.context().scalar_as_mpoly(other)
672+
return other._mod_mpoly_(self)
673+
444674
def __contains__(self, x):
445675
"""
446676
Returns True if `self` contains a term with exponent vector `x` and a non-zero coefficient.

0 commit comments

Comments
 (0)