diff --git a/.gitmodules b/.gitmodules index 082cca8232a4539ad1276d212fd7abc76d7adda2..cf8c41bffee40150983e64ce2208936887a7c205 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "isl"] path = isl - url = git://repo.or.cz/isl.git + url = git://github.com/inducer/isl-mirror [submodule "bpl-subset"] path = bpl-subset url = git://github.com/inducer/bpl-subset diff --git a/doc/index.rst b/doc/index.rst index 865ed46f5d91b8b6a337bc8e74e41bafc5904f3f..ed81114a391a7822c865f75d4da5709afef41a42 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -61,7 +61,7 @@ package `_ is also quite helpful to get an idea. .. toctree:: - :maxdepth: 3 + :maxdepth: 2 misc reference diff --git a/doc/misc.rst b/doc/misc.rst index 9611dd1ffb4b34f1f99d52b1acae4ff99b02e86a..e899fff2cae1c0cd419984389c10cdd037bd8df1 100644 --- a/doc/misc.rst +++ b/doc/misc.rst @@ -52,6 +52,9 @@ OTHER DEALINGS IN THE SOFTWARE. isl itself is now also licensed under the `MIT license `_. + GMP, which is a dependency of isl and thus islpy, is licensed under the + Lesser GNU Public License. + Relation with isl's C interface =============================== @@ -71,7 +74,7 @@ See also :ref:`gen-remarks`. User-visible Changes ==================== -Version 2013.4 +Version 2014.1 -------------- .. note:: @@ -79,6 +82,29 @@ Version 2013.4 This version is currently in development and can be obtained from islpy's version control. +isl's handling of integer's has changed, forcing islpy to make +incompatible changes as well. + +Now :class:`islpy.Val` is used to represent all numbers going +into and out of :mod:`islpy`. :mod:`gmpy` is no longer a dependency +of :mod:`islpy`. The following rules apply for this interface change: + +* You can pass (up to ``long int``-sized) integers to methods of + isl objects without manual conversion to :class:`islpy.Val`. + For larger numbers, you need to convert manually for now. + +* All numbers returned from :mod:`islpy` will be of type :class:`islpy.Val`. + If they are integers, they can be converted + +* Since upstream made the decision to make ``isl_XXX_do_something_val`` + not always semantically equivalent to ``isl_XXX_do_something``, the + old functions were removed. + + One example of this is ``isl_aff_get_constant``, which returned just + the constant, and ``isl_aff_get_constant_val``, which returns the + constant divided by the :class:`islpy.Aff`'s denominator as a rational + value. + Version 2011.3 -------------- diff --git a/doc/reference.rst b/doc/reference.rst index 29004ca084b99f4203a88ad71174876844014778..631a9a21ed30408fed3519fd1d04b5d9cafcce7e 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -6,6 +6,17 @@ Reference guide .. _gen-remarks: +Table of Contents +^^^^^^^^^^^^^^^^^ + +.. toctree:: + :maxdepth: 3 + + reference + +.. Referring to this document makes sphinx spew 'circular reference' warnings. +.. "self" would apparently be the correct way, but it does not work. + General Remarks ^^^^^^^^^^^^^^^ @@ -106,6 +117,12 @@ Context .. class:: Context() +Id +-- + +.. autoclass:: Id + :members: + Space ----- @@ -126,6 +143,18 @@ Constraints .. autoclass:: Constraint :members: +Value +----- + +.. autoclass:: Val + :members: + +Multi-Value +----------- + +.. autoclass:: MultiVal + :members: + Vector ------ @@ -243,6 +272,12 @@ Union of Piecewise Multiply Affine Expression Quasipolynomials ^^^^^^^^^^^^^^^^ +Term +---- + +.. autoclass:: Term + :members: + QPolynomial ----------- @@ -294,6 +329,12 @@ Schedule .. autoclass:: Schedule :members: +ScheduleConstraints +------------------- + +.. autoclass:: ScheduleConstraints + :members: + Dataflow ^^^^^^^^ diff --git a/gen_wrap.py b/gen_wrap.py index c00d37c9d1a58bdac3424e026744594b75cd3115..2c44accafda60698122da06a969ffe9bb6c73ec8 100644 --- a/gen_wrap.py +++ b/gen_wrap.py @@ -25,6 +25,8 @@ def for lambda try """.split() +# {{{ data model + class Argument: def __init__(self, name, semantics, base_type, ptr): self.name = name @@ -76,33 +78,42 @@ class Method: def __repr__(self): return "" % self.c_name +# }}} + PART_TO_CLASSES = { + # If you change this, change: + # - src/wrapper/wrap_isl.hpp to add WRAP_CLASS(...) + # - src/wrapper/wrap_isl_partN.hpp to add MAKE_WRAP(...) + # - doc/reference.rst + "part1": [ - "basic_set_list", "set_list", "aff_list", "pw_aff_list", "band_list", - "printer", "val", "multi_val", "vec", "mat", "id", - "aff", "pw_aff", - "multi_aff", "multi_pw_aff", "pw_multi_aff", "union_pw_multi_aff", + "basic_set_list", "set_list", "aff_list", "pw_aff_list", "band_list", + "printer", "val", "multi_val", "vec", "mat", + "aff", "pw_aff", + "multi_aff", "multi_pw_aff", "pw_multi_aff", "union_pw_multi_aff", - "constraint", "space", "local_space", + "id", + "constraint", "space", "local_space", ], "part2": [ - "basic_set", "basic_map", - "set", "map", - "union_map", "union_set", - "point", "vertex", "cell", "vertices", + "basic_set", "basic_map", + "set", "map", + "union_map", "union_set", + "point", "vertex", "cell", "vertices", ], "part3": [ - "qpolynomial_fold", "pw_qpolynomial_fold", - "union_pw_qpolynomial_fold", - "union_pw_qpolynomial", "term", - "qpolynomial", "pw_qpolynomial", + "qpolynomial_fold", "pw_qpolynomial_fold", + "union_pw_qpolynomial_fold", + "union_pw_qpolynomial", + "qpolynomial", "pw_qpolynomial", + "term", - "band", "schedule", + "band", "schedule", "schedule_constraints", - "access_info", "flow", "restriction", + "access_info", "flow", "restriction", ] } CLASSES = [] @@ -117,9 +128,12 @@ CLASS_MAP = { ENUMS = ["isl_dim_type", "isl_fold"] -SAFE_TYPES = ENUMS + ["int", "unsigned", "uint32_t", "size_t"] +SAFE_TYPES = ENUMS + ["int", "unsigned", "uint32_t", "size_t", "double", + "long", "unsigned long"] SAFE_IN_TYPES = SAFE_TYPES + ["const char *", "char *"] +# {{{ parser + DECL_RE = re.compile(r""" ((?:\w+\s+)*) (\**) \s* (?# return type) (\w+) (?# func name) @@ -363,6 +377,16 @@ class FunctionData: if found_class: name = name[len(cls)+1:] + # Don't be tempted to chop off "_val"--the "_val" versions of + # some methods are incompatible with the isl_int ones. + # + # (For example, isl_aff_get_constant() returns just the constant, + # but isl_aff_get_constant_val() returns the constant divided by + # the denominator.) + # + # To avoid breaking user code in non-obvious ways, the new + # names are carried over to the Python level. + if not found_class: for fake_cls, cls in CLASS_MAP.items(): if name.startswith(fake_cls): @@ -407,6 +431,8 @@ class FunctionData: return_semantics, return_base_type, return_ptr, args, is_exported=is_exported, is_constructor=is_constructor)) +# }}} + def get_callback(cb_name, cb): body = [] @@ -477,6 +503,8 @@ def get_callback(cb_name, cb): passed_args=", ".join(passed_args)) +# {{{ wrapper generator + def write_wrapper(outf, meth): body = [] checks = [] @@ -547,43 +575,91 @@ def write_wrapper(outf, meth): else: raise SignatureNotSupported("int *") - elif arg.base_type == "isl_int" and arg.ptr == "*": - # assume it's meant as a return value - body.append(""" - py::object arg_%(name)s(py::handle<>((PyObject *) Pympz_new())); - managed_int arg_mi_%(name)s; + elif arg.base_type == "isl_val" and arg.ptr == "*" and arg_idx > 0: + # {{{ val input argument - """ % dict(name=arg.name)) - passed_args.append("&arg_mi_%s.m_data" % arg.name) - post_call.append(""" - isl_int_get_gmp( - arg_mi_%(name)s.m_data, - Pympz_AS_MPZ(arg_%(name)s.ptr())); - """ % dict(name=arg.name)) + arg_descr = ":param %s: :class:`Val`" % arg.name + input_args.append("py::object py_%s" % arg.name) + checks.append(""" + std::auto_ptr auto_arg_%(name)s; + py::extract ex_%(name)s(py_%(name)s); + isl_ctx *ctx_for_%(name)s = + %(first_arg_base_type)s_get_ctx(arg_%(first_arg)s.m_data); + + if (ex_%(name)s.check()) + { + val *arg_%(name)s = ex_%(name)s(); + if (!auto_arg_%(name)s->is_valid()) + throw isl::error( + "passed invalid val for %(name)s"); + + isl_val *tmp_ptr = isl_val_copy(arg_%(name)s->m_data); + if (!tmp_ptr) + throw isl::error("failed to copy arg %(name)s"); + auto_arg_%(name)s = std::auto_ptr(new val(tmp_ptr)); + } + else if (PyLong_Check(py_%(name)s.ptr())) + { + int overflow; - extra_ret_vals.append("arg_%s" % arg.name) - extra_ret_descrs.append("%s (integer)" % arg.name) + long value = PyLong_AsLongAndOverflow( + py_%(name)s.ptr(), &overflow); - arg_names.pop() + if (overflow) + { + throw isl::error( + "overflow on conversion of long for %(name)s"); + } + + isl_val *tmp_ptr = isl_val_int_from_si(ctx_for_%(name)s, value); + if (!tmp_ptr) + throw isl::error("failed to create arg %(name)s from integer"); + auto_arg_%(name)s = std::auto_ptr(new val(tmp_ptr)); + } + """ % dict( + name=arg.name, + first_arg_base_type=meth.args[0].base_type, + first_arg=meth.args[0].name, + )) + + if sys.version_info < (3,): + checks.append(""" + else if (PyInt_Check(py_%(name)s.ptr())) + { + isl_val *tmp_ptr = isl_val_int_from_si(ctx_for_%(name)s, + PyInt_AsLong(py_%(name)s.ptr())); + if (!tmp_ptr) + throw isl::error("failed to create arg " + "%(name)s from integer"); + auto_arg_%(name)s = std::auto_ptr(new val(tmp_ptr)); + } + """ % dict( + name=arg.name, + )) - elif arg.base_type == "isl_int" and not arg.ptr: - input_args.append("py::object %s" % ("arg_"+arg.name)) checks.append(""" - managed_int arg_mi_%(name)s; + else { - PyObject *converted; - if (Pympz_convert_arg(arg_%(name)s.ptr(), &converted) == 0) - throw py::error_already_set(); - py::handle<> converted_arg_%(name)s = py::handle<>(converted); - isl_int_set_gmp(arg_mi_%(name)s.m_data, - Pympz_AS_MPZ(converted_arg_%(name)s.get())); + throw isl::error("unrecognized argument for %(name)s"); } - """ % dict(name=arg.name, meth="%s_%s" % (meth.cls, meth.name))) - passed_args.append("arg_mi_%s.m_data" % arg.name) + """ % dict( + name=arg.name, + )) + + if arg.semantics is None and arg.base_type != "isl_ctx": + raise Undocumented(meth) + + if arg.semantics is SEM_TAKE: + post_call.append("auto_arg_%s.release();" % arg.name) - docs.append(":param %s: integer" % arg.name) + passed_args.append("auto_arg_%s->m_data" % arg.name) + docs.append(arg_descr) + + # }}} elif arg.base_type.startswith("isl_") and arg.ptr == "*": + # {{{ isl types input arguments + need_nonconst = False arg_cls = arg.base_type[4:] @@ -645,7 +721,11 @@ def write_wrapper(outf, meth): docs.append(arg_descr) + # }}} + elif arg.base_type.startswith("isl_") and arg.ptr == "**": + # {{{ isl types output arguments + if arg.semantics is not SEM_GIVE: raise SignatureNotSupported("non-give secondary ptr return value") @@ -671,6 +751,8 @@ def write_wrapper(outf, meth): extra_ret_descrs.append( "%s (:class:`%s`)" % (arg.name, to_py_class(ret_cls))) + # }}} + elif arg.base_type == "FILE" and arg.ptr == "*": if sys.version_info >= (3,): raise SignatureNotSupported( @@ -682,6 +764,17 @@ def write_wrapper(outf, meth): "(NOTE: This will cease to be supported in Python 3.)" % arg.name) + elif (arg.base_type == "void" + and arg.ptr == "*" + and arg.name == "user"): + body.append("Py_INCREF(arg_%s.ptr());" % arg.name) + passed_args.append("arg_%s.ptr()" % arg.name) + input_args.append("py::object %s" % ("arg_"+arg.name)) + post_call.append(""" + isl_{cls}_set_free_user(result, my_decref); + """.format(cls=meth.cls)) + docs.append(":param %s: a user-specified Python object" % arg.name) + else: raise SignatureNotSupported("arg type %s %s" % (arg.base_type, arg.ptr)) @@ -701,6 +794,8 @@ def write_wrapper(outf, meth): body += post_call + # {{{ return value processing + if meth.return_base_type == "int" and not meth.return_ptr: body.append(""" if (result == -1) @@ -804,6 +899,16 @@ def write_wrapper(outf, meth): ret_descr = "string" + elif (meth.return_base_type == "void" + and meth.return_ptr == "*" + and meth.name == "get_user"): + + body.append(""" + return py::object(py::handle<>(py::borrowed((PyObject *) result))); + """) + ret_descr = "a user-specified python object" + processed_return_type = "py::object" + elif meth.return_base_type == "void" and not meth.return_ptr: if extra_ret_vals: processed_return_type = "py::object" @@ -821,6 +926,8 @@ def write_wrapper(outf, meth): raise SignatureNotSupported("ret type: %s %s in %s" % ( meth.return_base_type, meth.return_ptr, meth)) + # }}} + outf.write(""" %s %s %s_%s(%s) @@ -839,6 +946,10 @@ def write_wrapper(outf, meth): return arg_names, "\n".join(docs) +# }}} + + +# {{{ exposer generator def write_exposer(outf, meth, arg_names, doc_str, static_decls): func_name = "isl::%s_%s" % (meth.cls, meth.name) @@ -873,18 +984,31 @@ def write_exposer(outf, meth, arg_names, doc_str, static_decls): static_decls.append("wrap_%s.staticmethod(\"%s\");\n" % ( wrap_class, exp_py_name)) +# }}} + def write_wrappers(expf, wrapf, methods): undoc = [] static_decls = [] for meth in methods: - if meth.name.endswith("_si") or meth.name.endswith("_ui") \ - and len([ - meth2.name == meth.name[:-3] - for meth2 in methods]): - # no need to expose C integer versions of things - continue + #print "TRY_WRAP:", meth + if meth.name.endswith("_si") or meth.name.endswith("_ui"): + val_versions = [ + meth2 + for meth2 in methods + if meth2.cls == meth.cls + and ( + meth2.name == meth.name[:-3] + or meth2.name == meth.name[:-3] + "_val" + ) + ] + + if val_versions: + # no need to expose C integer versions of things + print("SKIP (val version available): %s -> %s" + % (meth, ", ".join(str(s) for s in val_versions))) + continue try: arg_names, doc_str = write_wrapper(wrapf, meth) @@ -910,6 +1034,7 @@ def write_wrappers(expf, wrapf, methods): def gen_wrapper(include_dirs): fdata = FunctionData(["."] + include_dirs) fdata.read_header("isl_list.h") + fdata.read_header("isl/id.h") fdata.read_header("isl/space.h") fdata.read_header("isl/set.h") fdata.read_header("isl/map.h") @@ -946,3 +1071,5 @@ def gen_wrapper(include_dirs): if __name__ == "__main__": from os.path import expanduser gen_wrapper([expanduser("isl/include")]) + +# vim: foldmethod=marker diff --git a/isl b/isl index 95e2da06beccaef26fda146d853d3286c0737f97..766056b02386aa0955c0bdb9eaadef72a0b98ded 160000 --- a/isl +++ b/isl @@ -1 +1 @@ -Subproject commit 95e2da06beccaef26fda146d853d3286c0737f97 +Subproject commit 766056b02386aa0955c0bdb9eaadef72a0b98ded diff --git a/islpy/__init__.py b/islpy/__init__.py index 6f71dcfaef7170c6f3d15f413524a52112cf93b1..7b1ba73289ddee14536392f7971c083005d50882 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -1,24 +1,6 @@ from __future__ import division -# {{{ check gmpy version - -def _check_gmpy_version(): - import gmpy - gmpy_ver_num = tuple(int(s) for s in gmpy.version().split(".")) - - import sys - if sys.version_info >= (3,) and gmpy_ver_num < (1, 17): - raise ImportError("gmpy 1.17 or newer is required for " - "Python 3 support") - -try: - _check_gmpy_version() -except ValueError: - pass - -# }}} - from islpy._isl import * # noqa from islpy.version import * # noqa @@ -230,7 +212,7 @@ def _add_functionality(): New for :class:`Aff` """ for i, coeff in enumerate(args): - self = self.set_coefficient(dim_tp, i, coeff) + self = self.set_coefficient_val(dim_tp, i, coeff) return self @@ -257,7 +239,7 @@ def _add_functionality(): self = self.set_constant(coeff) else: tp, idx = name_to_dim[name] - self = self.set_coefficient(tp, idx, coeff) + self = self.set_coefficient_val(tp, idx, coeff) return self @@ -300,6 +282,26 @@ def _add_functionality(): # }}} + # {{{ Id + + def id_new(cls, name, user=None, context=None): + if context is None: + context = _DEFAULT_CONTEXT + + result = cls.alloc(context, name, user) + result._made_from_python = True + return result + + def id_bogus_init(self, name, user=None, context=None): + assert self._made_from_python + del self._made_from_python + + Id.__new__ = staticmethod(id_new) + Id.__init__ = id_bogus_init + Id.user = property(Id.get_user) + + # }}} + # {{{ Constraint def eq_from_names(space, coefficients={}): @@ -435,7 +437,7 @@ def _add_functionality(): def _number_to_aff(template, num): number_aff = Aff.zero_on_domain(template.get_domain_space()) - number_aff = number_aff.set_constant(num) + number_aff = number_aff.set_constant_val(num) if isinstance(template, PwAff): result = PwAff.empty(template.get_space()) @@ -480,7 +482,7 @@ def _add_functionality(): return NotImplemented def aff_flordiv(self, other): - return self.scale_down(other).floor() + return self.scale_down_val(other).floor() for aff_class in [Aff, PwAff]: aff_class.__add__ = aff_add @@ -490,11 +492,71 @@ def _add_functionality(): aff_class.__mul__ = aff_mul aff_class.__rmul__ = aff_mul aff_class.__neg__ = aff_class.neg - aff_class.__mod__ = aff_class.mod + aff_class.__mod__ = aff_class.mod_val aff_class.__floordiv__ = aff_flordiv # }}} + # {{{ Val + + def val_new(cls, src, context=None): + if context is None: + context = _DEFAULT_CONTEXT + + if isinstance(src, (str, unicode)): + result = cls.read_from_str(context, src) + elif isinstance(src, (int, long)): + result = cls.int_from_si(context, src) + else: + raise TypeError("'src' must be int or string") + + result._made_from_python = True + return result + + def val_bogus_init(self, src, context=None): + assert self._made_from_python + del self._made_from_python + + def val_rsub(self, other): + return -self + other + + def val_nonzero(self): + return not self.is_zero() + + def val_repr(self): + return "%s(\"%s\")" % (type(self).__name__, self.to_str()) + + def val_to_python(self): + if not self.is_int(): + raise ValueError("can only convert integer Val to python") + + return long(self.to_str()) + + Val.__new__ = staticmethod(val_new) + Val.__init__ = val_bogus_init + Val.__add__ = Val.add + Val.__radd__ = Val.add + Val.__sub__ = Val.sub + Val.__rsub__ = val_rsub + Val.__mul__ = Val.mul + Val.__rmul__ = Val.mul + Val.__neg__ = Val.neg + Val.__mod__ = Val.mod + Val.__bool__ = Val.__nonzero__ = val_nonzero + + Val.__lt__ = Val.lt + Val.__gt__ = Val.gt + Val.__le__ = Val.le + Val.__ge__ = Val.ge + Val.__eq__ = Val.eq + Val.__ne__ = Val.ne + + Val.__repr__ = val_repr + Val.__str__ = Val.to_str + Val.to_python = val_to_python + + # }}} + # {{{ add automatic 'self' upcasts # note: automatic upcasts for method arguments are provided through diff --git a/islpy/version.py b/islpy/version.py index 1c631c284d95ce9f2bee416f8ed78a80807f9dee..92c29262fa4d3e5d7e00f6e6bef07af819a6d872 100644 --- a/islpy/version.py +++ b/islpy/version.py @@ -1,2 +1,2 @@ -VERSION = (2013, 4) +VERSION = (2014, 1) VERSION_TEXT = ".".join(str(i) for i in VERSION) diff --git a/setup.py b/setup.py index 611cab1398b6b54ab0afe9b78ace960f541124e4..df076f7f3ec578f3fe83068418c31f1944c14a27 100644 --- a/setup.py +++ b/setup.py @@ -127,7 +127,6 @@ def main(): install_requires=[ "pytest>=2", - "gmpy>=1.17,<2", # "Mako>=0.3.6", ], ext_modules=[ diff --git a/src/wrapper/gmpy.h b/src/wrapper/gmpy.h deleted file mode 100644 index 57476def05c364808ff00ccd04c62770ce17d771..0000000000000000000000000000000000000000 --- a/src/wrapper/gmpy.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - gmpy C API extension header file. - Part of Python's gmpy module since version 0.4 - - Created by Pearu Peterson , November 2000. - Edited by A. Martelli , December 2000. - Version 1.02, February 2007. - Version 1.03, June 2008 - Version 1.04, June 2008 (no changes) - Version 1.05, February 2009 (support MPIR) - */ - -#ifndef Py_GMPYMODULE_H -#define Py_GMPYMODULE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MS_WIN32) && defined(_MSC_VER) -/* the __MPN determination in stock gmp.h doesn't work, so...: */ -# define __MPN(x) __gmpn_##x -# define _PROTO(x) x -#define inline __inline -#endif - -#if defined MPIR -#include "mpir.h" -#else -#include "gmp.h" -#endif - -/* ensure 2.5 compatibility */ -#if PY_VERSION_HEX < 0x02050000 -typedef int Py_ssize_t; -#define PY_FORMAT_SIZE_T "" -#endif -#ifndef Py_TPFLAGS_HAVE_INDEX -#define Py_TPFLAGS_HAVE_INDEX 0 -#endif - -#if PY_VERSION_HEX < 0x030200A3 -typedef long Py_hash_t; -typedef unsigned long Py_uhash_t; -#endif - -/* Header file for gmpy */ -typedef struct { - PyObject_HEAD - /* PyObject* callable; */ - /* long flags; */ -} mpob; -typedef struct { - mpob ob; - mpz_t z; -} PympzObject; -typedef struct { - mpob ob; - mpq_t q; -} PympqObject; -typedef struct { - mpob ob; - mpf_t f; - size_t rebits; -} PympfObject; - -/* #define MPOBCAL(obj) ((mpob*)obj)->callable */ -/* #define MPOBFLA(obj) ((mpob*)obj)->flags */ - -#define Pympz_AS_MPZ(obj) (((PympzObject *)(obj))->z) -#define Pympq_AS_MPQ(obj) (((PympqObject *)(obj))->q) -#define Pympf_AS_MPF(obj) (((PympfObject *)(obj))->f) - - -#define Pympz_Type_NUM 0 -#define Pympq_Type_NUM 1 -#define Pympf_Type_NUM 2 - - /* C API functions */ - -#define Pympz_new_NUM 3 -#define Pympz_new_RETURN PympzObject * -#define Pympz_new_PROTO (void) - -#define Pympq_new_NUM 4 -#define Pympq_new_RETURN PympqObject * -#define Pympq_new_PROTO (void) - -#define Pympf_new_NUM 5 -#define Pympf_new_RETURN PympfObject * -#define Pympf_new_PROTO (size_t bits) - -#define Pympz_dealloc_NUM 6 -#define Pympz_dealloc_RETURN void -#define Pympz_dealloc_PROTO (PympzObject *self) - -#define Pympq_dealloc_NUM 7 -#define Pympq_dealloc_RETURN void -#define Pympq_dealloc_PROTO (PympqObject *self) - -#define Pympf_dealloc_NUM 8 -#define Pympf_dealloc_RETURN void -#define Pympf_dealloc_PROTO (PympfObject *self) - -#define Pympz_convert_arg_NUM 9 -#define Pympz_convert_arg_RETURN int -#define Pympz_convert_arg_PROTO (PyObject *arg, PyObject **ptr) - -#define Pympq_convert_arg_NUM 10 -#define Pympq_convert_arg_RETURN int -#define Pympq_convert_arg_PROTO (PyObject *arg, PyObject **ptr) - -#define Pympf_convert_arg_NUM 11 -#define Pympf_convert_arg_RETURN int -#define Pympf_convert_arg_PROTO (PyObject *arg, PyObject **ptr) - -/* Total number of C API pointers */ -#define Pygmpy_API_pointers 12 - -#ifdef GMPY_MODULE -/* This section is used when compiling gmpy.c */ -static PyTypeObject Pympz_Type; -#define Pympz_Check(v) (((PyObject*)v)->ob_type == &Pympz_Type) -static PyTypeObject Pympq_Type; -#define Pympq_Check(v) (((PyObject*)v)->ob_type == &Pympq_Type) -static PyTypeObject Pympf_Type; -#define Pympf_Check(v) (((PyObject*)v)->ob_type == &Pympf_Type) - -static Pympz_new_RETURN Pympz_new Pympz_new_PROTO; -static Pympz_dealloc_RETURN Pympz_dealloc Pympz_dealloc_PROTO; -static Pympz_convert_arg_RETURN Pympz_convert_arg Pympz_convert_arg_PROTO; -static Pympq_new_RETURN Pympq_new Pympq_new_PROTO; -static Pympq_dealloc_RETURN Pympq_dealloc Pympq_dealloc_PROTO; -static Pympq_convert_arg_RETURN Pympq_convert_arg Pympq_convert_arg_PROTO; -static Pympf_new_RETURN Pympf_new Pympf_new_PROTO; -static Pympf_dealloc_RETURN Pympf_dealloc Pympf_dealloc_PROTO; -static Pympf_convert_arg_RETURN Pympf_convert_arg Pympf_convert_arg_PROTO; - -#if PY_MAJOR_VERSION < 3 -#define export_gmpy(m) { \ - PyObject *d; \ - static void *Pygmpy_API[Pygmpy_API_pointers]; \ - PyObject *c_api_object; \ -\ - Pygmpy_API[Pympz_Type_NUM] = (void*)&Pympz_Type;\ - Pygmpy_API[Pympq_Type_NUM] = (void*)&Pympq_Type;\ - Pygmpy_API[Pympf_Type_NUM] = (void*)&Pympf_Type;\ -\ - Pygmpy_API[Pympz_new_NUM] = (void*)Pympz_new;\ - Pygmpy_API[Pympz_dealloc_NUM] = (void*)Pympz_dealloc;\ - Pygmpy_API[Pympz_convert_arg_NUM] = (void*)Pympz_convert_arg;\ - Pygmpy_API[Pympq_new_NUM] = (void*)Pympq_new;\ - Pygmpy_API[Pympq_dealloc_NUM] = (void*)Pympq_dealloc;\ - Pygmpy_API[Pympq_convert_arg_NUM] = (void*)Pympq_convert_arg;\ - Pygmpy_API[Pympf_new_NUM] = (void*)Pympf_new;\ - Pygmpy_API[Pympf_dealloc_NUM] = (void*)Pympf_dealloc;\ - Pygmpy_API[Pympf_convert_arg_NUM] = (void*)Pympf_convert_arg;\ -\ - c_api_object = PyCObject_FromVoidPtr((void*)Pygmpy_API, NULL);\ - d = PyModule_GetDict(m);\ - PyDict_SetItemString(d, "_C_API", c_api_object);\ - } -#endif - -#else -/* This section is used in other C-coded modules that use gmpy's API */ - -static void **Pygmpy_API; - -#define Pympz_Check(op) \ - ((op)->ob_type == (PyTypeObject *)Pygmpy_API[Pympz_Type_NUM]) -#define Pympz_Type (*(PyTypeObject *)Pygmpy_API[Pympz_Type_NUM]) -#define Pympq_Check(op) \ - ((op)->ob_type == (PyTypeObject *)Pygmpy_API[Pympq_Type_NUM]) -#define Pympq_Type (*(PyTypeObject *)Pygmpy_API[Pympq_Type_NUM]) -#define Pympf_Check(op) \ - ((op)->ob_type == (PyTypeObject *)Pygmpy_API[Pympf_Type_NUM]) -#define Pympf_Type (*(PyTypeObject *)Pygmpy_API[Pympf_Type_NUM]) - -#define Pympz_new \ - (*(Pympz_new_RETURN (*)Pympz_new_PROTO) Pygmpy_API[Pympz_new_NUM]) -#define Pympz_dealloc \ - (*(Pympz_dealloc_RETURN (*)Pympz_dealloc_PROTO) Pygmpy_API[Pympz_dealloc_NUM]) -#define Pympz_convert_arg \ - (*(Pympz_convert_arg_RETURN (*)Pympz_convert_arg_PROTO) Pygmpy_API[Pympz_convert_arg_NUM]) -#define Pympq_new \ - (*(Pympq_new_RETURN (*)Pympq_new_PROTO) Pygmpy_API[Pympq_new_NUM]) -#define Pympq_dealloc \ - (*(Pympq_dealloc_RETURN (*)Pympq_dealloc_PROTO) Pygmpy_API[Pympq_dealloc_NUM]) -#define Pympq_convert_arg \ - (*(Pympq_convert_arg_RETURN (*)Pympq_convert_arg_PROTO) Pygmpy_API[Pympq_convert_arg_NUM]) -#define Pympf_new \ - (*(Pympf_new_RETURN (*)Pympf_new_PROTO) Pygmpy_API[Pympf_new_NUM]) -#define Pympf_dealloc \ - (*(Pympf_dealloc_RETURN (*)Pympf_dealloc_PROTO) Pygmpy_API[Pympf_dealloc_NUM]) -#define Pympf_convert_arg \ - (*(Pympf_convert_arg_RETURN (*)Pympf_convert_arg_PROTO) Pygmpy_API[Pympf_convert_arg_NUM]) - -#if PY_MAJOR_VERSION < 3 -#define import_gmpy() \ - { \ - PyObject *module = PyImport_ImportModule("gmpy");\ - if (module != NULL) { \ - PyObject *module_dict = PyModule_GetDict(module); \ - PyObject *c_api_object = PyDict_GetItemString(module_dict, "_C_API"); \ - if (PyCObject_Check(c_api_object)) { \ - Pygmpy_API = (void **)PyCObject_AsVoidPtr(c_api_object); \ - } \ - } \ - } -#else -static int -import_gmpy(void) -{ - Pygmpy_API = (void **)PyCapsule_Import("gmpy._C_API", 0); - return (Pygmpy_API != NULL) ? 0 : -1; -} -#endif -#endif - -#ifdef __cplusplus -} -#endif -#endif /* !defined(Py_GMPYMODULE_H */ diff --git a/src/wrapper/wrap_isl.cpp b/src/wrapper/wrap_isl.cpp index 8f22c517a10d41948a6df7cd3e5827df6c586e0b..37608b9ea58f3a47b39e164b74e2ad9638ad3682 100644 --- a/src/wrapper/wrap_isl.cpp +++ b/src/wrapper/wrap_isl.cpp @@ -31,8 +31,6 @@ BOOST_PYTHON_MODULE(_isl) py::docstring_options doc_opt(true, false, false); - import_gmpy(); - /* { typedef isl_options cls; @@ -101,5 +99,4 @@ BOOST_PYTHON_MODULE(_isl) py::implicitly_convertible(); py::implicitly_convertible(); py::implicitly_convertible(); - } diff --git a/src/wrapper/wrap_isl.hpp b/src/wrapper/wrap_isl.hpp index 1e3f2d75dae238f9b2113246a4e7990111cefb78..18d674ad729e2cbad39e100ffa7d2baf2529fcd0 100644 --- a/src/wrapper/wrap_isl.hpp +++ b/src/wrapper/wrap_isl.hpp @@ -1,3 +1,7 @@ +// workaround for +// https://gmplib.org/list-archives/gmp-bugs/2006-November/000627.html +#include + #include #include #include @@ -20,7 +24,6 @@ #include #include #include -#include "gmpy.h" #include "wrap_helpers.hpp" // TODO: flow.h @@ -38,20 +41,6 @@ namespace isl { } }; - struct managed_int - { - isl_int m_data; - - managed_int() - { - isl_int_init(m_data); - } - ~managed_int() - { - isl_int_clear(m_data); - } - }; - struct ctx; typedef boost::unordered_map ctx_use_map_t; @@ -219,6 +208,7 @@ namespace isl WRAP_CLASS(band); WRAP_CLASS(schedule); + WRAP_CLASS(schedule_constraints); WRAP_CLASS(access_info); WRAP_CLASS(flow); @@ -242,6 +232,11 @@ namespace isl } class format { }; + + inline void my_decref(void *user) + { + Py_DECREF((PyObject *) user); + } } diff --git a/src/wrapper/wrap_isl_part1.cpp b/src/wrapper/wrap_isl_part1.cpp index 35956ea21d8f024220bf152ed0cf187200bc7881..9389c4170f546112cb4dec5d1c2c1285de4ae1fb 100644 --- a/src/wrapper/wrap_isl_part1.cpp +++ b/src/wrapper/wrap_isl_part1.cpp @@ -9,8 +9,6 @@ namespace isl void islpy_expose_part1() { - import_gmpy(); - { typedef isl::ctx cls; py::class_, boost::noncopyable> @@ -43,7 +41,6 @@ void islpy_expose_part1() MAKE_WRAP(multi_val, MultiVal); MAKE_WRAP(vec, Vec); MAKE_WRAP(mat, Mat); - MAKE_WRAP(id, Id); MAKE_WRAP(aff, Aff); MAKE_WRAP(pw_aff, PwAff); @@ -52,6 +49,7 @@ void islpy_expose_part1() MAKE_WRAP(pw_multi_aff, PwMultiAff); MAKE_WRAP(union_pw_multi_aff, UnionPwMultiAff); + MAKE_WRAP(id, Id); MAKE_WRAP(constraint, Constraint); MAKE_WRAP(space, Space); MAKE_WRAP(local_space, LocalSpace); diff --git a/src/wrapper/wrap_isl_part2.cpp b/src/wrapper/wrap_isl_part2.cpp index 8dc8873c61c8ba09e178092927d8ee9c798d8da7..cc247e7f307ba2c9beb15b04155e73d85a1d2232 100644 --- a/src/wrapper/wrap_isl_part2.cpp +++ b/src/wrapper/wrap_isl_part2.cpp @@ -7,8 +7,6 @@ namespace isl void islpy_expose_part2() { - import_gmpy(); - MAKE_WRAP(basic_set, BasicSet); MAKE_WRAP(basic_map, BasicMap); MAKE_WRAP(set, Set); diff --git a/src/wrapper/wrap_isl_part3.cpp b/src/wrapper/wrap_isl_part3.cpp index 30e161560d957af85669c2e09f1cbf6713200e8a..6249ac65da4cdb8bb17858c4a2b1068c68231192 100644 --- a/src/wrapper/wrap_isl_part3.cpp +++ b/src/wrapper/wrap_isl_part3.cpp @@ -7,18 +7,19 @@ namespace isl void islpy_expose_part3() { - import_gmpy(); - - MAKE_WRAP(qpolynomial, QPolynomial); - MAKE_WRAP(pw_qpolynomial, PwQPolynomial); MAKE_WRAP(qpolynomial_fold, QPolynomialFold); MAKE_WRAP(pw_qpolynomial_fold, PwQPolynomialFold); - MAKE_WRAP(union_pw_qpolynomial, UnionPwQPolynomial); MAKE_WRAP(union_pw_qpolynomial_fold, UnionPwQPolynomialFold); + MAKE_WRAP(union_pw_qpolynomial, UnionPwQPolynomial); + + MAKE_WRAP(qpolynomial, QPolynomial); + MAKE_WRAP(pw_qpolynomial, PwQPolynomial); + MAKE_WRAP(term, Term); MAKE_WRAP(band, Band); MAKE_WRAP(schedule, Schedule); + MAKE_WRAP(schedule_constraints, ScheduleConstraints); MAKE_WRAP(access_info, AccessInfo); MAKE_WRAP(flow, Flow); diff --git a/test/test_isl.py b/test/test_isl.py index f5f824aecf52d414187ee5bcf8e7f8969a1fedb3..b5c4d6d8382d8021f63a93a90dc0fc69b7886e01 100644 --- a/test/test_isl.py +++ b/test/test_isl.py @@ -44,7 +44,7 @@ def test_error_on_invalid_index(): def test_pwqpoly(): def term_handler(term): - print(term.get_num()) + print(term.get_coefficient()) def piece_handler(set, qpoly): qpoly.foreach_term(term_handler) @@ -53,6 +53,23 @@ def test_pwqpoly(): pwqp.foreach_piece(piece_handler) +def test_id_user(): + ctx = isl.Context() + foo = isl.Id("foo", context=ctx) # noqa + t = (1, 2) + bar = isl.Id("bar", t, context=ctx) + + assert bar.user is t + + +def test_val(): + for src in [17, "17"]: + v = isl.Val(src) + print v + assert v == 17 + assert v.to_python() == 17 + + if __name__ == "__main__": import sys if len(sys.argv) > 1: