diff --git a/.github/workflows/buildwheel.yml b/.github/workflows/buildwheel.yml index 34bd3007..05630625 100644 --- a/.github/workflows/buildwheel.yml +++ b/.github/workflows/buildwheel.yml @@ -43,7 +43,7 @@ jobs: CIBW_BEFORE_ALL_MACOS: bin/cibw_before_all_macosx_x86_64.sh CIBW_BEFORE_ALL_WINDOWS: msys2 -c bin/cibw_before_all_windows.sh CIBW_BEFORE_BUILD_WINDOWS: msys2 -c bin/cibw_before_build_windows.sh - CIBW_BEFORE_BUILD: pip install numpy cython delvewheel + CIBW_BEFORE_BUILD: pip install numpy cython==3.0.0b2 delvewheel CIBW_ENVIRONMENT: > C_INCLUDE_PATH=$(pwd)/.local/include/ LIBRARY_PATH=$(pwd)/.local/lib/ diff --git a/.gitignore b/.gitignore index aa5aa82d..4c66d67b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ MANIFEST *.egg-info .coverage *.swp +.python-version diff --git a/bin/build_dependencies_unix.sh b/bin/build_dependencies_unix.sh index fefa9227..ade0d8a9 100755 --- a/bin/build_dependencies_unix.sh +++ b/bin/build_dependencies_unix.sh @@ -48,6 +48,10 @@ do PATCH_GMP_ARM64=yes shift ;; + --use-gmp-github-mirror) + USE_GMP_GITHUB_MIRROR=yes + shift + ;; *) 2>&1 echo "unrecognised argument:" $key exit 1 @@ -82,17 +86,22 @@ if [ $USE_GMP = "gmp" ]; then # # # ----------------------------------------------------------------------- # - curl -O https://gmplib.org/download/gmp/gmp-$GMPVER.tar.xz + if [ $USE_GMP_GITHUB_MIRROR = "yes" ]; then + # Needed in GitHub Actions because it is blocked from gmplib.org + git clone https://github.com/oscarbenjamin/gmp_mirror.git + cp gmp_mirror/gmp-$GMPVER.tar.xz . + else + curl -O https://gmplib.org/download/gmp/gmp-$GMPVER.tar.xz + fi + tar xf gmp-$GMPVER.tar.xz cd gmp-$GMPVER # # See https://github.com/aleaxit/gmpy/issues/350 # - # We need to patch GMP for OSX arm64 (Apple M1) hardware. This patch is - # from the GMP repo but was applied after the release of GMP 6.2.1. - # Hopefully when a newer version of GMP is released we will not need to - # apply this patch any more. + # We need to patch GMP for OSX arm64 (Apple M1) hardware for GMP 6.2.1. + # Now with GMP 6.3.0 this should not be needed any more. # if [ $PATCH_GMP_ARM64 = "yes" ]; then echo @@ -103,6 +112,7 @@ if [ $USE_GMP = "gmp" ]; then fi # Show the output of configfsf.guess + chmod +x configfsf.guess ./configfsf.guess ./configure --prefix=$PREFIX\ --enable-fat\ diff --git a/bin/build_variables.sh b/bin/build_variables.sh index 50d673f4..b7b4b113 100644 --- a/bin/build_variables.sh +++ b/bin/build_variables.sh @@ -13,7 +13,7 @@ PREFIX=$(pwd)/.local mkdir -p $PREFIX -GMPVER=6.2.1 +GMPVER=6.3.0 YASMVER=1.3.0 MPIRVER=3.0.0 MPFRVER=4.1.0 diff --git a/bin/cibw_before_all_linux.sh b/bin/cibw_before_all_linux.sh index e3183269..405d89dc 100755 --- a/bin/cibw_before_all_linux.sh +++ b/bin/cibw_before_all_linux.sh @@ -3,4 +3,5 @@ yum install -y xz bin/build_dependencies_unix.sh\ --gmp gmp\ - --host x86_64-pc-linux-gnu + --host x86_64-pc-linux-gnu\ + --use-gmp-github-mirror diff --git a/bin/cibw_before_all_macosx_arm64.sh b/bin/cibw_before_all_macosx_arm64.sh index 2fc3dee8..5a306c75 100755 --- a/bin/cibw_before_all_macosx_arm64.sh +++ b/bin/cibw_before_all_macosx_arm64.sh @@ -6,4 +6,4 @@ export LDFLAGS=" -arch arm64" bin/build_dependencies_unix.sh\ --gmp gmp\ --host aarch64-apple-darwin\ - --patch-gmp-arm64 + --use-gmp-github-mirror diff --git a/bin/cibw_before_all_macosx_x86_64.sh b/bin/cibw_before_all_macosx_x86_64.sh index db7a2d89..2eda5411 100755 --- a/bin/cibw_before_all_macosx_x86_64.sh +++ b/bin/cibw_before_all_macosx_x86_64.sh @@ -2,4 +2,5 @@ bin/build_dependencies_unix.sh\ --gmp gmp\ - --host x86_64-apple-darwin + --host x86_64-apple-darwin\ + --use-gmp-github-mirror diff --git a/bin/cibw_before_all_windows.sh b/bin/cibw_before_all_windows.sh index ea2f8a89..479ce126 100755 --- a/bin/cibw_before_all_windows.sh +++ b/bin/cibw_before_all_windows.sh @@ -17,4 +17,4 @@ cat setup.cfg pacman -S --noconfirm mingw-w64-x86_64-gcc m4 make mingw-w64-x86_64-tools-git # This takes ~30mins -bin/build_dependencies_unix.sh +bin/build_dependencies_unix.sh --use-gmp-github-mirror diff --git a/bin/cibw_before_build_windows.sh b/bin/cibw_before_build_windows.sh index d0410b35..d618e72b 100644 --- a/bin/cibw_before_build_windows.sh +++ b/bin/cibw_before_build_windows.sh @@ -40,4 +40,4 @@ mv libpython${VER}.a libs # Install build dependencies # ################################################### -pip install Cython numpy delvewheel +pip install cython numpy delvewheel diff --git a/setup.py b/setup.py index 913c2fef..cdd19c99 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,10 @@ define_macros = [] -compiler_directives = {'language_level':3} +compiler_directives = { + 'language_level': 3, + 'binding': False, +} # Enable coverage tracing diff --git a/src/flint/acb.pyx b/src/flint/acb.pyx index 98b3b36b..a7151a55 100644 --- a/src/flint/acb.pyx +++ b/src/flint/acb.pyx @@ -156,23 +156,18 @@ cdef class acb(flint_scalar): return (self.real._mpf_, self.imag._mpf_) def __richcmp__(s, t, int op): - cdef acb_struct sval[1] cdef acb_struct tval[1] cdef bint res - cdef int stype, ttype + cdef int ttype if not (op == 2 or op == 3): raise ValueError("comparing complex numbers") - stype = acb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: - return NotImplemented ttype = acb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented if op == 2: - res = acb_eq(sval, tval) + res = acb_eq(s.val, tval) else: - res = acb_ne(sval, tval) - if stype == FMPZ_TMP: acb_clear(sval) + res = acb_ne(s.val, tval) if ttype == FMPZ_TMP: acb_clear(tval) return res @@ -363,92 +358,116 @@ cdef class acb(flint_scalar): return res def __add__(s, t): - cdef acb_struct sval[1] cdef acb_struct tval[1] - cdef int stype, ttype - stype = acb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: + cdef int ttype + ttype = acb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: return NotImplemented + u = acb.__new__(acb) + acb_add((u).val, (s).val, tval, getprec()) + if ttype == FMPZ_TMP: acb_clear(tval) + return u + + def __radd__(s, t): + cdef acb_struct tval[1] + cdef int ttype ttype = acb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented u = acb.__new__(acb) - acb_add((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: acb_clear(sval) + acb_add((u).val, tval, s.val, getprec()) if ttype == FMPZ_TMP: acb_clear(tval) return u def __sub__(s, t): - cdef acb_struct sval[1] cdef acb_struct tval[1] - cdef int stype, ttype - stype = acb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: + cdef int ttype + ttype = acb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: return NotImplemented + u = acb.__new__(acb) + acb_sub((u).val, (s).val, tval, getprec()) + if ttype == FMPZ_TMP: acb_clear(tval) + return u + + def __rsub__(s, t): + cdef acb_struct tval[1] + cdef int ttype ttype = acb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented u = acb.__new__(acb) - acb_sub((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: acb_clear(sval) + acb_sub((u).val, tval, s.val, getprec()) if ttype == FMPZ_TMP: acb_clear(tval) return u def __mul__(s, t): - cdef acb_struct sval[1] cdef acb_struct tval[1] - cdef int stype, ttype - stype = acb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: - return NotImplemented + cdef int ttype ttype = acb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented u = acb.__new__(acb) - acb_mul((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: acb_clear(sval) + acb_mul((u).val, (s).val, tval, getprec()) if ttype == FMPZ_TMP: acb_clear(tval) return u - # important: must not be cdef because of cython magic - @staticmethod - def _div_(s, t): - cdef acb_struct sval[1] + def __rmul__(s, t): cdef acb_struct tval[1] - cdef int stype, ttype - stype = acb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: - return NotImplemented + cdef int ttype ttype = acb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented u = acb.__new__(acb) - acb_div((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: acb_clear(sval) + acb_mul((u).val, tval, s.val, getprec()) if ttype == FMPZ_TMP: acb_clear(tval) return u def __truediv__(s, t): - return acb._div_(s, t) + cdef acb_struct tval[1] + cdef int ttype + ttype = acb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: + return NotImplemented + u = acb.__new__(acb) + acb_div((u).val, (s).val, tval, getprec()) + if ttype == FMPZ_TMP: acb_clear(tval) + return u - def __div__(s, t): - return acb._div_(s, t) + def __rtruediv__(s, t): + cdef acb_struct tval[1] + cdef int ttype + ttype = acb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: + return NotImplemented + u = acb.__new__(acb) + acb_div((u).val, tval, s.val, getprec()) + if ttype == FMPZ_TMP: acb_clear(tval) + return u def __pow__(s, t, u): - cdef acb_struct sval[1] cdef acb_struct tval[1] - cdef int stype, ttype + cdef int ttype if u is not None: raise ValueError("modular exponentiation of complex number") - stype = acb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: + ttype = acb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: return NotImplemented + u = acb.__new__(acb) + acb_pow((u).val, (s).val, tval, getprec()) + if ttype == FMPZ_TMP: acb_clear(tval) + return u + + def __rpow__(s, t, u): + cdef acb_struct tval[1] + cdef int ttype + if u is not None: + raise ValueError("modular exponentiation of complex number") ttype = acb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented u = acb.__new__(acb) - acb_pow((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: acb_clear(sval) + acb_pow((u).val, tval, s.val, getprec()) if ttype == FMPZ_TMP: acb_clear(tval) return u @@ -2560,4 +2579,3 @@ cdef class acb(flint_scalar): acb_hypgeom_coulomb(NULL, (G).val, NULL, NULL, (l).val, (eta).val, (self).val, getprec()) return G - diff --git a/src/flint/acb_mat.pyx b/src/flint/acb_mat.pyx index ceacaf4d..4f80870d 100644 --- a/src/flint/acb_mat.pyx +++ b/src/flint/acb_mat.pyx @@ -1,14 +1,8 @@ cdef acb_mat_coerce_operands(x, y): - if typecheck(x, acb_mat): - if isinstance(y, (fmpz_mat, fmpq_mat, arb_mat)): - return x, acb_mat(y) - if isinstance(y, (int, long, float, complex, fmpz, fmpq, arb, acb)): - return x, acb_mat(x.nrows(), x.ncols(), y) - elif typecheck(y, acb_mat): - if isinstance(x, (fmpz_mat, fmpq_mat, arb_mat)): - return acb_mat(x), y - if isinstance(y, (int, long, float, complex, fmpz, fmpq, arb, acb)): - return acb_mat(y.nrows(), y.ncols(), x), y + if isinstance(y, (fmpz_mat, fmpq_mat, arb_mat)): + return x, acb_mat(y) + if isinstance(y, (int, long, float, complex, fmpz, fmpq, arb, acb)): + return x, acb_mat(x.nrows(), x.ncols(), y) return NotImplemented, NotImplemented cdef acb_mat_coerce_scalar(x, y): @@ -226,35 +220,49 @@ cdef class acb_mat(flint_mat): def __add__(s, t): cdef long m, n - if type(s) is type(t): - m = (s).nrows() - n = (s).ncols() - if m != (t).nrows() or n != (t).ncols(): - raise ValueError("incompatible shapes for matrix addition") - u = acb_mat.__new__(acb_mat) - acb_mat_init((u).val, m, n) - acb_mat_add((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, acb_mat): + s, t = acb_mat_coerce_operands(s, t) + if s is NotImplemented: + return s + return s + t + + m = (s).nrows() + n = (s).ncols() + if m != (t).nrows() or n != (t).ncols(): + raise ValueError("incompatible shapes for matrix addition") + u = acb_mat.__new__(acb_mat) + acb_mat_init((u).val, m, n) + acb_mat_add((u).val, (s).val, (t).val, getprec()) + return u + + def __radd__(s, t): s, t = acb_mat_coerce_operands(s, t) if s is NotImplemented: return s - return s + t + return t + s def __sub__(s, t): cdef long m, n - if type(s) is type(t): - m = (s).nrows() - n = (s).ncols() - if m != (t).nrows() or n != (t).ncols(): - raise ValueError("incompatible shapes for matrix addition") - u = acb_mat.__new__(acb_mat) - acb_mat_init((u).val, m, n) - acb_mat_sub((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, acb_mat): + s, t = acb_mat_coerce_operands(s, t) + if s is NotImplemented: + return s + return s - t + + m = (s).nrows() + n = (s).ncols() + if m != (t).nrows() or n != (t).ncols(): + raise ValueError("incompatible shapes for matrix addition") + u = acb_mat.__new__(acb_mat) + acb_mat_init((u).val, m, n) + acb_mat_sub((u).val, (s).val, (t).val, getprec()) + return u + + def __rsub__(s, t): s, t = acb_mat_coerce_operands(s, t) if s is NotImplemented: return s - return s - t + return t - s def _scalar_mul_(s, acb t): cdef acb_mat u @@ -265,25 +273,30 @@ cdef class acb_mat(flint_mat): def __mul__(s, t): cdef acb_mat u - if type(s) is type(t): - if acb_mat_ncols((s).val) != acb_mat_nrows((t).val): - raise ValueError("incompatible shapes for matrix multiplication") - u = acb_mat.__new__(acb_mat) - acb_mat_init(u.val, acb_mat_nrows((s).val), acb_mat_ncols((t).val)) - acb_mat_mul(u.val, (s).val, (t).val, getprec()) - return u - if typecheck(s, acb_mat): + if not isinstance(t, acb_mat): c, d = acb_mat_coerce_scalar(s, t) if c is not NotImplemented: return c._scalar_mul_(d) - else: - d, c = acb_mat_coerce_scalar(t, s) - if d is not NotImplemented: - return d._scalar_mul_(c) + s, t = acb_mat_coerce_operands(s, t) + if s is NotImplemented: + return s + return s * t + + if acb_mat_ncols((s).val) != acb_mat_nrows((t).val): + raise ValueError("incompatible shapes for matrix multiplication") + u = acb_mat.__new__(acb_mat) + acb_mat_init(u.val, acb_mat_nrows((s).val), acb_mat_ncols((t).val)) + acb_mat_mul(u.val, (s).val, (t).val, getprec()) + return u + + def __rmul__(s, t): + c, d = acb_mat_coerce_scalar(s, t) + if c is not NotImplemented: + return c._scalar_mul_(d) s, t = acb_mat_coerce_operands(s, t) if s is NotImplemented: return s - return s * t + return t * s def _scalar_div_(s, acb t): cdef acb_mat u @@ -292,8 +305,7 @@ cdef class acb_mat(flint_mat): acb_mat_scalar_div_acb(u.val, s.val, t.val, getprec()) return u - @staticmethod - def _div_(s, t): + def __truediv__(s, t): cdef acb_mat u if typecheck(s, acb_mat): s, t = acb_mat_coerce_scalar(s, t) @@ -302,12 +314,6 @@ cdef class acb_mat(flint_mat): return s._scalar_div_(t) return NotImplemented - def __truediv__(s, t): - return acb_mat._div_(s, t) - - def __div__(s, t): - return acb_mat._div_(s, t) - def __pow__(s, e, m): cdef acb_mat u cdef ulong exp diff --git a/src/flint/acb_poly.pyx b/src/flint/acb_poly.pyx index 1c15fc8b..252e57d9 100644 --- a/src/flint/acb_poly.pyx +++ b/src/flint/acb_poly.pyx @@ -1,10 +1,6 @@ cdef acb_poly_coerce_operands(x, y): - if typecheck(x, acb_poly): - if isinstance(y, (int, long, float, complex, fmpz, fmpq, arb, acb, fmpz_poly, fmpq_poly, arb_poly)): - return x, acb_poly(y) - else: - if isinstance(x, (int, long, float, complex, fmpz, fmpq, arb, acb, fmpz_poly, fmpq_poly, arb_poly)): - return acb_poly(x), y + if isinstance(y, (int, long, float, complex, fmpz, fmpq, arb, acb, fmpz_poly, fmpq_poly, arb_poly)): + return x, acb_poly(y) return NotImplemented, NotImplemented cdef acb_poly_set_list(acb_poly_t poly, list val, long prec): @@ -188,76 +184,112 @@ cdef class acb_poly(flint_poly): return u def __add__(s, t): - if type(s) is type(t): - u = acb_poly.__new__(acb_poly) - acb_poly_add((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, acb_poly): + s, t = acb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s + t + u = acb_poly.__new__(acb_poly) + acb_poly_add((u).val, (s).val, (t).val, getprec()) + return u + + def __radd__(s, t): s, t = acb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s + t + return t + s def __sub__(s, t): - if type(s) is type(t): - u = acb_poly.__new__(acb_poly) - acb_poly_sub((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, acb_poly): + s, t = acb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s - t + u = acb_poly.__new__(acb_poly) + acb_poly_sub((u).val, (s).val, (t).val, getprec()) + return u + + def __rsub__(s, t): s, t = acb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s - t + return t - s def __mul__(s, t): - if type(s) is type(t): - u = acb_poly.__new__(acb_poly) - acb_poly_mul((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, acb_poly): + s, t = acb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s * t + u = acb_poly.__new__(acb_poly) + acb_poly_mul((u).val, (s).val, (t).val, getprec()) + return u + + def __rmul__(s, t): s, t = acb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s * t + return t * s def __floordiv__(s, t): - if type(s) is type(t): - q = acb_poly.__new__(acb_poly) - r = acb_poly.__new__(acb_poly) - if acb_poly_divrem((q).val, (r).val, - (s).val, (t).val, getprec()): - return q - else: - raise ZeroDivisionError("acb_poly leading coefficient must be nonzero") + if not isinstance(t, acb_poly): + s, t = acb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s // t + q = acb_poly.__new__(acb_poly) + r = acb_poly.__new__(acb_poly) + if acb_poly_divrem((q).val, (r).val, + (s).val, (t).val, getprec()): + return q + else: + raise ZeroDivisionError("acb_poly leading coefficient must be nonzero") + + def __rfloordiv__(s, t): s, t = acb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s // t + return t // s def __mod__(s, t): - if type(s) is type(t): - q = acb_poly.__new__(acb_poly) - r = acb_poly.__new__(acb_poly) - if acb_poly_divrem((q).val, (r).val, - (s).val, (t).val, getprec()): - return r - else: - raise ZeroDivisionError("acb_poly leading coefficient must be nonzero") + if not isinstance(t, acb_poly): + s, t = acb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s % t + q = acb_poly.__new__(acb_poly) + r = acb_poly.__new__(acb_poly) + if acb_poly_divrem((q).val, (r).val, + (s).val, (t).val, getprec()): + return r + else: + raise ZeroDivisionError("acb_poly leading coefficient must be nonzero") + + def __rmod__(s, t): s, t = acb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s % t + return t % s def __divmod__(s, t): - if type(s) is type(t): - q = acb_poly.__new__(acb_poly) - r = acb_poly.__new__(acb_poly) - if acb_poly_divrem((q).val, (r).val, - (s).val, (t).val, getprec()): - return q, r - else: - raise ZeroDivisionError("acb_poly leading coefficient must be nonzero") + if not isinstance(t, acb_poly): + s, t = acb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return divmod(s, t) + q = acb_poly.__new__(acb_poly) + r = acb_poly.__new__(acb_poly) + if acb_poly_divrem((q).val, (r).val, + (s).val, (t).val, getprec()): + return q, r + else: + raise ZeroDivisionError("acb_poly leading coefficient must be nonzero") + + def __rdivmod__(s, t): s, t = acb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return divmod(s, t) + return divmod(t, s) def __pow__(acb_poly s, ulong exp, mod): if mod is not None: diff --git a/src/flint/acb_series.pyx b/src/flint/acb_series.pyx index 89fc7893..dd2eba22 100644 --- a/src/flint/acb_series.pyx +++ b/src/flint/acb_series.pyx @@ -1,10 +1,6 @@ cdef acb_series_coerce_operands(x, y): - if typecheck(x, acb_series): - if isinstance(y, (int, long, float, complex, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly, fmpq_series, arb, arb_poly, arb_series, acb, acb_poly)): - return x, acb_series(y) - else: - if isinstance(x, (int, long, float, complex, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly, fmpq_series, arb, arb_poly, arb_series, acb, acb_poly)): - return acb_series(x), y + if isinstance(y, (int, long, float, complex, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly, fmpq_series, arb, arb_poly, arb_series, acb, acb_poly)): + return x, acb_series(y) return NotImplemented, NotImplemented cdef class acb_series(flint_series): @@ -95,53 +91,74 @@ cdef class acb_series(flint_series): def __add__(s, t): cdef long cap - if type(s) is type(t): - u = acb_series.__new__(acb_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - acb_poly_add((u).val, (s).val, (t).val, getprec()) - acb_poly_truncate((u).val, cap) - (u).prec = cap - return u + if not isinstance(t, acb_series): + s, t = acb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s + t + + u = acb_series.__new__(acb_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + acb_poly_add((u).val, (s).val, (t).val, getprec()) + acb_poly_truncate((u).val, cap) + (u).prec = cap + return u + + def __radd__(s, t): s, t = acb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s + t + return t + s def __sub__(s, t): cdef long cap - if type(s) is type(t): - u = acb_series.__new__(acb_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - acb_poly_sub((u).val, (s).val, (t).val, getprec()) - acb_poly_truncate((u).val, cap) - (u).prec = cap - return u + if not isinstance(t, acb_series): + s, t = acb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s - t + + u = acb_series.__new__(acb_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + acb_poly_sub((u).val, (s).val, (t).val, getprec()) + acb_poly_truncate((u).val, cap) + (u).prec = cap + return u + + def __rsub__(s, t): s, t = acb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s - t + return t - s def __mul__(s, t): cdef long cap - if type(s) is type(t): - u = acb_series.__new__(acb_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - acb_poly_mullow((u).val, (s).val, (t).val, cap, getprec()) - (u).prec = cap - return u + if not isinstance(t, acb_series): + s, t = acb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s * t + + u = acb_series.__new__(acb_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + acb_poly_mullow((u).val, (s).val, (t).val, cap, getprec()) + (u).prec = cap + return u + + def __rmul__(s, t): s, t = acb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s * t + return t * s cpdef valuation(self): cdef long i @@ -152,76 +169,83 @@ cdef class acb_series(flint_series): i += 1 return i - @staticmethod - def _truediv_(s, t): + def __truediv__(s, t): cdef long cap, sval, tval cdef acb_poly_t stmp, ttmp - if type(s) is type(t): - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if (t).length() == 0: - raise ZeroDivisionError("power series division") + if not isinstance(t, acb_series): + s, t = acb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s / t - u = acb_series.__new__(acb_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) - if (s).length() == 0: - u.cap = cap - return u + if (t).length() == 0: + raise ZeroDivisionError("power series division") - sval = (s).valuation() - tval = (t).valuation() + u = acb_series.__new__(acb_series) - if sval < tval: - raise ValueError("quotient would not be a power series") + if (s).length() == 0: + u.cap = cap + return u - if acb_contains_zero(&((t).val.coeffs[tval])): - raise ValueError("leading term in denominator is not nonzero") + sval = (s).valuation() + tval = (t).valuation() - if tval == 0: - acb_poly_div_series((u).val, (s).val, (t).val, cap, getprec()) - else: - acb_poly_init(stmp) - acb_poly_init(ttmp) - acb_poly_shift_right(stmp, (s).val, tval) - acb_poly_shift_right(ttmp, (t).val, tval) - cap -= tval - acb_poly_div_series((u).val, stmp, ttmp, cap, getprec()) - acb_poly_clear(stmp) - acb_poly_clear(ttmp) + if sval < tval: + raise ValueError("quotient would not be a power series") - (u).prec = cap - return u + if acb_contains_zero(&((t).val.coeffs[tval])): + raise ValueError("leading term in denominator is not nonzero") + if tval == 0: + acb_poly_div_series((u).val, (s).val, (t).val, cap, getprec()) + else: + acb_poly_init(stmp) + acb_poly_init(ttmp) + acb_poly_shift_right(stmp, (s).val, tval) + acb_poly_shift_right(ttmp, (t).val, tval) + cap -= tval + acb_poly_div_series((u).val, stmp, ttmp, cap, getprec()) + acb_poly_clear(stmp) + acb_poly_clear(ttmp) + + (u).prec = cap + return u + + def __rtruediv__(s, t): s, t = acb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s / t - - def __truediv__(s, t): - return acb_series._div_(s, t) - - def __div__(s, t): - return acb_series._div_(s, t) + return t / s def __pow__(s, t, mod): cdef long cap if mod is not None: raise NotImplementedError("modular exponentiation") - if type(s) is type(t): - u = acb_series.__new__(acb_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - acb_poly_pow_series((u).val, (s).val, (t).val, cap, getprec()) - (u).prec = cap - return u + if not isinstance(t, acb_series): + s, t = acb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s ** t + + u = acb_series.__new__(acb_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + acb_poly_pow_series((u).val, (s).val, (t).val, cap, getprec()) + (u).prec = cap + return u + + def __rpow__(s, t): s, t = acb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s ** t + return t ** s def __call__(s, t): cdef long cap diff --git a/src/flint/arb.pyx b/src/flint/arb.pyx index 7c09e942..6a52c557 100644 --- a/src/flint/arb.pyx +++ b/src/flint/arb.pyx @@ -116,22 +116,6 @@ cdef any_as_arb_or_notimplemented(x): return NotImplemented return t -cdef _arb_div_(s, t): - cdef arb_struct sval[1] - cdef arb_struct tval[1] - cdef int stype, ttype - stype = arb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: - return NotImplemented - ttype = arb_set_any_ref(tval, t) - if ttype == FMPZ_UNKNOWN: - return NotImplemented - u = arb.__new__(arb) - arb_div((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: arb_clear(sval) - if ttype == FMPZ_TMP: arb_clear(tval) - return u - cdef class arb(flint_scalar): ur""" Represents a real number `x` by a midpoint `m` and a radius `r` @@ -550,74 +534,116 @@ cdef class arb(flint_scalar): return res def __add__(s, t): - cdef arb_struct sval[1] cdef arb_struct tval[1] - cdef int stype, ttype - stype = arb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: + cdef int ttype + ttype = arb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: return NotImplemented + u = arb.__new__(arb) + arb_add((u).val, (s).val, tval, getprec()) + if ttype == FMPZ_TMP: arb_clear(tval) + return u + + def __radd__(s, t): + cdef arb_struct tval[1] + cdef int ttype ttype = arb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented u = arb.__new__(arb) - arb_add((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: arb_clear(sval) + arb_add((u).val, tval, s.val, getprec()) if ttype == FMPZ_TMP: arb_clear(tval) return u def __sub__(s, t): - cdef arb_struct sval[1] cdef arb_struct tval[1] - cdef int stype, ttype - stype = arb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: + cdef int ttype + ttype = arb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: return NotImplemented + u = arb.__new__(arb) + arb_sub((u).val, (s).val, tval, getprec()) + if ttype == FMPZ_TMP: arb_clear(tval) + return u + + def __rsub__(s, t): + cdef arb_struct tval[1] + cdef int ttype ttype = arb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented u = arb.__new__(arb) - arb_sub((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: arb_clear(sval) + arb_sub((u).val, tval, s.val, getprec()) if ttype == FMPZ_TMP: arb_clear(tval) return u def __mul__(s, t): - cdef arb_struct sval[1] cdef arb_struct tval[1] - cdef int stype, ttype - stype = arb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: + cdef int ttype + ttype = arb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: return NotImplemented + u = arb.__new__(arb) + arb_mul((u).val, (s).val, tval, getprec()) + if ttype == FMPZ_TMP: arb_clear(tval) + return u + + def __rmul__(s, t): + cdef arb_struct tval[1] + cdef int ttype ttype = arb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented u = arb.__new__(arb) - arb_mul((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: arb_clear(sval) + arb_mul((u).val, tval, s.val, getprec()) if ttype == FMPZ_TMP: arb_clear(tval) return u def __truediv__(s, t): - return _arb_div_(s, t) + cdef arb_struct tval[1] + cdef int ttype + ttype = arb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: + return NotImplemented + u = arb.__new__(arb) + arb_div((u).val, (s).val, tval, getprec()) + if ttype == FMPZ_TMP: arb_clear(tval) + return u - def __div__(s, t): - return _arb_div_(s, t) + def __rtruediv__(s, t): + cdef arb_struct tval[1] + cdef int ttype + ttype = arb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: + return NotImplemented + u = arb.__new__(arb) + arb_div((u).val, tval, s.val, getprec()) + if ttype == FMPZ_TMP: arb_clear(tval) + return u def __pow__(s, t, modulus): - cdef arb_struct sval[1] cdef arb_struct tval[1] - cdef int stype, ttype + cdef int ttype if modulus is not None: raise TypeError("three-argument pow() not supported by arb type") - stype = arb_set_any_ref(sval, s) - if stype == FMPZ_UNKNOWN: + ttype = arb_set_any_ref(tval, t) + if ttype == FMPZ_UNKNOWN: return NotImplemented + u = arb.__new__(arb) + arb_pow((u).val, (s).val, tval, getprec()) + if ttype == FMPZ_TMP: arb_clear(tval) + return u + + def __rpow__(s, t, modulus): + cdef arb_struct tval[1] + cdef int ttype + if modulus is not None: + raise TypeError("three-argument pow() not supported by arb type") ttype = arb_set_any_ref(tval, t) if ttype == FMPZ_UNKNOWN: return NotImplemented u = arb.__new__(arb) - arb_pow((u).val, sval, tval, getprec()) - if stype == FMPZ_TMP: arb_clear(sval) + arb_pow((u).val, tval, s.val, getprec()) if ttype == FMPZ_TMP: arb_clear(tval) return u @@ -2421,4 +2447,3 @@ cdef class arb(flint_scalar): arb_hypgeom_coulomb(NULL, (G).val, (l).val, (eta).val, (self).val, getprec()) return G - diff --git a/src/flint/arb_mat.pyx b/src/flint/arb_mat.pyx index b571ca63..0cb89378 100644 --- a/src/flint/arb_mat.pyx +++ b/src/flint/arb_mat.pyx @@ -1,18 +1,10 @@ cdef arb_mat_coerce_operands(x, y): - if typecheck(x, arb_mat): - if isinstance(y, (fmpz_mat, fmpq_mat)): - return x, arb_mat(y) - if isinstance(y, (int, long, float, fmpz, fmpq, arb)): - return x, arb_mat(x.nrows(), x.ncols(), y) - if isinstance(y, (complex, acb)): - return acb_mat(x), acb_mat(x.nrows(), x.ncols(), y) - elif typecheck(y, arb_mat): - if isinstance(x, (fmpz_mat, fmpq_mat)): - return arb_mat(x), y - if isinstance(y, (int, long, float, fmpz, fmpq, arb)): - return arb_mat(y.nrows(), y.ncols(), x), y - if isinstance(y, (complex, acb)): - return acb_mat(y.nrows(), y.ncols(), x), acb_mat(y) + if isinstance(y, (fmpz_mat, fmpq_mat)): + return x, arb_mat(y) + if isinstance(y, (int, long, float, fmpz, fmpq, arb)): + return x, arb_mat(x.nrows(), x.ncols(), y) + if isinstance(y, (complex, acb)): + return acb_mat(x), acb_mat(x.nrows(), x.ncols(), y) return NotImplemented, NotImplemented cdef arb_mat_coerce_scalar(x, y): @@ -216,35 +208,49 @@ cdef class arb_mat(flint_mat): def __add__(s, t): cdef long m, n - if type(s) is type(t): - m = (s).nrows() - n = (s).ncols() - if m != (t).nrows() or n != (t).ncols(): - raise ValueError("incompatible shapes for matrix addition") - u = arb_mat.__new__(arb_mat) - arb_mat_init((u).val, m, n) - arb_mat_add((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, arb_mat): + s, t = arb_mat_coerce_operands(s, t) + if s is NotImplemented: + return s + return s + t + + m = (s).nrows() + n = (s).ncols() + if m != (t).nrows() or n != (t).ncols(): + raise ValueError("incompatible shapes for matrix addition") + u = arb_mat.__new__(arb_mat) + arb_mat_init((u).val, m, n) + arb_mat_add((u).val, (s).val, (t).val, getprec()) + return u + + def __radd__(s, t): s, t = arb_mat_coerce_operands(s, t) if s is NotImplemented: return s - return s + t + return t + s def __sub__(s, t): cdef long m, n - if type(s) is type(t): - m = (s).nrows() - n = (s).ncols() - if m != (t).nrows() or n != (t).ncols(): - raise ValueError("incompatible shapes for matrix addition") - u = arb_mat.__new__(arb_mat) - arb_mat_init((u).val, m, n) - arb_mat_sub((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, arb_mat): + s, t = arb_mat_coerce_operands(s, t) + if s is NotImplemented: + return s + return s - t + + m = (s).nrows() + n = (s).ncols() + if m != (t).nrows() or n != (t).ncols(): + raise ValueError("incompatible shapes for matrix addition") + u = arb_mat.__new__(arb_mat) + arb_mat_init((u).val, m, n) + arb_mat_sub((u).val, (s).val, (t).val, getprec()) + return u + + def __rsub__(s, t): s, t = arb_mat_coerce_operands(s, t) if s is NotImplemented: return s - return s - t + return t - s def _scalar_mul_(s, arb t): cdef arb_mat u @@ -255,25 +261,31 @@ cdef class arb_mat(flint_mat): def __mul__(s, t): cdef arb_mat u - if type(s) is type(t): - if arb_mat_ncols((s).val) != arb_mat_nrows((t).val): - raise ValueError("incompatible shapes for matrix multiplication") - u = arb_mat.__new__(arb_mat) - arb_mat_init(u.val, arb_mat_nrows((s).val), arb_mat_ncols((t).val)) - arb_mat_mul(u.val, (s).val, (t).val, getprec()) - return u - if typecheck(s, arb_mat): + if not isinstance(t, arb_mat): c, d = arb_mat_coerce_scalar(s, t) if c is not NotImplemented: return c._scalar_mul_(d) - else: - d, c = arb_mat_coerce_scalar(t, s) - if d is not NotImplemented: - return d._scalar_mul_(c) + s, t = arb_mat_coerce_operands(s, t) + if s is NotImplemented: + return s + return s * t + + if arb_mat_ncols((s).val) != arb_mat_nrows((t).val): + raise ValueError("incompatible shapes for matrix multiplication") + u = arb_mat.__new__(arb_mat) + arb_mat_init(u.val, arb_mat_nrows((s).val), arb_mat_ncols((t).val)) + arb_mat_mul(u.val, (s).val, (t).val, getprec()) + return u + + def __rmul__(s, t): + cdef arb_mat u + c, d = arb_mat_coerce_scalar(s, t) + if c is not NotImplemented: + return c._scalar_mul_(d) s, t = arb_mat_coerce_operands(s, t) if s is NotImplemented: return s - return s * t + return t * s def _scalar_div_(s, arb t): cdef arb_mat u @@ -282,28 +294,17 @@ cdef class arb_mat(flint_mat): arb_mat_scalar_div_arb(u.val, s.val, t.val, getprec()) return u - @staticmethod - def _div_(s, t): - cdef arb_mat u - if typecheck(s, arb_mat): - s, t = arb_mat_coerce_scalar(s, t) - if s is NotImplemented: - return s - return s._scalar_div_(t) - return NotImplemented - def __truediv__(s, t): - return arb_mat._div_(s, t) - - def __div__(s, t): - return arb_mat._div_(s, t) + cdef arb_mat u + s, t = arb_mat_coerce_scalar(s, t) + if s is NotImplemented: + return s + return s._scalar_div_(t) def __pow__(s, e, m): cdef arb_mat u cdef ulong exp cdef long n - if not typecheck(s, arb_mat): - return NotImplemented exp = e n = arb_mat_nrows((s).val) if n != arb_mat_ncols((s).val): diff --git a/src/flint/arb_poly.pyx b/src/flint/arb_poly.pyx index 95776948..a13ed454 100644 --- a/src/flint/arb_poly.pyx +++ b/src/flint/arb_poly.pyx @@ -1,14 +1,8 @@ cdef arb_poly_coerce_operands(x, y): - if typecheck(x, arb_poly): - if isinstance(y, (int, long, float, fmpz, fmpq, arb, fmpz_poly, fmpq_poly)): - return x, arb_poly(y) - if isinstance(y, (complex, acb)): - return acb_poly(x), acb_poly(y) - else: - if isinstance(x, (int, long, float, fmpz, fmpq, arb, fmpz_poly, fmpq_poly)): - return arb_poly(x), y - if isinstance(x, (complex, acb)): - return acb_poly(x), acb_poly(y) + if isinstance(y, (int, long, float, fmpz, fmpq, arb, fmpz_poly, fmpq_poly)): + return x, arb_poly(y) + if isinstance(y, (complex, acb)): + return acb_poly(x), acb_poly(y) return NotImplemented, NotImplemented cdef arb_poly_set_list(arb_poly_t poly, list val, long prec): @@ -183,76 +177,112 @@ cdef class arb_poly(flint_poly): return u def __add__(s, t): - if type(s) is type(t): - u = arb_poly.__new__(arb_poly) - arb_poly_add((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, arb_poly): + s, t = arb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s + t + u = arb_poly.__new__(arb_poly) + arb_poly_add((u).val, (s).val, (t).val, getprec()) + return u + + def __radd__(s, t): s, t = arb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s + t + return t + s def __sub__(s, t): - if type(s) is type(t): - u = arb_poly.__new__(arb_poly) - arb_poly_sub((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, arb_poly): + s, t = arb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s - t + u = arb_poly.__new__(arb_poly) + arb_poly_sub((u).val, (s).val, (t).val, getprec()) + return u + + def __rsub__(s, t): s, t = arb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s - t + return t - s def __mul__(s, t): - if type(s) is type(t): - u = arb_poly.__new__(arb_poly) - arb_poly_mul((u).val, (s).val, (t).val, getprec()) - return u + if not isinstance(t, arb_poly): + s, t = arb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s * t + u = arb_poly.__new__(arb_poly) + arb_poly_mul((u).val, (s).val, (t).val, getprec()) + return u + + def __rmul__(s, t): s, t = arb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s * t + return t * s def __floordiv__(s, t): - if type(s) is type(t): - q = arb_poly.__new__(arb_poly) - r = arb_poly.__new__(arb_poly) - if arb_poly_divrem((q).val, (r).val, - (s).val, (t).val, getprec()): - return q - else: - raise ZeroDivisionError("arb_poly leading coefficient must be nonzero") + if not isinstance(t, arb_poly): + s, t = arb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s // t + q = arb_poly.__new__(arb_poly) + r = arb_poly.__new__(arb_poly) + if arb_poly_divrem((q).val, (r).val, + (s).val, (t).val, getprec()): + return q + else: + raise ZeroDivisionError("arb_poly leading coefficient must be nonzero") + + def __rfloordiv__(s, t): s, t = arb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s // t + return t // s def __mod__(s, t): - if type(s) is type(t): - q = arb_poly.__new__(arb_poly) - r = arb_poly.__new__(arb_poly) - if arb_poly_divrem((q).val, (r).val, - (s).val, (t).val, getprec()): - return r - else: - raise ZeroDivisionError("arb_poly leading coefficient must be nonzero") + if not isinstance(t, arb_poly): + s, t = arb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return s % t + q = arb_poly.__new__(arb_poly) + r = arb_poly.__new__(arb_poly) + if arb_poly_divrem((q).val, (r).val, + (s).val, (t).val, getprec()): + return r + else: + raise ZeroDivisionError("arb_poly leading coefficient must be nonzero") + + def __rmod__(s, t): s, t = arb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return s % t + return t % s def __divmod__(s, t): - if type(s) is type(t): - q = arb_poly.__new__(arb_poly) - r = arb_poly.__new__(arb_poly) - if arb_poly_divrem((q).val, (r).val, - (s).val, (t).val, getprec()): - return q, r - else: - raise ZeroDivisionError("arb_poly leading coefficient must be nonzero") + if not isinstance(t, arb_poly): + s, t = arb_poly_coerce_operands(s, t) + if s is NotImplemented: + return s + return divmod(s, t) + q = arb_poly.__new__(arb_poly) + r = arb_poly.__new__(arb_poly) + if arb_poly_divrem((q).val, (r).val, + (s).val, (t).val, getprec()): + return q, r + else: + raise ZeroDivisionError("arb_poly leading coefficient must be nonzero") + + def __rdivmod__(s, t): s, t = arb_poly_coerce_operands(s, t) if s is NotImplemented: return s - return divmod(s, t) + return divmod(t, s) def __pow__(arb_poly s, ulong exp, mod): if mod is not None: @@ -288,4 +318,3 @@ cdef class arb_poly(flint_poly): return u else: return None - diff --git a/src/flint/arb_series.pyx b/src/flint/arb_series.pyx index f489d417..7eff177b 100644 --- a/src/flint/arb_series.pyx +++ b/src/flint/arb_series.pyx @@ -1,14 +1,8 @@ cdef arb_series_coerce_operands(x, y): - if typecheck(x, arb_series): - if isinstance(y, (int, long, float, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly, fmpq_series, arb, arb_poly)): - return x, arb_series(y) - if isinstance(y, (complex, acb, acb_poly, acb_series)): - return acb_series(x), acb_series(y) - else: - if isinstance(x, (int, long, float, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly, fmpq_series, arb, arb_poly)): - return arb_series(x), y - if isinstance(x, (complex, acb, acb_poly, acb_series)): - return acb_series(x), acb_series(y) + if isinstance(y, (int, long, float, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly, fmpq_series, arb, arb_poly)): + return x, arb_series(y) + if isinstance(y, (complex, acb, acb_poly, acb_series)): + return acb_series(x), acb_series(y) return NotImplemented, NotImplemented cdef class arb_series(flint_series): @@ -96,53 +90,72 @@ cdef class arb_series(flint_series): def __add__(s, t): cdef long cap - if type(s) is type(t): - u = arb_series.__new__(arb_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - arb_poly_add((u).val, (s).val, (t).val, getprec()) - arb_poly_truncate((u).val, cap) - (u).prec = cap - return u + if not isinstance(t, arb_series): + s, t = arb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s + t + u = arb_series.__new__(arb_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + arb_poly_add((u).val, (s).val, (t).val, getprec()) + arb_poly_truncate((u).val, cap) + (u).prec = cap + return u + + def __radd__(s, t): s, t = arb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s + t + return t + s def __sub__(s, t): cdef long cap - if type(s) is type(t): - u = arb_series.__new__(arb_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - arb_poly_sub((u).val, (s).val, (t).val, getprec()) - arb_poly_truncate((u).val, cap) - (u).prec = cap - return u + if not isinstance(t, arb_series): + s, t = arb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s - t + u = arb_series.__new__(arb_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + arb_poly_sub((u).val, (s).val, (t).val, getprec()) + arb_poly_truncate((u).val, cap) + (u).prec = cap + return u + + def __rsub__(s, t): s, t = arb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s - t + return t - s def __mul__(s, t): cdef long cap - if type(s) is type(t): - u = arb_series.__new__(arb_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - arb_poly_mullow((u).val, (s).val, (t).val, cap, getprec()) - (u).prec = cap - return u + if not isinstance(t, arb_series): + s, t = arb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s * t + u = arb_series.__new__(arb_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + arb_poly_mul((u).val, (s).val, (t).val, getprec()) + arb_poly_truncate((u).val, cap) + (u).prec = cap + return u + + def __rmul__(s, t): s, t = arb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s * t + return t * s cpdef valuation(self): cdef long i @@ -153,76 +166,82 @@ cdef class arb_series(flint_series): i += 1 return i - @staticmethod - def _div_(s, t): + def __truediv__(s, t): cdef long cap, sval, tval cdef arb_poly_t stmp, ttmp - if type(s) is type(t): - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) + if not isinstance(t, arb_series): + s, t = arb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s / t - if (t).length() == 0: - raise ZeroDivisionError("power series division") + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) - u = arb_series.__new__(arb_series) + if (t).length() == 0: + raise ZeroDivisionError("power series division") - if (s).length() == 0: - u.cap = cap - return u + u = arb_series.__new__(arb_series) - sval = (s).valuation() - tval = (t).valuation() + if (s).length() == 0: + u.cap = cap + return u - if sval < tval: - raise ValueError("quotient would not be a power series") + sval = (s).valuation() + tval = (t).valuation() - if not arb_is_nonzero(&((t).val.coeffs[tval])): - raise ValueError("leading term in denominator is not nonzero") + if sval < tval: + raise ValueError("quotient would not be a power series") - if tval == 0: - arb_poly_div_series((u).val, (s).val, (t).val, cap, getprec()) - else: - arb_poly_init(stmp) - arb_poly_init(ttmp) - arb_poly_shift_right(stmp, (s).val, tval) - arb_poly_shift_right(ttmp, (t).val, tval) - cap -= tval - arb_poly_div_series((u).val, stmp, ttmp, cap, getprec()) - arb_poly_clear(stmp) - arb_poly_clear(ttmp) + if not arb_is_nonzero(&((t).val.coeffs[tval])): + raise ValueError("leading term in denominator is not nonzero") - (u).prec = cap - return u + if tval == 0: + arb_poly_div_series((u).val, (s).val, (t).val, cap, getprec()) + else: + arb_poly_init(stmp) + arb_poly_init(ttmp) + arb_poly_shift_right(stmp, (s).val, tval) + arb_poly_shift_right(ttmp, (t).val, tval) + cap -= tval + arb_poly_div_series((u).val, stmp, ttmp, cap, getprec()) + arb_poly_clear(stmp) + arb_poly_clear(ttmp) + + (u).prec = cap + return u + def __rtruediv__(s, t): s, t = arb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s / t - - def __truediv__(s, t): - return arb_series._div_(s, t) - - def __div__(s, t): - return arb_series._div_(s, t) + return t / s def __pow__(s, t, mod): cdef long cap if mod is not None: raise NotImplementedError("modular exponentiation") - if type(s) is type(t): - u = arb_series.__new__(arb_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - arb_poly_pow_series((u).val, (s).val, (t).val, cap, getprec()) - (u).prec = cap - return u + if not isinstance(t, arb_series): + s, t = arb_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s ** t + + u = arb_series.__new__(arb_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + arb_poly_pow_series((u).val, (s).val, (t).val, cap, getprec()) + (u).prec = cap + return u + + def __rpow__(s, t, mod): s, t = arb_series_coerce_operands(s, t) if s is NotImplemented: return s - return s ** t + return t ** s def __call__(s, t): cdef long cap diff --git a/src/flint/arf.pyx b/src/flint/arf.pyx index 72960eb5..9790218c 100644 --- a/src/flint/arf.pyx +++ b/src/flint/arf.pyx @@ -139,34 +139,29 @@ cdef class arf: return res def __add__(s, t): - if typecheck(s, arf): - if typecheck(t, arf): - u = arf.__new__(arf) - arf_add((u).val, (s).val, (t).val, getprec(), thectx.rnd) - return u - return NotImplemented + if not typecheck(t, arf): + return NotImplemented + u = arf.__new__(arf) + arf_add((u).val, (s).val, (t).val, getprec(), thectx.rnd) + return u def __sub__(s, t): - if typecheck(s, arf): - if typecheck(t, arf): - u = arf.__new__(arf) - arf_sub((u).val, (s).val, (t).val, getprec(), thectx.rnd) - return u - return NotImplemented + if not typecheck(t, arf): + return NotImplemented + u = arf.__new__(arf) + arf_sub((u).val, (s).val, (t).val, getprec(), thectx.rnd) + return u def __mul__(s, t): - if typecheck(s, arf): - if typecheck(t, arf): - u = arf.__new__(arf) - arf_mul((u).val, (s).val, (t).val, getprec(), thectx.rnd) - return u - return NotImplemented + if not typecheck(t, arf): + return NotImplemented + u = arf.__new__(arf) + arf_mul((u).val, (s).val, (t).val, getprec(), thectx.rnd) + return u def __div__(s, t): - if typecheck(s, arf): - if typecheck(t, arf): - u = arf.__new__(arf) - arf_div((u).val, (s).val, (t).val, getprec(), thectx.rnd) - return u - return NotImplemented - + if not typecheck(t, arf): + return NotImplemented + u = arf.__new__(arf) + arf_div((u).val, (s).val, (t).val, getprec(), thectx.rnd) + return u diff --git a/src/flint/fmpq.pyx b/src/flint/fmpq.pyx index 580053b2..f0f384f4 100644 --- a/src/flint/fmpq.pyx +++ b/src/flint/fmpq.pyx @@ -143,9 +143,6 @@ cdef class fmpq(flint_scalar): def __add__(s, t): cdef fmpq r - s = any_as_fmpq(s) - if s is NotImplemented: - return s t = any_as_fmpq(t) if t is NotImplemented: return t @@ -153,11 +150,17 @@ cdef class fmpq(flint_scalar): fmpq_add(r.val, (s).val, (t).val) return r + def __radd__(s, t): + cdef fmpq r + t = any_as_fmpq(t) + if t is NotImplemented: + return t + r = fmpq.__new__(fmpq) + fmpq_add(r.val, (t).val, (s).val) + return r + def __sub__(s, t): cdef fmpq r - s = any_as_fmpq(s) - if s is NotImplemented: - return s t = any_as_fmpq(t) if t is NotImplemented: return t @@ -165,11 +168,17 @@ cdef class fmpq(flint_scalar): fmpq_sub(r.val, (s).val, (t).val) return r + def __rsub__(s, t): + cdef fmpq r + t = any_as_fmpq(t) + if t is NotImplemented: + return t + r = fmpq.__new__(fmpq) + fmpq_sub(r.val, (t).val, (s).val) + return r + def __mul__(s, t): cdef fmpq r - s = any_as_fmpq(s) - if s is NotImplemented: - return s t = any_as_fmpq(t) if t is NotImplemented: return t @@ -177,6 +186,15 @@ cdef class fmpq(flint_scalar): fmpq_mul(r.val, (s).val, (t).val) return r + def __rmul__(s, t): + cdef fmpq r + t = any_as_fmpq(t) + if t is NotImplemented: + return t + r = fmpq.__new__(fmpq) + fmpq_mul(r.val, (t).val, (s).val) + return r + @staticmethod def _div_(s, t): cdef fmpq r @@ -195,8 +213,8 @@ cdef class fmpq(flint_scalar): def __truediv__(s, t): return fmpq._div_(s, t) - def __div__(s, t): - return fmpq._div_(s, t) + def __rtruediv__(s, t): + return fmpq._div_(t, s) def next(s, bint signed=True, bint minimal=True): """ diff --git a/src/flint/fmpq_mat.pyx b/src/flint/fmpq_mat.pyx index a259ba6e..e81875e4 100644 --- a/src/flint/fmpq_mat.pyx +++ b/src/flint/fmpq_mat.pyx @@ -145,9 +145,6 @@ cdef class fmpq_mat(flint_mat): cdef fmpq_mat u cdef fmpq_mat_struct *sval cdef fmpq_mat_struct *tval - s = any_as_fmpq_mat(s) - if s is NotImplemented: - return s t = any_as_fmpq_mat(t) if t is NotImplemented: return t @@ -165,9 +162,6 @@ cdef class fmpq_mat(flint_mat): cdef fmpq_mat u cdef fmpq_mat_struct *sval cdef fmpq_mat_struct *tval - s = any_as_fmpq_mat(s) - if s is NotImplemented: - return s t = any_as_fmpq_mat(t) if t is NotImplemented: return t @@ -225,30 +219,31 @@ cdef class fmpq_mat(flint_mat): def __mul__(s, t): cdef fmpz_mat u - if typecheck(s, fmpq_mat): - if typecheck(t, fmpq_mat): - return (s).__mul_fmpq_mat(t) - elif typecheck(t, fmpz_mat): - return (s).__mul_fmpz_mat(t) - else: - c = any_as_fmpz(t) - if c is not NotImplemented: - return (s).__mul_fmpz(c) - c = any_as_fmpq(t) - if c is not NotImplemented: - return (s).__mul_fmpq(c) - return NotImplemented + if typecheck(t, fmpq_mat): + return (s).__mul_fmpq_mat(t) + elif typecheck(t, fmpz_mat): + return (s).__mul_fmpz_mat(t) else: - if typecheck(s, fmpz_mat): - return (t).__mul_r_fmpz_mat(s) - else: - c = any_as_fmpz(s) - if c is not NotImplemented: - return (t).__mul_fmpz(c) - c = any_as_fmpq(s) - if c is not NotImplemented: - return (t).__mul_fmpq(c) - return NotImplemented + c = any_as_fmpz(t) + if c is not NotImplemented: + return (s).__mul_fmpz(c) + c = any_as_fmpq(t) + if c is not NotImplemented: + return (s).__mul_fmpq(c) + return NotImplemented + + def __rmul__(s, t): + cdef fmpz_mat u + if typecheck(t, fmpz_mat): + return (s).__mul_r_fmpz_mat(t) + else: + c = any_as_fmpz(t) + if c is not NotImplemented: + return (s).__mul_fmpz(c) + c = any_as_fmpq(t) + if c is not NotImplemented: + return (s).__mul_fmpq(c) + return NotImplemented @staticmethod def _div_(fmpq_mat s, t): diff --git a/src/flint/fmpq_poly.pyx b/src/flint/fmpq_poly.pyx index 892c20a2..c3e68cef 100644 --- a/src/flint/fmpq_poly.pyx +++ b/src/flint/fmpq_poly.pyx @@ -176,11 +176,8 @@ cdef class fmpq_poly(flint_poly): fmpq_poly_neg(res.val, self.val) return res - def __add__(s, t): + def _add_(s, t): cdef fmpq_poly r - s = any_as_fmpq_poly(s) - if s is NotImplemented: - return s t = any_as_fmpq_poly(t) if t is NotImplemented: return t @@ -188,23 +185,32 @@ cdef class fmpq_poly(flint_poly): fmpq_poly_add(r.val, (s).val, (t).val) return r - def __sub__(s, t): + def __add__(s, t): + return s._add_(t) + + def __radd__(s, t): + return s._add_(t) + + def _sub_(s, t): cdef fmpq_poly r - s = any_as_fmpq_poly(s) - if s is NotImplemented: - return s - t = any_as_fmpq_poly(t) - if t is NotImplemented: - return t r = fmpq_poly.__new__(fmpq_poly) fmpq_poly_sub(r.val, (s).val, (t).val) return r - def __mul__(s, t): + def __sub__(s, t): + t = any_as_fmpq_poly(t) + if t is NotImplemented: + return t + return s._sub_(t) + + def __rsub__(s, t): + t = any_as_fmpq_poly(t) + if t is NotImplemented: + return t + return t._sub_(s) + + def _mul_(s, t): cdef fmpq_poly r - s = any_as_fmpq_poly(s) - if s is NotImplemented: - return s t = any_as_fmpq_poly(t) if t is NotImplemented: return t @@ -212,34 +218,56 @@ cdef class fmpq_poly(flint_poly): fmpq_poly_mul(r.val, (s).val, (t).val) return r - def __floordiv__(s, t): + def __mul__(s, t): + return s._mul_(t) + + def __rmul__(s, t): + return s._mul_(t) + + def _floordiv_(s, t): cdef fmpq_poly r - s = any_as_fmpq_poly(s) - if s is NotImplemented: - return s - t = any_as_fmpq_poly(t) - if t is NotImplemented: - return t if fmpq_poly_is_zero((t).val): raise ZeroDivisionError("fmpq_poly division by 0") r = fmpq_poly.__new__(fmpq_poly) fmpq_poly_div(r.val, (s).val, (t).val) return r - def __mod__(s, t): + def __floordiv__(s, t): + cdef fmpq_poly r + t = any_as_fmpq_poly(t) + if t is NotImplemented: + return t + return s._floordiv_(t) + + def __rfloordiv__(s, t): cdef fmpq_poly r - s = any_as_fmpq_poly(s) - if s is NotImplemented: - return s t = any_as_fmpq_poly(t) if t is NotImplemented: return t + return t._floordiv_(s) + + def _mod_(s, t): + cdef fmpq_poly r if fmpq_poly_is_zero((t).val): raise ZeroDivisionError("fmpq_poly division by 0") r = fmpq_poly.__new__(fmpq_poly) fmpq_poly_rem(r.val, (s).val, (t).val) return r + def __mod__(s, t): + cdef fmpq_poly r + t = any_as_fmpq_poly(t) + if t is NotImplemented: + return t + return s._mod_(t) + + def __rmod__(s, t): + cdef fmpq_poly r + t = any_as_fmpq_poly(t) + if t is NotImplemented: + return t + return t._mod_(s) + @staticmethod def _div_(fmpq_poly s, t): cdef fmpq_poly r @@ -258,14 +286,8 @@ cdef class fmpq_poly(flint_poly): def __truediv__(s, t): return fmpq_poly._div_(s, t) - def __divmod__(s, t): + def _divmod_(s, t): cdef fmpq_poly P, Q - s = any_as_fmpq_poly(s) - if s is NotImplemented: - return s - t = any_as_fmpq_poly(t) - if t is NotImplemented: - return t if fmpq_poly_is_zero((t).val): raise ZeroDivisionError("fmpq_poly divmod by 0") P = fmpq_poly.__new__(fmpq_poly) @@ -273,6 +295,18 @@ cdef class fmpq_poly(flint_poly): fmpq_poly_divrem(P.val, Q.val, (s).val, (t).val) return P, Q + def __divmod__(s, t): + t = any_as_fmpq_poly(t) + if t is NotImplemented: + return t + return s._divmod_(t) + + def __rdivmod__(s, t): + t = any_as_fmpq_poly(t) + if t is NotImplemented: + return t + return t._divmod_(s) + def __pow__(fmpq_poly self, ulong exp, mod): cdef fmpq_poly res if mod is not None: diff --git a/src/flint/fmpq_series.pyx b/src/flint/fmpq_series.pyx index 6fcbeb29..a5300ddc 100644 --- a/src/flint/fmpq_series.pyx +++ b/src/flint/fmpq_series.pyx @@ -1,22 +1,12 @@ cdef fmpq_series_coerce_operands(x, y): - if typecheck(x, fmpq_series): - if isinstance(y, (int, long, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly)): - return x, fmpq_series(y) - #if isinstance(y, (nmod, nmod_poly, nmod_series)): - # return nmod_series(x), nmod_series(y) - if isinstance(y, (float, arb, arb_poly, arb_series)): - return arb_series(x), arb_series(y) - if isinstance(y, (complex, acb, acb_poly, acb_series)): - return acb_series(x), acb_series(y) - else: - if isinstance(x,(int, long, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly)): - return fmpq_series(x), y - #if isinstance(x, (nmod, nmod_poly, nmod_series)): - # return nmod_series(x), nmod_series(y) - if isinstance(x, (float, arb, arb_poly, arb_series)): - return arb_series(x), arb_series(y) - if isinstance(x, (complex, acb, acb_poly, acb_series)): - return acb_series(x), acb_series(y) + if isinstance(y, (int, long, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly)): + return x, fmpq_series(y) + #if isinstance(y, (nmod, nmod_poly, nmod_series)): + # return nmod_series(x), nmod_series(y) + if isinstance(y, (float, arb, arb_poly, arb_series)): + return arb_series(x), arb_series(y) + if isinstance(y, (complex, acb, acb_poly, acb_series)): + return acb_series(x), acb_series(y) return NotImplemented, NotImplemented cdef class fmpq_series(flint_series): @@ -133,54 +123,72 @@ cdef class fmpq_series(flint_series): return u def __add__(s, t): + if not isinstance(t, fmpq_series): + s, t = fmpq_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s + t cdef long cap - if type(s) is type(t): - u = fmpq_series.__new__(fmpq_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - fmpq_poly_add((u).val, (s).val, (t).val) - fmpq_poly_truncate((u).val, cap) - (u).prec = cap - return u + u = fmpq_series.__new__(fmpq_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + fmpq_poly_add((u).val, (s).val, (t).val) + fmpq_poly_truncate((u).val, cap) + (u).prec = cap + return u + + def __radd__(s, t): s, t = fmpq_series_coerce_operands(s, t) if s is NotImplemented: return s - return s + t + return t + s def __sub__(s, t): + if not isinstance(t, fmpq_series): + s, t = fmpq_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s - t cdef long cap - if type(s) is type(t): - u = fmpq_series.__new__(fmpq_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - fmpq_poly_sub((u).val, (s).val, (t).val) - fmpq_poly_truncate((u).val, cap) - (u).prec = cap - return u + u = fmpq_series.__new__(fmpq_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + fmpq_poly_sub((u).val, (s).val, (t).val) + fmpq_poly_truncate((u).val, cap) + (u).prec = cap + return u + + def __rsub__(s, t): s, t = fmpq_series_coerce_operands(s, t) if s is NotImplemented: return s - return s - t + return t - s def __mul__(s, t): + if not isinstance(t, fmpq_series): + s, t = fmpq_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s * t cdef long cap - if type(s) is type(t): - u = fmpq_series.__new__(fmpq_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - fmpq_poly_mullow((u).val, (s).val, (t).val, cap) - (u).prec = cap - return u + u = fmpq_series.__new__(fmpq_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + fmpq_poly_mullow((u).val, (s).val, (t).val, cap) + (u).prec = cap + return u + + def __rmul__(s, t): s, t = fmpq_series_coerce_operands(s, t) if s is NotImplemented: return s - return s * t + return t * s cpdef valuation(self): cdef long i @@ -195,54 +203,56 @@ cdef class fmpq_series(flint_series): def _div_(s, t): cdef long cap, sval, tval cdef fmpq_poly_t stmp, ttmp - if type(s) is type(t): - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - - if fmpq_poly_is_zero((t).val): - raise ZeroDivisionError("power series division") + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) - u = fmpq_series.__new__(fmpq_series) + if fmpq_poly_is_zero((t).val): + raise ZeroDivisionError("power series division") - if fmpq_poly_is_zero((s).val): - (u).prec = cap - return u + u = fmpq_series.__new__(fmpq_series) - sval = (s).valuation() - tval = (t).valuation() + if fmpq_poly_is_zero((s).val): + (u).prec = cap + return u - if sval < tval: - raise ValueError("quotient would not be a power series") + sval = (s).valuation() + tval = (t).valuation() - if fmpz_is_zero(&((t).val.coeffs[tval])): - raise ValueError("leading term in denominator is not a unit") + if sval < tval: + raise ValueError("quotient would not be a power series") - if tval == 0: - fmpq_poly_div_series((u).val, (s).val, (t).val, cap) - else: - fmpq_poly_init(stmp) - fmpq_poly_init(ttmp) - fmpq_poly_shift_right(stmp, (s).val, tval) - fmpq_poly_shift_right(ttmp, (t).val, tval) - cap -= tval - fmpq_poly_div_series((u).val, stmp, ttmp, cap) - fmpq_poly_clear(stmp) - fmpq_poly_clear(ttmp) + if fmpz_is_zero(&((t).val.coeffs[tval])): + raise ValueError("leading term in denominator is not a unit") - (u).prec = cap - return u + if tval == 0: + fmpq_poly_div_series((u).val, (s).val, (t).val, cap) + else: + fmpq_poly_init(stmp) + fmpq_poly_init(ttmp) + fmpq_poly_shift_right(stmp, (s).val, tval) + fmpq_poly_shift_right(ttmp, (t).val, tval) + cap -= tval + fmpq_poly_div_series((u).val, stmp, ttmp, cap) + fmpq_poly_clear(stmp) + fmpq_poly_clear(ttmp) - s, t = fmpq_series_coerce_operands(s, t) - if s is NotImplemented: - return s - return s / t + (u).prec = cap + return u def __truediv__(s, t): + if not isinstance(t, fmpq_series): + s, t = fmpq_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s / t return fmpq_series._div_(s, t) - def __div__(s, t): - return fmpq_series._div_(s, t) + def __rtruediv__(s, t): + s, t = fmpq_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return t / s # generic exponentiation (fallback code) # XXX: use fmpq_poly_pow_trunc instead? diff --git a/src/flint/fmpz.pyx b/src/flint/fmpz.pyx index dd2703b5..ee689de0 100644 --- a/src/flint/fmpz.pyx +++ b/src/flint/fmpz.pyx @@ -174,57 +174,73 @@ cdef class fmpz(flint_scalar): return -self def __add__(s, t): - cdef fmpz_struct sval[1] cdef fmpz_struct tval[1] - cdef int stype = FMPZ_UNKNOWN cdef int ttype = FMPZ_UNKNOWN u = NotImplemented - stype = fmpz_set_any_ref(sval, s) - if stype != FMPZ_UNKNOWN: - ttype = fmpz_set_any_ref(tval, t) - if ttype != FMPZ_UNKNOWN: - u = fmpz.__new__(fmpz) - fmpz_add((u).val, sval, tval) - if stype == FMPZ_TMP: fmpz_clear(sval) + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: + u = fmpz.__new__(fmpz) + fmpz_add((u).val, (s).val, tval) + if ttype == FMPZ_TMP: fmpz_clear(tval) + return u + + def __radd__(s, t): + cdef fmpz_struct tval[1] + cdef int ttype = FMPZ_UNKNOWN + u = NotImplemented + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: + u = fmpz.__new__(fmpz) + fmpz_add((u).val, tval, (s).val) if ttype == FMPZ_TMP: fmpz_clear(tval) return u def __sub__(s, t): - cdef fmpz_struct sval[1] cdef fmpz_struct tval[1] - cdef int stype = FMPZ_UNKNOWN cdef int ttype = FMPZ_UNKNOWN u = NotImplemented - stype = fmpz_set_any_ref(sval, s) - if stype != FMPZ_UNKNOWN: - ttype = fmpz_set_any_ref(tval, t) - if ttype != FMPZ_UNKNOWN: - u = fmpz.__new__(fmpz) - fmpz_sub((u).val, sval, tval) - if stype == FMPZ_TMP: fmpz_clear(sval) + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: + u = fmpz.__new__(fmpz) + fmpz_sub((u).val, (s).val, tval) + if ttype == FMPZ_TMP: fmpz_clear(tval) + return u + + def __rsub__(s, t): + cdef fmpz_struct tval[1] + cdef int ttype = FMPZ_UNKNOWN + u = NotImplemented + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: + u = fmpz.__new__(fmpz) + fmpz_sub((u).val, tval, (s).val) if ttype == FMPZ_TMP: fmpz_clear(tval) return u def __mul__(s, t): - cdef fmpz_struct sval[1] cdef fmpz_struct tval[1] - cdef int stype = FMPZ_UNKNOWN cdef int ttype = FMPZ_UNKNOWN u = NotImplemented - stype = fmpz_set_any_ref(sval, s) - if stype != FMPZ_UNKNOWN: - ttype = fmpz_set_any_ref(tval, t) - if ttype != FMPZ_UNKNOWN: - u = fmpz.__new__(fmpz) - fmpz_mul((u).val, sval, tval) - if stype == FMPZ_TMP: fmpz_clear(sval) + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: + u = fmpz.__new__(fmpz) + fmpz_mul((u).val, (s).val, tval) + if ttype == FMPZ_TMP: fmpz_clear(tval) + return u + + def __rmul__(s, t): + cdef fmpz_struct tval[1] + cdef int ttype = FMPZ_UNKNOWN + u = NotImplemented + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: + u = fmpz.__new__(fmpz) + fmpz_mul((u).val, tval, (s).val) if ttype == FMPZ_TMP: fmpz_clear(tval) return u def __floordiv__(s, t): - cdef fmpz_struct sval[1] cdef fmpz_struct tval[1] - cdef int stype = FMPZ_UNKNOWN cdef int ttype = FMPZ_UNKNOWN u = NotImplemented ttype = fmpz_set_any_ref(tval, t) @@ -233,18 +249,28 @@ cdef class fmpz(flint_scalar): if ttype == FMPZ_TMP: fmpz_clear(tval) raise ZeroDivisionError("fmpz division by zero") - stype = fmpz_set_any_ref(sval, s) - if stype != FMPZ_UNKNOWN: - u = fmpz.__new__(fmpz) - fmpz_fdiv_q((u).val, sval, tval) - if stype == FMPZ_TMP: fmpz_clear(sval) + u = fmpz.__new__(fmpz) + fmpz_fdiv_q((u).val, (s).val, tval) + if ttype == FMPZ_TMP: fmpz_clear(tval) + return u + + def __rfloordiv__(s, t): + cdef fmpz_struct tval[1] + cdef int ttype = FMPZ_UNKNOWN + u = NotImplemented + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: + if fmpz_is_zero((s).val): + if ttype == FMPZ_TMP: + fmpz_clear(tval) + raise ZeroDivisionError("fmpz division by zero") + u = fmpz.__new__(fmpz) + fmpz_fdiv_q((u).val, tval, (s).val) if ttype == FMPZ_TMP: fmpz_clear(tval) return u def __mod__(s, t): - cdef fmpz_struct sval[1] cdef fmpz_struct tval[1] - cdef int stype = FMPZ_UNKNOWN cdef int ttype = FMPZ_UNKNOWN u = NotImplemented ttype = fmpz_set_any_ref(tval, t) @@ -253,18 +279,28 @@ cdef class fmpz(flint_scalar): if ttype == FMPZ_TMP: fmpz_clear(tval) raise ZeroDivisionError("fmpz division by zero") - stype = fmpz_set_any_ref(sval, s) - if stype != FMPZ_UNKNOWN: - u = fmpz.__new__(fmpz) - fmpz_fdiv_r((u).val, sval, tval) - if stype == FMPZ_TMP: fmpz_clear(sval) + u = fmpz.__new__(fmpz) + fmpz_fdiv_r((u).val, (s).val, tval) + if ttype == FMPZ_TMP: fmpz_clear(tval) + return u + + def __rmod__(s, t): + cdef fmpz_struct tval[1] + cdef int ttype = FMPZ_UNKNOWN + u = NotImplemented + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: + if fmpz_is_zero((s).val): + if ttype == FMPZ_TMP: + fmpz_clear(tval) + raise ZeroDivisionError("fmpz division by zero") + u = fmpz.__new__(fmpz) + fmpz_fdiv_r((u).val, tval, (s).val) if ttype == FMPZ_TMP: fmpz_clear(tval) return u def __divmod__(s, t): - cdef fmpz_struct sval[1] cdef fmpz_struct tval[1] - cdef int stype = FMPZ_UNKNOWN cdef int ttype = FMPZ_UNKNOWN u = NotImplemented ttype = fmpz_set_any_ref(tval, t) @@ -273,29 +309,53 @@ cdef class fmpz(flint_scalar): if ttype == FMPZ_TMP: fmpz_clear(tval) raise ZeroDivisionError("fmpz division by zero") - stype = fmpz_set_any_ref(sval, s) - if stype != FMPZ_UNKNOWN: - u1 = fmpz.__new__(fmpz) - u2 = fmpz.__new__(fmpz) - fmpz_fdiv_qr((u1).val, (u2).val, sval, tval) - u = u1, u2 - if stype == FMPZ_TMP: fmpz_clear(sval) + u1 = fmpz.__new__(fmpz) + u2 = fmpz.__new__(fmpz) + fmpz_fdiv_qr((u1).val, (u2).val, (s).val, tval) + u = u1, u2 + if ttype == FMPZ_TMP: fmpz_clear(tval) + return u + + def __rdivmod__(s, t): + cdef fmpz_struct tval[1] + cdef int ttype = FMPZ_UNKNOWN + u = NotImplemented + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: + if fmpz_is_zero((s).val): + if ttype == FMPZ_TMP: + fmpz_clear(tval) + raise ZeroDivisionError("fmpz division by zero") + u1 = fmpz.__new__(fmpz) + u2 = fmpz.__new__(fmpz) + fmpz_fdiv_qr((u1).val, (u2).val, tval, (s).val) + u = u1, u2 if ttype == FMPZ_TMP: fmpz_clear(tval) return u def __pow__(s, t, m): - cdef fmpz_struct sval[1] + cdef ulong exp + u = NotImplemented + if m is not None: + raise NotImplementedError("modular exponentiation") + c = t + u = fmpz.__new__(fmpz) + fmpz_pow_ui((u).val, (s).val, c) + return u + + def __rpow__(s, t, m): + cdef fmpz_struct tval[1] cdef int stype = FMPZ_UNKNOWN cdef ulong exp u = NotImplemented if m is not None: raise NotImplementedError("modular exponentiation") - stype = fmpz_set_any_ref(sval, s) - if stype != FMPZ_UNKNOWN: - c = t + ttype = fmpz_set_any_ref(tval, t) + if ttype != FMPZ_UNKNOWN: u = fmpz.__new__(fmpz) - fmpz_pow_ui((u).val, sval, c) - if stype == FMPZ_TMP: fmpz_clear(sval) + s_ulong = fmpz_get_ui(s.val) + fmpz_pow_ui((u).val, tval, s_ulong) + if ttype == FMPZ_TMP: fmpz_clear(tval) return u def gcd(self, other): diff --git a/src/flint/fmpz_mat.pyx b/src/flint/fmpz_mat.pyx index 1f18520f..1ff56ab7 100644 --- a/src/flint/fmpz_mat.pyx +++ b/src/flint/fmpz_mat.pyx @@ -190,9 +190,6 @@ cdef class fmpz_mat(flint_mat): cdef fmpz_mat u cdef fmpz_mat_struct *sval cdef fmpz_mat_struct *tval - sm = any_as_fmpz_mat(s) - if sm is NotImplemented: - return sm tm = any_as_fmpz_mat(t) if tm is NotImplemented: return tm @@ -210,9 +207,6 @@ cdef class fmpz_mat(flint_mat): cdef fmpz_mat u cdef fmpz_mat_struct *sval cdef fmpz_mat_struct *tval - sm = any_as_fmpz_mat(s) - if sm is NotImplemented: - return sm tm = any_as_fmpz_mat(t) if tm is NotImplemented: return tm @@ -238,7 +232,7 @@ cdef class fmpz_mat(flint_mat): cdef fmpz_mat_struct *sval cdef fmpz_mat_struct *tval cdef int ttype - if typecheck(s, fmpz_mat) and typecheck(t, fmpz_mat): + if typecheck(t, fmpz_mat): sval = &(s).val[0] tval = &(t).val[0] if fmpz_mat_ncols(sval) != fmpz_mat_nrows(tval): @@ -248,8 +242,6 @@ cdef class fmpz_mat(flint_mat): fmpz_mat_mul(u.val, sval, tval) return u else: - if typecheck(t, fmpz_mat): - s, t = t, s c = any_as_fmpz(t) if c is not NotImplemented: return (s).__mul_fmpz(c) @@ -259,6 +251,16 @@ cdef class fmpz_mat(flint_mat): return fmpq_mat(s) * t return NotImplemented + def __rmul__(s, t): + c = any_as_fmpz(t) + if c is not NotImplemented: + return (s).__mul_fmpz(c) + c = any_as_fmpq(t) + if c is not NotImplemented: + # XXX: improve this + return fmpq_mat(s) * t + return NotImplemented + @staticmethod def _div_(fmpz_mat s, t): return s * (1 / fmpq(t)) diff --git a/src/flint/fmpz_poly.pyx b/src/flint/fmpz_poly.pyx index 69549d6a..3f570ca4 100644 --- a/src/flint/fmpz_poly.pyx +++ b/src/flint/fmpz_poly.pyx @@ -147,11 +147,8 @@ cdef class fmpz_poly(flint_poly): fmpz_poly_neg(res.val, self.val) return res - def __add__(self, other): + def _add_(self, other): cdef fmpz_poly res - self = any_as_fmpz_poly(self) - if self is NotImplemented: - return self other = any_as_fmpz_poly(other) if other is NotImplemented: return other @@ -159,11 +156,14 @@ cdef class fmpz_poly(flint_poly): fmpz_poly_add(res.val, (self).val, (other).val) return res + def __add__(self, other): + return self._add_(other) + + def __radd__(self, other): + return self._add_(other) + def __sub__(self, other): cdef fmpz_poly res - self = any_as_fmpz_poly(self) - if self is NotImplemented: - return self other = any_as_fmpz_poly(other) if other is NotImplemented: return other @@ -171,54 +171,72 @@ cdef class fmpz_poly(flint_poly): fmpz_poly_sub(res.val, (self).val, (other).val) return res - def __mul__(self, other): + def __rsub__(self, other): cdef fmpz_poly res - self = any_as_fmpz_poly(self) - if self is NotImplemented: - return self other = any_as_fmpz_poly(other) if other is NotImplemented: return other res = fmpz_poly.__new__(fmpz_poly) - fmpz_poly_mul(res.val, (self).val, (other).val) + fmpz_poly_sub(res.val, (other).val, (self).val) return res - def __floordiv__(self, other): + def _mul_(self, other): cdef fmpz_poly res - self = any_as_fmpz_poly(self) - if self is NotImplemented: - return self other = any_as_fmpz_poly(other) if other is NotImplemented: return other + res = fmpz_poly.__new__(fmpz_poly) + fmpz_poly_mul(res.val, (self).val, (other).val) + return res + + def __mul__(self, other): + return self._mul_(other) + + def __rmul__(self, other): + return self._mul_(other) + + def _floordiv_(self, other): + cdef fmpz_poly res if fmpz_poly_is_zero((other).val): raise ZeroDivisionError("fmpz_poly division by 0") res = fmpz_poly.__new__(fmpz_poly) fmpz_poly_div(res.val, (self).val, (other).val) return res - def __mod__(self, other): - cdef fmpz_poly res - self = any_as_fmpz_poly(self) - if self is NotImplemented: - return self + def __floordiv__(self, other): + other = any_as_fmpz_poly(other) + if other is NotImplemented: + return other + return self._floordiv_(other) + + def __rfloordiv__(self, other): other = any_as_fmpz_poly(other) if other is NotImplemented: return other + return other._floordiv_(self) + + def _mod_(self, other): + cdef fmpz_poly res if fmpz_poly_is_zero((other).val): raise ZeroDivisionError("fmpz_poly division by 0") res = fmpz_poly.__new__(fmpz_poly) fmpz_poly_rem(res.val, (self).val, (other).val) return res - def __divmod__(self, other): - cdef fmpz_poly P, Q - self = any_as_fmpz_poly(self) - if self is NotImplemented: - return self + def __mod__(self, other): other = any_as_fmpz_poly(other) if other is NotImplemented: return other + return self._mod_(other) + + def __rmod__(self, other): + other = any_as_fmpz_poly(other) + if other is NotImplemented: + return other + return other._mod_(self) + + def _divmod_(self, other): + cdef fmpz_poly P, Q if fmpz_poly_is_zero((other).val): raise ZeroDivisionError("fmpz_poly divmod by 0") P = fmpz_poly.__new__(fmpz_poly) @@ -226,6 +244,18 @@ cdef class fmpz_poly(flint_poly): fmpz_poly_divrem(P.val, Q.val, (self).val, (other).val) return P, Q + def __divmod__(self, other): + other = any_as_fmpz_poly(other) + if other is NotImplemented: + return other + return self._divmod_(other) + + def __rdivmod__(self, other): + other = any_as_fmpz_poly(other) + if other is NotImplemented: + return other + return other._divmod_(self) + def __pow__(fmpz_poly self, ulong exp, mod): cdef fmpz_poly res if mod is not None: diff --git a/src/flint/fmpz_series.pyx b/src/flint/fmpz_series.pyx index 4cfa0d56..c8f31343 100644 --- a/src/flint/fmpz_series.pyx +++ b/src/flint/fmpz_series.pyx @@ -1,26 +1,14 @@ cdef fmpz_series_coerce_operands(x, y): - if typecheck(x, fmpz_series): - if isinstance(y, (int, long, fmpz, fmpz_poly)): - return x, fmpz_series(y) - if isinstance(y, (fmpq, fmpq_poly, fmpq_series)): - return fmpq_series(x), fmpq_series(y) - #if isinstance(y, (nmod, nmod_poly, nmod_series)): - # return nmod_series(x), nmod_series(y) - if isinstance(y, (float, arb, arb_poly, arb_series)): - return arb_series(x), arb_series(y) - if isinstance(y, (complex, acb, acb_poly, acb_series)): - return acb_series(x), acb_series(y) - else: - if isinstance(x, (int, long, fmpz, fmpz_poly)): - return fmpz_series(x), y - if isinstance(x, (fmpq, fmpq_poly, fmpq_series)): - return fmpq_series(x), fmpq_series(y) - #if isinstance(x, (nmod, nmod_poly, nmod_series)): - # return nmod_series(x), nmod_series(y) - if isinstance(x, (float, arb, arb_poly, arb_series)): - return arb_series(x), arb_series(y) - if isinstance(x, (complex, acb, acb_poly, acb_series)): - return acb_series(x), acb_series(y) + if isinstance(y, (int, long, fmpz, fmpz_poly)): + return x, fmpz_series(y) + if isinstance(y, (fmpq, fmpq_poly, fmpq_series)): + return fmpq_series(x), fmpq_series(y) + #if isinstance(y, (nmod, nmod_poly, nmod_series)): + # return nmod_series(x), nmod_series(y) + if isinstance(y, (float, arb, arb_poly, arb_series)): + return arb_series(x), arb_series(y) + if isinstance(y, (complex, acb, acb_poly, acb_series)): + return acb_series(x), acb_series(y) return NotImplemented, NotImplemented cdef class fmpz_series(flint_series): @@ -124,54 +112,72 @@ cdef class fmpz_series(flint_series): return u def __add__(s, t): + if not isinstance(t, fmpz_series): + s, t = fmpz_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s + t cdef long cap - if type(s) is type(t): - u = fmpz_series.__new__(fmpz_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - fmpz_poly_add((u).val, (s).val, (t).val) - fmpz_poly_truncate((u).val, cap) - (u).prec = cap - return u + u = fmpz_series.__new__(fmpz_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + fmpz_poly_add((u).val, (s).val, (t).val) + fmpz_poly_truncate((u).val, cap) + (u).prec = cap + return u + + def __radd__(s, t): s, t = fmpz_series_coerce_operands(s, t) if s is NotImplemented: return s - return s + t + return t + s def __sub__(s, t): + if not isinstance(t, fmpz_series): + s, t = fmpz_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s - t cdef long cap - if type(s) is type(t): - u = fmpz_series.__new__(fmpz_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - fmpz_poly_sub((u).val, (s).val, (t).val) - fmpz_poly_truncate((u).val, cap) - (u).prec = cap - return u + u = fmpz_series.__new__(fmpz_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + fmpz_poly_sub((u).val, (s).val, (t).val) + fmpz_poly_truncate((u).val, cap) + (u).prec = cap + return u + + def __rsub__(s, t): s, t = fmpz_series_coerce_operands(s, t) if s is NotImplemented: return s - return s - t + return t - s def __mul__(s, t): + if not isinstance(t, fmpz_series): + s, t = fmpz_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return s * t cdef long cap - if type(s) is type(t): - u = fmpz_series.__new__(fmpz_series) - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) - if cap > 0: - fmpz_poly_mullow((u).val, (s).val, (t).val, cap) - (u).prec = cap - return u + u = fmpz_series.__new__(fmpz_series) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) + if cap > 0: + fmpz_poly_mullow((u).val, (s).val, (t).val, cap) + (u).prec = cap + return u + + def __rmul__(s, t): s, t = fmpz_series_coerce_operands(s, t) if s is NotImplemented: return s - return s * t + return t * s cpdef valuation(self): """ @@ -215,54 +221,56 @@ cdef class fmpz_series(flint_series): """ cdef long cap, sval, tval cdef fmpz_poly_t stmp, ttmp - if type(s) is type(t): - cap = getcap() - cap = min(cap, (s).prec) - cap = min(cap, (t).prec) + cap = getcap() + cap = min(cap, (s).prec) + cap = min(cap, (t).prec) - if fmpz_poly_is_zero((t).val): - raise ZeroDivisionError("power series division") + if fmpz_poly_is_zero((t).val): + raise ZeroDivisionError("power series division") - u = fmpz_series.__new__(fmpz_series) + u = fmpz_series.__new__(fmpz_series) - if fmpz_poly_is_zero((s).val): - (u).prec = cap - return u + if fmpz_poly_is_zero((s).val): + (u).prec = cap + return u - sval = (s).valuation() - tval = (t).valuation() + sval = (s).valuation() + tval = (t).valuation() - if sval < tval: - raise ValueError("quotient would not be a power series") + if sval < tval: + raise ValueError("quotient would not be a power series") - if not fmpz_is_pm1(fmpz_poly_get_coeff_ptr((t).val, tval)): - raise ValueError("leading term in denominator is not a unit") + if not fmpz_is_pm1(fmpz_poly_get_coeff_ptr((t).val, tval)): + raise ValueError("leading term in denominator is not a unit") - if tval == 0: - fmpz_poly_div_series((u).val, (s).val, (t).val, cap) - else: - fmpz_poly_init(stmp) - fmpz_poly_init(ttmp) - fmpz_poly_shift_right(stmp, (s).val, tval) - fmpz_poly_shift_right(ttmp, (t).val, tval) - cap -= tval - fmpz_poly_div_series((u).val, stmp, ttmp, cap) - fmpz_poly_clear(stmp) - fmpz_poly_clear(ttmp) + if tval == 0: + fmpz_poly_div_series((u).val, (s).val, (t).val, cap) + else: + fmpz_poly_init(stmp) + fmpz_poly_init(ttmp) + fmpz_poly_shift_right(stmp, (s).val, tval) + fmpz_poly_shift_right(ttmp, (t).val, tval) + cap -= tval + fmpz_poly_div_series((u).val, stmp, ttmp, cap) + fmpz_poly_clear(stmp) + fmpz_poly_clear(ttmp) - (u).prec = cap - return u + (u).prec = cap + return u + def __truediv__(s, t): + if isinstance(t, fmpz_series): + return fmpz_series._div_(s, t) s, t = fmpz_series_coerce_operands(s, t) if s is NotImplemented: return s return s / t - def __div__(s, t): - return fmpz_series._div_(s, t) - - def __truediv__(s, t): - return fmpz_series._div_(s, t) + def __rtruediv__(s, t): + s, t = fmpz_series_coerce_operands(s, t) + if s is NotImplemented: + return s + return t / s def __pow__(fmpz_series s, ulong exp, mod): """ diff --git a/src/flint/nmod.pyx b/src/flint/nmod.pyx index 4ecd97f5..75bce0c3 100644 --- a/src/flint/nmod.pyx +++ b/src/flint/nmod.pyx @@ -85,8 +85,6 @@ cdef class nmod(flint_scalar): def __add__(s, t): cdef nmod r cdef mp_limb_t val - if not typecheck(s, nmod): - s, t = t, s if any_as_nmod(&val, t, (s).mod): r = nmod.__new__(nmod) r.mod = (s).mod @@ -94,28 +92,39 @@ cdef class nmod(flint_scalar): return r return NotImplemented + def __radd__(s, t): + cdef nmod r + cdef mp_limb_t val + if any_as_nmod(&val, t, (s).mod): + r = nmod.__new__(nmod) + r.mod = (s).mod + r.val = nmod_add((s).val, val, r.mod) + return r + return NotImplemented + def __sub__(s, t): cdef nmod r cdef mp_limb_t val - if typecheck(s, nmod): - if any_as_nmod(&val, t, (s).mod): - r = nmod.__new__(nmod) - r.mod = (s).mod - r.val = nmod_sub((s).val, val, r.mod) - return r - else: - if any_as_nmod(&val, s, (t).mod): - r = nmod.__new__(nmod) - r.mod = (t).mod - r.val = nmod_sub(val, (t).val, r.mod) - return r + if any_as_nmod(&val, t, (s).mod): + r = nmod.__new__(nmod) + r.mod = (s).mod + r.val = nmod_sub((s).val, val, r.mod) + return r + return NotImplemented + + def __rsub__(s, t): + cdef nmod r + cdef mp_limb_t val + if any_as_nmod(&val, t, (s).mod): + r = nmod.__new__(nmod) + r.mod = (s).mod + r.val = nmod_sub(val, (s).val, r.mod) + return r return NotImplemented def __mul__(s, t): cdef nmod r cdef mp_limb_t val - if not typecheck(s, nmod): - s, t = t, s if any_as_nmod(&val, t, (s).mod): r = nmod.__new__(nmod) r.mod = (s).mod @@ -123,6 +132,16 @@ cdef class nmod(flint_scalar): return r return NotImplemented + def __rmul__(s, t): + cdef nmod r + cdef mp_limb_t val + if any_as_nmod(&val, t, (s).mod): + r = nmod.__new__(nmod) + r.mod = (s).mod + r.val = nmod_mul((s).val, val, r.mod) + return r + return NotImplemented + @staticmethod def _div_(s, t): cdef nmod r @@ -152,9 +171,8 @@ cdef class nmod(flint_scalar): def __truediv__(s, t): return nmod._div_(s, t) - def __div__(s, t): - return nmod._div_(s, t) + def __rtruediv__(s, t): + return nmod._div_(t, s) def __invert__(self): return (1 / self) # XXX: speed up - diff --git a/src/flint/nmod_mat.pyx b/src/flint/nmod_mat.pyx index 10f6ac0a..9d9e918d 100644 --- a/src/flint/nmod_mat.pyx +++ b/src/flint/nmod_mat.pyx @@ -190,18 +190,29 @@ cdef class nmod_mat: cdef nmod_mat r cdef nmod_mat_struct *sv cdef nmod_mat_struct *tv - if typecheck(s, nmod_mat): - sv = &(s).val[0] - t = any_as_nmod_mat(t, sv.mod) - if t is NotImplemented: - return t - tv = &(t).val[0] - else: - tv = &(t).val[0] - s = any_as_nmod_mat(s, tv.mod) - if s is NotImplemented: - return s - sv = &(s).val[0] + sv = &(s).val[0] + t = any_as_nmod_mat(t, sv.mod) + if t is NotImplemented: + return t + tv = &(t).val[0] + if sv.mod.n != tv.mod.n: + raise ValueError("cannot add nmod_mats with different moduli") + if sv.r != tv.r or sv.c != tv.c: + raise ValueError("incompatible shapes for matrix addition") + r = nmod_mat.__new__(nmod_mat) + nmod_mat_init(r.val, sv.r, sv.c, sv.mod.n) + nmod_mat_add(r.val, sv, tv) + return r + + def __radd__(s, t): + cdef nmod_mat r + cdef nmod_mat_struct *sv + cdef nmod_mat_struct *tv + sv = &(s).val[0] + t = any_as_nmod_mat(t, sv.mod) + if t is NotImplemented: + return t + tv = &(t).val[0] if sv.mod.n != tv.mod.n: raise ValueError("cannot add nmod_mats with different moduli") if sv.r != tv.r or sv.c != tv.c: @@ -215,18 +226,11 @@ cdef class nmod_mat: cdef nmod_mat r cdef nmod_mat_struct *sv cdef nmod_mat_struct *tv - if typecheck(s, nmod_mat): - sv = &(s).val[0] - t = any_as_nmod_mat(t, sv.mod) - if t is NotImplemented: - return t - tv = &(t).val[0] - else: - tv = &(t).val[0] - s = any_as_nmod_mat(s, tv.mod) - if s is NotImplemented: - return s - sv = &(s).val[0] + sv = &(s).val[0] + t = any_as_nmod_mat(t, sv.mod) + if t is NotImplemented: + return t + tv = &(t).val[0] if sv.mod.n != tv.mod.n: raise ValueError("cannot subtract nmod_mats with different moduli") if sv.r != tv.r or sv.c != tv.c: @@ -236,6 +240,24 @@ cdef class nmod_mat: nmod_mat_sub(r.val, sv, tv) return r + def __rsub__(s, t): + cdef nmod_mat r + cdef nmod_mat_struct *sv + cdef nmod_mat_struct *tv + sv = &(s).val[0] + t = any_as_nmod_mat(t, sv.mod) + if t is NotImplemented: + return t + tv = &(t).val[0] + if sv.mod.n != tv.mod.n: + raise ValueError("cannot subtract nmod_mats with different moduli") + if sv.r != tv.r or sv.c != tv.c: + raise ValueError("incompatible shapes for matrix subtraction") + r = nmod_mat.__new__(nmod_mat) + nmod_mat_init(r.val, sv.r, sv.c, sv.mod.n) + nmod_mat_sub(r.val, tv, sv) + return r + cdef __mul_nmod(self, mp_limb_t c): cdef nmod_mat r = nmod_mat.__new__(nmod_mat) nmod_mat_init(r.val, self.val.r, self.val.c, self.val.mod.n) @@ -247,22 +269,13 @@ cdef class nmod_mat: cdef nmod_mat_struct *sv cdef nmod_mat_struct *tv cdef mp_limb_t c - if typecheck(s, nmod_mat): - sv = &(s).val[0] - u = any_as_nmod_mat(t, sv.mod) - if u is NotImplemented: - if any_as_nmod(&c, t, sv.mod): - return (s).__mul_nmod(c) - return NotImplemented - tv = &(u).val[0] - else: - tv = &(t).val[0] - u = any_as_nmod_mat(s, tv.mod) - if u is NotImplemented: - if any_as_nmod(&c, s, tv.mod): - return (t).__mul_nmod(c) - return NotImplemented - sv = &(u).val[0] + sv = &(s).val[0] + u = any_as_nmod_mat(t, sv.mod) + if u is NotImplemented: + if any_as_nmod(&c, t, sv.mod): + return (s).__mul_nmod(c) + return NotImplemented + tv = &(u).val[0] if sv.mod.n != tv.mod.n: raise ValueError("cannot multiply nmod_mats with different moduli") if sv.c != tv.r: @@ -272,6 +285,17 @@ cdef class nmod_mat: nmod_mat_mul(r.val, sv, tv) return r + def __rmul__(s, t): + cdef nmod_mat_struct *sv + cdef mp_limb_t c + sv = &(s).val[0] + if any_as_nmod(&c, t, sv.mod): + return (s).__mul_nmod(c) + u = any_as_nmod_mat(t, sv.mod) + if u is NotImplemented: + return u + return u * s + @staticmethod def _div_(nmod_mat s, t): cdef mp_limb_t v diff --git a/src/flint/nmod_poly.pyx b/src/flint/nmod_poly.pyx index fe1aee1c..9e43194c 100644 --- a/src/flint/nmod_poly.pyx +++ b/src/flint/nmod_poly.pyx @@ -169,16 +169,11 @@ cdef class nmod_poly(flint_poly): nmod_poly_neg(r.val, self.val) return r - def __add__(s, t): + def _add_(s, t): cdef nmod_poly r - if typecheck(s, nmod_poly): - t = any_as_nmod_poly(t, (s).val.mod) - if t is NotImplemented: - return t - else: - s = any_as_nmod_poly(s, (t).val.mod) - if s is NotImplemented: - return s + t = any_as_nmod_poly(t, (s).val.mod) + if t is NotImplemented: + return t if (s).val.mod.n != (t).val.mod.n: raise ValueError("cannot add nmod_polys with different moduli") r = nmod_poly.__new__(nmod_poly) @@ -186,16 +181,14 @@ cdef class nmod_poly(flint_poly): nmod_poly_add(r.val, (s).val, (t).val) return r - def __sub__(s, t): + def __add__(s, t): + return s._add_(t) + + def __radd__(s, t): + return s._add_(t) + + def _sub_(s, t): cdef nmod_poly r - if typecheck(s, nmod_poly): - t = any_as_nmod_poly(t, (s).val.mod) - if t is NotImplemented: - return t - else: - s = any_as_nmod_poly(s, (t).val.mod) - if s is NotImplemented: - return s if (s).val.mod.n != (t).val.mod.n: raise ValueError("cannot subtract nmod_polys with different moduli") r = nmod_poly.__new__(nmod_poly) @@ -203,16 +196,23 @@ cdef class nmod_poly(flint_poly): nmod_poly_sub(r.val, (s).val, (t).val) return r - def __mul__(s, t): + def __sub__(s, t): + t = any_as_nmod_poly(t, (s).val.mod) + if t is NotImplemented: + return t + return s._sub_(t) + + def __rsub__(s, t): + t = any_as_nmod_poly(t, (s).val.mod) + if t is NotImplemented: + return t + return t._sub_(s) + + def _mul_(s, t): cdef nmod_poly r - if typecheck(s, nmod_poly): - t = any_as_nmod_poly(t, (s).val.mod) - if t is NotImplemented: - return t - else: - s = any_as_nmod_poly(s, (t).val.mod) - if s is NotImplemented: - return s + t = any_as_nmod_poly(t, (s).val.mod) + if t is NotImplemented: + return t if (s).val.mod.n != (t).val.mod.n: raise ValueError("cannot multiply nmod_polys with different moduli") r = nmod_poly.__new__(nmod_poly) @@ -220,18 +220,16 @@ cdef class nmod_poly(flint_poly): nmod_poly_mul(r.val, (s).val, (t).val) return r + def __mul__(s, t): + return s._mul_(t) + + def __rmul__(s, t): + return s._mul_(t) + # TODO: __div__, __truediv__ - def __floordiv__(s, t): + def _floordiv_(s, t): cdef nmod_poly r - if typecheck(s, nmod_poly): - t = any_as_nmod_poly(t, (s).val.mod) - if t is NotImplemented: - return t - else: - s = any_as_nmod_poly(s, (t).val.mod) - if s is NotImplemented: - return s if (s).val.mod.n != (t).val.mod.n: raise ValueError("cannot divide nmod_polys with different moduli") if nmod_poly_is_zero((t).val): @@ -241,16 +239,20 @@ cdef class nmod_poly(flint_poly): nmod_poly_div(r.val, (s).val, (t).val) return r - def __divmod__(s, t): + def __floordiv__(s, t): + t = any_as_nmod_poly(t, (s).val.mod) + if t is NotImplemented: + return t + return s._floordiv_(t) + + def __rfloordiv__(s, t): + t = any_as_nmod_poly(t, (s).val.mod) + if t is NotImplemented: + return t + return t._floordiv_(s) + + def _divmod_(s, t): cdef nmod_poly P, Q - if typecheck(s, nmod_poly): - t = any_as_nmod_poly(t, (s).val.mod) - if t is NotImplemented: - return t - else: - s = any_as_nmod_poly(s, (t).val.mod) - if s is NotImplemented: - return s if (s).val.mod.n != (t).val.mod.n: raise ValueError("cannot divide nmod_polys with different moduli") if nmod_poly_is_zero((t).val): @@ -262,9 +264,24 @@ cdef class nmod_poly(flint_poly): nmod_poly_divrem(P.val, Q.val, (s).val, (t).val) return P, Q + def __divmod__(s, t): + t = any_as_nmod_poly(t, (s).val.mod) + if t is NotImplemented: + return t + return s._divmod_(t) + + def __rdivmod__(s, t): + t = any_as_nmod_poly(t, (s).val.mod) + if t is NotImplemented: + return t + return t._divmod_(s) + def __mod__(s, t): return divmod(s, t)[1] # XXX + def __rmod__(s, t): + return divmod(t, s)[1] # XXX + def __pow__(nmod_poly self, ulong exp, mod): cdef nmod_poly res if mod is not None: