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: