From 87082ee3eca24c2ad4a77ef1de9ced0a52aff775 Mon Sep 17 00:00:00 2001 From: giacomopope Date: Fri, 18 Aug 2023 21:30:20 +0100 Subject: [PATCH 1/7] Refactor out typecheck as a util --- src/flint/utils/typecheck.pxd | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/flint/utils/typecheck.pxd diff --git a/src/flint/utils/typecheck.pxd b/src/flint/utils/typecheck.pxd new file mode 100644 index 00000000..b8394837 --- /dev/null +++ b/src/flint/utils/typecheck.pxd @@ -0,0 +1,4 @@ +from flint._flint cimport PyTypeObject, PyObject_TypeCheck + +cdef inline bint typecheck(object ob, object tp): + return PyObject_TypeCheck(ob, tp) From e2904c6cfb7f207842a64d01f80be127b5494779 Mon Sep 17 00:00:00 2001 From: giacomopope Date: Fri, 18 Aug 2023 21:30:40 +0100 Subject: [PATCH 2/7] Update imports for typecheck util --- src/flint/acb.pyx | 1 + src/flint/acb_mat.pyx | 2 +- src/flint/acb_poly.pyx | 5 ++- src/flint/acb_series.pyx | 1 + src/flint/arb.pyx | 1 + src/flint/arb_mat.pyx | 1 + src/flint/arb_poly.pyx | 5 ++- src/flint/arb_series.pyx | 1 + src/flint/arf.pyx | 1 + src/flint/fmpq.pyx | 1 + src/flint/fmpq_mat.pyx | 1 + src/flint/fmpq_poly.pyx | 5 ++- src/flint/fmpq_series.pyx | 1 + src/flint/fmpz.pyx | 1 + src/flint/fmpz_mat.pyx | 1 + src/flint/fmpz_mpoly.pyx | 1 + src/flint/fmpz_poly.pyx | 5 ++- src/flint/fmpz_series.pyx | 1 + src/flint/nmod.pyx | 1 + src/flint/nmod_mat.pyx | 1 + src/flint/nmod_poly.pyx | 5 ++- src/flint/pyflint.pyx | 66 --------------------------------------- 22 files changed, 26 insertions(+), 82 deletions(-) diff --git a/src/flint/acb.pyx b/src/flint/acb.pyx index a3cb36c7..7a123bc5 100644 --- a/src/flint/acb.pyx +++ b/src/flint/acb.pyx @@ -1,3 +1,4 @@ +from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_base cimport flint_scalar from flint.flint_base.flint_context cimport getprec diff --git a/src/flint/acb_mat.pyx b/src/flint/acb_mat.pyx index 6755edd2..5c9c9b5d 100644 --- a/src/flint/acb_mat.pyx +++ b/src/flint/acb_mat.pyx @@ -1,5 +1,5 @@ +from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_context cimport getprec - from flint.flint_base.flint_base cimport flint_mat cdef acb_mat_coerce_operands(x, y): diff --git a/src/flint/acb_poly.pyx b/src/flint/acb_poly.pyx index fe41577c..64e7d3cc 100644 --- a/src/flint/acb_poly.pyx +++ b/src/flint/acb_poly.pyx @@ -1,7 +1,6 @@ +from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_context cimport getprec -# TODO: waiting for fix on the roots method, currently -# globally defined. -# from flint.flint_base.flint_base cimport flint_poly +from flint.flint_base.flint_base cimport flint_poly cdef acb_poly_coerce_operands(x, y): if isinstance(y, (int, long, float, complex, fmpz, fmpq, arb, acb, fmpz_poly, fmpq_poly, arb_poly)): diff --git a/src/flint/acb_series.pyx b/src/flint/acb_series.pyx index a642c46f..fc399b14 100644 --- a/src/flint/acb_series.pyx +++ b/src/flint/acb_series.pyx @@ -1,3 +1,4 @@ +from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_context cimport getprec, getcap from flint.flint_base.flint_base cimport flint_series diff --git a/src/flint/arb.pyx b/src/flint/arb.pyx index 19f31ecd..fea26eae 100644 --- a/src/flint/arb.pyx +++ b/src/flint/arb.pyx @@ -2,6 +2,7 @@ from cpython.version cimport PY_MAJOR_VERSION from flint.flint_base.flint_context cimport getprec from flint.flint_base.flint_base cimport flint_scalar +from flint.utils.typecheck cimport typecheck from flint.utils.conversion cimport chars_from_str, str_from_chars cdef _str_trunc(s, trunc=0): diff --git a/src/flint/arb_mat.pyx b/src/flint/arb_mat.pyx index 16cea15b..a7e778dc 100644 --- a/src/flint/arb_mat.pyx +++ b/src/flint/arb_mat.pyx @@ -1,3 +1,4 @@ +from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_context cimport getprec from flint.flint_base.flint_base cimport flint_mat diff --git a/src/flint/arb_poly.pyx b/src/flint/arb_poly.pyx index 518cdd51..bca26fd3 100644 --- a/src/flint/arb_poly.pyx +++ b/src/flint/arb_poly.pyx @@ -1,7 +1,6 @@ +from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_context cimport getprec -# TODO: waiting for fix on the roots method, currently -# globally defined. -# from flint.flint_base.flint_base cimport flint_poly +from flint.flint_base.flint_base cimport flint_poly cdef arb_poly_coerce_operands(x, y): if isinstance(y, (int, long, float, fmpz, fmpq, arb, fmpz_poly, fmpq_poly)): diff --git a/src/flint/arb_series.pyx b/src/flint/arb_series.pyx index 8713080d..30c018b9 100644 --- a/src/flint/arb_series.pyx +++ b/src/flint/arb_series.pyx @@ -1,3 +1,4 @@ +from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_context cimport getprec, getcap from flint.flint_base.flint_base cimport flint_series diff --git a/src/flint/arf.pyx b/src/flint/arf.pyx index 91da4290..b13b5539 100644 --- a/src/flint/arf.pyx +++ b/src/flint/arf.pyx @@ -1,4 +1,5 @@ from flint.flint_base.flint_context cimport getprec +from flint.utils.typecheck cimport typecheck from flint.utils.conversion cimport prec_to_dps cdef class arf: diff --git a/src/flint/fmpq.pyx b/src/flint/fmpq.pyx index e8e79b3b..10fb162d 100644 --- a/src/flint/fmpq.pyx +++ b/src/flint/fmpq.pyx @@ -1,4 +1,5 @@ from flint.flint_base.flint_base cimport flint_scalar +from flint.utils.typecheck cimport typecheck cdef any_as_fmpq(obj): if typecheck(obj, fmpq): diff --git a/src/flint/fmpq_mat.pyx b/src/flint/fmpq_mat.pyx index 65d8a0a9..a8442e5a 100644 --- a/src/flint/fmpq_mat.pyx +++ b/src/flint/fmpq_mat.pyx @@ -1,4 +1,5 @@ from flint.flint_base.flint_base cimport flint_mat +from flint.utils.typecheck cimport typecheck cdef any_as_fmpq_mat(obj): if typecheck(obj, fmpq_mat): diff --git a/src/flint/fmpq_poly.pyx b/src/flint/fmpq_poly.pyx index db2c08ab..7e3d957d 100644 --- a/src/flint/fmpq_poly.pyx +++ b/src/flint/fmpq_poly.pyx @@ -1,6 +1,5 @@ -# TODO: waiting for fix on the roots method, currently -# globally defined. -# from flint.flint_base.flint_base cimport flint_poly +from flint.utils.typecheck cimport typecheck +from flint.flint_base.flint_base cimport flint_poly cdef any_as_fmpq_poly(obj): if typecheck(obj, fmpq_poly): diff --git a/src/flint/fmpq_series.pyx b/src/flint/fmpq_series.pyx index 9c76f69d..5dc26225 100644 --- a/src/flint/fmpq_series.pyx +++ b/src/flint/fmpq_series.pyx @@ -1,4 +1,5 @@ from flint.flint_base.flint_base cimport flint_series +from flint.utils.typecheck cimport typecheck cdef fmpq_series_coerce_operands(x, y): if isinstance(y, (int, long, fmpz, fmpz_poly, fmpz_series, fmpq, fmpq_poly)): diff --git a/src/flint/fmpz.pyx b/src/flint/fmpz.pyx index c91359f8..b898cfd2 100644 --- a/src/flint/fmpz.pyx +++ b/src/flint/fmpz.pyx @@ -1,6 +1,7 @@ from cpython.version cimport PY_MAJOR_VERSION from flint.flint_base.flint_base cimport flint_scalar +from flint.utils.typecheck cimport typecheck from flint.utils.conversion cimport chars_from_str cdef inline int fmpz_set_pylong(fmpz_t x, obj): diff --git a/src/flint/fmpz_mat.pyx b/src/flint/fmpz_mat.pyx index 887750b2..d7a4857c 100644 --- a/src/flint/fmpz_mat.pyx +++ b/src/flint/fmpz_mat.pyx @@ -1,4 +1,5 @@ from flint.flint_base.flint_base cimport flint_mat +from flint.utils.typecheck cimport typecheck cdef any_as_fmpz_mat(obj): if typecheck(obj, fmpz_mat): diff --git a/src/flint/fmpz_mpoly.pyx b/src/flint/fmpz_mpoly.pyx index f4ddf026..f94c085d 100644 --- a/src/flint/fmpz_mpoly.pyx +++ b/src/flint/fmpz_mpoly.pyx @@ -1,6 +1,7 @@ from cpython.version cimport PY_MAJOR_VERSION from flint.utils.conversion cimport str_from_chars +from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_base cimport flint_mpoly cdef any_as_fmpz_mpoly(x): diff --git a/src/flint/fmpz_poly.pyx b/src/flint/fmpz_poly.pyx index 0b9ad86a..a61a7d99 100644 --- a/src/flint/fmpz_poly.pyx +++ b/src/flint/fmpz_poly.pyx @@ -1,9 +1,8 @@ from cpython.version cimport PY_MAJOR_VERSION from flint.flint_base.flint_context cimport getprec -# TODO: waiting for fix on the roots method, currently -# globally defined. -# from flint.flint_base.flint_base cimport flint_poly +from flint.flint_base.flint_base cimport flint_poly +from flint.utils.typecheck cimport typecheck cdef any_as_fmpz_poly(x): cdef fmpz_poly res diff --git a/src/flint/fmpz_series.pyx b/src/flint/fmpz_series.pyx index dcb8cb3a..bfcbc6a9 100644 --- a/src/flint/fmpz_series.pyx +++ b/src/flint/fmpz_series.pyx @@ -1,3 +1,4 @@ +from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_base cimport flint_series cdef fmpz_series_coerce_operands(x, y): diff --git a/src/flint/nmod.pyx b/src/flint/nmod.pyx index e212b668..0ffaadaf 100644 --- a/src/flint/nmod.pyx +++ b/src/flint/nmod.pyx @@ -1,4 +1,5 @@ from flint.flint_base.flint_base cimport flint_scalar +from flint.utils.typecheck cimport typecheck cdef int any_as_nmod(mp_limb_t * val, obj, nmod_t mod) except -1: cdef int success diff --git a/src/flint/nmod_mat.pyx b/src/flint/nmod_mat.pyx index 14a86309..a6d50a7e 100644 --- a/src/flint/nmod_mat.pyx +++ b/src/flint/nmod_mat.pyx @@ -1,4 +1,5 @@ from flint.utils.conversion cimport matrix_to_str +from flint.utils.typecheck cimport typecheck cdef any_as_nmod_mat(obj, nmod_t mod): cdef nmod_mat r diff --git a/src/flint/nmod_poly.pyx b/src/flint/nmod_poly.pyx index 2e928ecc..3f69f6c7 100644 --- a/src/flint/nmod_poly.pyx +++ b/src/flint/nmod_poly.pyx @@ -1,6 +1,5 @@ -# TODO: waiting for fix on the roots method, currently -# globally defined. -# from flint.flint_base.flint_base cimport flint_poly +from flint.flint_base.flint_base cimport flint_poly +from flint.utils.typecheck cimport typecheck cdef any_as_nmod_poly(obj, nmod_t mod): cdef nmod_poly r diff --git a/src/flint/pyflint.pyx b/src/flint/pyflint.pyx index 44d4a626..a9c14ccb 100644 --- a/src/flint/pyflint.pyx +++ b/src/flint/pyflint.pyx @@ -24,78 +24,12 @@ cdef extern from "Python.h": double PyComplex_RealAsDouble(PyObject *op) double PyComplex_ImagAsDouble(PyObject *op) -cdef inline bint typecheck(object ob, object tp): - return PyObject_TypeCheck(ob, tp) - DEF FMPZ_UNKNOWN = 0 DEF FMPZ_REF = 1 DEF FMPZ_TMP = 2 ctx = thectx -# TODO: -# This should be factored out into flint_base -# but we cannot do this until we can import -# acb_poly to allow the roots() method to remain - -from flint.flint_base.flint_base cimport flint_elem - -cdef class flint_poly(flint_elem): - """ - Base class for polynomials. - """ - - def __iter__(self): - cdef long i, n - n = self.length() - for i in range(n): - yield self[i] - - def coeffs(self): - return list(self) - - def str(self, bint ascending=False): - """ - Convert to a human-readable string (generic implementation for - all polynomial types). - - If *ascending* is *True*, the monomials are output from low degree to - high, otherwise from high to low. - """ - coeffs = [str(c) for c in self] - if not coeffs: - return "0" - s = [] - coeffs = enumerate(coeffs) - if not ascending: - coeffs = reversed(list(coeffs)) - for i, c in coeffs: - if c == "0": - continue - else: - if c.startswith("-") or (" " in c): - c = "(" + c + ")" - if i == 0: - s.append("%s" % c) - elif i == 1: - if c == "1": - s.append("x") - else: - s.append("%s*x" % c) - else: - if c == "1": - s.append("x^%s" % i) - else: - s.append("%s*x^%s" % (c, i)) - return " + ".join(s) - - def roots(self, **kwargs): - """ - Isolates the complex roots of *self*. See :meth:`.acb_poly.roots` - for details. - """ - return acb_poly(self).roots(**kwargs) - include "fmpz.pyx" include "fmpz_poly.pyx" include "fmpz_mpoly.pyx" From b0a5722a0d132520e30f87a43a84984e64758d30 Mon Sep 17 00:00:00 2001 From: giacomopope Date: Fri, 18 Aug 2023 21:31:35 +0100 Subject: [PATCH 3/7] Depreciate roots() on flint_poly and refactor out into submodule --- src/flint/flint_base/flint_base.pxd | 6 +- src/flint/flint_base/flint_base.pyx | 130 ++++++++++++++-------------- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/flint/flint_base/flint_base.pxd b/src/flint/flint_base/flint_base.pxd index e8782db2..95f87e9a 100644 --- a/src/flint/flint_base/flint_base.pxd +++ b/src/flint/flint_base/flint_base.pxd @@ -4,10 +4,8 @@ cdef class flint_elem: cdef class flint_scalar(flint_elem): pass -# TODO: -# See .pyx file -# cdef class flint_poly(flint_elem): -# pass +cdef class flint_poly(flint_elem): + pass cdef class flint_mpoly(flint_elem): pass diff --git a/src/flint/flint_base/flint_base.pyx b/src/flint/flint_base/flint_base.pyx index 5e4ebff0..6988eab0 100644 --- a/src/flint/flint_base/flint_base.pyx +++ b/src/flint/flint_base/flint_base.pyx @@ -1,3 +1,5 @@ +from warnings import warn + from flint.flint_base.flint_context cimport thectx cdef class flint_elem: @@ -10,78 +12,78 @@ cdef class flint_elem: def __str__(self): return self.str() + cdef class flint_scalar(flint_elem): pass - -# TODO: -# We cannot include this class until we can import -# acb_poly, so for now we leave this class as a global -# inside pyflint.pyx -# -# cdef class flint_poly(flint_elem): -# """ -# Base class for polynomials. -# """ - -# def __iter__(self): -# cdef long i, n -# n = self.length() -# for i in range(n): -# yield self[i] - -# def coeffs(self): -# return list(self) - -# def str(self, bint ascending=False): -# """ -# Convert to a human-readable string (generic implementation for -# all polynomial types). - -# If *ascending* is *True*, the monomials are output from low degree to -# high, otherwise from high to low. -# """ -# coeffs = [str(c) for c in self] -# if not coeffs: -# return "0" -# s = [] -# coeffs = enumerate(coeffs) -# if not ascending: -# coeffs = reversed(list(coeffs)) -# for i, c in coeffs: -# if c == "0": -# continue -# else: -# if c.startswith("-") or (" " in c): -# c = "(" + c + ")" -# if i == 0: -# s.append("%s" % c) -# elif i == 1: -# if c == "1": -# s.append("x") -# else: -# s.append("%s*x" % c) -# else: -# if c == "1": -# s.append("x^%s" % i) -# else: -# s.append("%s*x^%s" % (c, i)) -# return " + ".join(s) - -# def roots(self, **kwargs): -# """ -# Isolates the complex roots of *self*. See :meth:`.acb_poly.roots` -# for details. -# """ -# # TODO: -# # To avoid circular imports, we import within the method -# from XXX.XXX.acb_poly import acb_poly -# return acb_poly(self).roots(**kwargs) + + +cdef class flint_poly(flint_elem): + """ + Base class for polynomials. + """ + + def __iter__(self): + cdef long i, n + n = self.length() + for i in range(n): + yield self[i] + + def coeffs(self): + return list(self) + + def str(self, bint ascending=False): + """ + Convert to a human-readable string (generic implementation for + all polynomial types). + + If *ascending* is *True*, the monomials are output from low degree to + high, otherwise from high to low. + """ + coeffs = [str(c) for c in self] + if not coeffs: + return "0" + s = [] + coeffs = enumerate(coeffs) + if not ascending: + coeffs = reversed(list(coeffs)) + for i, c in coeffs: + if c == "0": + continue + else: + if c.startswith("-") or (" " in c): + c = "(" + c + ")" + if i == 0: + s.append("%s" % c) + elif i == 1: + if c == "1": + s.append("x") + else: + s.append("%s*x" % c) + else: + if c == "1": + s.append("x^%s" % i) + else: + s.append("%s*x^%s" % (c, i)) + return " + ".join(s) + + def roots(self): + """ + Depreciated function. + + To recover roots of a polynomial, first convert to acb: + + acb_poly(input_poly).roots() + """ + warn('This method is deprecated.', DeprecationWarning) + + cdef class flint_mpoly(flint_elem): """ Base class for multivariate polynomials. """ + cdef class flint_series(flint_elem): """ Base class for power series. From ddf83656e62da53d480c33e12824395531f256d6 Mon Sep 17 00:00:00 2001 From: giacomopope Date: Fri, 18 Aug 2023 21:37:14 +0100 Subject: [PATCH 4/7] More verbose depreciation warning --- src/flint/flint_base/flint_base.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flint/flint_base/flint_base.pyx b/src/flint/flint_base/flint_base.pyx index 6988eab0..8c118098 100644 --- a/src/flint/flint_base/flint_base.pyx +++ b/src/flint/flint_base/flint_base.pyx @@ -74,7 +74,7 @@ cdef class flint_poly(flint_elem): acb_poly(input_poly).roots() """ - warn('This method is deprecated.', DeprecationWarning) + warn('This method is deprecated. Please instead use acb_poly(input_poly).roots()', DeprecationWarning) From 4d8e3adb647ef16ad034068ab262332d24b43021 Mon Sep 17 00:00:00 2001 From: giacomopope Date: Fri, 18 Aug 2023 23:06:46 +0100 Subject: [PATCH 5/7] fix typo --- src/flint/flint_base/flint_base.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flint/flint_base/flint_base.pyx b/src/flint/flint_base/flint_base.pyx index 8c118098..bd5657f6 100644 --- a/src/flint/flint_base/flint_base.pyx +++ b/src/flint/flint_base/flint_base.pyx @@ -68,7 +68,7 @@ cdef class flint_poly(flint_elem): def roots(self): """ - Depreciated function. + Deprecated function. To recover roots of a polynomial, first convert to acb: From 4d46c694b7865f51220c659d2ac9b71f2164dcda Mon Sep 17 00:00:00 2001 From: giacomopope Date: Fri, 18 Aug 2023 23:14:59 +0100 Subject: [PATCH 6/7] Address review comments: typo and raise Error, not warning --- src/flint/flint_base/flint_base.pyx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/flint/flint_base/flint_base.pyx b/src/flint/flint_base/flint_base.pyx index bd5657f6..1ddf099d 100644 --- a/src/flint/flint_base/flint_base.pyx +++ b/src/flint/flint_base/flint_base.pyx @@ -1,5 +1,3 @@ -from warnings import warn - from flint.flint_base.flint_context cimport thectx cdef class flint_elem: @@ -74,7 +72,7 @@ cdef class flint_poly(flint_elem): acb_poly(input_poly).roots() """ - warn('This method is deprecated. Please instead use acb_poly(input_poly).roots()', DeprecationWarning) + raise NotImplementedError('This method has been deprecated. Please instead use acb_poly(input_poly).roots()') From f43b2919843e2c0b86e6393f94853bec0fe6c1f4 Mon Sep 17 00:00:00 2001 From: giacomopope Date: Fri, 18 Aug 2023 23:28:46 +0100 Subject: [PATCH 7/7] Add changelog --- README.md | 7 +++++++ src/flint/flint_base/flint_base.pyx | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 829133b0..0ef8de85 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,13 @@ To do * Improved printing and string input/output * IPython hooks (TeX pretty-printing etc.) +CHANGELOG +------------- + +0.5.0 + +- gh-63: The `roots` method of `arb_poly`, and `nmod_poly` is no longer supported. Use `acb_roots(p).roots()` to get the old behaviour of returning the roots as `acb`. Note that the `roots` method of `fmpz_poly` and `fmpq_poly` currently returns the complex roots of the polynomial. + License ------------ diff --git a/src/flint/flint_base/flint_base.pyx b/src/flint/flint_base/flint_base.pyx index 1ddf099d..3b5c7434 100644 --- a/src/flint/flint_base/flint_base.pyx +++ b/src/flint/flint_base/flint_base.pyx @@ -72,7 +72,7 @@ cdef class flint_poly(flint_elem): acb_poly(input_poly).roots() """ - raise NotImplementedError('This method has been deprecated. Please instead use acb_poly(input_poly).roots()') + raise NotImplementedError('This method is no longer supported. To recover the complex roots first convert to acb_poly')