Update to isl-0.20-35-ge0a98b62

git-svn-id: https://llvm.org/svn/llvm-project/polly/trunk@338501 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/External/isl/ChangeLog b/lib/External/isl/ChangeLog
index 56c9ad2..c09ebdf 100644
--- a/lib/External/isl/ChangeLog
+++ b/lib/External/isl/ChangeLog
@@ -1,3 +1,10 @@
+version: 0.20
+date: Sat Jul 21 18:10:08 CEST 2018
+changes:
+	- keep track of domain in 0D isl_multi_pw_aff and isl_multi_union_pw_aff
+	- add isl_aff_eval and isl_pw_aff_eval
+	- add fixed-size rectangular box hull
+---
 version: 0.19
 date: Sat Mar  3 10:44:49 CET 2018
 changes:
diff --git a/lib/External/isl/GIT_HEAD_ID b/lib/External/isl/GIT_HEAD_ID
index b4b437e..e22dafc 100644
--- a/lib/External/isl/GIT_HEAD_ID
+++ b/lib/External/isl/GIT_HEAD_ID
@@ -1 +1 @@
-isl-0.19-224-gce84a511
+isl-0.20-35-ge0a98b62
diff --git a/lib/External/isl/Makefile.am b/lib/External/isl/Makefile.am
index 70d36f7..6c1729b 100644
--- a/lib/External/isl/Makefile.am
+++ b/lib/External/isl/Makefile.am
@@ -1,5 +1,8 @@
 if HAVE_CLANG
-    MAYBE_INTERFACE = interface
+MAYBE_INTERFACE = interface
+FORCE:
+interface/extract_interface: FORCE
+	$(MAKE) $(AM_MAKEFLAGS) -C interface extract_interface
 endif
 SUBDIRS = . $(MAYBE_INTERFACE) doc
 DIST_SUBDIRS = $(MAYBE_INTERFACE) doc
@@ -15,6 +18,28 @@
 	isl_flow isl_flow_cmp isl_schedule_cmp
 TESTS = isl_test codegen_test.sh pip_test.sh bound_test.sh isl_test_int \
 	flow_test.sh schedule_test.sh
+if HAVE_CPP_ISL_H
+  CPP_H = include/isl/cpp.h
+if HAVE_CXX11
+  noinst_PROGRAMS += isl_test_cpp
+  TESTS += isl_test_cpp
+endif
+endif
+if HAVE_CLANG
+if HAVE_CXX11
+  noinst_PROGRAMS += isl_test_cpp-checked isl_test_cpp-checked-conversion
+  TESTS += isl_test_cpp-checked isl_test_cpp-checked-conversion
+endif
+if HAVE_PYTHON
+  TESTS += isl_test_python.py
+  isl_test_python.py: interface/isl.py libisl.la
+endif
+endif
+TEST_EXTENSIONS = .py
+AM_TESTS_ENVIRONMENT = \
+	export PYTHONPATH=interface; \
+	export LD_LIBRARY_PATH=.libs;
+PY_LOG_COMPILER = $(PYTHON)
 
 if IMATH_FOR_MP
 
@@ -58,7 +83,8 @@
 MP_INCLUDE_H = include/isl/val_gmp.h
 endif
 
-AM_CPPFLAGS = -I. -I$(srcdir) -I$(srcdir)/include -Iinclude/ @MP_CPPFLAGS@
+includes = -I. -I$(srcdir) -I$(srcdir)/include -Iinclude/
+AM_CPPFLAGS = $(includes) @MP_CPPFLAGS@
 AM_CFLAGS = @WARNING_FLAGS@
 
 libisl_la_SOURCES = \
@@ -264,9 +290,75 @@
 isl_closure_SOURCES = \
 	closure.c
 
+isl_test_cpp_CXXFLAGS = @CXX11FLAGS@
+isl_test_cpp_SOURCES = \
+	isl_test_cpp.cc \
+	include/isl/cpp.h
+isl_test_cpp_LDFLAGS = @MP_LDFLAGS@
+isl_test_cpp_LDADD = libisl.la @MP_LIBS@
+
+isl_test_cpp_checked_CXXFLAGS = @CXX11FLAGS@
+isl_test_cpp_checked_SOURCES = \
+	isl_test_cpp-checked.cc \
+	include/isl/cpp-checked.h
+isl_test_cpp_checked_LDFLAGS = @MP_LDFLAGS@
+isl_test_cpp_checked_LDADD = libisl.la @MP_LIBS@
+
+isl_test_cpp_checked_conversion_CXXFLAGS = @CXX11FLAGS@
+isl_test_cpp_checked_conversion_SOURCES = \
+	isl_test_cpp-checked-conversion.cc \
+	include/isl/cpp-checked-conversion.h
+isl_test_cpp_checked_conversion_LDFLAGS = @MP_LDFLAGS@
+isl_test_cpp_checked_conversion_LDADD = libisl.la @MP_LIBS@
+
+# dummy library that captures the dependencies on all headers
+# that are relevant for the bindings
+noinst_LIBRARIES = libdep.a
+libdep_a_SOURCES = all.c
+
+if HAVE_CLANG
+interface/isl.py: interface/extract_interface libdep.a python/isl.py.top
+	(cat $(srcdir)/python/isl.py.top && \
+		interface/extract_interface$(EXEEXT) --language=python \
+			$(includes) $(srcdir)/all.h) \
+			> $@ || (rm $@ && false)
+
+include/isl/cpp.h: interface/extract_interface libdep.a \
+		cpp/cpp.h.top cpp/cpp.h.pre cpp/cpp.h.bot
+	$(MKDIR_P) "include/isl/cpp" && \
+	(cat $(srcdir)/cpp/cpp.h.top $(srcdir)/all.h \
+	    $(srcdir)/cpp/cpp.h.pre && \
+		interface/extract_interface$(EXEEXT) --language=cpp \
+			$(includes) $(srcdir)/all.h && \
+		cat $(srcdir)/cpp/cpp.h.bot) \
+			> $@ || (rm $@ && false)
+
+include/isl/cpp-checked.h: interface/extract_interface libdep.a \
+		cpp/cpp-checked.h.top \
+		cpp/cpp-checked.h.pre cpp/cpp-checked.h.bot
+	(cat $(srcdir)/cpp/cpp-checked.h.top $(srcdir)/all.h \
+	    $(srcdir)/cpp/cpp-checked.h.pre && \
+		interface/extract_interface$(EXEEXT) \
+			--language=cpp-checked \
+			$(includes) $(srcdir)/all.h && \
+		cat $(srcdir)/cpp/cpp-checked.h.bot) \
+			> $@ || (rm $@ && false)
+
+include/isl/cpp-checked-conversion.h: interface/extract_interface libdep.a \
+		cpp/cpp-checked-conversion.h.top \
+		cpp/cpp-checked-conversion.h.bot
+	(cat $(srcdir)/cpp/cpp-checked-conversion.h.top && \
+		interface/extract_interface$(EXEEXT) \
+			--language=cpp-checked-conversion \
+			$(includes) $(srcdir)/all.h && \
+		cat $(srcdir)/cpp/cpp-checked-conversion.h.bot) \
+			> $@ || (rm $@ && false)
+endif
+
 nodist_pkginclude_HEADERS = \
 	include/isl/stdint.h
 pkginclude_HEADERS = \
+	$(CPP_H) \
 	$(MP_INCLUDE_H) \
 	include/isl/aff.h \
 	include/isl/aff_type.h \
@@ -327,10 +419,14 @@
 	include/isl/version.h \
 	include/isl/vertices.h
 
-BUILT_SOURCES = gitversion.h
-
-CLEANFILES = \
-	gitversion.h
+if HAVE_CLANG
+    CPP_INTERFACES = \
+	include/isl/cpp.h \
+	include/isl/cpp-checked.h \
+	include/isl/cpp-checked-conversion.h
+endif
+BUILT_SOURCES = gitversion.h $(CPP_INTERFACES)
+CLEANFILES = gitversion.h interface/isl.py $(CPP_INTERFACES)
 
 DISTCLEANFILES = \
 	isl-uninstalled.sh \
@@ -407,12 +503,19 @@
 	imath/imath.h \
 	imath/imrat.c \
 	imath/imrat.h \
-	interface/all.h \
-	interface/isl.py.top \
-	interface/isl_test_python.py \
+	all.h \
+	cpp \
+	python \
+	isl_test_cpp-generic.cc \
+	isl_test_python.py \
 	test_inputs
 
+if HAVE_CLANG
+dist-hook: interface/isl.py
+	cp interface/isl.py $(distdir)/interface/
+else
 dist-hook:
+endif
 	echo @GIT_HEAD_VERSION@ > $(distdir)/GIT_HEAD_ID
 	(cd doc; make manual.pdf)
 	cp doc/manual.pdf $(distdir)/doc/
diff --git a/lib/External/isl/Makefile.in b/lib/External/isl/Makefile.in
index 1b67097..0f96253 100644
--- a/lib/External/isl/Makefile.in
+++ b/lib/External/isl/Makefile.in
@@ -17,6 +17,7 @@
 
 
 
+
 VPATH = @srcdir@
 am__is_gnu_make = { \
   if test -z '$(MAKELEVEL)'; then \
@@ -98,17 +99,23 @@
 	isl_closure$(EXEEXT) isl_bound$(EXEEXT) isl_schedule$(EXEEXT) \
 	isl_codegen$(EXEEXT) isl_test_int$(EXEEXT) isl_flow$(EXEEXT) \
 	isl_flow_cmp$(EXEEXT) isl_schedule_cmp$(EXEEXT) \
-	$(am__EXEEXT_1)
+	$(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
 TESTS = isl_test$(EXEEXT) codegen_test.sh pip_test.sh bound_test.sh \
 	isl_test_int$(EXEEXT) flow_test.sh schedule_test.sh \
-	$(am__EXEEXT_1)
-@IMATH_FOR_MP_TRUE@am__append_1 = isl_test_imath
-@IMATH_FOR_MP_TRUE@am__append_2 = isl_test_imath
-@IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_TRUE@am__append_3 = isl_int_sioimath.h \
+	$(am__EXEEXT_1) $(am__EXEEXT_2) $(am__append_5) \
+	$(am__EXEEXT_3)
+@HAVE_CPP_ISL_H_TRUE@@HAVE_CXX11_TRUE@am__append_1 = isl_test_cpp
+@HAVE_CPP_ISL_H_TRUE@@HAVE_CXX11_TRUE@am__append_2 = isl_test_cpp
+@HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@am__append_3 = isl_test_cpp-checked isl_test_cpp-checked-conversion
+@HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@am__append_4 = isl_test_cpp-checked isl_test_cpp-checked-conversion
+@HAVE_CLANG_TRUE@@HAVE_PYTHON_TRUE@am__append_5 = isl_test_python.py
+@IMATH_FOR_MP_TRUE@am__append_6 = isl_test_imath
+@IMATH_FOR_MP_TRUE@am__append_7 = isl_test_imath
+@IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_TRUE@am__append_8 = isl_int_sioimath.h \
 @IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_TRUE@	isl_int_sioimath.c \
 @IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_TRUE@	isl_val_sioimath.c
 
-@IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_FALSE@am__append_4 = isl_val_imath.c
+@IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_FALSE@am__append_9 = isl_val_imath.c
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
@@ -117,6 +124,8 @@
 	$(top_srcdir)/m4/ax_compiler_vendor.m4 \
 	$(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
 	$(top_srcdir)/m4/ax_create_stdint_h.m4 \
+	$(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+	$(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
 	$(top_srcdir)/m4/ax_detect_clang.m4 \
 	$(top_srcdir)/m4/ax_detect_git_head.m4 \
 	$(top_srcdir)/m4/ax_detect_gmp.m4 \
@@ -141,6 +150,16 @@
 CONFIG_CLEAN_FILES = isl_srcdir.c bound_test.sh codegen_test.sh \
 	pip_test.sh flow_test.sh schedule_test.sh
 CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo "  AR      " $@;
+am__v_AR_1 = 
+libdep_a_AR = $(AR) $(ARFLAGS)
+libdep_a_LIBADD =
+am_libdep_a_OBJECTS = all.$(OBJEXT)
+libdep_a_OBJECTS = $(am_libdep_a_OBJECTS)
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -259,7 +278,11 @@
 libisl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(libisl_la_LDFLAGS) $(LDFLAGS) -o $@
-@IMATH_FOR_MP_TRUE@am__EXEEXT_1 = isl_test_imath$(EXEEXT)
+@HAVE_CPP_ISL_H_TRUE@@HAVE_CXX11_TRUE@am__EXEEXT_1 =  \
+@HAVE_CPP_ISL_H_TRUE@@HAVE_CXX11_TRUE@	isl_test_cpp$(EXEEXT)
+@HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@am__EXEEXT_2 = isl_test_cpp-checked$(EXEEXT) \
+@HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	isl_test_cpp-checked-conversion$(EXEEXT)
+@IMATH_FOR_MP_TRUE@am__EXEEXT_3 = isl_test_imath$(EXEEXT)
 PROGRAMS = $(noinst_PROGRAMS)
 am_isl_bound_OBJECTS = bound.$(OBJEXT)
 isl_bound_OBJECTS = $(am_isl_bound_OBJECTS)
@@ -335,6 +358,28 @@
 isl_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(isl_test_LDFLAGS) $(LDFLAGS) -o $@
+am_isl_test_cpp_OBJECTS = isl_test_cpp-isl_test_cpp.$(OBJEXT)
+isl_test_cpp_OBJECTS = $(am_isl_test_cpp_OBJECTS)
+isl_test_cpp_DEPENDENCIES = libisl.la
+isl_test_cpp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(isl_test_cpp_CXXFLAGS) \
+	$(CXXFLAGS) $(isl_test_cpp_LDFLAGS) $(LDFLAGS) -o $@
+am_isl_test_cpp_checked_OBJECTS =  \
+	isl_test_cpp_checked-isl_test_cpp-checked.$(OBJEXT)
+isl_test_cpp_checked_OBJECTS = $(am_isl_test_cpp_checked_OBJECTS)
+isl_test_cpp_checked_DEPENDENCIES = libisl.la
+isl_test_cpp_checked_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) \
+	$(isl_test_cpp_checked_LDFLAGS) $(LDFLAGS) -o $@
+am_isl_test_cpp_checked_conversion_OBJECTS = isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.$(OBJEXT)
+isl_test_cpp_checked_conversion_OBJECTS =  \
+	$(am_isl_test_cpp_checked_conversion_OBJECTS)
+isl_test_cpp_checked_conversion_DEPENDENCIES = libisl.la
+isl_test_cpp_checked_conversion_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) \
+	$(isl_test_cpp_checked_conversion_LDFLAGS) $(LDFLAGS) -o $@
 isl_test_imath_SOURCES = isl_test_imath.c
 isl_test_imath_OBJECTS = isl_test_imath.$(OBJEXT)
 @IMATH_FOR_MP_TRUE@isl_test_imath_DEPENDENCIES = libisl.la
@@ -382,23 +427,46 @@
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
-SOURCES = $(libisl_la_SOURCES) $(isl_bound_SOURCES) $(isl_cat_SOURCES) \
-	$(isl_closure_SOURCES) $(isl_codegen_SOURCES) \
-	$(isl_flow_SOURCES) $(isl_flow_cmp_SOURCES) $(isl_pip_SOURCES) \
-	$(isl_polyhedron_detect_equalities_SOURCES) \
-	$(isl_polyhedron_minimize_SOURCES) \
-	$(isl_polyhedron_sample_SOURCES) $(isl_polytope_scan_SOURCES) \
-	$(isl_schedule_SOURCES) $(isl_schedule_cmp_SOURCES) isl_test.c \
-	isl_test_imath.c isl_test_int.c
-DIST_SOURCES = $(am__libisl_la_SOURCES_DIST) $(isl_bound_SOURCES) \
-	$(isl_cat_SOURCES) $(isl_closure_SOURCES) \
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo "  CXX     " $@;
+am__v_CXX_1 = 
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo "  CXXLD   " $@;
+am__v_CXXLD_1 = 
+SOURCES = $(libdep_a_SOURCES) $(libisl_la_SOURCES) \
+	$(isl_bound_SOURCES) $(isl_cat_SOURCES) $(isl_closure_SOURCES) \
 	$(isl_codegen_SOURCES) $(isl_flow_SOURCES) \
 	$(isl_flow_cmp_SOURCES) $(isl_pip_SOURCES) \
 	$(isl_polyhedron_detect_equalities_SOURCES) \
 	$(isl_polyhedron_minimize_SOURCES) \
 	$(isl_polyhedron_sample_SOURCES) $(isl_polytope_scan_SOURCES) \
 	$(isl_schedule_SOURCES) $(isl_schedule_cmp_SOURCES) isl_test.c \
-	isl_test_imath.c isl_test_int.c
+	$(isl_test_cpp_SOURCES) $(isl_test_cpp_checked_SOURCES) \
+	$(isl_test_cpp_checked_conversion_SOURCES) isl_test_imath.c \
+	isl_test_int.c
+DIST_SOURCES = $(libdep_a_SOURCES) $(am__libisl_la_SOURCES_DIST) \
+	$(isl_bound_SOURCES) $(isl_cat_SOURCES) $(isl_closure_SOURCES) \
+	$(isl_codegen_SOURCES) $(isl_flow_SOURCES) \
+	$(isl_flow_cmp_SOURCES) $(isl_pip_SOURCES) \
+	$(isl_polyhedron_detect_equalities_SOURCES) \
+	$(isl_polyhedron_minimize_SOURCES) \
+	$(isl_polyhedron_sample_SOURCES) $(isl_polytope_scan_SOURCES) \
+	$(isl_schedule_SOURCES) $(isl_schedule_cmp_SOURCES) isl_test.c \
+	$(isl_test_cpp_SOURCES) $(isl_test_cpp_checked_SOURCES) \
+	$(isl_test_cpp_checked_conversion_SOURCES) isl_test_imath.c \
+	isl_test_int.c
 RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
 	ctags-recursive dvi-recursive html-recursive info-recursive \
 	install-data-recursive install-dvi-recursive \
@@ -413,27 +481,27 @@
     *) (install-info --version) >/dev/null 2>&1;; \
   esac
 DATA = $(pkgconfig_DATA)
-am__pkginclude_HEADERS_DIST = include/isl/val_gmp.h include/isl/aff.h \
-	include/isl/aff_type.h include/isl/arg.h include/isl/ast.h \
-	include/isl/ast_type.h include/isl/ast_build.h \
-	include/isl/constraint.h include/isl/ctx.h \
-	include/isl/fixed_box.h include/isl/flow.h include/isl/id.h \
-	include/isl/id_type.h include/isl/id_to_ast_expr.h \
-	include/isl/id_to_id.h include/isl/id_to_pw_aff.h \
-	include/isl/ilp.h include/isl/hash.h include/isl/hmap.h \
-	include/isl/hmap_templ.c include/isl/list.h \
-	include/isl/local_space.h include/isl/lp.h include/isl/mat.h \
-	include/isl/map.h include/isl/map_to_basic_set.h \
-	include/isl/map_type.h include/isl/maybe.h \
-	include/isl/maybe_ast_expr.h include/isl/maybe_basic_set.h \
-	include/isl/maybe_id.h include/isl/maybe_pw_aff.h \
-	include/isl/maybe_templ.h include/isl/multi.h \
-	include/isl/obj.h include/isl/options.h include/isl/point.h \
-	include/isl/polynomial.h include/isl/polynomial_type.h \
-	include/isl/printer.h include/isl/printer_type.h \
-	include/isl/schedule.h include/isl/schedule_node.h \
-	include/isl/schedule_type.h include/isl/set.h \
-	include/isl/set_type.h include/isl/space.h \
+am__pkginclude_HEADERS_DIST = include/isl/cpp.h include/isl/val_gmp.h \
+	include/isl/aff.h include/isl/aff_type.h include/isl/arg.h \
+	include/isl/ast.h include/isl/ast_type.h \
+	include/isl/ast_build.h include/isl/constraint.h \
+	include/isl/ctx.h include/isl/fixed_box.h include/isl/flow.h \
+	include/isl/id.h include/isl/id_type.h \
+	include/isl/id_to_ast_expr.h include/isl/id_to_id.h \
+	include/isl/id_to_pw_aff.h include/isl/ilp.h \
+	include/isl/hash.h include/isl/hmap.h include/isl/hmap_templ.c \
+	include/isl/list.h include/isl/local_space.h include/isl/lp.h \
+	include/isl/mat.h include/isl/map.h \
+	include/isl/map_to_basic_set.h include/isl/map_type.h \
+	include/isl/maybe.h include/isl/maybe_ast_expr.h \
+	include/isl/maybe_basic_set.h include/isl/maybe_id.h \
+	include/isl/maybe_pw_aff.h include/isl/maybe_templ.h \
+	include/isl/multi.h include/isl/obj.h include/isl/options.h \
+	include/isl/point.h include/isl/polynomial.h \
+	include/isl/polynomial_type.h include/isl/printer.h \
+	include/isl/printer_type.h include/isl/schedule.h \
+	include/isl/schedule_node.h include/isl/schedule_type.h \
+	include/isl/set.h include/isl/set_type.h include/isl/space.h \
 	include/isl/space_type.h include/isl/stream.h \
 	include/isl/stride_info.h include/isl/union_map.h \
 	include/isl/union_map_type.h include/isl/union_set.h \
@@ -627,7 +695,6 @@
   bases=`echo $$bases`
 RECHECK_LOGS = $(TEST_LOGS)
 TEST_SUITE_LOG = test-suite.log
-TEST_EXTENSIONS = @EXEEXT@ .test
 LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
 LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
 am__set_b = \
@@ -642,10 +709,9 @@
   esac
 am__test_logs1 = $(TESTS:=.log)
 am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
-TEST_LOGS = $(am__test_logs2:.test.log=.log)
-TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
-TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
-	$(TEST_LOG_FLAGS)
+TEST_LOGS = $(am__test_logs2:.py.log=.log)
+PY_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+PY_LOG_COMPILE = $(PY_LOG_COMPILER) $(AM_PY_LOG_FLAGS) $(PY_LOG_FLAGS)
 am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/bound_test.sh.in \
 	$(srcdir)/codegen_test.sh.in $(srcdir)/flow_test.sh.in \
 	$(srcdir)/isl_config.h.in $(srcdir)/isl_srcdir.c.in \
@@ -711,6 +777,7 @@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CXX = @CXX@
+CXX11FLAGS = @CXX11FLAGS@
 CXXCPP = @CXXCPP@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
@@ -730,6 +797,7 @@
 GIT_HEAD_ID = @GIT_HEAD_ID@
 GIT_HEAD_VERSION = @GIT_HEAD_VERSION@
 GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -849,6 +917,13 @@
 ACLOCAL_AMFLAGS = -I m4
 AUTOMAKE_OPTIONS = nostdinc subdir-objects
 lib_LTLIBRARIES = libisl.la
+@HAVE_CPP_ISL_H_TRUE@CPP_H = include/isl/cpp.h
+TEST_EXTENSIONS = .py
+AM_TESTS_ENVIRONMENT = \
+	export PYTHONPATH=interface; \
+	export LD_LIBRARY_PATH=.libs;
+
+PY_LOG_COMPILER = $(PYTHON)
 @GMP_FOR_MP_TRUE@MP_SRC = \
 @GMP_FOR_MP_TRUE@	$(GET_MEMORY_FUNCTIONS) \
 @GMP_FOR_MP_TRUE@	isl_int_gmp.h \
@@ -859,12 +934,13 @@
 @IMATH_FOR_MP_TRUE@	imath_wrap/gmp_compat.h imath_wrap/imath.h \
 @IMATH_FOR_MP_TRUE@	imath_wrap/imrat.h imath_wrap/wrap.h \
 @IMATH_FOR_MP_TRUE@	imath_wrap/gmp_compat.c imath_wrap/imath.c \
-@IMATH_FOR_MP_TRUE@	imath_wrap/imrat.c $(am__append_3) \
-@IMATH_FOR_MP_TRUE@	$(am__append_4)
+@IMATH_FOR_MP_TRUE@	imath_wrap/imrat.c $(am__append_8) \
+@IMATH_FOR_MP_TRUE@	$(am__append_9)
 @GMP_FOR_MP_TRUE@MP_INCLUDE_H = include/isl/val_gmp.h
 @IMATH_FOR_MP_TRUE@MP_INCLUDE_H = 
 @GMP_FOR_MP_TRUE@@NEED_GET_MEMORY_FUNCTIONS_TRUE@GET_MEMORY_FUNCTIONS = mp_get_memory_functions.c
-AM_CPPFLAGS = -I. -I$(srcdir) -I$(srcdir)/include -Iinclude/ @MP_CPPFLAGS@
+includes = -I. -I$(srcdir) -I$(srcdir)/include -Iinclude/
+AM_CPPFLAGS = $(includes) @MP_CPPFLAGS@
 AM_CFLAGS = @WARNING_FLAGS@
 libisl_la_SOURCES = \
 	$(MP_SRC) \
@@ -1065,10 +1141,37 @@
 isl_closure_SOURCES = \
 	closure.c
 
+isl_test_cpp_CXXFLAGS = @CXX11FLAGS@
+isl_test_cpp_SOURCES = \
+	isl_test_cpp.cc \
+	include/isl/cpp.h
+
+isl_test_cpp_LDFLAGS = @MP_LDFLAGS@
+isl_test_cpp_LDADD = libisl.la @MP_LIBS@
+isl_test_cpp_checked_CXXFLAGS = @CXX11FLAGS@
+isl_test_cpp_checked_SOURCES = \
+	isl_test_cpp-checked.cc \
+	include/isl/cpp-checked.h
+
+isl_test_cpp_checked_LDFLAGS = @MP_LDFLAGS@
+isl_test_cpp_checked_LDADD = libisl.la @MP_LIBS@
+isl_test_cpp_checked_conversion_CXXFLAGS = @CXX11FLAGS@
+isl_test_cpp_checked_conversion_SOURCES = \
+	isl_test_cpp-checked-conversion.cc \
+	include/isl/cpp-checked-conversion.h
+
+isl_test_cpp_checked_conversion_LDFLAGS = @MP_LDFLAGS@
+isl_test_cpp_checked_conversion_LDADD = libisl.la @MP_LIBS@
+
+# dummy library that captures the dependencies on all headers
+# that are relevant for the bindings
+noinst_LIBRARIES = libdep.a
+libdep_a_SOURCES = all.c
 nodist_pkginclude_HEADERS = \
 	include/isl/stdint.h
 
 pkginclude_HEADERS = \
+	$(CPP_H) \
 	$(MP_INCLUDE_H) \
 	include/isl/aff.h \
 	include/isl/aff_type.h \
@@ -1129,10 +1232,13 @@
 	include/isl/version.h \
 	include/isl/vertices.h
 
-BUILT_SOURCES = gitversion.h
-CLEANFILES = \
-	gitversion.h
+@HAVE_CLANG_TRUE@CPP_INTERFACES = \
+@HAVE_CLANG_TRUE@	include/isl/cpp.h \
+@HAVE_CLANG_TRUE@	include/isl/cpp-checked.h \
+@HAVE_CLANG_TRUE@	include/isl/cpp-checked-conversion.h
 
+BUILT_SOURCES = gitversion.h $(CPP_INTERFACES)
+CLEANFILES = gitversion.h interface/isl.py $(CPP_INTERFACES)
 DISTCLEANFILES = \
 	isl-uninstalled.sh \
 	isl-uninstalled.pc \
@@ -1208,9 +1314,11 @@
 	imath/imath.h \
 	imath/imrat.c \
 	imath/imrat.h \
-	interface/all.h \
-	interface/isl.py.top \
-	interface/isl_test_python.py \
+	all.h \
+	cpp \
+	python \
+	isl_test_cpp-generic.cc \
+	isl_test_python.py \
 	test_inputs
 
 pkgconfigdir = $(pkgconfig_libdir)
@@ -1219,7 +1327,7 @@
 	$(MAKE) $(AM_MAKEFLAGS) all-recursive
 
 .SUFFIXES:
-.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+.SUFFIXES: .c .cc .lo .log .o .obj .py .py$(EXEEXT) .trs
 am--refresh: Makefile
 	@:
 $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
@@ -1281,6 +1389,14 @@
 schedule_test.sh: $(top_builddir)/config.status $(srcdir)/schedule_test.sh.in
 	cd $(top_builddir) && $(SHELL) ./config.status $@
 
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libdep.a: $(libdep_a_OBJECTS) $(libdep_a_DEPENDENCIES) $(EXTRA_libdep_a_DEPENDENCIES) 
+	$(AM_V_at)-rm -f libdep.a
+	$(AM_V_AR)$(libdep_a_AR) libdep.a $(libdep_a_OBJECTS) $(libdep_a_LIBADD)
+	$(AM_V_at)$(RANLIB) libdep.a
+
 install-libLTLIBRARIES: $(lib_LTLIBRARIES)
 	@$(NORMAL_INSTALL)
 	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
@@ -1396,6 +1512,18 @@
 	@rm -f isl_test$(EXEEXT)
 	$(AM_V_CCLD)$(isl_test_LINK) $(isl_test_OBJECTS) $(isl_test_LDADD) $(LIBS)
 
+isl_test_cpp$(EXEEXT): $(isl_test_cpp_OBJECTS) $(isl_test_cpp_DEPENDENCIES) $(EXTRA_isl_test_cpp_DEPENDENCIES) 
+	@rm -f isl_test_cpp$(EXEEXT)
+	$(AM_V_CXXLD)$(isl_test_cpp_LINK) $(isl_test_cpp_OBJECTS) $(isl_test_cpp_LDADD) $(LIBS)
+
+isl_test_cpp-checked$(EXEEXT): $(isl_test_cpp_checked_OBJECTS) $(isl_test_cpp_checked_DEPENDENCIES) $(EXTRA_isl_test_cpp_checked_DEPENDENCIES) 
+	@rm -f isl_test_cpp-checked$(EXEEXT)
+	$(AM_V_CXXLD)$(isl_test_cpp_checked_LINK) $(isl_test_cpp_checked_OBJECTS) $(isl_test_cpp_checked_LDADD) $(LIBS)
+
+isl_test_cpp-checked-conversion$(EXEEXT): $(isl_test_cpp_checked_conversion_OBJECTS) $(isl_test_cpp_checked_conversion_DEPENDENCIES) $(EXTRA_isl_test_cpp_checked_conversion_DEPENDENCIES) 
+	@rm -f isl_test_cpp-checked-conversion$(EXEEXT)
+	$(AM_V_CXXLD)$(isl_test_cpp_checked_conversion_LINK) $(isl_test_cpp_checked_conversion_OBJECTS) $(isl_test_cpp_checked_conversion_LDADD) $(LIBS)
+
 isl_test_imath$(EXEEXT): $(isl_test_imath_OBJECTS) $(isl_test_imath_DEPENDENCIES) $(EXTRA_isl_test_imath_DEPENDENCIES) 
 	@rm -f isl_test_imath$(EXEEXT)
 	$(AM_V_CCLD)$(isl_test_imath_LINK) $(isl_test_imath_OBJECTS) $(isl_test_imath_LDADD) $(LIBS)
@@ -1412,6 +1540,7 @@
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/all.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basis_reduction_tab.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bound.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cat.Po@am__quote@
@@ -1491,6 +1620,9 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_tab_pip.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_tarjan.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_test_cpp-isl_test_cpp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_test_imath.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_test_int.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_transitive_closure.Plo@am__quote@
@@ -1539,6 +1671,72 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
+.cc.o:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+isl_test_cpp-isl_test_cpp.o: isl_test_cpp.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp-isl_test_cpp.o -MD -MP -MF $(DEPDIR)/isl_test_cpp-isl_test_cpp.Tpo -c -o isl_test_cpp-isl_test_cpp.o `test -f 'isl_test_cpp.cc' || echo '$(srcdir)/'`isl_test_cpp.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp-isl_test_cpp.Tpo $(DEPDIR)/isl_test_cpp-isl_test_cpp.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp.cc' object='isl_test_cpp-isl_test_cpp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp-isl_test_cpp.o `test -f 'isl_test_cpp.cc' || echo '$(srcdir)/'`isl_test_cpp.cc
+
+isl_test_cpp-isl_test_cpp.obj: isl_test_cpp.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp-isl_test_cpp.obj -MD -MP -MF $(DEPDIR)/isl_test_cpp-isl_test_cpp.Tpo -c -o isl_test_cpp-isl_test_cpp.obj `if test -f 'isl_test_cpp.cc'; then $(CYGPATH_W) 'isl_test_cpp.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp-isl_test_cpp.Tpo $(DEPDIR)/isl_test_cpp-isl_test_cpp.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp.cc' object='isl_test_cpp-isl_test_cpp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp-isl_test_cpp.obj `if test -f 'isl_test_cpp.cc'; then $(CYGPATH_W) 'isl_test_cpp.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp.cc'; fi`
+
+isl_test_cpp_checked-isl_test_cpp-checked.o: isl_test_cpp-checked.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp_checked-isl_test_cpp-checked.o -MD -MP -MF $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Tpo -c -o isl_test_cpp_checked-isl_test_cpp-checked.o `test -f 'isl_test_cpp-checked.cc' || echo '$(srcdir)/'`isl_test_cpp-checked.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Tpo $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp-checked.cc' object='isl_test_cpp_checked-isl_test_cpp-checked.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp_checked-isl_test_cpp-checked.o `test -f 'isl_test_cpp-checked.cc' || echo '$(srcdir)/'`isl_test_cpp-checked.cc
+
+isl_test_cpp_checked-isl_test_cpp-checked.obj: isl_test_cpp-checked.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp_checked-isl_test_cpp-checked.obj -MD -MP -MF $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Tpo -c -o isl_test_cpp_checked-isl_test_cpp-checked.obj `if test -f 'isl_test_cpp-checked.cc'; then $(CYGPATH_W) 'isl_test_cpp-checked.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp-checked.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Tpo $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp-checked.cc' object='isl_test_cpp_checked-isl_test_cpp-checked.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp_checked-isl_test_cpp-checked.obj `if test -f 'isl_test_cpp-checked.cc'; then $(CYGPATH_W) 'isl_test_cpp-checked.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp-checked.cc'; fi`
+
+isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o: isl_test_cpp-checked-conversion.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o -MD -MP -MF $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Tpo -c -o isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o `test -f 'isl_test_cpp-checked-conversion.cc' || echo '$(srcdir)/'`isl_test_cpp-checked-conversion.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Tpo $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp-checked-conversion.cc' object='isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o `test -f 'isl_test_cpp-checked-conversion.cc' || echo '$(srcdir)/'`isl_test_cpp-checked-conversion.cc
+
+isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj: isl_test_cpp-checked-conversion.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj -MD -MP -MF $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Tpo -c -o isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj `if test -f 'isl_test_cpp-checked-conversion.cc'; then $(CYGPATH_W) 'isl_test_cpp-checked-conversion.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp-checked-conversion.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Tpo $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp-checked-conversion.cc' object='isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj `if test -f 'isl_test_cpp-checked-conversion.cc'; then $(CYGPATH_W) 'isl_test_cpp-checked-conversion.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp-checked-conversion.cc'; fi`
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
@@ -1908,6 +2106,27 @@
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+isl_test_cpp.log: isl_test_cpp$(EXEEXT)
+	@p='isl_test_cpp$(EXEEXT)'; \
+	b='isl_test_cpp'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+isl_test_cpp-checked.log: isl_test_cpp-checked$(EXEEXT)
+	@p='isl_test_cpp-checked$(EXEEXT)'; \
+	b='isl_test_cpp-checked'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+isl_test_cpp-checked-conversion.log: isl_test_cpp-checked-conversion$(EXEEXT)
+	@p='isl_test_cpp-checked-conversion$(EXEEXT)'; \
+	b='isl_test_cpp-checked-conversion'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 isl_test_imath.log: isl_test_imath$(EXEEXT)
 	@p='isl_test_imath$(EXEEXT)'; \
 	b='isl_test_imath'; \
@@ -1915,19 +2134,19 @@
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
-.test.log:
+.py.log:
 	@p='$<'; \
 	$(am__set_b); \
-	$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+	$(am__check_pre) $(PY_LOG_DRIVER) --test-name "$$f" \
 	--log-file $$b.log --trs-file $$b.trs \
-	$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+	$(am__common_driver_flags) $(AM_PY_LOG_DRIVER_FLAGS) $(PY_LOG_DRIVER_FLAGS) -- $(PY_LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
-@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@.py$(EXEEXT).log:
 @am__EXEEXT_TRUE@	@p='$<'; \
 @am__EXEEXT_TRUE@	$(am__set_b); \
-@am__EXEEXT_TRUE@	$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@	$(am__check_pre) $(PY_LOG_DRIVER) --test-name "$$f" \
 @am__EXEEXT_TRUE@	--log-file $$b.log --trs-file $$b.trs \
-@am__EXEEXT_TRUE@	$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@	$(am__common_driver_flags) $(AM_PY_LOG_DRIVER_FLAGS) $(PY_LOG_DRIVER_FLAGS) -- $(PY_LOG_COMPILE) \
 @am__EXEEXT_TRUE@	"$$tst" $(AM_TESTS_FD_REDIRECT)
 
 distdir: $(DISTFILES)
@@ -2125,8 +2344,8 @@
 	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
 check: $(BUILT_SOURCES)
 	$(MAKE) $(AM_MAKEFLAGS) check-recursive
-all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) \
-		isl_config.h
+all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(PROGRAMS) $(DATA) \
+		$(HEADERS) isl_config.h
 installdirs: installdirs-recursive
 installdirs-am:
 	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgincludedir)" "$(DESTDIR)$(pkgincludedir)"; do \
@@ -2174,7 +2393,7 @@
 clean: clean-recursive
 
 clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
-	clean-noinstPROGRAMS mostlyclean-am
+	clean-noinstLIBRARIES clean-noinstPROGRAMS mostlyclean-am
 
 distclean: distclean-recursive
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
@@ -2254,16 +2473,17 @@
 .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
 	am--refresh check check-TESTS check-am clean clean-cscope \
 	clean-generic clean-libLTLIBRARIES clean-libtool \
-	clean-noinstPROGRAMS cscope cscopelist-am ctags ctags-am dist \
-	dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \
-	dist-tarZ dist-xz dist-zip distcheck distclean \
-	distclean-compile distclean-generic distclean-hdr \
-	distclean-libtool distclean-tags distcleancheck distdir \
-	distuninstallcheck dvi dvi-am html html-am info info-am \
-	install install-am install-data install-data-am \
-	install-data-local install-dvi install-dvi-am install-exec \
-	install-exec-am install-html install-html-am install-info \
-	install-info-am install-libLTLIBRARIES install-man \
+	clean-noinstLIBRARIES clean-noinstPROGRAMS cscope \
+	cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+	dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \
+	dist-zip distcheck distclean distclean-compile \
+	distclean-generic distclean-hdr distclean-libtool \
+	distclean-tags distcleancheck distdir distuninstallcheck dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-data-local install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am \
+	install-libLTLIBRARIES install-man \
 	install-nodist_pkgincludeHEADERS install-pdf install-pdf-am \
 	install-pkgconfigDATA install-pkgincludeHEADERS install-ps \
 	install-ps-am install-strip installcheck installcheck-am \
@@ -2277,8 +2497,51 @@
 
 .PRECIOUS: Makefile
 
+@HAVE_CLANG_TRUE@FORCE:
+@HAVE_CLANG_TRUE@interface/extract_interface: FORCE
+@HAVE_CLANG_TRUE@	$(MAKE) $(AM_MAKEFLAGS) -C interface extract_interface
+@HAVE_CLANG_TRUE@@HAVE_PYTHON_TRUE@  isl_test_python.py: interface/isl.py libisl.la
 
-dist-hook:
+@HAVE_CLANG_TRUE@interface/isl.py: interface/extract_interface libdep.a python/isl.py.top
+@HAVE_CLANG_TRUE@	(cat $(srcdir)/python/isl.py.top && \
+@HAVE_CLANG_TRUE@		interface/extract_interface$(EXEEXT) --language=python \
+@HAVE_CLANG_TRUE@			$(includes) $(srcdir)/all.h) \
+@HAVE_CLANG_TRUE@			> $@ || (rm $@ && false)
+
+@HAVE_CLANG_TRUE@include/isl/cpp.h: interface/extract_interface libdep.a \
+@HAVE_CLANG_TRUE@		cpp/cpp.h.top cpp/cpp.h.pre cpp/cpp.h.bot
+@HAVE_CLANG_TRUE@	$(MKDIR_P) "include/isl/cpp" && \
+@HAVE_CLANG_TRUE@	(cat $(srcdir)/cpp/cpp.h.top $(srcdir)/all.h \
+@HAVE_CLANG_TRUE@	    $(srcdir)/cpp/cpp.h.pre && \
+@HAVE_CLANG_TRUE@		interface/extract_interface$(EXEEXT) --language=cpp \
+@HAVE_CLANG_TRUE@			$(includes) $(srcdir)/all.h && \
+@HAVE_CLANG_TRUE@		cat $(srcdir)/cpp/cpp.h.bot) \
+@HAVE_CLANG_TRUE@			> $@ || (rm $@ && false)
+
+@HAVE_CLANG_TRUE@include/isl/cpp-checked.h: interface/extract_interface libdep.a \
+@HAVE_CLANG_TRUE@		cpp/cpp-checked.h.top \
+@HAVE_CLANG_TRUE@		cpp/cpp-checked.h.pre cpp/cpp-checked.h.bot
+@HAVE_CLANG_TRUE@	(cat $(srcdir)/cpp/cpp-checked.h.top $(srcdir)/all.h \
+@HAVE_CLANG_TRUE@	    $(srcdir)/cpp/cpp-checked.h.pre && \
+@HAVE_CLANG_TRUE@		interface/extract_interface$(EXEEXT) \
+@HAVE_CLANG_TRUE@			--language=cpp-checked \
+@HAVE_CLANG_TRUE@			$(includes) $(srcdir)/all.h && \
+@HAVE_CLANG_TRUE@		cat $(srcdir)/cpp/cpp-checked.h.bot) \
+@HAVE_CLANG_TRUE@			> $@ || (rm $@ && false)
+
+@HAVE_CLANG_TRUE@include/isl/cpp-checked-conversion.h: interface/extract_interface libdep.a \
+@HAVE_CLANG_TRUE@		cpp/cpp-checked-conversion.h.top \
+@HAVE_CLANG_TRUE@		cpp/cpp-checked-conversion.h.bot
+@HAVE_CLANG_TRUE@	(cat $(srcdir)/cpp/cpp-checked-conversion.h.top && \
+@HAVE_CLANG_TRUE@		interface/extract_interface$(EXEEXT) \
+@HAVE_CLANG_TRUE@			--language=cpp-checked-conversion \
+@HAVE_CLANG_TRUE@			$(includes) $(srcdir)/all.h && \
+@HAVE_CLANG_TRUE@		cat $(srcdir)/cpp/cpp-checked-conversion.h.bot) \
+@HAVE_CLANG_TRUE@			> $@ || (rm $@ && false)
+
+@HAVE_CLANG_TRUE@dist-hook: interface/isl.py
+@HAVE_CLANG_TRUE@	cp interface/isl.py $(distdir)/interface/
+@HAVE_CLANG_FALSE@dist-hook:
 	echo @GIT_HEAD_VERSION@ > $(distdir)/GIT_HEAD_ID
 	(cd doc; make manual.pdf)
 	cp doc/manual.pdf $(distdir)/doc/
diff --git a/lib/External/isl/aclocal.m4 b/lib/External/isl/aclocal.m4
index 4531eb9..2a7bc35 100644
--- a/lib/External/isl/aclocal.m4
+++ b/lib/External/isl/aclocal.m4
@@ -1392,6 +1392,8 @@
 m4_include([m4/ax_compiler_vendor.m4])
 m4_include([m4/ax_create_pkgconfig_info.m4])
 m4_include([m4/ax_create_stdint_h.m4])
+m4_include([m4/ax_cxx_compile_stdcxx.m4])
+m4_include([m4/ax_cxx_compile_stdcxx_11.m4])
 m4_include([m4/ax_detect_clang.m4])
 m4_include([m4/ax_detect_git_head.m4])
 m4_include([m4/ax_detect_gmp.m4])
diff --git a/lib/External/isl/all.c b/lib/External/isl/all.c
new file mode 100644
index 0000000..3344a3c
--- /dev/null
+++ b/lib/External/isl/all.c
@@ -0,0 +1 @@
+#include "all.h"
diff --git a/lib/External/isl/interface/all.h b/lib/External/isl/all.h
similarity index 100%
rename from lib/External/isl/interface/all.h
rename to lib/External/isl/all.h
diff --git a/lib/External/isl/configure b/lib/External/isl/configure
index c001422..d4a3c15 100755
--- a/lib/External/isl/configure
+++ b/lib/External/isl/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for isl 0.19.
+# Generated by GNU Autoconf 2.69 for isl 0.20.
 #
 # Report bugs to <isl-development@googlegroups.com>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='isl'
 PACKAGE_TARNAME='isl'
-PACKAGE_VERSION='0.19'
-PACKAGE_STRING='isl 0.19'
+PACKAGE_VERSION='0.20'
+PACKAGE_STRING='isl 0.20'
 PACKAGE_BUGREPORT='isl-development@googlegroups.com'
 PACKAGE_URL=''
 
@@ -641,6 +641,8 @@
 pkgconfig_libfile
 pkgconfig_libdir
 WARNING_FLAGS
+HAVE_CPP_ISL_H_FALSE
+HAVE_CPP_ISL_H_TRUE
 HAVE_CLANG_FALSE
 HAVE_CLANG_TRUE
 LIB_CLANG_EDIT
@@ -650,6 +652,8 @@
 CLANG_CXXFLAGS
 SMALL_INT_OPT_FALSE
 SMALL_INT_OPT_TRUE
+HAVE_CXX11_FALSE
+HAVE_CXX11_TRUE
 GMP_FOR_MP_FALSE
 GMP_FOR_MP_TRUE
 IMATH_FOR_MP_FALSE
@@ -699,6 +703,8 @@
 SED
 LIBTOOL
 GREP
+HAVE_CXX11
+CXX11FLAGS
 PRTDIAG
 host_os
 host_vendor
@@ -1387,7 +1393,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures isl 0.19 to adapt to many kinds of systems.
+\`configure' configures isl 0.20 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1458,7 +1464,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of isl 0.19:";;
+     short | recursive ) echo "Configuration of isl 0.20:";;
    esac
   cat <<\_ACEOF
 
@@ -1589,7 +1595,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-isl configure 0.19
+isl configure 0.20
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2484,7 +2490,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by isl $as_me 0.19, which was
+It was created by isl $as_me 0.20, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3348,7 +3354,7 @@
 
 # Define the identity of the package.
  PACKAGE='isl'
- VERSION='0.19'
+ VERSION='0.20'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3481,7 +3487,7 @@
 AM_BACKSLASH='\'
 
 
-versioninfo=19:0:0
+versioninfo=20:0:1
 
 if test "x$prefix" != "xNONE"; then
 	prefix_wd=`cd $prefix && pwd`
@@ -5934,6 +5940,682 @@
   fi
 
 
+# CXX11FLAGS contains the flags (if any) added by AX_CXX_COMPILE_STDCXX_11
+# Original state of CXX and CXXCPP is preserved because CXX11FLAGS
+# is only needed for compiling interface/isl_test_cpp
+
+ac_save_CXX="$CXX"
+ac_save_CXXCPP="$CXXCPP"
+
+  ax_cxx_compile_alternatives="11 0x"    ax_cxx_compile_cxx11_required=false
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+  ac_success=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5
+$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; }
+if ${ax_cv_cxx_compile_cxx11+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ax_cv_cxx_compile_cxx11=yes
+else
+  ax_cv_cxx_compile_cxx11=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5
+$as_echo "$ax_cv_cxx_compile_cxx11" >&6; }
+  if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+    ac_success=yes
+  fi
+
+
+
+    if test x$ac_success = xno; then
+                for alternative in ${ax_cxx_compile_alternatives}; do
+      for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
+        cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh`
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5
+$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; }
+if eval \${$cachevar+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_CXX="$CXX"
+           CXX="$CXX $switch"
+           cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  eval $cachevar=yes
+else
+  eval $cachevar=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+           CXX="$ac_save_CXX"
+fi
+eval ac_res=\$$cachevar
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+        if eval test x\$$cachevar = xyes; then
+          CXX="$CXX $switch"
+          if test -n "$CXXCPP" ; then
+            CXXCPP="$CXXCPP $switch"
+          fi
+          ac_success=yes
+          break
+        fi
+      done
+      if test x$ac_success = xyes; then
+        break
+      fi
+    done
+  fi
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+  if test x$ax_cxx_compile_cxx11_required = xtrue; then
+    if test x$ac_success = xno; then
+      as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5
+    fi
+  fi
+  if test x$ac_success = xno; then
+    HAVE_CXX11=0
+    { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5
+$as_echo "$as_me: No compiler with C++11 support was found" >&6;}
+  else
+    HAVE_CXX11=1
+
+$as_echo "#define HAVE_CXX11 1" >>confdefs.h
+
+  fi
+
+
+
+CXX11FLAGS=${CXX#$ac_save_CXX}
+CXX="$ac_save_CXX"
+CXXCPP="$ac_save_CXXCPP"
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
 $as_echo_n "checking for grep that handles long lines and -e... " >&6; }
 if ${ac_cv_path_GREP+:} false; then :
@@ -9633,7 +10315,6 @@
 
 
 
-
 func_stripname_cnf ()
 {
   case $2 in
@@ -18507,6 +19188,14 @@
 fi
 
 
+ if test "x$HAVE_CXX11" = "x1"; then
+  HAVE_CXX11_TRUE=
+  HAVE_CXX11_FALSE='#'
+else
+  HAVE_CXX11_TRUE='#'
+  HAVE_CXX11_FALSE=
+fi
+
  if test "x$with_int" == "ximath-32"; then
   SMALL_INT_OPT_TRUE=
   SMALL_INT_OPT_FALSE='#'
@@ -19399,6 +20088,14 @@
   HAVE_CLANG_FALSE=
 fi
 
+ if test $with_clang = system -o -f $srcdir/include/isl/cpp.h; then
+  HAVE_CPP_ISL_H_TRUE=
+  HAVE_CPP_ISL_H_FALSE='#'
+else
+  HAVE_CPP_ISL_H_TRUE='#'
+  HAVE_CPP_ISL_H_FALSE=
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler vendor" >&5
@@ -19851,6 +20548,10 @@
   as_fn_error $? "conditional \"GMP_FOR_MP\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${HAVE_CXX11_TRUE}" && test -z "${HAVE_CXX11_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_CXX11\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${SMALL_INT_OPT_TRUE}" && test -z "${SMALL_INT_OPT_FALSE}"; then
   as_fn_error $? "conditional \"SMALL_INT_OPT\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -19859,6 +20560,10 @@
   as_fn_error $? "conditional \"HAVE_CLANG\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${HAVE_CPP_ISL_H_TRUE}" && test -z "${HAVE_CPP_ISL_H_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_CPP_ISL_H\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 
 : "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
@@ -20256,7 +20961,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by isl $as_me 0.19, which was
+This file was extended by isl $as_me 0.20, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -20322,7 +21027,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-isl config.status 0.19
+isl config.status 0.20
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/lib/External/isl/configure.ac b/lib/External/isl/configure.ac
index df46c86..5d7fc69 100644
--- a/lib/External/isl/configure.ac
+++ b/lib/External/isl/configure.ac
@@ -1,10 +1,10 @@
-AC_INIT([isl], [0.19], [isl-development@googlegroups.com])
+AC_INIT([isl], [0.20], [isl-development@googlegroups.com])
 AC_CONFIG_AUX_DIR([.])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([foreign])
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 AC_SUBST(versioninfo)
-versioninfo=19:0:0
+versioninfo=20:0:1
 
 if test "x$prefix" != "xNONE"; then
 	prefix_wd=`cd $prefix && pwd`
@@ -25,6 +25,17 @@
 AX_GCC_WARN_UNUSED_RESULT
 AX_C___ATTRIBUTE__
 
+# CXX11FLAGS contains the flags (if any) added by AX_CXX_COMPILE_STDCXX_11
+# Original state of CXX and CXXCPP is preserved because CXX11FLAGS
+# is only needed for compiling interface/isl_test_cpp
+AC_SUBST(CXX11FLAGS)
+ac_save_CXX="$CXX"
+ac_save_CXXCPP="$CXXCPP"
+AX_CXX_COMPILE_STDCXX_11([noext], [optional])
+CXX11FLAGS=${CXX#$ac_save_CXX}
+CXX="$ac_save_CXX"
+CXXCPP="$ac_save_CXXCPP"
+
 AC_PROG_GREP
 AC_PROG_LIBTOOL
 AC_PROG_SED
@@ -70,6 +81,7 @@
 AM_CONDITIONAL(IMATH_FOR_MP, test x$with_int = ximath -o x$with_int = ximath-32)
 AM_CONDITIONAL(GMP_FOR_MP, test x$with_int = xgmp)
 
+AM_CONDITIONAL(HAVE_CXX11, test "x$HAVE_CXX11" = "x1")
 AM_CONDITIONAL(SMALL_INT_OPT, test "x$with_int" == "ximath-32")
 AS_IF([test "x$with_int" == "ximath-32"], [
 	AC_DEFINE([USE_SMALL_INT_OPT], [], [Use small integer optimization])
@@ -106,6 +118,8 @@
 	;;
 esac
 AM_CONDITIONAL(HAVE_CLANG, test $with_clang = system)
+AM_CONDITIONAL(HAVE_CPP_ISL_H,
+    [test $with_clang = system -o -f $srcdir/include/isl/cpp.h])
 
 AX_SET_WARNING_FLAGS
 
diff --git a/lib/External/isl/cpp/cpp-checked-conversion.h.bot b/lib/External/isl/cpp/cpp-checked-conversion.h.bot
new file mode 100644
index 0000000..35ef163
--- /dev/null
+++ b/lib/External/isl/cpp/cpp-checked-conversion.h.bot
@@ -0,0 +1,2 @@
+
+#endif /* ISL_CPP_CHECKED_CONVERSION */
diff --git a/lib/External/isl/cpp/cpp-checked-conversion.h.top b/lib/External/isl/cpp/cpp-checked-conversion.h.top
new file mode 100644
index 0000000..402fc3d
--- /dev/null
+++ b/lib/External/isl/cpp/cpp-checked-conversion.h.top
@@ -0,0 +1,14 @@
+/// These are automatically generated conversions between
+/// the default and the checked C++ bindings for isl.
+///
+/// isl is a library for computing with integer sets and maps described by
+/// Presburger formulas. On top of this, isl provides various tools for
+/// polyhedral compilation, ranging from dependence analysis over scheduling
+/// to AST generation.
+
+#ifndef ISL_CPP_CHECKED_CONVERSION
+#define ISL_CPP_CHECKED_CONVERSION
+
+#include <isl/cpp.h>
+#include <isl/cpp-checked.h>
+
diff --git a/lib/External/isl/cpp/cpp-checked.h.bot b/lib/External/isl/cpp/cpp-checked.h.bot
new file mode 100644
index 0000000..4d66f89
--- /dev/null
+++ b/lib/External/isl/cpp/cpp-checked.h.bot
@@ -0,0 +1,2 @@
+
+#endif /* ISL_CPP_CHECKED */
diff --git a/lib/External/isl/cpp/cpp-checked.h.pre b/lib/External/isl/cpp/cpp-checked.h.pre
new file mode 100644
index 0000000..43911e5
--- /dev/null
+++ b/lib/External/isl/cpp/cpp-checked.h.pre
@@ -0,0 +1,119 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <functional>
+#include <string>
+
+namespace isl {
+namespace checked {
+
+#define ISLPP_STRINGIZE_(X) #X
+#define ISLPP_STRINGIZE(X) ISLPP_STRINGIZE_(X)
+
+#define ISLPP_ASSERT(test, message)                          \
+  do {                                                       \
+    if (test)                                                \
+      break;                                                 \
+    fputs("Assertion \"" #test "\" failed at " __FILE__      \
+      ":" ISLPP_STRINGIZE(__LINE__) "\n  " message "\n",     \
+      stderr);                                               \
+    abort();                                                 \
+  } while (0)
+
+class boolean {
+private:
+  mutable bool checked = false;
+  isl_bool val;
+
+  friend boolean manage(isl_bool val);
+  boolean(isl_bool val): val(val) {}
+public:
+  boolean()
+      : val(isl_bool_error) {}
+  ~boolean() {
+    ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
+  }
+
+  /* implicit */ boolean(bool val)
+      : val(val ? isl_bool_true : isl_bool_false) {}
+
+  bool is_error() const { checked = true; return val == isl_bool_error; }
+  bool is_false() const { checked = true; return val == isl_bool_false; }
+  bool is_true() const { checked = true; return val == isl_bool_true; }
+
+  explicit operator bool() const {
+    ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked error state");
+    ISLPP_ASSERT(!is_error(), "IMPLEMENTATION ERROR: Unhandled error state");
+    return is_true();
+  }
+
+  boolean operator!() const {
+    if (is_error())
+      return *this;
+    return !is_true();
+  }
+};
+
+inline boolean manage(isl_bool val) {
+  return boolean(val);
+}
+
+class ctx {
+  isl_ctx *ptr;
+public:
+  /* implicit */ ctx(isl_ctx *ctx)
+      : ptr(ctx) {}
+  isl_ctx *release() {
+    auto tmp = ptr;
+    ptr = nullptr;
+    return tmp;
+  }
+  isl_ctx *get() {
+    return ptr;
+  }
+};
+
+/* Class encapsulating an isl_stat value.
+ */
+class stat {
+private:
+	mutable bool checked = false;
+	isl_stat val;
+
+	friend stat manage(isl_stat val);
+	constexpr stat(isl_stat val) : val(val) {}
+public:
+	static stat ok() {
+		return stat(isl_stat_ok);
+	}
+	static stat error() {
+		return stat(isl_stat_error);
+	}
+	stat() : val(isl_stat_error) {}
+	~stat() {
+		ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
+	}
+
+	isl_stat release() {
+		checked = true;
+		return val;
+	}
+
+	bool is_error() const {
+		checked = true;
+		return val == isl_stat_error;
+	}
+	bool is_ok() const {
+		checked = true;
+		return val == isl_stat_ok;
+	}
+};
+
+inline stat manage(isl_stat val)
+{
+	return stat(val);
+}
+
+}
+} // namespace isl
diff --git a/lib/External/isl/cpp/cpp-checked.h.top b/lib/External/isl/cpp/cpp-checked.h.top
new file mode 100644
index 0000000..d33ee35
--- /dev/null
+++ b/lib/External/isl/cpp/cpp-checked.h.top
@@ -0,0 +1,10 @@
+/// These are automatically generated checked C++ bindings for isl.
+///
+/// isl is a library for computing with integer sets and maps described by
+/// Presburger formulas. On top of this, isl provides various tools for
+/// polyhedral compilation, ranging from dependence analysis over scheduling
+/// to AST generation.
+
+#ifndef ISL_CPP_CHECKED
+#define ISL_CPP_CHECKED
+
diff --git a/lib/External/isl/cpp/cpp.h.bot b/lib/External/isl/cpp/cpp.h.bot
new file mode 100644
index 0000000..f98e87c
--- /dev/null
+++ b/lib/External/isl/cpp/cpp.h.bot
@@ -0,0 +1,2 @@
+
+#endif /* ISL_CPP */
diff --git a/lib/External/isl/cpp/cpp.h.pre b/lib/External/isl/cpp/cpp.h.pre
new file mode 100644
index 0000000..0e72c2b
--- /dev/null
+++ b/lib/External/isl/cpp/cpp.h.pre
@@ -0,0 +1,249 @@
+
+#include <isl/ctx.h>
+#include <isl/options.h>
+
+#include <functional>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+/* ISL_USE_EXCEPTIONS should be defined to 1 if exceptions are available.
+ * gcc and clang define __cpp_exceptions; MSVC and xlC define _CPPUNWIND.
+ * If exceptions are not available, any error condition will result
+ * in an abort.
+ */
+#ifndef ISL_USE_EXCEPTIONS
+#if defined(__cpp_exceptions) || defined(_CPPUNWIND)
+#define ISL_USE_EXCEPTIONS	1
+#else
+#define ISL_USE_EXCEPTIONS	0
+#endif
+#endif
+
+namespace isl {
+
+class ctx {
+	isl_ctx *ptr;
+public:
+	/* implicit */ ctx(isl_ctx *ctx) : ptr(ctx) {}
+	isl_ctx *release() {
+		auto tmp = ptr;
+		ptr = nullptr;
+		return tmp;
+	}
+	isl_ctx *get() {
+		return ptr;
+	}
+};
+
+/* Macros hiding try/catch.
+ * If exceptions are not available, then no exceptions will be thrown and
+ * there is nothing to catch.
+ */
+#if ISL_USE_EXCEPTIONS
+#define ISL_CPP_TRY		try
+#define ISL_CPP_CATCH_ALL	catch (...)
+#else
+#define ISL_CPP_TRY		if (1)
+#define ISL_CPP_CATCH_ALL	if (0)
+#endif
+
+#if ISL_USE_EXCEPTIONS
+
+/* Class capturing isl errors.
+ *
+ * The what() return value is stored in a reference counted string
+ * to ensure that the copy constructor and the assignment operator
+ * do not throw any exceptions.
+ */
+class exception : public std::exception {
+	std::shared_ptr<std::string> what_str;
+
+protected:
+	inline exception(const char *what_arg, const char *msg,
+		const char *file, int line);
+public:
+	exception() {}
+	exception(const char *what_arg) {
+		what_str = std::make_shared<std::string>(what_arg);
+	}
+	static inline exception create(enum isl_error error, const char *msg,
+		const char *file, int line);
+	static inline exception create_from_last_error(ctx ctx);
+	virtual const char *what() const noexcept {
+		return what_str->c_str();
+	}
+
+	/* Default behavior on error conditions that occur inside isl calls
+	 * performed from inside the bindings.
+	 * In the case exceptions are available, isl should continue
+	 * without printing a warning since the warning message
+	 * will be included in the exception thrown from inside the bindings.
+	 */
+	static constexpr auto on_error = ISL_ON_ERROR_CONTINUE;
+	/* Wrapper for throwing an exception on NULL input.
+	 */
+	static void throw_NULL_input(const char *file, int line) {
+		throw create(isl_error_invalid, "NULL input", file, line);
+	}
+	/* Wrapper for throwing an exception corresponding to the last
+	 * error on "ctx".
+	 */
+	static void throw_last_error(ctx ctx) {
+		throw create_from_last_error(ctx);
+	}
+};
+
+/* Create an exception of a type described by "what_arg", with
+ * error message "msg" in line "line" of file "file".
+ *
+ * Create a string holding the what() return value that
+ * corresponds to what isl would have printed.
+ * If no error message or no error file was set, then use "what_arg" instead.
+ */
+exception::exception(const char *what_arg, const char *msg, const char *file,
+	int line)
+{
+	if (!msg || !file)
+		what_str = std::make_shared<std::string>(what_arg);
+	else
+		what_str = std::make_shared<std::string>(std::string(file) +
+				    ":" + std::to_string(line) + ": " + msg);
+}
+
+class exception_abort : public exception {
+	friend exception;
+	exception_abort(const char *msg, const char *file, int line) :
+		exception("execution aborted", msg, file, line) {}
+};
+
+class exception_alloc : public exception {
+	friend exception;
+	exception_alloc(const char *msg, const char *file, int line) :
+		exception("memory allocation failure", msg, file, line) {}
+};
+
+class exception_unknown : public exception {
+	friend exception;
+	exception_unknown(const char *msg, const char *file, int line) :
+		exception("unknown failure", msg, file, line) {}
+};
+
+class exception_internal : public exception {
+	friend exception;
+	exception_internal(const char *msg, const char *file, int line) :
+		exception("internal error", msg, file, line) {}
+};
+
+class exception_invalid : public exception {
+	friend exception;
+	exception_invalid(const char *msg, const char *file, int line) :
+		exception("invalid argument", msg, file, line) {}
+};
+
+class exception_quota : public exception {
+	friend exception;
+	exception_quota(const char *msg, const char *file, int line) :
+		exception("quota exceeded", msg, file, line) {}
+};
+
+class exception_unsupported : public exception {
+	friend exception;
+	exception_unsupported(const char *msg, const char *file, int line) :
+		exception("unsupported operation", msg, file, line) {}
+};
+
+/* Create an exception of the class that corresponds to "error", with
+ * error message "msg" in line "line" of file "file".
+ *
+ * isl_error_none is treated as an invalid error type.
+ */
+exception exception::create(enum isl_error error, const char *msg,
+	const char *file, int line)
+{
+	switch (error) {
+	case isl_error_none:
+		break;
+	case isl_error_abort: return exception_abort(msg, file, line);
+	case isl_error_alloc: return exception_alloc(msg, file, line);
+	case isl_error_unknown: return exception_unknown(msg, file, line);
+	case isl_error_internal: return exception_internal(msg, file, line);
+	case isl_error_invalid: return exception_invalid(msg, file, line);
+	case isl_error_quota: return exception_quota(msg, file, line);
+	case isl_error_unsupported:
+				return exception_unsupported(msg, file, line);
+	}
+
+	throw exception_invalid("invalid error type", file, line);
+}
+
+/* Create an exception from the last error that occurred on "ctx" and
+ * reset the error.
+ *
+ * If "ctx" is NULL or if it is not in an error state at the start,
+ * then an invalid argument exception is thrown.
+ */
+exception exception::create_from_last_error(ctx ctx)
+{
+	enum isl_error error;
+	const char *msg, *file;
+	int line;
+
+	error = isl_ctx_last_error(ctx.get());
+	msg = isl_ctx_last_error_msg(ctx.get());
+	file = isl_ctx_last_error_file(ctx.get());
+	line = isl_ctx_last_error_line(ctx.get());
+	isl_ctx_reset_error(ctx.get());
+
+	return create(error, msg, file, line);
+}
+
+#else
+
+#include <stdio.h>
+#include <stdlib.h>
+
+class exception {
+public:
+	/* Default behavior on error conditions that occur inside isl calls
+	 * performed from inside the bindings.
+	 * In the case exceptions are not available, isl should abort.
+	 */
+	static constexpr auto on_error = ISL_ON_ERROR_ABORT;
+	/* Wrapper for throwing an exception on NULL input.
+	 * In the case exceptions are not available, print an error and abort.
+	 */
+	static void throw_NULL_input(const char *file, int line) {
+		fprintf(stderr, "%s:%d: NULL input\n", file, line);
+		abort();
+	}
+	/* Wrapper for throwing an exception corresponding to the last
+	 * error on "ctx".
+	 * isl should already abort when an error condition occurs,
+	 * so this function should never be called.
+	 */
+	static void throw_last_error(ctx ctx) {
+		abort();
+	}
+};
+
+#endif
+
+/* Helper class for setting the on_error and resetting the option
+ * to the original value when leaving the scope.
+ */
+class options_scoped_set_on_error {
+	isl_ctx *ctx;
+	int saved_on_error;
+public:
+	options_scoped_set_on_error(class ctx ctx, int on_error) {
+		this->ctx = ctx.get();
+		saved_on_error = isl_options_get_on_error(this->ctx);
+		isl_options_set_on_error(this->ctx, on_error);
+	}
+	~options_scoped_set_on_error() {
+		isl_options_set_on_error(ctx, saved_on_error);
+	}
+};
+
+} // namespace isl
diff --git a/lib/External/isl/cpp/cpp.h.top b/lib/External/isl/cpp/cpp.h.top
new file mode 100644
index 0000000..793c0ef
--- /dev/null
+++ b/lib/External/isl/cpp/cpp.h.top
@@ -0,0 +1,10 @@
+/// These are automatically generated C++ bindings for isl.
+///
+/// isl is a library for computing with integer sets and maps described by
+/// Presburger formulas. On top of this, isl provides various tools for
+/// polyhedral compilation, ranging from dependence analysis over scheduling
+/// to AST generation.
+
+#ifndef ISL_CPP
+#define ISL_CPP
+
diff --git a/lib/External/isl/doc/Makefile.in b/lib/External/isl/doc/Makefile.in
index 108fda9..57dc445 100644
--- a/lib/External/isl/doc/Makefile.in
+++ b/lib/External/isl/doc/Makefile.in
@@ -95,6 +95,8 @@
 	$(top_srcdir)/m4/ax_compiler_vendor.m4 \
 	$(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
 	$(top_srcdir)/m4/ax_create_stdint_h.m4 \
+	$(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+	$(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
 	$(top_srcdir)/m4/ax_detect_clang.m4 \
 	$(top_srcdir)/m4/ax_detect_git_head.m4 \
 	$(top_srcdir)/m4/ax_detect_gmp.m4 \
@@ -153,6 +155,7 @@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CXX = @CXX@
+CXX11FLAGS = @CXX11FLAGS@
 CXXCPP = @CXXCPP@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
@@ -172,6 +175,7 @@
 GIT_HEAD_ID = @GIT_HEAD_ID@
 GIT_HEAD_VERSION = @GIT_HEAD_VERSION@
 GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
diff --git a/lib/External/isl/doc/user.pod b/lib/External/isl/doc/user.pod
index 5d23357..319974c 100644
--- a/lib/External/isl/doc/user.pod
+++ b/lib/External/isl/doc/user.pod
@@ -9765,6 +9765,7 @@
 and may also prevent fusing of unrelated dimensions. A value of -1 means that
 this option does not introduce bounds on the variable or parameter
 coefficients.
+This option has no effect on the Feautrier style scheduler.
 
 =item * schedule_max_constant_term
 
diff --git a/lib/External/isl/include/isl/arg.h b/lib/External/isl/include/isl/arg.h
index 0d37d1c..66c560c 100644
--- a/lib/External/isl/include/isl/arg.h
+++ b/lib/External/isl/include/isl/arg.h
@@ -192,7 +192,7 @@
 	.offset = offsetof(st, f),					\
 	.help_msg = h,							\
 	.flags = fl,							\
-	.u = { .ul = { .default_value = d } }				\
+	.u = { .i = { .default_value = d } }				\
 },
 #define ISL_ARG_INT(st,f,s,l,a,d,h)					\
 	ISL_ARG_INT_F(st,f,s,l,a,d,h,0)
diff --git a/lib/External/isl/include/isl/cpp-checked-conversion.h b/lib/External/isl/include/isl/cpp-checked-conversion.h
new file mode 100644
index 0000000..848d52d
--- /dev/null
+++ b/lib/External/isl/include/isl/cpp-checked-conversion.h
@@ -0,0 +1,219 @@
+/// These are automatically generated conversions between
+/// the default and the checked C++ bindings for isl.
+///
+/// isl is a library for computing with integer sets and maps described by
+/// Presburger formulas. On top of this, isl provides various tools for
+/// polyhedral compilation, ranging from dependence analysis over scheduling
+/// to AST generation.
+
+#ifndef ISL_CPP_CHECKED_CONVERSION
+#define ISL_CPP_CHECKED_CONVERSION
+
+#include <isl/cpp.h>
+#include <isl/cpp-checked.h>
+
+namespace isl {
+
+checked::aff check(aff obj) {
+	return checked::manage(obj.copy());
+}
+
+aff uncheck(checked::aff obj) {
+	return manage(obj.copy());
+}
+
+checked::ast_build check(ast_build obj) {
+	return checked::manage(obj.copy());
+}
+
+ast_build uncheck(checked::ast_build obj) {
+	return manage(obj.copy());
+}
+
+checked::ast_expr check(ast_expr obj) {
+	return checked::manage(obj.copy());
+}
+
+ast_expr uncheck(checked::ast_expr obj) {
+	return manage(obj.copy());
+}
+
+checked::ast_node check(ast_node obj) {
+	return checked::manage(obj.copy());
+}
+
+ast_node uncheck(checked::ast_node obj) {
+	return manage(obj.copy());
+}
+
+checked::basic_map check(basic_map obj) {
+	return checked::manage(obj.copy());
+}
+
+basic_map uncheck(checked::basic_map obj) {
+	return manage(obj.copy());
+}
+
+checked::basic_set check(basic_set obj) {
+	return checked::manage(obj.copy());
+}
+
+basic_set uncheck(checked::basic_set obj) {
+	return manage(obj.copy());
+}
+
+checked::map check(map obj) {
+	return checked::manage(obj.copy());
+}
+
+map uncheck(checked::map obj) {
+	return manage(obj.copy());
+}
+
+checked::multi_aff check(multi_aff obj) {
+	return checked::manage(obj.copy());
+}
+
+multi_aff uncheck(checked::multi_aff obj) {
+	return manage(obj.copy());
+}
+
+checked::multi_pw_aff check(multi_pw_aff obj) {
+	return checked::manage(obj.copy());
+}
+
+multi_pw_aff uncheck(checked::multi_pw_aff obj) {
+	return manage(obj.copy());
+}
+
+checked::multi_union_pw_aff check(multi_union_pw_aff obj) {
+	return checked::manage(obj.copy());
+}
+
+multi_union_pw_aff uncheck(checked::multi_union_pw_aff obj) {
+	return manage(obj.copy());
+}
+
+checked::multi_val check(multi_val obj) {
+	return checked::manage(obj.copy());
+}
+
+multi_val uncheck(checked::multi_val obj) {
+	return manage(obj.copy());
+}
+
+checked::point check(point obj) {
+	return checked::manage(obj.copy());
+}
+
+point uncheck(checked::point obj) {
+	return manage(obj.copy());
+}
+
+checked::pw_aff check(pw_aff obj) {
+	return checked::manage(obj.copy());
+}
+
+pw_aff uncheck(checked::pw_aff obj) {
+	return manage(obj.copy());
+}
+
+checked::pw_multi_aff check(pw_multi_aff obj) {
+	return checked::manage(obj.copy());
+}
+
+pw_multi_aff uncheck(checked::pw_multi_aff obj) {
+	return manage(obj.copy());
+}
+
+checked::schedule check(schedule obj) {
+	return checked::manage(obj.copy());
+}
+
+schedule uncheck(checked::schedule obj) {
+	return manage(obj.copy());
+}
+
+checked::schedule_constraints check(schedule_constraints obj) {
+	return checked::manage(obj.copy());
+}
+
+schedule_constraints uncheck(checked::schedule_constraints obj) {
+	return manage(obj.copy());
+}
+
+checked::schedule_node check(schedule_node obj) {
+	return checked::manage(obj.copy());
+}
+
+schedule_node uncheck(checked::schedule_node obj) {
+	return manage(obj.copy());
+}
+
+checked::set check(set obj) {
+	return checked::manage(obj.copy());
+}
+
+set uncheck(checked::set obj) {
+	return manage(obj.copy());
+}
+
+checked::union_access_info check(union_access_info obj) {
+	return checked::manage(obj.copy());
+}
+
+union_access_info uncheck(checked::union_access_info obj) {
+	return manage(obj.copy());
+}
+
+checked::union_flow check(union_flow obj) {
+	return checked::manage(obj.copy());
+}
+
+union_flow uncheck(checked::union_flow obj) {
+	return manage(obj.copy());
+}
+
+checked::union_map check(union_map obj) {
+	return checked::manage(obj.copy());
+}
+
+union_map uncheck(checked::union_map obj) {
+	return manage(obj.copy());
+}
+
+checked::union_pw_aff check(union_pw_aff obj) {
+	return checked::manage(obj.copy());
+}
+
+union_pw_aff uncheck(checked::union_pw_aff obj) {
+	return manage(obj.copy());
+}
+
+checked::union_pw_multi_aff check(union_pw_multi_aff obj) {
+	return checked::manage(obj.copy());
+}
+
+union_pw_multi_aff uncheck(checked::union_pw_multi_aff obj) {
+	return manage(obj.copy());
+}
+
+checked::union_set check(union_set obj) {
+	return checked::manage(obj.copy());
+}
+
+union_set uncheck(checked::union_set obj) {
+	return manage(obj.copy());
+}
+
+checked::val check(val obj) {
+	return checked::manage(obj.copy());
+}
+
+val uncheck(checked::val obj) {
+	return manage(obj.copy());
+}
+
+} // namespace isl
+
+#endif /* ISL_CPP_CHECKED_CONVERSION */
diff --git a/lib/External/isl/include/isl/cpp-checked.h b/lib/External/isl/include/isl/cpp-checked.h
new file mode 100644
index 0000000..aaa51a2
--- /dev/null
+++ b/lib/External/isl/include/isl/cpp-checked.h
@@ -0,0 +1,4881 @@
+/// These are automatically generated checked C++ bindings for isl.
+///
+/// isl is a library for computing with integer sets and maps described by
+/// Presburger formulas. On top of this, isl provides various tools for
+/// polyhedral compilation, ranging from dependence analysis over scheduling
+/// to AST generation.
+
+#ifndef ISL_CPP_CHECKED
+#define ISL_CPP_CHECKED
+
+#include <isl/val.h>
+#include <isl/aff.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/ilp.h>
+#include <isl/union_set.h>
+#include <isl/union_map.h>
+#include <isl/flow.h>
+#include <isl/schedule.h>
+#include <isl/schedule_node.h>
+#include <isl/ast_build.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <functional>
+#include <string>
+
+namespace isl {
+namespace checked {
+
+#define ISLPP_STRINGIZE_(X) #X
+#define ISLPP_STRINGIZE(X) ISLPP_STRINGIZE_(X)
+
+#define ISLPP_ASSERT(test, message)                          \
+  do {                                                       \
+    if (test)                                                \
+      break;                                                 \
+    fputs("Assertion \"" #test "\" failed at " __FILE__      \
+      ":" ISLPP_STRINGIZE(__LINE__) "\n  " message "\n",     \
+      stderr);                                               \
+    abort();                                                 \
+  } while (0)
+
+class boolean {
+private:
+  mutable bool checked = false;
+  isl_bool val;
+
+  friend boolean manage(isl_bool val);
+  boolean(isl_bool val): val(val) {}
+public:
+  boolean()
+      : val(isl_bool_error) {}
+  ~boolean() {
+    ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
+  }
+
+  /* implicit */ boolean(bool val)
+      : val(val ? isl_bool_true : isl_bool_false) {}
+
+  bool is_error() const { checked = true; return val == isl_bool_error; }
+  bool is_false() const { checked = true; return val == isl_bool_false; }
+  bool is_true() const { checked = true; return val == isl_bool_true; }
+
+  explicit operator bool() const {
+    ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked error state");
+    ISLPP_ASSERT(!is_error(), "IMPLEMENTATION ERROR: Unhandled error state");
+    return is_true();
+  }
+
+  boolean operator!() const {
+    if (is_error())
+      return *this;
+    return !is_true();
+  }
+};
+
+inline boolean manage(isl_bool val) {
+  return boolean(val);
+}
+
+class ctx {
+  isl_ctx *ptr;
+public:
+  /* implicit */ ctx(isl_ctx *ctx)
+      : ptr(ctx) {}
+  isl_ctx *release() {
+    auto tmp = ptr;
+    ptr = nullptr;
+    return tmp;
+  }
+  isl_ctx *get() {
+    return ptr;
+  }
+};
+
+/* Class encapsulating an isl_stat value.
+ */
+class stat {
+private:
+	mutable bool checked = false;
+	isl_stat val;
+
+	friend stat manage(isl_stat val);
+	constexpr stat(isl_stat val) : val(val) {}
+public:
+	static stat ok() {
+		return stat(isl_stat_ok);
+	}
+	static stat error() {
+		return stat(isl_stat_error);
+	}
+	stat() : val(isl_stat_error) {}
+	~stat() {
+		ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
+	}
+
+	isl_stat release() {
+		checked = true;
+		return val;
+	}
+
+	bool is_error() const {
+		checked = true;
+		return val == isl_stat_error;
+	}
+	bool is_ok() const {
+		checked = true;
+		return val == isl_stat_ok;
+	}
+};
+
+inline stat manage(isl_stat val)
+{
+	return stat(val);
+}
+
+}
+} // namespace isl
+
+namespace isl {
+
+namespace checked {
+
+// forward declarations
+class aff;
+class ast_build;
+class ast_expr;
+class ast_node;
+class basic_map;
+class basic_set;
+class map;
+class multi_aff;
+class multi_pw_aff;
+class multi_union_pw_aff;
+class multi_val;
+class point;
+class pw_aff;
+class pw_multi_aff;
+class schedule;
+class schedule_constraints;
+class schedule_node;
+class set;
+class union_access_info;
+class union_flow;
+class union_map;
+class union_pw_aff;
+class union_pw_multi_aff;
+class union_set;
+class val;
+
+// declarations for isl::aff
+inline aff manage(__isl_take isl_aff *ptr);
+inline aff manage_copy(__isl_keep isl_aff *ptr);
+
+class aff {
+  friend inline aff manage(__isl_take isl_aff *ptr);
+  friend inline aff manage_copy(__isl_keep isl_aff *ptr);
+
+  isl_aff *ptr = nullptr;
+
+  inline explicit aff(__isl_take isl_aff *ptr);
+
+public:
+  inline /* implicit */ aff();
+  inline /* implicit */ aff(const aff &obj);
+  inline explicit aff(ctx ctx, const std::string &str);
+  inline aff &operator=(aff obj);
+  inline ~aff();
+  inline __isl_give isl_aff *copy() const &;
+  inline __isl_give isl_aff *copy() && = delete;
+  inline __isl_keep isl_aff *get() const;
+  inline __isl_give isl_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline aff add(aff aff2) const;
+  inline aff ceil() const;
+  inline aff div(aff aff2) const;
+  inline set eq_set(aff aff2) const;
+  inline aff floor() const;
+  inline set ge_set(aff aff2) const;
+  inline set gt_set(aff aff2) const;
+  inline set le_set(aff aff2) const;
+  inline set lt_set(aff aff2) const;
+  inline aff mod(val mod) const;
+  inline aff mul(aff aff2) const;
+  inline set ne_set(aff aff2) const;
+  inline aff neg() const;
+  inline aff pullback(multi_aff ma) const;
+  inline aff scale(val v) const;
+  inline aff scale_down(val v) const;
+  inline aff sub(aff aff2) const;
+};
+
+// declarations for isl::ast_build
+inline ast_build manage(__isl_take isl_ast_build *ptr);
+inline ast_build manage_copy(__isl_keep isl_ast_build *ptr);
+
+class ast_build {
+  friend inline ast_build manage(__isl_take isl_ast_build *ptr);
+  friend inline ast_build manage_copy(__isl_keep isl_ast_build *ptr);
+
+  isl_ast_build *ptr = nullptr;
+
+  inline explicit ast_build(__isl_take isl_ast_build *ptr);
+
+public:
+  inline /* implicit */ ast_build();
+  inline /* implicit */ ast_build(const ast_build &obj);
+  inline explicit ast_build(ctx ctx);
+  inline ast_build &operator=(ast_build obj);
+  inline ~ast_build();
+  inline __isl_give isl_ast_build *copy() const &;
+  inline __isl_give isl_ast_build *copy() && = delete;
+  inline __isl_keep isl_ast_build *get() const;
+  inline __isl_give isl_ast_build *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline ast_expr access_from(pw_multi_aff pma) const;
+  inline ast_expr access_from(multi_pw_aff mpa) const;
+  inline ast_expr call_from(pw_multi_aff pma) const;
+  inline ast_expr call_from(multi_pw_aff mpa) const;
+  inline ast_expr expr_from(set set) const;
+  inline ast_expr expr_from(pw_aff pa) const;
+  static inline ast_build from_context(set set);
+  inline ast_node node_from_schedule_map(union_map schedule) const;
+};
+
+// declarations for isl::ast_expr
+inline ast_expr manage(__isl_take isl_ast_expr *ptr);
+inline ast_expr manage_copy(__isl_keep isl_ast_expr *ptr);
+
+class ast_expr {
+  friend inline ast_expr manage(__isl_take isl_ast_expr *ptr);
+  friend inline ast_expr manage_copy(__isl_keep isl_ast_expr *ptr);
+
+  isl_ast_expr *ptr = nullptr;
+
+  inline explicit ast_expr(__isl_take isl_ast_expr *ptr);
+
+public:
+  inline /* implicit */ ast_expr();
+  inline /* implicit */ ast_expr(const ast_expr &obj);
+  inline ast_expr &operator=(ast_expr obj);
+  inline ~ast_expr();
+  inline __isl_give isl_ast_expr *copy() const &;
+  inline __isl_give isl_ast_expr *copy() && = delete;
+  inline __isl_keep isl_ast_expr *get() const;
+  inline __isl_give isl_ast_expr *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline std::string to_C_str() const;
+};
+
+// declarations for isl::ast_node
+inline ast_node manage(__isl_take isl_ast_node *ptr);
+inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
+
+class ast_node {
+  friend inline ast_node manage(__isl_take isl_ast_node *ptr);
+  friend inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
+
+  isl_ast_node *ptr = nullptr;
+
+  inline explicit ast_node(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node();
+  inline /* implicit */ ast_node(const ast_node &obj);
+  inline ast_node &operator=(ast_node obj);
+  inline ~ast_node();
+  inline __isl_give isl_ast_node *copy() const &;
+  inline __isl_give isl_ast_node *copy() && = delete;
+  inline __isl_keep isl_ast_node *get() const;
+  inline __isl_give isl_ast_node *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline std::string to_C_str() const;
+};
+
+// declarations for isl::basic_map
+inline basic_map manage(__isl_take isl_basic_map *ptr);
+inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+
+class basic_map {
+  friend inline basic_map manage(__isl_take isl_basic_map *ptr);
+  friend inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+
+  isl_basic_map *ptr = nullptr;
+
+  inline explicit basic_map(__isl_take isl_basic_map *ptr);
+
+public:
+  inline /* implicit */ basic_map();
+  inline /* implicit */ basic_map(const basic_map &obj);
+  inline explicit basic_map(ctx ctx, const std::string &str);
+  inline basic_map &operator=(basic_map obj);
+  inline ~basic_map();
+  inline __isl_give isl_basic_map *copy() const &;
+  inline __isl_give isl_basic_map *copy() && = delete;
+  inline __isl_keep isl_basic_map *get() const;
+  inline __isl_give isl_basic_map *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline basic_map affine_hull() const;
+  inline basic_map apply_domain(basic_map bmap2) const;
+  inline basic_map apply_range(basic_map bmap2) const;
+  inline basic_set deltas() const;
+  inline basic_map detect_equalities() const;
+  inline basic_map flatten() const;
+  inline basic_map flatten_domain() const;
+  inline basic_map flatten_range() const;
+  inline basic_map gist(basic_map context) const;
+  inline basic_map intersect(basic_map bmap2) const;
+  inline basic_map intersect_domain(basic_set bset) const;
+  inline basic_map intersect_range(basic_set bset) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const basic_map &bmap2) const;
+  inline boolean is_subset(const basic_map &bmap2) const;
+  inline map lexmax() const;
+  inline map lexmin() const;
+  inline basic_map reverse() const;
+  inline basic_map sample() const;
+  inline map unite(basic_map bmap2) const;
+};
+
+// declarations for isl::basic_set
+inline basic_set manage(__isl_take isl_basic_set *ptr);
+inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+
+class basic_set {
+  friend inline basic_set manage(__isl_take isl_basic_set *ptr);
+  friend inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+
+  isl_basic_set *ptr = nullptr;
+
+  inline explicit basic_set(__isl_take isl_basic_set *ptr);
+
+public:
+  inline /* implicit */ basic_set();
+  inline /* implicit */ basic_set(const basic_set &obj);
+  inline explicit basic_set(ctx ctx, const std::string &str);
+  inline /* implicit */ basic_set(point pnt);
+  inline basic_set &operator=(basic_set obj);
+  inline ~basic_set();
+  inline __isl_give isl_basic_set *copy() const &;
+  inline __isl_give isl_basic_set *copy() && = delete;
+  inline __isl_keep isl_basic_set *get() const;
+  inline __isl_give isl_basic_set *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline basic_set affine_hull() const;
+  inline basic_set apply(basic_map bmap) const;
+  inline basic_set detect_equalities() const;
+  inline val dim_max_val(int pos) const;
+  inline basic_set flatten() const;
+  inline basic_set gist(basic_set context) const;
+  inline basic_set intersect(basic_set bset2) const;
+  inline basic_set intersect_params(basic_set bset2) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const basic_set &bset2) const;
+  inline boolean is_subset(const basic_set &bset2) const;
+  inline boolean is_wrapping() const;
+  inline set lexmax() const;
+  inline set lexmin() const;
+  inline basic_set sample() const;
+  inline point sample_point() const;
+  inline set unite(basic_set bset2) const;
+};
+
+// declarations for isl::map
+inline map manage(__isl_take isl_map *ptr);
+inline map manage_copy(__isl_keep isl_map *ptr);
+
+class map {
+  friend inline map manage(__isl_take isl_map *ptr);
+  friend inline map manage_copy(__isl_keep isl_map *ptr);
+
+  isl_map *ptr = nullptr;
+
+  inline explicit map(__isl_take isl_map *ptr);
+
+public:
+  inline /* implicit */ map();
+  inline /* implicit */ map(const map &obj);
+  inline explicit map(ctx ctx, const std::string &str);
+  inline /* implicit */ map(basic_map bmap);
+  inline map &operator=(map obj);
+  inline ~map();
+  inline __isl_give isl_map *copy() const &;
+  inline __isl_give isl_map *copy() && = delete;
+  inline __isl_keep isl_map *get() const;
+  inline __isl_give isl_map *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline basic_map affine_hull() const;
+  inline map apply_domain(map map2) const;
+  inline map apply_range(map map2) const;
+  inline map coalesce() const;
+  inline map complement() const;
+  inline set deltas() const;
+  inline map detect_equalities() const;
+  inline map flatten() const;
+  inline map flatten_domain() const;
+  inline map flatten_range() const;
+  inline stat foreach_basic_map(const std::function<stat(basic_map)> &fn) const;
+  inline map gist(map context) const;
+  inline map gist_domain(set context) const;
+  inline map intersect(map map2) const;
+  inline map intersect_domain(set set) const;
+  inline map intersect_params(set params) const;
+  inline map intersect_range(set set) const;
+  inline boolean is_bijective() const;
+  inline boolean is_disjoint(const map &map2) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const map &map2) const;
+  inline boolean is_injective() const;
+  inline boolean is_single_valued() const;
+  inline boolean is_strict_subset(const map &map2) const;
+  inline boolean is_subset(const map &map2) const;
+  inline map lexmax() const;
+  inline map lexmin() const;
+  inline basic_map polyhedral_hull() const;
+  inline map reverse() const;
+  inline basic_map sample() const;
+  inline map subtract(map map2) const;
+  inline map unite(map map2) const;
+  inline basic_map unshifted_simple_hull() const;
+};
+
+// declarations for isl::multi_aff
+inline multi_aff manage(__isl_take isl_multi_aff *ptr);
+inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+
+class multi_aff {
+  friend inline multi_aff manage(__isl_take isl_multi_aff *ptr);
+  friend inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+
+  isl_multi_aff *ptr = nullptr;
+
+  inline explicit multi_aff(__isl_take isl_multi_aff *ptr);
+
+public:
+  inline /* implicit */ multi_aff();
+  inline /* implicit */ multi_aff(const multi_aff &obj);
+  inline /* implicit */ multi_aff(aff aff);
+  inline explicit multi_aff(ctx ctx, const std::string &str);
+  inline multi_aff &operator=(multi_aff obj);
+  inline ~multi_aff();
+  inline __isl_give isl_multi_aff *copy() const &;
+  inline __isl_give isl_multi_aff *copy() && = delete;
+  inline __isl_keep isl_multi_aff *get() const;
+  inline __isl_give isl_multi_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline multi_aff add(multi_aff multi2) const;
+  inline multi_aff flat_range_product(multi_aff multi2) const;
+  inline multi_aff product(multi_aff multi2) const;
+  inline multi_aff pullback(multi_aff ma2) const;
+  inline multi_aff range_product(multi_aff multi2) const;
+};
+
+// declarations for isl::multi_pw_aff
+inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
+inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+
+class multi_pw_aff {
+  friend inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
+  friend inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+
+  isl_multi_pw_aff *ptr = nullptr;
+
+  inline explicit multi_pw_aff(__isl_take isl_multi_pw_aff *ptr);
+
+public:
+  inline /* implicit */ multi_pw_aff();
+  inline /* implicit */ multi_pw_aff(const multi_pw_aff &obj);
+  inline /* implicit */ multi_pw_aff(multi_aff ma);
+  inline /* implicit */ multi_pw_aff(pw_aff pa);
+  inline /* implicit */ multi_pw_aff(pw_multi_aff pma);
+  inline explicit multi_pw_aff(ctx ctx, const std::string &str);
+  inline multi_pw_aff &operator=(multi_pw_aff obj);
+  inline ~multi_pw_aff();
+  inline __isl_give isl_multi_pw_aff *copy() const &;
+  inline __isl_give isl_multi_pw_aff *copy() && = delete;
+  inline __isl_keep isl_multi_pw_aff *get() const;
+  inline __isl_give isl_multi_pw_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline multi_pw_aff add(multi_pw_aff multi2) const;
+  inline multi_pw_aff flat_range_product(multi_pw_aff multi2) const;
+  inline multi_pw_aff product(multi_pw_aff multi2) const;
+  inline multi_pw_aff pullback(multi_aff ma) const;
+  inline multi_pw_aff pullback(pw_multi_aff pma) const;
+  inline multi_pw_aff pullback(multi_pw_aff mpa2) const;
+  inline multi_pw_aff range_product(multi_pw_aff multi2) const;
+};
+
+// declarations for isl::multi_union_pw_aff
+inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
+inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+
+class multi_union_pw_aff {
+  friend inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
+  friend inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+
+  isl_multi_union_pw_aff *ptr = nullptr;
+
+  inline explicit multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr);
+
+public:
+  inline /* implicit */ multi_union_pw_aff();
+  inline /* implicit */ multi_union_pw_aff(const multi_union_pw_aff &obj);
+  inline /* implicit */ multi_union_pw_aff(union_pw_aff upa);
+  inline /* implicit */ multi_union_pw_aff(multi_pw_aff mpa);
+  inline explicit multi_union_pw_aff(ctx ctx, const std::string &str);
+  inline multi_union_pw_aff &operator=(multi_union_pw_aff obj);
+  inline ~multi_union_pw_aff();
+  inline __isl_give isl_multi_union_pw_aff *copy() const &;
+  inline __isl_give isl_multi_union_pw_aff *copy() && = delete;
+  inline __isl_keep isl_multi_union_pw_aff *get() const;
+  inline __isl_give isl_multi_union_pw_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline multi_union_pw_aff add(multi_union_pw_aff multi2) const;
+  inline multi_union_pw_aff flat_range_product(multi_union_pw_aff multi2) const;
+  inline multi_union_pw_aff pullback(union_pw_multi_aff upma) const;
+  inline multi_union_pw_aff range_product(multi_union_pw_aff multi2) const;
+  inline multi_union_pw_aff union_add(multi_union_pw_aff mupa2) const;
+};
+
+// declarations for isl::multi_val
+inline multi_val manage(__isl_take isl_multi_val *ptr);
+inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+
+class multi_val {
+  friend inline multi_val manage(__isl_take isl_multi_val *ptr);
+  friend inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+
+  isl_multi_val *ptr = nullptr;
+
+  inline explicit multi_val(__isl_take isl_multi_val *ptr);
+
+public:
+  inline /* implicit */ multi_val();
+  inline /* implicit */ multi_val(const multi_val &obj);
+  inline multi_val &operator=(multi_val obj);
+  inline ~multi_val();
+  inline __isl_give isl_multi_val *copy() const &;
+  inline __isl_give isl_multi_val *copy() && = delete;
+  inline __isl_keep isl_multi_val *get() const;
+  inline __isl_give isl_multi_val *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline multi_val add(multi_val multi2) const;
+  inline multi_val flat_range_product(multi_val multi2) const;
+  inline multi_val product(multi_val multi2) const;
+  inline multi_val range_product(multi_val multi2) const;
+};
+
+// declarations for isl::point
+inline point manage(__isl_take isl_point *ptr);
+inline point manage_copy(__isl_keep isl_point *ptr);
+
+class point {
+  friend inline point manage(__isl_take isl_point *ptr);
+  friend inline point manage_copy(__isl_keep isl_point *ptr);
+
+  isl_point *ptr = nullptr;
+
+  inline explicit point(__isl_take isl_point *ptr);
+
+public:
+  inline /* implicit */ point();
+  inline /* implicit */ point(const point &obj);
+  inline point &operator=(point obj);
+  inline ~point();
+  inline __isl_give isl_point *copy() const &;
+  inline __isl_give isl_point *copy() && = delete;
+  inline __isl_keep isl_point *get() const;
+  inline __isl_give isl_point *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+};
+
+// declarations for isl::pw_aff
+inline pw_aff manage(__isl_take isl_pw_aff *ptr);
+inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+
+class pw_aff {
+  friend inline pw_aff manage(__isl_take isl_pw_aff *ptr);
+  friend inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+
+  isl_pw_aff *ptr = nullptr;
+
+  inline explicit pw_aff(__isl_take isl_pw_aff *ptr);
+
+public:
+  inline /* implicit */ pw_aff();
+  inline /* implicit */ pw_aff(const pw_aff &obj);
+  inline /* implicit */ pw_aff(aff aff);
+  inline explicit pw_aff(ctx ctx, const std::string &str);
+  inline pw_aff &operator=(pw_aff obj);
+  inline ~pw_aff();
+  inline __isl_give isl_pw_aff *copy() const &;
+  inline __isl_give isl_pw_aff *copy() && = delete;
+  inline __isl_keep isl_pw_aff *get() const;
+  inline __isl_give isl_pw_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline pw_aff add(pw_aff pwaff2) const;
+  inline pw_aff ceil() const;
+  inline pw_aff cond(pw_aff pwaff_true, pw_aff pwaff_false) const;
+  inline pw_aff div(pw_aff pa2) const;
+  inline set eq_set(pw_aff pwaff2) const;
+  inline pw_aff floor() const;
+  inline set ge_set(pw_aff pwaff2) const;
+  inline set gt_set(pw_aff pwaff2) const;
+  inline set le_set(pw_aff pwaff2) const;
+  inline set lt_set(pw_aff pwaff2) const;
+  inline pw_aff max(pw_aff pwaff2) const;
+  inline pw_aff min(pw_aff pwaff2) const;
+  inline pw_aff mod(val mod) const;
+  inline pw_aff mul(pw_aff pwaff2) const;
+  inline set ne_set(pw_aff pwaff2) const;
+  inline pw_aff neg() const;
+  inline pw_aff pullback(multi_aff ma) const;
+  inline pw_aff pullback(pw_multi_aff pma) const;
+  inline pw_aff pullback(multi_pw_aff mpa) const;
+  inline pw_aff scale(val v) const;
+  inline pw_aff scale_down(val f) const;
+  inline pw_aff sub(pw_aff pwaff2) const;
+  inline pw_aff tdiv_q(pw_aff pa2) const;
+  inline pw_aff tdiv_r(pw_aff pa2) const;
+  inline pw_aff union_add(pw_aff pwaff2) const;
+};
+
+// declarations for isl::pw_multi_aff
+inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
+inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+
+class pw_multi_aff {
+  friend inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
+  friend inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+
+  isl_pw_multi_aff *ptr = nullptr;
+
+  inline explicit pw_multi_aff(__isl_take isl_pw_multi_aff *ptr);
+
+public:
+  inline /* implicit */ pw_multi_aff();
+  inline /* implicit */ pw_multi_aff(const pw_multi_aff &obj);
+  inline /* implicit */ pw_multi_aff(multi_aff ma);
+  inline /* implicit */ pw_multi_aff(pw_aff pa);
+  inline explicit pw_multi_aff(ctx ctx, const std::string &str);
+  inline pw_multi_aff &operator=(pw_multi_aff obj);
+  inline ~pw_multi_aff();
+  inline __isl_give isl_pw_multi_aff *copy() const &;
+  inline __isl_give isl_pw_multi_aff *copy() && = delete;
+  inline __isl_keep isl_pw_multi_aff *get() const;
+  inline __isl_give isl_pw_multi_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline pw_multi_aff add(pw_multi_aff pma2) const;
+  inline pw_multi_aff flat_range_product(pw_multi_aff pma2) const;
+  inline pw_multi_aff product(pw_multi_aff pma2) const;
+  inline pw_multi_aff pullback(multi_aff ma) const;
+  inline pw_multi_aff pullback(pw_multi_aff pma2) const;
+  inline pw_multi_aff range_product(pw_multi_aff pma2) const;
+  inline pw_multi_aff union_add(pw_multi_aff pma2) const;
+};
+
+// declarations for isl::schedule
+inline schedule manage(__isl_take isl_schedule *ptr);
+inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+
+class schedule {
+  friend inline schedule manage(__isl_take isl_schedule *ptr);
+  friend inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+
+  isl_schedule *ptr = nullptr;
+
+  inline explicit schedule(__isl_take isl_schedule *ptr);
+
+public:
+  inline /* implicit */ schedule();
+  inline /* implicit */ schedule(const schedule &obj);
+  inline explicit schedule(ctx ctx, const std::string &str);
+  inline schedule &operator=(schedule obj);
+  inline ~schedule();
+  inline __isl_give isl_schedule *copy() const &;
+  inline __isl_give isl_schedule *copy() && = delete;
+  inline __isl_keep isl_schedule *get() const;
+  inline __isl_give isl_schedule *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_map get_map() const;
+  inline schedule_node get_root() const;
+  inline schedule pullback(union_pw_multi_aff upma) const;
+};
+
+// declarations for isl::schedule_constraints
+inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
+inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+
+class schedule_constraints {
+  friend inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
+  friend inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+
+  isl_schedule_constraints *ptr = nullptr;
+
+  inline explicit schedule_constraints(__isl_take isl_schedule_constraints *ptr);
+
+public:
+  inline /* implicit */ schedule_constraints();
+  inline /* implicit */ schedule_constraints(const schedule_constraints &obj);
+  inline explicit schedule_constraints(ctx ctx, const std::string &str);
+  inline schedule_constraints &operator=(schedule_constraints obj);
+  inline ~schedule_constraints();
+  inline __isl_give isl_schedule_constraints *copy() const &;
+  inline __isl_give isl_schedule_constraints *copy() && = delete;
+  inline __isl_keep isl_schedule_constraints *get() const;
+  inline __isl_give isl_schedule_constraints *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline schedule compute_schedule() const;
+  inline union_map get_coincidence() const;
+  inline union_map get_conditional_validity() const;
+  inline union_map get_conditional_validity_condition() const;
+  inline set get_context() const;
+  inline union_set get_domain() const;
+  inline union_map get_proximity() const;
+  inline union_map get_validity() const;
+  static inline schedule_constraints on_domain(union_set domain);
+  inline schedule_constraints set_coincidence(union_map coincidence) const;
+  inline schedule_constraints set_conditional_validity(union_map condition, union_map validity) const;
+  inline schedule_constraints set_context(set context) const;
+  inline schedule_constraints set_proximity(union_map proximity) const;
+  inline schedule_constraints set_validity(union_map validity) const;
+};
+
+// declarations for isl::schedule_node
+inline schedule_node manage(__isl_take isl_schedule_node *ptr);
+inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+
+class schedule_node {
+  friend inline schedule_node manage(__isl_take isl_schedule_node *ptr);
+  friend inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+
+  isl_schedule_node *ptr = nullptr;
+
+  inline explicit schedule_node(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node();
+  inline /* implicit */ schedule_node(const schedule_node &obj);
+  inline schedule_node &operator=(schedule_node obj);
+  inline ~schedule_node();
+  inline __isl_give isl_schedule_node *copy() const &;
+  inline __isl_give isl_schedule_node *copy() && = delete;
+  inline __isl_keep isl_schedule_node *get() const;
+  inline __isl_give isl_schedule_node *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline boolean band_member_get_coincident(int pos) const;
+  inline schedule_node band_member_set_coincident(int pos, int coincident) const;
+  inline schedule_node child(int pos) const;
+  inline multi_union_pw_aff get_prefix_schedule_multi_union_pw_aff() const;
+  inline union_map get_prefix_schedule_union_map() const;
+  inline union_pw_multi_aff get_prefix_schedule_union_pw_multi_aff() const;
+  inline schedule get_schedule() const;
+  inline schedule_node parent() const;
+};
+
+// declarations for isl::set
+inline set manage(__isl_take isl_set *ptr);
+inline set manage_copy(__isl_keep isl_set *ptr);
+
+class set {
+  friend inline set manage(__isl_take isl_set *ptr);
+  friend inline set manage_copy(__isl_keep isl_set *ptr);
+
+  isl_set *ptr = nullptr;
+
+  inline explicit set(__isl_take isl_set *ptr);
+
+public:
+  inline /* implicit */ set();
+  inline /* implicit */ set(const set &obj);
+  inline explicit set(ctx ctx, const std::string &str);
+  inline /* implicit */ set(basic_set bset);
+  inline /* implicit */ set(point pnt);
+  inline set &operator=(set obj);
+  inline ~set();
+  inline __isl_give isl_set *copy() const &;
+  inline __isl_give isl_set *copy() && = delete;
+  inline __isl_keep isl_set *get() const;
+  inline __isl_give isl_set *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline basic_set affine_hull() const;
+  inline set apply(map map) const;
+  inline set coalesce() const;
+  inline set complement() const;
+  inline set detect_equalities() const;
+  inline set flatten() const;
+  inline stat foreach_basic_set(const std::function<stat(basic_set)> &fn) const;
+  inline val get_stride(int pos) const;
+  inline set gist(set context) const;
+  inline map identity() const;
+  inline set intersect(set set2) const;
+  inline set intersect_params(set params) const;
+  inline boolean is_disjoint(const set &set2) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const set &set2) const;
+  inline boolean is_strict_subset(const set &set2) const;
+  inline boolean is_subset(const set &set2) const;
+  inline boolean is_wrapping() const;
+  inline set lexmax() const;
+  inline set lexmin() const;
+  inline val max_val(const aff &obj) const;
+  inline val min_val(const aff &obj) const;
+  inline basic_set polyhedral_hull() const;
+  inline basic_set sample() const;
+  inline point sample_point() const;
+  inline set subtract(set set2) const;
+  inline set unite(set set2) const;
+  inline basic_set unshifted_simple_hull() const;
+};
+
+// declarations for isl::union_access_info
+inline union_access_info manage(__isl_take isl_union_access_info *ptr);
+inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+
+class union_access_info {
+  friend inline union_access_info manage(__isl_take isl_union_access_info *ptr);
+  friend inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+
+  isl_union_access_info *ptr = nullptr;
+
+  inline explicit union_access_info(__isl_take isl_union_access_info *ptr);
+
+public:
+  inline /* implicit */ union_access_info();
+  inline /* implicit */ union_access_info(const union_access_info &obj);
+  inline explicit union_access_info(union_map sink);
+  inline union_access_info &operator=(union_access_info obj);
+  inline ~union_access_info();
+  inline __isl_give isl_union_access_info *copy() const &;
+  inline __isl_give isl_union_access_info *copy() && = delete;
+  inline __isl_keep isl_union_access_info *get() const;
+  inline __isl_give isl_union_access_info *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_flow compute_flow() const;
+  inline union_access_info set_kill(union_map kill) const;
+  inline union_access_info set_may_source(union_map may_source) const;
+  inline union_access_info set_must_source(union_map must_source) const;
+  inline union_access_info set_schedule(schedule schedule) const;
+  inline union_access_info set_schedule_map(union_map schedule_map) const;
+};
+
+// declarations for isl::union_flow
+inline union_flow manage(__isl_take isl_union_flow *ptr);
+inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+
+class union_flow {
+  friend inline union_flow manage(__isl_take isl_union_flow *ptr);
+  friend inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+
+  isl_union_flow *ptr = nullptr;
+
+  inline explicit union_flow(__isl_take isl_union_flow *ptr);
+
+public:
+  inline /* implicit */ union_flow();
+  inline /* implicit */ union_flow(const union_flow &obj);
+  inline union_flow &operator=(union_flow obj);
+  inline ~union_flow();
+  inline __isl_give isl_union_flow *copy() const &;
+  inline __isl_give isl_union_flow *copy() && = delete;
+  inline __isl_keep isl_union_flow *get() const;
+  inline __isl_give isl_union_flow *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_map get_full_may_dependence() const;
+  inline union_map get_full_must_dependence() const;
+  inline union_map get_may_dependence() const;
+  inline union_map get_may_no_source() const;
+  inline union_map get_must_dependence() const;
+  inline union_map get_must_no_source() const;
+};
+
+// declarations for isl::union_map
+inline union_map manage(__isl_take isl_union_map *ptr);
+inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+
+class union_map {
+  friend inline union_map manage(__isl_take isl_union_map *ptr);
+  friend inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+
+  isl_union_map *ptr = nullptr;
+
+  inline explicit union_map(__isl_take isl_union_map *ptr);
+
+public:
+  inline /* implicit */ union_map();
+  inline /* implicit */ union_map(const union_map &obj);
+  inline /* implicit */ union_map(basic_map bmap);
+  inline /* implicit */ union_map(map map);
+  inline explicit union_map(ctx ctx, const std::string &str);
+  inline union_map &operator=(union_map obj);
+  inline ~union_map();
+  inline __isl_give isl_union_map *copy() const &;
+  inline __isl_give isl_union_map *copy() && = delete;
+  inline __isl_keep isl_union_map *get() const;
+  inline __isl_give isl_union_map *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_map affine_hull() const;
+  inline union_map apply_domain(union_map umap2) const;
+  inline union_map apply_range(union_map umap2) const;
+  inline union_map coalesce() const;
+  inline union_map compute_divs() const;
+  inline union_set deltas() const;
+  inline union_map detect_equalities() const;
+  inline union_set domain() const;
+  inline union_map domain_factor_domain() const;
+  inline union_map domain_factor_range() const;
+  inline union_map domain_map() const;
+  inline union_pw_multi_aff domain_map_union_pw_multi_aff() const;
+  inline union_map domain_product(union_map umap2) const;
+  inline union_map eq_at(multi_union_pw_aff mupa) const;
+  inline union_map factor_domain() const;
+  inline union_map factor_range() const;
+  inline union_map fixed_power(val exp) const;
+  inline stat foreach_map(const std::function<stat(map)> &fn) const;
+  static inline union_map from(union_pw_multi_aff upma);
+  static inline union_map from(multi_union_pw_aff mupa);
+  static inline union_map from_domain(union_set uset);
+  static inline union_map from_domain_and_range(union_set domain, union_set range);
+  static inline union_map from_range(union_set uset);
+  inline union_map gist(union_map context) const;
+  inline union_map gist_domain(union_set uset) const;
+  inline union_map gist_params(set set) const;
+  inline union_map gist_range(union_set uset) const;
+  inline union_map intersect(union_map umap2) const;
+  inline union_map intersect_domain(union_set uset) const;
+  inline union_map intersect_params(set set) const;
+  inline union_map intersect_range(union_set uset) const;
+  inline boolean is_bijective() const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const union_map &umap2) const;
+  inline boolean is_injective() const;
+  inline boolean is_single_valued() const;
+  inline boolean is_strict_subset(const union_map &umap2) const;
+  inline boolean is_subset(const union_map &umap2) const;
+  inline union_map lexmax() const;
+  inline union_map lexmin() const;
+  inline union_map polyhedral_hull() const;
+  inline union_map product(union_map umap2) const;
+  inline union_map project_out_all_params() const;
+  inline union_set range() const;
+  inline union_map range_factor_domain() const;
+  inline union_map range_factor_range() const;
+  inline union_map range_map() const;
+  inline union_map range_product(union_map umap2) const;
+  inline union_map reverse() const;
+  inline union_map subtract(union_map umap2) const;
+  inline union_map subtract_domain(union_set dom) const;
+  inline union_map subtract_range(union_set dom) const;
+  inline union_map unite(union_map umap2) const;
+  inline union_set wrap() const;
+  inline union_map zip() const;
+};
+
+// declarations for isl::union_pw_aff
+inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
+inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+
+class union_pw_aff {
+  friend inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
+  friend inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+
+  isl_union_pw_aff *ptr = nullptr;
+
+  inline explicit union_pw_aff(__isl_take isl_union_pw_aff *ptr);
+
+public:
+  inline /* implicit */ union_pw_aff();
+  inline /* implicit */ union_pw_aff(const union_pw_aff &obj);
+  inline /* implicit */ union_pw_aff(pw_aff pa);
+  inline explicit union_pw_aff(ctx ctx, const std::string &str);
+  inline union_pw_aff &operator=(union_pw_aff obj);
+  inline ~union_pw_aff();
+  inline __isl_give isl_union_pw_aff *copy() const &;
+  inline __isl_give isl_union_pw_aff *copy() && = delete;
+  inline __isl_keep isl_union_pw_aff *get() const;
+  inline __isl_give isl_union_pw_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_pw_aff add(union_pw_aff upa2) const;
+  inline union_pw_aff pullback(union_pw_multi_aff upma) const;
+  inline union_pw_aff union_add(union_pw_aff upa2) const;
+};
+
+// declarations for isl::union_pw_multi_aff
+inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
+inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+
+class union_pw_multi_aff {
+  friend inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
+  friend inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+
+  isl_union_pw_multi_aff *ptr = nullptr;
+
+  inline explicit union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr);
+
+public:
+  inline /* implicit */ union_pw_multi_aff();
+  inline /* implicit */ union_pw_multi_aff(const union_pw_multi_aff &obj);
+  inline /* implicit */ union_pw_multi_aff(pw_multi_aff pma);
+  inline explicit union_pw_multi_aff(ctx ctx, const std::string &str);
+  inline /* implicit */ union_pw_multi_aff(union_pw_aff upa);
+  inline union_pw_multi_aff &operator=(union_pw_multi_aff obj);
+  inline ~union_pw_multi_aff();
+  inline __isl_give isl_union_pw_multi_aff *copy() const &;
+  inline __isl_give isl_union_pw_multi_aff *copy() && = delete;
+  inline __isl_keep isl_union_pw_multi_aff *get() const;
+  inline __isl_give isl_union_pw_multi_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_pw_multi_aff add(union_pw_multi_aff upma2) const;
+  inline union_pw_multi_aff flat_range_product(union_pw_multi_aff upma2) const;
+  inline union_pw_multi_aff pullback(union_pw_multi_aff upma2) const;
+  inline union_pw_multi_aff union_add(union_pw_multi_aff upma2) const;
+};
+
+// declarations for isl::union_set
+inline union_set manage(__isl_take isl_union_set *ptr);
+inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+
+class union_set {
+  friend inline union_set manage(__isl_take isl_union_set *ptr);
+  friend inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+
+  isl_union_set *ptr = nullptr;
+
+  inline explicit union_set(__isl_take isl_union_set *ptr);
+
+public:
+  inline /* implicit */ union_set();
+  inline /* implicit */ union_set(const union_set &obj);
+  inline /* implicit */ union_set(basic_set bset);
+  inline /* implicit */ union_set(set set);
+  inline /* implicit */ union_set(point pnt);
+  inline explicit union_set(ctx ctx, const std::string &str);
+  inline union_set &operator=(union_set obj);
+  inline ~union_set();
+  inline __isl_give isl_union_set *copy() const &;
+  inline __isl_give isl_union_set *copy() && = delete;
+  inline __isl_keep isl_union_set *get() const;
+  inline __isl_give isl_union_set *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_set affine_hull() const;
+  inline union_set apply(union_map umap) const;
+  inline union_set coalesce() const;
+  inline union_set compute_divs() const;
+  inline union_set detect_equalities() const;
+  inline stat foreach_point(const std::function<stat(point)> &fn) const;
+  inline stat foreach_set(const std::function<stat(set)> &fn) const;
+  inline union_set gist(union_set context) const;
+  inline union_set gist_params(set set) const;
+  inline union_map identity() const;
+  inline union_set intersect(union_set uset2) const;
+  inline union_set intersect_params(set set) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const union_set &uset2) const;
+  inline boolean is_strict_subset(const union_set &uset2) const;
+  inline boolean is_subset(const union_set &uset2) const;
+  inline union_set lexmax() const;
+  inline union_set lexmin() const;
+  inline union_set polyhedral_hull() const;
+  inline union_set preimage(multi_aff ma) const;
+  inline union_set preimage(pw_multi_aff pma) const;
+  inline union_set preimage(union_pw_multi_aff upma) const;
+  inline point sample_point() const;
+  inline union_set subtract(union_set uset2) const;
+  inline union_set unite(union_set uset2) const;
+  inline union_map unwrap() const;
+};
+
+// declarations for isl::val
+inline val manage(__isl_take isl_val *ptr);
+inline val manage_copy(__isl_keep isl_val *ptr);
+
+class val {
+  friend inline val manage(__isl_take isl_val *ptr);
+  friend inline val manage_copy(__isl_keep isl_val *ptr);
+
+  isl_val *ptr = nullptr;
+
+  inline explicit val(__isl_take isl_val *ptr);
+
+public:
+  inline /* implicit */ val();
+  inline /* implicit */ val(const val &obj);
+  inline explicit val(ctx ctx, const std::string &str);
+  inline explicit val(ctx ctx, long i);
+  inline val &operator=(val obj);
+  inline ~val();
+  inline __isl_give isl_val *copy() const &;
+  inline __isl_give isl_val *copy() && = delete;
+  inline __isl_keep isl_val *get() const;
+  inline __isl_give isl_val *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline val abs() const;
+  inline boolean abs_eq(const val &v2) const;
+  inline val add(val v2) const;
+  inline val ceil() const;
+  inline int cmp_si(long i) const;
+  inline val div(val v2) const;
+  inline boolean eq(const val &v2) const;
+  inline val floor() const;
+  inline val gcd(val v2) const;
+  inline boolean ge(const val &v2) const;
+  inline boolean gt(const val &v2) const;
+  static inline val infty(ctx ctx);
+  inline val inv() const;
+  inline boolean is_divisible_by(const val &v2) const;
+  inline boolean is_infty() const;
+  inline boolean is_int() const;
+  inline boolean is_nan() const;
+  inline boolean is_neg() const;
+  inline boolean is_neginfty() const;
+  inline boolean is_negone() const;
+  inline boolean is_nonneg() const;
+  inline boolean is_nonpos() const;
+  inline boolean is_one() const;
+  inline boolean is_pos() const;
+  inline boolean is_rat() const;
+  inline boolean is_zero() const;
+  inline boolean le(const val &v2) const;
+  inline boolean lt(const val &v2) const;
+  inline val max(val v2) const;
+  inline val min(val v2) const;
+  inline val mod(val v2) const;
+  inline val mul(val v2) const;
+  static inline val nan(ctx ctx);
+  inline boolean ne(const val &v2) const;
+  inline val neg() const;
+  static inline val neginfty(ctx ctx);
+  static inline val negone(ctx ctx);
+  static inline val one(ctx ctx);
+  inline int sgn() const;
+  inline val sub(val v2) const;
+  inline val trunc() const;
+  static inline val zero(ctx ctx);
+};
+
+// implementations for isl::aff
+aff manage(__isl_take isl_aff *ptr) {
+  return aff(ptr);
+}
+aff manage_copy(__isl_keep isl_aff *ptr) {
+  ptr = isl_aff_copy(ptr);
+  return aff(ptr);
+}
+
+aff::aff()
+    : ptr(nullptr) {}
+
+aff::aff(const aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+aff::aff(__isl_take isl_aff *ptr)
+    : ptr(ptr) {}
+
+aff::aff(ctx ctx, const std::string &str)
+{
+  auto res = isl_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+aff &aff::operator=(aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+aff::~aff() {
+  if (ptr)
+    isl_aff_free(ptr);
+}
+
+__isl_give isl_aff *aff::copy() const & {
+  return isl_aff_copy(ptr);
+}
+
+__isl_keep isl_aff *aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_aff *aff::release() {
+  isl_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx aff::get_ctx() const {
+  return ctx(isl_aff_get_ctx(ptr));
+}
+
+aff aff::add(aff aff2) const
+{
+  auto res = isl_aff_add(copy(), aff2.release());
+  return manage(res);
+}
+
+aff aff::ceil() const
+{
+  auto res = isl_aff_ceil(copy());
+  return manage(res);
+}
+
+aff aff::div(aff aff2) const
+{
+  auto res = isl_aff_div(copy(), aff2.release());
+  return manage(res);
+}
+
+set aff::eq_set(aff aff2) const
+{
+  auto res = isl_aff_eq_set(copy(), aff2.release());
+  return manage(res);
+}
+
+aff aff::floor() const
+{
+  auto res = isl_aff_floor(copy());
+  return manage(res);
+}
+
+set aff::ge_set(aff aff2) const
+{
+  auto res = isl_aff_ge_set(copy(), aff2.release());
+  return manage(res);
+}
+
+set aff::gt_set(aff aff2) const
+{
+  auto res = isl_aff_gt_set(copy(), aff2.release());
+  return manage(res);
+}
+
+set aff::le_set(aff aff2) const
+{
+  auto res = isl_aff_le_set(copy(), aff2.release());
+  return manage(res);
+}
+
+set aff::lt_set(aff aff2) const
+{
+  auto res = isl_aff_lt_set(copy(), aff2.release());
+  return manage(res);
+}
+
+aff aff::mod(val mod) const
+{
+  auto res = isl_aff_mod_val(copy(), mod.release());
+  return manage(res);
+}
+
+aff aff::mul(aff aff2) const
+{
+  auto res = isl_aff_mul(copy(), aff2.release());
+  return manage(res);
+}
+
+set aff::ne_set(aff aff2) const
+{
+  auto res = isl_aff_ne_set(copy(), aff2.release());
+  return manage(res);
+}
+
+aff aff::neg() const
+{
+  auto res = isl_aff_neg(copy());
+  return manage(res);
+}
+
+aff aff::pullback(multi_aff ma) const
+{
+  auto res = isl_aff_pullback_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+aff aff::scale(val v) const
+{
+  auto res = isl_aff_scale_val(copy(), v.release());
+  return manage(res);
+}
+
+aff aff::scale_down(val v) const
+{
+  auto res = isl_aff_scale_down_val(copy(), v.release());
+  return manage(res);
+}
+
+aff aff::sub(aff aff2) const
+{
+  auto res = isl_aff_sub(copy(), aff2.release());
+  return manage(res);
+}
+
+// implementations for isl::ast_build
+ast_build manage(__isl_take isl_ast_build *ptr) {
+  return ast_build(ptr);
+}
+ast_build manage_copy(__isl_keep isl_ast_build *ptr) {
+  ptr = isl_ast_build_copy(ptr);
+  return ast_build(ptr);
+}
+
+ast_build::ast_build()
+    : ptr(nullptr) {}
+
+ast_build::ast_build(const ast_build &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+ast_build::ast_build(__isl_take isl_ast_build *ptr)
+    : ptr(ptr) {}
+
+ast_build::ast_build(ctx ctx)
+{
+  auto res = isl_ast_build_alloc(ctx.release());
+  ptr = res;
+}
+
+ast_build &ast_build::operator=(ast_build obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_build::~ast_build() {
+  if (ptr)
+    isl_ast_build_free(ptr);
+}
+
+__isl_give isl_ast_build *ast_build::copy() const & {
+  return isl_ast_build_copy(ptr);
+}
+
+__isl_keep isl_ast_build *ast_build::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_build *ast_build::release() {
+  isl_ast_build *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_build::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx ast_build::get_ctx() const {
+  return ctx(isl_ast_build_get_ctx(ptr));
+}
+
+ast_expr ast_build::access_from(pw_multi_aff pma) const
+{
+  auto res = isl_ast_build_access_from_pw_multi_aff(get(), pma.release());
+  return manage(res);
+}
+
+ast_expr ast_build::access_from(multi_pw_aff mpa) const
+{
+  auto res = isl_ast_build_access_from_multi_pw_aff(get(), mpa.release());
+  return manage(res);
+}
+
+ast_expr ast_build::call_from(pw_multi_aff pma) const
+{
+  auto res = isl_ast_build_call_from_pw_multi_aff(get(), pma.release());
+  return manage(res);
+}
+
+ast_expr ast_build::call_from(multi_pw_aff mpa) const
+{
+  auto res = isl_ast_build_call_from_multi_pw_aff(get(), mpa.release());
+  return manage(res);
+}
+
+ast_expr ast_build::expr_from(set set) const
+{
+  auto res = isl_ast_build_expr_from_set(get(), set.release());
+  return manage(res);
+}
+
+ast_expr ast_build::expr_from(pw_aff pa) const
+{
+  auto res = isl_ast_build_expr_from_pw_aff(get(), pa.release());
+  return manage(res);
+}
+
+ast_build ast_build::from_context(set set)
+{
+  auto res = isl_ast_build_from_context(set.release());
+  return manage(res);
+}
+
+ast_node ast_build::node_from_schedule_map(union_map schedule) const
+{
+  auto res = isl_ast_build_node_from_schedule_map(get(), schedule.release());
+  return manage(res);
+}
+
+// implementations for isl::ast_expr
+ast_expr manage(__isl_take isl_ast_expr *ptr) {
+  return ast_expr(ptr);
+}
+ast_expr manage_copy(__isl_keep isl_ast_expr *ptr) {
+  ptr = isl_ast_expr_copy(ptr);
+  return ast_expr(ptr);
+}
+
+ast_expr::ast_expr()
+    : ptr(nullptr) {}
+
+ast_expr::ast_expr(const ast_expr &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+ast_expr::ast_expr(__isl_take isl_ast_expr *ptr)
+    : ptr(ptr) {}
+
+
+ast_expr &ast_expr::operator=(ast_expr obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_expr::~ast_expr() {
+  if (ptr)
+    isl_ast_expr_free(ptr);
+}
+
+__isl_give isl_ast_expr *ast_expr::copy() const & {
+  return isl_ast_expr_copy(ptr);
+}
+
+__isl_keep isl_ast_expr *ast_expr::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_expr *ast_expr::release() {
+  isl_ast_expr *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_expr::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx ast_expr::get_ctx() const {
+  return ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+std::string ast_expr::to_C_str() const
+{
+  auto res = isl_ast_expr_to_C_str(get());
+  std::string tmp(res);
+  free(res);
+  return tmp;
+}
+
+// implementations for isl::ast_node
+ast_node manage(__isl_take isl_ast_node *ptr) {
+  return ast_node(ptr);
+}
+ast_node manage_copy(__isl_keep isl_ast_node *ptr) {
+  ptr = isl_ast_node_copy(ptr);
+  return ast_node(ptr);
+}
+
+ast_node::ast_node()
+    : ptr(nullptr) {}
+
+ast_node::ast_node(const ast_node &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+ast_node::ast_node(__isl_take isl_ast_node *ptr)
+    : ptr(ptr) {}
+
+
+ast_node &ast_node::operator=(ast_node obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_node::~ast_node() {
+  if (ptr)
+    isl_ast_node_free(ptr);
+}
+
+__isl_give isl_ast_node *ast_node::copy() const & {
+  return isl_ast_node_copy(ptr);
+}
+
+__isl_keep isl_ast_node *ast_node::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_node *ast_node::release() {
+  isl_ast_node *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_node::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx ast_node::get_ctx() const {
+  return ctx(isl_ast_node_get_ctx(ptr));
+}
+
+std::string ast_node::to_C_str() const
+{
+  auto res = isl_ast_node_to_C_str(get());
+  std::string tmp(res);
+  free(res);
+  return tmp;
+}
+
+// implementations for isl::basic_map
+basic_map manage(__isl_take isl_basic_map *ptr) {
+  return basic_map(ptr);
+}
+basic_map manage_copy(__isl_keep isl_basic_map *ptr) {
+  ptr = isl_basic_map_copy(ptr);
+  return basic_map(ptr);
+}
+
+basic_map::basic_map()
+    : ptr(nullptr) {}
+
+basic_map::basic_map(const basic_map &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+basic_map::basic_map(__isl_take isl_basic_map *ptr)
+    : ptr(ptr) {}
+
+basic_map::basic_map(ctx ctx, const std::string &str)
+{
+  auto res = isl_basic_map_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+basic_map &basic_map::operator=(basic_map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+basic_map::~basic_map() {
+  if (ptr)
+    isl_basic_map_free(ptr);
+}
+
+__isl_give isl_basic_map *basic_map::copy() const & {
+  return isl_basic_map_copy(ptr);
+}
+
+__isl_keep isl_basic_map *basic_map::get() const {
+  return ptr;
+}
+
+__isl_give isl_basic_map *basic_map::release() {
+  isl_basic_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool basic_map::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx basic_map::get_ctx() const {
+  return ctx(isl_basic_map_get_ctx(ptr));
+}
+
+basic_map basic_map::affine_hull() const
+{
+  auto res = isl_basic_map_affine_hull(copy());
+  return manage(res);
+}
+
+basic_map basic_map::apply_domain(basic_map bmap2) const
+{
+  auto res = isl_basic_map_apply_domain(copy(), bmap2.release());
+  return manage(res);
+}
+
+basic_map basic_map::apply_range(basic_map bmap2) const
+{
+  auto res = isl_basic_map_apply_range(copy(), bmap2.release());
+  return manage(res);
+}
+
+basic_set basic_map::deltas() const
+{
+  auto res = isl_basic_map_deltas(copy());
+  return manage(res);
+}
+
+basic_map basic_map::detect_equalities() const
+{
+  auto res = isl_basic_map_detect_equalities(copy());
+  return manage(res);
+}
+
+basic_map basic_map::flatten() const
+{
+  auto res = isl_basic_map_flatten(copy());
+  return manage(res);
+}
+
+basic_map basic_map::flatten_domain() const
+{
+  auto res = isl_basic_map_flatten_domain(copy());
+  return manage(res);
+}
+
+basic_map basic_map::flatten_range() const
+{
+  auto res = isl_basic_map_flatten_range(copy());
+  return manage(res);
+}
+
+basic_map basic_map::gist(basic_map context) const
+{
+  auto res = isl_basic_map_gist(copy(), context.release());
+  return manage(res);
+}
+
+basic_map basic_map::intersect(basic_map bmap2) const
+{
+  auto res = isl_basic_map_intersect(copy(), bmap2.release());
+  return manage(res);
+}
+
+basic_map basic_map::intersect_domain(basic_set bset) const
+{
+  auto res = isl_basic_map_intersect_domain(copy(), bset.release());
+  return manage(res);
+}
+
+basic_map basic_map::intersect_range(basic_set bset) const
+{
+  auto res = isl_basic_map_intersect_range(copy(), bset.release());
+  return manage(res);
+}
+
+boolean basic_map::is_empty() const
+{
+  auto res = isl_basic_map_is_empty(get());
+  return manage(res);
+}
+
+boolean basic_map::is_equal(const basic_map &bmap2) const
+{
+  auto res = isl_basic_map_is_equal(get(), bmap2.get());
+  return manage(res);
+}
+
+boolean basic_map::is_subset(const basic_map &bmap2) const
+{
+  auto res = isl_basic_map_is_subset(get(), bmap2.get());
+  return manage(res);
+}
+
+map basic_map::lexmax() const
+{
+  auto res = isl_basic_map_lexmax(copy());
+  return manage(res);
+}
+
+map basic_map::lexmin() const
+{
+  auto res = isl_basic_map_lexmin(copy());
+  return manage(res);
+}
+
+basic_map basic_map::reverse() const
+{
+  auto res = isl_basic_map_reverse(copy());
+  return manage(res);
+}
+
+basic_map basic_map::sample() const
+{
+  auto res = isl_basic_map_sample(copy());
+  return manage(res);
+}
+
+map basic_map::unite(basic_map bmap2) const
+{
+  auto res = isl_basic_map_union(copy(), bmap2.release());
+  return manage(res);
+}
+
+// implementations for isl::basic_set
+basic_set manage(__isl_take isl_basic_set *ptr) {
+  return basic_set(ptr);
+}
+basic_set manage_copy(__isl_keep isl_basic_set *ptr) {
+  ptr = isl_basic_set_copy(ptr);
+  return basic_set(ptr);
+}
+
+basic_set::basic_set()
+    : ptr(nullptr) {}
+
+basic_set::basic_set(const basic_set &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+basic_set::basic_set(__isl_take isl_basic_set *ptr)
+    : ptr(ptr) {}
+
+basic_set::basic_set(ctx ctx, const std::string &str)
+{
+  auto res = isl_basic_set_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+basic_set::basic_set(point pnt)
+{
+  auto res = isl_basic_set_from_point(pnt.release());
+  ptr = res;
+}
+
+basic_set &basic_set::operator=(basic_set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+basic_set::~basic_set() {
+  if (ptr)
+    isl_basic_set_free(ptr);
+}
+
+__isl_give isl_basic_set *basic_set::copy() const & {
+  return isl_basic_set_copy(ptr);
+}
+
+__isl_keep isl_basic_set *basic_set::get() const {
+  return ptr;
+}
+
+__isl_give isl_basic_set *basic_set::release() {
+  isl_basic_set *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool basic_set::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx basic_set::get_ctx() const {
+  return ctx(isl_basic_set_get_ctx(ptr));
+}
+
+basic_set basic_set::affine_hull() const
+{
+  auto res = isl_basic_set_affine_hull(copy());
+  return manage(res);
+}
+
+basic_set basic_set::apply(basic_map bmap) const
+{
+  auto res = isl_basic_set_apply(copy(), bmap.release());
+  return manage(res);
+}
+
+basic_set basic_set::detect_equalities() const
+{
+  auto res = isl_basic_set_detect_equalities(copy());
+  return manage(res);
+}
+
+val basic_set::dim_max_val(int pos) const
+{
+  auto res = isl_basic_set_dim_max_val(copy(), pos);
+  return manage(res);
+}
+
+basic_set basic_set::flatten() const
+{
+  auto res = isl_basic_set_flatten(copy());
+  return manage(res);
+}
+
+basic_set basic_set::gist(basic_set context) const
+{
+  auto res = isl_basic_set_gist(copy(), context.release());
+  return manage(res);
+}
+
+basic_set basic_set::intersect(basic_set bset2) const
+{
+  auto res = isl_basic_set_intersect(copy(), bset2.release());
+  return manage(res);
+}
+
+basic_set basic_set::intersect_params(basic_set bset2) const
+{
+  auto res = isl_basic_set_intersect_params(copy(), bset2.release());
+  return manage(res);
+}
+
+boolean basic_set::is_empty() const
+{
+  auto res = isl_basic_set_is_empty(get());
+  return manage(res);
+}
+
+boolean basic_set::is_equal(const basic_set &bset2) const
+{
+  auto res = isl_basic_set_is_equal(get(), bset2.get());
+  return manage(res);
+}
+
+boolean basic_set::is_subset(const basic_set &bset2) const
+{
+  auto res = isl_basic_set_is_subset(get(), bset2.get());
+  return manage(res);
+}
+
+boolean basic_set::is_wrapping() const
+{
+  auto res = isl_basic_set_is_wrapping(get());
+  return manage(res);
+}
+
+set basic_set::lexmax() const
+{
+  auto res = isl_basic_set_lexmax(copy());
+  return manage(res);
+}
+
+set basic_set::lexmin() const
+{
+  auto res = isl_basic_set_lexmin(copy());
+  return manage(res);
+}
+
+basic_set basic_set::sample() const
+{
+  auto res = isl_basic_set_sample(copy());
+  return manage(res);
+}
+
+point basic_set::sample_point() const
+{
+  auto res = isl_basic_set_sample_point(copy());
+  return manage(res);
+}
+
+set basic_set::unite(basic_set bset2) const
+{
+  auto res = isl_basic_set_union(copy(), bset2.release());
+  return manage(res);
+}
+
+// implementations for isl::map
+map manage(__isl_take isl_map *ptr) {
+  return map(ptr);
+}
+map manage_copy(__isl_keep isl_map *ptr) {
+  ptr = isl_map_copy(ptr);
+  return map(ptr);
+}
+
+map::map()
+    : ptr(nullptr) {}
+
+map::map(const map &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+map::map(__isl_take isl_map *ptr)
+    : ptr(ptr) {}
+
+map::map(ctx ctx, const std::string &str)
+{
+  auto res = isl_map_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+map::map(basic_map bmap)
+{
+  auto res = isl_map_from_basic_map(bmap.release());
+  ptr = res;
+}
+
+map &map::operator=(map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+map::~map() {
+  if (ptr)
+    isl_map_free(ptr);
+}
+
+__isl_give isl_map *map::copy() const & {
+  return isl_map_copy(ptr);
+}
+
+__isl_keep isl_map *map::get() const {
+  return ptr;
+}
+
+__isl_give isl_map *map::release() {
+  isl_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool map::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx map::get_ctx() const {
+  return ctx(isl_map_get_ctx(ptr));
+}
+
+basic_map map::affine_hull() const
+{
+  auto res = isl_map_affine_hull(copy());
+  return manage(res);
+}
+
+map map::apply_domain(map map2) const
+{
+  auto res = isl_map_apply_domain(copy(), map2.release());
+  return manage(res);
+}
+
+map map::apply_range(map map2) const
+{
+  auto res = isl_map_apply_range(copy(), map2.release());
+  return manage(res);
+}
+
+map map::coalesce() const
+{
+  auto res = isl_map_coalesce(copy());
+  return manage(res);
+}
+
+map map::complement() const
+{
+  auto res = isl_map_complement(copy());
+  return manage(res);
+}
+
+set map::deltas() const
+{
+  auto res = isl_map_deltas(copy());
+  return manage(res);
+}
+
+map map::detect_equalities() const
+{
+  auto res = isl_map_detect_equalities(copy());
+  return manage(res);
+}
+
+map map::flatten() const
+{
+  auto res = isl_map_flatten(copy());
+  return manage(res);
+}
+
+map map::flatten_domain() const
+{
+  auto res = isl_map_flatten_domain(copy());
+  return manage(res);
+}
+
+map map::flatten_range() const
+{
+  auto res = isl_map_flatten_range(copy());
+  return manage(res);
+}
+
+stat map::foreach_basic_map(const std::function<stat(basic_map)> &fn) const
+{
+  struct fn_data {
+    const std::function<stat(basic_map)> *func;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_basic_map *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    stat ret = (*data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_map_foreach_basic_map(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+map map::gist(map context) const
+{
+  auto res = isl_map_gist(copy(), context.release());
+  return manage(res);
+}
+
+map map::gist_domain(set context) const
+{
+  auto res = isl_map_gist_domain(copy(), context.release());
+  return manage(res);
+}
+
+map map::intersect(map map2) const
+{
+  auto res = isl_map_intersect(copy(), map2.release());
+  return manage(res);
+}
+
+map map::intersect_domain(set set) const
+{
+  auto res = isl_map_intersect_domain(copy(), set.release());
+  return manage(res);
+}
+
+map map::intersect_params(set params) const
+{
+  auto res = isl_map_intersect_params(copy(), params.release());
+  return manage(res);
+}
+
+map map::intersect_range(set set) const
+{
+  auto res = isl_map_intersect_range(copy(), set.release());
+  return manage(res);
+}
+
+boolean map::is_bijective() const
+{
+  auto res = isl_map_is_bijective(get());
+  return manage(res);
+}
+
+boolean map::is_disjoint(const map &map2) const
+{
+  auto res = isl_map_is_disjoint(get(), map2.get());
+  return manage(res);
+}
+
+boolean map::is_empty() const
+{
+  auto res = isl_map_is_empty(get());
+  return manage(res);
+}
+
+boolean map::is_equal(const map &map2) const
+{
+  auto res = isl_map_is_equal(get(), map2.get());
+  return manage(res);
+}
+
+boolean map::is_injective() const
+{
+  auto res = isl_map_is_injective(get());
+  return manage(res);
+}
+
+boolean map::is_single_valued() const
+{
+  auto res = isl_map_is_single_valued(get());
+  return manage(res);
+}
+
+boolean map::is_strict_subset(const map &map2) const
+{
+  auto res = isl_map_is_strict_subset(get(), map2.get());
+  return manage(res);
+}
+
+boolean map::is_subset(const map &map2) const
+{
+  auto res = isl_map_is_subset(get(), map2.get());
+  return manage(res);
+}
+
+map map::lexmax() const
+{
+  auto res = isl_map_lexmax(copy());
+  return manage(res);
+}
+
+map map::lexmin() const
+{
+  auto res = isl_map_lexmin(copy());
+  return manage(res);
+}
+
+basic_map map::polyhedral_hull() const
+{
+  auto res = isl_map_polyhedral_hull(copy());
+  return manage(res);
+}
+
+map map::reverse() const
+{
+  auto res = isl_map_reverse(copy());
+  return manage(res);
+}
+
+basic_map map::sample() const
+{
+  auto res = isl_map_sample(copy());
+  return manage(res);
+}
+
+map map::subtract(map map2) const
+{
+  auto res = isl_map_subtract(copy(), map2.release());
+  return manage(res);
+}
+
+map map::unite(map map2) const
+{
+  auto res = isl_map_union(copy(), map2.release());
+  return manage(res);
+}
+
+basic_map map::unshifted_simple_hull() const
+{
+  auto res = isl_map_unshifted_simple_hull(copy());
+  return manage(res);
+}
+
+// implementations for isl::multi_aff
+multi_aff manage(__isl_take isl_multi_aff *ptr) {
+  return multi_aff(ptr);
+}
+multi_aff manage_copy(__isl_keep isl_multi_aff *ptr) {
+  ptr = isl_multi_aff_copy(ptr);
+  return multi_aff(ptr);
+}
+
+multi_aff::multi_aff()
+    : ptr(nullptr) {}
+
+multi_aff::multi_aff(const multi_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+multi_aff::multi_aff(__isl_take isl_multi_aff *ptr)
+    : ptr(ptr) {}
+
+multi_aff::multi_aff(aff aff)
+{
+  auto res = isl_multi_aff_from_aff(aff.release());
+  ptr = res;
+}
+multi_aff::multi_aff(ctx ctx, const std::string &str)
+{
+  auto res = isl_multi_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+multi_aff &multi_aff::operator=(multi_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_aff::~multi_aff() {
+  if (ptr)
+    isl_multi_aff_free(ptr);
+}
+
+__isl_give isl_multi_aff *multi_aff::copy() const & {
+  return isl_multi_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_aff *multi_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_aff *multi_aff::release() {
+  isl_multi_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx multi_aff::get_ctx() const {
+  return ctx(isl_multi_aff_get_ctx(ptr));
+}
+
+multi_aff multi_aff::add(multi_aff multi2) const
+{
+  auto res = isl_multi_aff_add(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_aff multi_aff::flat_range_product(multi_aff multi2) const
+{
+  auto res = isl_multi_aff_flat_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_aff multi_aff::product(multi_aff multi2) const
+{
+  auto res = isl_multi_aff_product(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_aff multi_aff::pullback(multi_aff ma2) const
+{
+  auto res = isl_multi_aff_pullback_multi_aff(copy(), ma2.release());
+  return manage(res);
+}
+
+multi_aff multi_aff::range_product(multi_aff multi2) const
+{
+  auto res = isl_multi_aff_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+// implementations for isl::multi_pw_aff
+multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr) {
+  return multi_pw_aff(ptr);
+}
+multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr) {
+  ptr = isl_multi_pw_aff_copy(ptr);
+  return multi_pw_aff(ptr);
+}
+
+multi_pw_aff::multi_pw_aff()
+    : ptr(nullptr) {}
+
+multi_pw_aff::multi_pw_aff(const multi_pw_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+multi_pw_aff::multi_pw_aff(__isl_take isl_multi_pw_aff *ptr)
+    : ptr(ptr) {}
+
+multi_pw_aff::multi_pw_aff(multi_aff ma)
+{
+  auto res = isl_multi_pw_aff_from_multi_aff(ma.release());
+  ptr = res;
+}
+multi_pw_aff::multi_pw_aff(pw_aff pa)
+{
+  auto res = isl_multi_pw_aff_from_pw_aff(pa.release());
+  ptr = res;
+}
+multi_pw_aff::multi_pw_aff(pw_multi_aff pma)
+{
+  auto res = isl_multi_pw_aff_from_pw_multi_aff(pma.release());
+  ptr = res;
+}
+multi_pw_aff::multi_pw_aff(ctx ctx, const std::string &str)
+{
+  auto res = isl_multi_pw_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+multi_pw_aff &multi_pw_aff::operator=(multi_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_pw_aff::~multi_pw_aff() {
+  if (ptr)
+    isl_multi_pw_aff_free(ptr);
+}
+
+__isl_give isl_multi_pw_aff *multi_pw_aff::copy() const & {
+  return isl_multi_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_pw_aff *multi_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_pw_aff *multi_pw_aff::release() {
+  isl_multi_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx multi_pw_aff::get_ctx() const {
+  return ctx(isl_multi_pw_aff_get_ctx(ptr));
+}
+
+multi_pw_aff multi_pw_aff::add(multi_pw_aff multi2) const
+{
+  auto res = isl_multi_pw_aff_add(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::flat_range_product(multi_pw_aff multi2) const
+{
+  auto res = isl_multi_pw_aff_flat_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::product(multi_pw_aff multi2) const
+{
+  auto res = isl_multi_pw_aff_product(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::pullback(multi_aff ma) const
+{
+  auto res = isl_multi_pw_aff_pullback_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::pullback(pw_multi_aff pma) const
+{
+  auto res = isl_multi_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::pullback(multi_pw_aff mpa2) const
+{
+  auto res = isl_multi_pw_aff_pullback_multi_pw_aff(copy(), mpa2.release());
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::range_product(multi_pw_aff multi2) const
+{
+  auto res = isl_multi_pw_aff_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+// implementations for isl::multi_union_pw_aff
+multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr) {
+  return multi_union_pw_aff(ptr);
+}
+multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr) {
+  ptr = isl_multi_union_pw_aff_copy(ptr);
+  return multi_union_pw_aff(ptr);
+}
+
+multi_union_pw_aff::multi_union_pw_aff()
+    : ptr(nullptr) {}
+
+multi_union_pw_aff::multi_union_pw_aff(const multi_union_pw_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+multi_union_pw_aff::multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr)
+    : ptr(ptr) {}
+
+multi_union_pw_aff::multi_union_pw_aff(union_pw_aff upa)
+{
+  auto res = isl_multi_union_pw_aff_from_union_pw_aff(upa.release());
+  ptr = res;
+}
+multi_union_pw_aff::multi_union_pw_aff(multi_pw_aff mpa)
+{
+  auto res = isl_multi_union_pw_aff_from_multi_pw_aff(mpa.release());
+  ptr = res;
+}
+multi_union_pw_aff::multi_union_pw_aff(ctx ctx, const std::string &str)
+{
+  auto res = isl_multi_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+multi_union_pw_aff &multi_union_pw_aff::operator=(multi_union_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_union_pw_aff::~multi_union_pw_aff() {
+  if (ptr)
+    isl_multi_union_pw_aff_free(ptr);
+}
+
+__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::copy() const & {
+  return isl_multi_union_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_union_pw_aff *multi_union_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::release() {
+  isl_multi_union_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_union_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx multi_union_pw_aff::get_ctx() const {
+  return ctx(isl_multi_union_pw_aff_get_ctx(ptr));
+}
+
+multi_union_pw_aff multi_union_pw_aff::add(multi_union_pw_aff multi2) const
+{
+  auto res = isl_multi_union_pw_aff_add(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_union_pw_aff multi_union_pw_aff::flat_range_product(multi_union_pw_aff multi2) const
+{
+  auto res = isl_multi_union_pw_aff_flat_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_union_pw_aff multi_union_pw_aff::pullback(union_pw_multi_aff upma) const
+{
+  auto res = isl_multi_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
+  return manage(res);
+}
+
+multi_union_pw_aff multi_union_pw_aff::range_product(multi_union_pw_aff multi2) const
+{
+  auto res = isl_multi_union_pw_aff_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_union_pw_aff multi_union_pw_aff::union_add(multi_union_pw_aff mupa2) const
+{
+  auto res = isl_multi_union_pw_aff_union_add(copy(), mupa2.release());
+  return manage(res);
+}
+
+// implementations for isl::multi_val
+multi_val manage(__isl_take isl_multi_val *ptr) {
+  return multi_val(ptr);
+}
+multi_val manage_copy(__isl_keep isl_multi_val *ptr) {
+  ptr = isl_multi_val_copy(ptr);
+  return multi_val(ptr);
+}
+
+multi_val::multi_val()
+    : ptr(nullptr) {}
+
+multi_val::multi_val(const multi_val &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+multi_val::multi_val(__isl_take isl_multi_val *ptr)
+    : ptr(ptr) {}
+
+
+multi_val &multi_val::operator=(multi_val obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_val::~multi_val() {
+  if (ptr)
+    isl_multi_val_free(ptr);
+}
+
+__isl_give isl_multi_val *multi_val::copy() const & {
+  return isl_multi_val_copy(ptr);
+}
+
+__isl_keep isl_multi_val *multi_val::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_val *multi_val::release() {
+  isl_multi_val *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_val::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx multi_val::get_ctx() const {
+  return ctx(isl_multi_val_get_ctx(ptr));
+}
+
+multi_val multi_val::add(multi_val multi2) const
+{
+  auto res = isl_multi_val_add(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_val multi_val::flat_range_product(multi_val multi2) const
+{
+  auto res = isl_multi_val_flat_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_val multi_val::product(multi_val multi2) const
+{
+  auto res = isl_multi_val_product(copy(), multi2.release());
+  return manage(res);
+}
+
+multi_val multi_val::range_product(multi_val multi2) const
+{
+  auto res = isl_multi_val_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+// implementations for isl::point
+point manage(__isl_take isl_point *ptr) {
+  return point(ptr);
+}
+point manage_copy(__isl_keep isl_point *ptr) {
+  ptr = isl_point_copy(ptr);
+  return point(ptr);
+}
+
+point::point()
+    : ptr(nullptr) {}
+
+point::point(const point &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+point::point(__isl_take isl_point *ptr)
+    : ptr(ptr) {}
+
+
+point &point::operator=(point obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+point::~point() {
+  if (ptr)
+    isl_point_free(ptr);
+}
+
+__isl_give isl_point *point::copy() const & {
+  return isl_point_copy(ptr);
+}
+
+__isl_keep isl_point *point::get() const {
+  return ptr;
+}
+
+__isl_give isl_point *point::release() {
+  isl_point *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool point::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx point::get_ctx() const {
+  return ctx(isl_point_get_ctx(ptr));
+}
+
+
+// implementations for isl::pw_aff
+pw_aff manage(__isl_take isl_pw_aff *ptr) {
+  return pw_aff(ptr);
+}
+pw_aff manage_copy(__isl_keep isl_pw_aff *ptr) {
+  ptr = isl_pw_aff_copy(ptr);
+  return pw_aff(ptr);
+}
+
+pw_aff::pw_aff()
+    : ptr(nullptr) {}
+
+pw_aff::pw_aff(const pw_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+pw_aff::pw_aff(__isl_take isl_pw_aff *ptr)
+    : ptr(ptr) {}
+
+pw_aff::pw_aff(aff aff)
+{
+  auto res = isl_pw_aff_from_aff(aff.release());
+  ptr = res;
+}
+pw_aff::pw_aff(ctx ctx, const std::string &str)
+{
+  auto res = isl_pw_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+pw_aff &pw_aff::operator=(pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+pw_aff::~pw_aff() {
+  if (ptr)
+    isl_pw_aff_free(ptr);
+}
+
+__isl_give isl_pw_aff *pw_aff::copy() const & {
+  return isl_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_pw_aff *pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_pw_aff *pw_aff::release() {
+  isl_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx pw_aff::get_ctx() const {
+  return ctx(isl_pw_aff_get_ctx(ptr));
+}
+
+pw_aff pw_aff::add(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_add(copy(), pwaff2.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::ceil() const
+{
+  auto res = isl_pw_aff_ceil(copy());
+  return manage(res);
+}
+
+pw_aff pw_aff::cond(pw_aff pwaff_true, pw_aff pwaff_false) const
+{
+  auto res = isl_pw_aff_cond(copy(), pwaff_true.release(), pwaff_false.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::div(pw_aff pa2) const
+{
+  auto res = isl_pw_aff_div(copy(), pa2.release());
+  return manage(res);
+}
+
+set pw_aff::eq_set(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_eq_set(copy(), pwaff2.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::floor() const
+{
+  auto res = isl_pw_aff_floor(copy());
+  return manage(res);
+}
+
+set pw_aff::ge_set(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_ge_set(copy(), pwaff2.release());
+  return manage(res);
+}
+
+set pw_aff::gt_set(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_gt_set(copy(), pwaff2.release());
+  return manage(res);
+}
+
+set pw_aff::le_set(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_le_set(copy(), pwaff2.release());
+  return manage(res);
+}
+
+set pw_aff::lt_set(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_lt_set(copy(), pwaff2.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::max(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_max(copy(), pwaff2.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::min(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_min(copy(), pwaff2.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::mod(val mod) const
+{
+  auto res = isl_pw_aff_mod_val(copy(), mod.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::mul(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_mul(copy(), pwaff2.release());
+  return manage(res);
+}
+
+set pw_aff::ne_set(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_ne_set(copy(), pwaff2.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::neg() const
+{
+  auto res = isl_pw_aff_neg(copy());
+  return manage(res);
+}
+
+pw_aff pw_aff::pullback(multi_aff ma) const
+{
+  auto res = isl_pw_aff_pullback_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::pullback(pw_multi_aff pma) const
+{
+  auto res = isl_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::pullback(multi_pw_aff mpa) const
+{
+  auto res = isl_pw_aff_pullback_multi_pw_aff(copy(), mpa.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::scale(val v) const
+{
+  auto res = isl_pw_aff_scale_val(copy(), v.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::scale_down(val f) const
+{
+  auto res = isl_pw_aff_scale_down_val(copy(), f.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::sub(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_sub(copy(), pwaff2.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::tdiv_q(pw_aff pa2) const
+{
+  auto res = isl_pw_aff_tdiv_q(copy(), pa2.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::tdiv_r(pw_aff pa2) const
+{
+  auto res = isl_pw_aff_tdiv_r(copy(), pa2.release());
+  return manage(res);
+}
+
+pw_aff pw_aff::union_add(pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_union_add(copy(), pwaff2.release());
+  return manage(res);
+}
+
+// implementations for isl::pw_multi_aff
+pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr) {
+  return pw_multi_aff(ptr);
+}
+pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr) {
+  ptr = isl_pw_multi_aff_copy(ptr);
+  return pw_multi_aff(ptr);
+}
+
+pw_multi_aff::pw_multi_aff()
+    : ptr(nullptr) {}
+
+pw_multi_aff::pw_multi_aff(const pw_multi_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+pw_multi_aff::pw_multi_aff(__isl_take isl_pw_multi_aff *ptr)
+    : ptr(ptr) {}
+
+pw_multi_aff::pw_multi_aff(multi_aff ma)
+{
+  auto res = isl_pw_multi_aff_from_multi_aff(ma.release());
+  ptr = res;
+}
+pw_multi_aff::pw_multi_aff(pw_aff pa)
+{
+  auto res = isl_pw_multi_aff_from_pw_aff(pa.release());
+  ptr = res;
+}
+pw_multi_aff::pw_multi_aff(ctx ctx, const std::string &str)
+{
+  auto res = isl_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+pw_multi_aff &pw_multi_aff::operator=(pw_multi_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+pw_multi_aff::~pw_multi_aff() {
+  if (ptr)
+    isl_pw_multi_aff_free(ptr);
+}
+
+__isl_give isl_pw_multi_aff *pw_multi_aff::copy() const & {
+  return isl_pw_multi_aff_copy(ptr);
+}
+
+__isl_keep isl_pw_multi_aff *pw_multi_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_pw_multi_aff *pw_multi_aff::release() {
+  isl_pw_multi_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool pw_multi_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx pw_multi_aff::get_ctx() const {
+  return ctx(isl_pw_multi_aff_get_ctx(ptr));
+}
+
+pw_multi_aff pw_multi_aff::add(pw_multi_aff pma2) const
+{
+  auto res = isl_pw_multi_aff_add(copy(), pma2.release());
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::flat_range_product(pw_multi_aff pma2) const
+{
+  auto res = isl_pw_multi_aff_flat_range_product(copy(), pma2.release());
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::product(pw_multi_aff pma2) const
+{
+  auto res = isl_pw_multi_aff_product(copy(), pma2.release());
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::pullback(multi_aff ma) const
+{
+  auto res = isl_pw_multi_aff_pullback_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::pullback(pw_multi_aff pma2) const
+{
+  auto res = isl_pw_multi_aff_pullback_pw_multi_aff(copy(), pma2.release());
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::range_product(pw_multi_aff pma2) const
+{
+  auto res = isl_pw_multi_aff_range_product(copy(), pma2.release());
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::union_add(pw_multi_aff pma2) const
+{
+  auto res = isl_pw_multi_aff_union_add(copy(), pma2.release());
+  return manage(res);
+}
+
+// implementations for isl::schedule
+schedule manage(__isl_take isl_schedule *ptr) {
+  return schedule(ptr);
+}
+schedule manage_copy(__isl_keep isl_schedule *ptr) {
+  ptr = isl_schedule_copy(ptr);
+  return schedule(ptr);
+}
+
+schedule::schedule()
+    : ptr(nullptr) {}
+
+schedule::schedule(const schedule &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+schedule::schedule(__isl_take isl_schedule *ptr)
+    : ptr(ptr) {}
+
+schedule::schedule(ctx ctx, const std::string &str)
+{
+  auto res = isl_schedule_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+schedule &schedule::operator=(schedule obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+schedule::~schedule() {
+  if (ptr)
+    isl_schedule_free(ptr);
+}
+
+__isl_give isl_schedule *schedule::copy() const & {
+  return isl_schedule_copy(ptr);
+}
+
+__isl_keep isl_schedule *schedule::get() const {
+  return ptr;
+}
+
+__isl_give isl_schedule *schedule::release() {
+  isl_schedule *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool schedule::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx schedule::get_ctx() const {
+  return ctx(isl_schedule_get_ctx(ptr));
+}
+
+union_map schedule::get_map() const
+{
+  auto res = isl_schedule_get_map(get());
+  return manage(res);
+}
+
+schedule_node schedule::get_root() const
+{
+  auto res = isl_schedule_get_root(get());
+  return manage(res);
+}
+
+schedule schedule::pullback(union_pw_multi_aff upma) const
+{
+  auto res = isl_schedule_pullback_union_pw_multi_aff(copy(), upma.release());
+  return manage(res);
+}
+
+// implementations for isl::schedule_constraints
+schedule_constraints manage(__isl_take isl_schedule_constraints *ptr) {
+  return schedule_constraints(ptr);
+}
+schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr) {
+  ptr = isl_schedule_constraints_copy(ptr);
+  return schedule_constraints(ptr);
+}
+
+schedule_constraints::schedule_constraints()
+    : ptr(nullptr) {}
+
+schedule_constraints::schedule_constraints(const schedule_constraints &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+schedule_constraints::schedule_constraints(__isl_take isl_schedule_constraints *ptr)
+    : ptr(ptr) {}
+
+schedule_constraints::schedule_constraints(ctx ctx, const std::string &str)
+{
+  auto res = isl_schedule_constraints_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+schedule_constraints &schedule_constraints::operator=(schedule_constraints obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+schedule_constraints::~schedule_constraints() {
+  if (ptr)
+    isl_schedule_constraints_free(ptr);
+}
+
+__isl_give isl_schedule_constraints *schedule_constraints::copy() const & {
+  return isl_schedule_constraints_copy(ptr);
+}
+
+__isl_keep isl_schedule_constraints *schedule_constraints::get() const {
+  return ptr;
+}
+
+__isl_give isl_schedule_constraints *schedule_constraints::release() {
+  isl_schedule_constraints *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool schedule_constraints::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx schedule_constraints::get_ctx() const {
+  return ctx(isl_schedule_constraints_get_ctx(ptr));
+}
+
+schedule schedule_constraints::compute_schedule() const
+{
+  auto res = isl_schedule_constraints_compute_schedule(copy());
+  return manage(res);
+}
+
+union_map schedule_constraints::get_coincidence() const
+{
+  auto res = isl_schedule_constraints_get_coincidence(get());
+  return manage(res);
+}
+
+union_map schedule_constraints::get_conditional_validity() const
+{
+  auto res = isl_schedule_constraints_get_conditional_validity(get());
+  return manage(res);
+}
+
+union_map schedule_constraints::get_conditional_validity_condition() const
+{
+  auto res = isl_schedule_constraints_get_conditional_validity_condition(get());
+  return manage(res);
+}
+
+set schedule_constraints::get_context() const
+{
+  auto res = isl_schedule_constraints_get_context(get());
+  return manage(res);
+}
+
+union_set schedule_constraints::get_domain() const
+{
+  auto res = isl_schedule_constraints_get_domain(get());
+  return manage(res);
+}
+
+union_map schedule_constraints::get_proximity() const
+{
+  auto res = isl_schedule_constraints_get_proximity(get());
+  return manage(res);
+}
+
+union_map schedule_constraints::get_validity() const
+{
+  auto res = isl_schedule_constraints_get_validity(get());
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::on_domain(union_set domain)
+{
+  auto res = isl_schedule_constraints_on_domain(domain.release());
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_coincidence(union_map coincidence) const
+{
+  auto res = isl_schedule_constraints_set_coincidence(copy(), coincidence.release());
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_conditional_validity(union_map condition, union_map validity) const
+{
+  auto res = isl_schedule_constraints_set_conditional_validity(copy(), condition.release(), validity.release());
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_context(set context) const
+{
+  auto res = isl_schedule_constraints_set_context(copy(), context.release());
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_proximity(union_map proximity) const
+{
+  auto res = isl_schedule_constraints_set_proximity(copy(), proximity.release());
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_validity(union_map validity) const
+{
+  auto res = isl_schedule_constraints_set_validity(copy(), validity.release());
+  return manage(res);
+}
+
+// implementations for isl::schedule_node
+schedule_node manage(__isl_take isl_schedule_node *ptr) {
+  return schedule_node(ptr);
+}
+schedule_node manage_copy(__isl_keep isl_schedule_node *ptr) {
+  ptr = isl_schedule_node_copy(ptr);
+  return schedule_node(ptr);
+}
+
+schedule_node::schedule_node()
+    : ptr(nullptr) {}
+
+schedule_node::schedule_node(const schedule_node &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+schedule_node::schedule_node(__isl_take isl_schedule_node *ptr)
+    : ptr(ptr) {}
+
+
+schedule_node &schedule_node::operator=(schedule_node obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+schedule_node::~schedule_node() {
+  if (ptr)
+    isl_schedule_node_free(ptr);
+}
+
+__isl_give isl_schedule_node *schedule_node::copy() const & {
+  return isl_schedule_node_copy(ptr);
+}
+
+__isl_keep isl_schedule_node *schedule_node::get() const {
+  return ptr;
+}
+
+__isl_give isl_schedule_node *schedule_node::release() {
+  isl_schedule_node *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool schedule_node::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx schedule_node::get_ctx() const {
+  return ctx(isl_schedule_node_get_ctx(ptr));
+}
+
+boolean schedule_node::band_member_get_coincident(int pos) const
+{
+  auto res = isl_schedule_node_band_member_get_coincident(get(), pos);
+  return manage(res);
+}
+
+schedule_node schedule_node::band_member_set_coincident(int pos, int coincident) const
+{
+  auto res = isl_schedule_node_band_member_set_coincident(copy(), pos, coincident);
+  return manage(res);
+}
+
+schedule_node schedule_node::child(int pos) const
+{
+  auto res = isl_schedule_node_child(copy(), pos);
+  return manage(res);
+}
+
+multi_union_pw_aff schedule_node::get_prefix_schedule_multi_union_pw_aff() const
+{
+  auto res = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(get());
+  return manage(res);
+}
+
+union_map schedule_node::get_prefix_schedule_union_map() const
+{
+  auto res = isl_schedule_node_get_prefix_schedule_union_map(get());
+  return manage(res);
+}
+
+union_pw_multi_aff schedule_node::get_prefix_schedule_union_pw_multi_aff() const
+{
+  auto res = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(get());
+  return manage(res);
+}
+
+schedule schedule_node::get_schedule() const
+{
+  auto res = isl_schedule_node_get_schedule(get());
+  return manage(res);
+}
+
+schedule_node schedule_node::parent() const
+{
+  auto res = isl_schedule_node_parent(copy());
+  return manage(res);
+}
+
+// implementations for isl::set
+set manage(__isl_take isl_set *ptr) {
+  return set(ptr);
+}
+set manage_copy(__isl_keep isl_set *ptr) {
+  ptr = isl_set_copy(ptr);
+  return set(ptr);
+}
+
+set::set()
+    : ptr(nullptr) {}
+
+set::set(const set &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+set::set(__isl_take isl_set *ptr)
+    : ptr(ptr) {}
+
+set::set(ctx ctx, const std::string &str)
+{
+  auto res = isl_set_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+set::set(basic_set bset)
+{
+  auto res = isl_set_from_basic_set(bset.release());
+  ptr = res;
+}
+set::set(point pnt)
+{
+  auto res = isl_set_from_point(pnt.release());
+  ptr = res;
+}
+
+set &set::operator=(set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+set::~set() {
+  if (ptr)
+    isl_set_free(ptr);
+}
+
+__isl_give isl_set *set::copy() const & {
+  return isl_set_copy(ptr);
+}
+
+__isl_keep isl_set *set::get() const {
+  return ptr;
+}
+
+__isl_give isl_set *set::release() {
+  isl_set *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool set::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx set::get_ctx() const {
+  return ctx(isl_set_get_ctx(ptr));
+}
+
+basic_set set::affine_hull() const
+{
+  auto res = isl_set_affine_hull(copy());
+  return manage(res);
+}
+
+set set::apply(map map) const
+{
+  auto res = isl_set_apply(copy(), map.release());
+  return manage(res);
+}
+
+set set::coalesce() const
+{
+  auto res = isl_set_coalesce(copy());
+  return manage(res);
+}
+
+set set::complement() const
+{
+  auto res = isl_set_complement(copy());
+  return manage(res);
+}
+
+set set::detect_equalities() const
+{
+  auto res = isl_set_detect_equalities(copy());
+  return manage(res);
+}
+
+set set::flatten() const
+{
+  auto res = isl_set_flatten(copy());
+  return manage(res);
+}
+
+stat set::foreach_basic_set(const std::function<stat(basic_set)> &fn) const
+{
+  struct fn_data {
+    const std::function<stat(basic_set)> *func;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_basic_set *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    stat ret = (*data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_set_foreach_basic_set(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+val set::get_stride(int pos) const
+{
+  auto res = isl_set_get_stride(get(), pos);
+  return manage(res);
+}
+
+set set::gist(set context) const
+{
+  auto res = isl_set_gist(copy(), context.release());
+  return manage(res);
+}
+
+map set::identity() const
+{
+  auto res = isl_set_identity(copy());
+  return manage(res);
+}
+
+set set::intersect(set set2) const
+{
+  auto res = isl_set_intersect(copy(), set2.release());
+  return manage(res);
+}
+
+set set::intersect_params(set params) const
+{
+  auto res = isl_set_intersect_params(copy(), params.release());
+  return manage(res);
+}
+
+boolean set::is_disjoint(const set &set2) const
+{
+  auto res = isl_set_is_disjoint(get(), set2.get());
+  return manage(res);
+}
+
+boolean set::is_empty() const
+{
+  auto res = isl_set_is_empty(get());
+  return manage(res);
+}
+
+boolean set::is_equal(const set &set2) const
+{
+  auto res = isl_set_is_equal(get(), set2.get());
+  return manage(res);
+}
+
+boolean set::is_strict_subset(const set &set2) const
+{
+  auto res = isl_set_is_strict_subset(get(), set2.get());
+  return manage(res);
+}
+
+boolean set::is_subset(const set &set2) const
+{
+  auto res = isl_set_is_subset(get(), set2.get());
+  return manage(res);
+}
+
+boolean set::is_wrapping() const
+{
+  auto res = isl_set_is_wrapping(get());
+  return manage(res);
+}
+
+set set::lexmax() const
+{
+  auto res = isl_set_lexmax(copy());
+  return manage(res);
+}
+
+set set::lexmin() const
+{
+  auto res = isl_set_lexmin(copy());
+  return manage(res);
+}
+
+val set::max_val(const aff &obj) const
+{
+  auto res = isl_set_max_val(get(), obj.get());
+  return manage(res);
+}
+
+val set::min_val(const aff &obj) const
+{
+  auto res = isl_set_min_val(get(), obj.get());
+  return manage(res);
+}
+
+basic_set set::polyhedral_hull() const
+{
+  auto res = isl_set_polyhedral_hull(copy());
+  return manage(res);
+}
+
+basic_set set::sample() const
+{
+  auto res = isl_set_sample(copy());
+  return manage(res);
+}
+
+point set::sample_point() const
+{
+  auto res = isl_set_sample_point(copy());
+  return manage(res);
+}
+
+set set::subtract(set set2) const
+{
+  auto res = isl_set_subtract(copy(), set2.release());
+  return manage(res);
+}
+
+set set::unite(set set2) const
+{
+  auto res = isl_set_union(copy(), set2.release());
+  return manage(res);
+}
+
+basic_set set::unshifted_simple_hull() const
+{
+  auto res = isl_set_unshifted_simple_hull(copy());
+  return manage(res);
+}
+
+// implementations for isl::union_access_info
+union_access_info manage(__isl_take isl_union_access_info *ptr) {
+  return union_access_info(ptr);
+}
+union_access_info manage_copy(__isl_keep isl_union_access_info *ptr) {
+  ptr = isl_union_access_info_copy(ptr);
+  return union_access_info(ptr);
+}
+
+union_access_info::union_access_info()
+    : ptr(nullptr) {}
+
+union_access_info::union_access_info(const union_access_info &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+union_access_info::union_access_info(__isl_take isl_union_access_info *ptr)
+    : ptr(ptr) {}
+
+union_access_info::union_access_info(union_map sink)
+{
+  auto res = isl_union_access_info_from_sink(sink.release());
+  ptr = res;
+}
+
+union_access_info &union_access_info::operator=(union_access_info obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_access_info::~union_access_info() {
+  if (ptr)
+    isl_union_access_info_free(ptr);
+}
+
+__isl_give isl_union_access_info *union_access_info::copy() const & {
+  return isl_union_access_info_copy(ptr);
+}
+
+__isl_keep isl_union_access_info *union_access_info::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_access_info *union_access_info::release() {
+  isl_union_access_info *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_access_info::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_access_info::get_ctx() const {
+  return ctx(isl_union_access_info_get_ctx(ptr));
+}
+
+union_flow union_access_info::compute_flow() const
+{
+  auto res = isl_union_access_info_compute_flow(copy());
+  return manage(res);
+}
+
+union_access_info union_access_info::set_kill(union_map kill) const
+{
+  auto res = isl_union_access_info_set_kill(copy(), kill.release());
+  return manage(res);
+}
+
+union_access_info union_access_info::set_may_source(union_map may_source) const
+{
+  auto res = isl_union_access_info_set_may_source(copy(), may_source.release());
+  return manage(res);
+}
+
+union_access_info union_access_info::set_must_source(union_map must_source) const
+{
+  auto res = isl_union_access_info_set_must_source(copy(), must_source.release());
+  return manage(res);
+}
+
+union_access_info union_access_info::set_schedule(schedule schedule) const
+{
+  auto res = isl_union_access_info_set_schedule(copy(), schedule.release());
+  return manage(res);
+}
+
+union_access_info union_access_info::set_schedule_map(union_map schedule_map) const
+{
+  auto res = isl_union_access_info_set_schedule_map(copy(), schedule_map.release());
+  return manage(res);
+}
+
+// implementations for isl::union_flow
+union_flow manage(__isl_take isl_union_flow *ptr) {
+  return union_flow(ptr);
+}
+union_flow manage_copy(__isl_keep isl_union_flow *ptr) {
+  ptr = isl_union_flow_copy(ptr);
+  return union_flow(ptr);
+}
+
+union_flow::union_flow()
+    : ptr(nullptr) {}
+
+union_flow::union_flow(const union_flow &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+union_flow::union_flow(__isl_take isl_union_flow *ptr)
+    : ptr(ptr) {}
+
+
+union_flow &union_flow::operator=(union_flow obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_flow::~union_flow() {
+  if (ptr)
+    isl_union_flow_free(ptr);
+}
+
+__isl_give isl_union_flow *union_flow::copy() const & {
+  return isl_union_flow_copy(ptr);
+}
+
+__isl_keep isl_union_flow *union_flow::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_flow *union_flow::release() {
+  isl_union_flow *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_flow::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_flow::get_ctx() const {
+  return ctx(isl_union_flow_get_ctx(ptr));
+}
+
+union_map union_flow::get_full_may_dependence() const
+{
+  auto res = isl_union_flow_get_full_may_dependence(get());
+  return manage(res);
+}
+
+union_map union_flow::get_full_must_dependence() const
+{
+  auto res = isl_union_flow_get_full_must_dependence(get());
+  return manage(res);
+}
+
+union_map union_flow::get_may_dependence() const
+{
+  auto res = isl_union_flow_get_may_dependence(get());
+  return manage(res);
+}
+
+union_map union_flow::get_may_no_source() const
+{
+  auto res = isl_union_flow_get_may_no_source(get());
+  return manage(res);
+}
+
+union_map union_flow::get_must_dependence() const
+{
+  auto res = isl_union_flow_get_must_dependence(get());
+  return manage(res);
+}
+
+union_map union_flow::get_must_no_source() const
+{
+  auto res = isl_union_flow_get_must_no_source(get());
+  return manage(res);
+}
+
+// implementations for isl::union_map
+union_map manage(__isl_take isl_union_map *ptr) {
+  return union_map(ptr);
+}
+union_map manage_copy(__isl_keep isl_union_map *ptr) {
+  ptr = isl_union_map_copy(ptr);
+  return union_map(ptr);
+}
+
+union_map::union_map()
+    : ptr(nullptr) {}
+
+union_map::union_map(const union_map &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+union_map::union_map(__isl_take isl_union_map *ptr)
+    : ptr(ptr) {}
+
+union_map::union_map(basic_map bmap)
+{
+  auto res = isl_union_map_from_basic_map(bmap.release());
+  ptr = res;
+}
+union_map::union_map(map map)
+{
+  auto res = isl_union_map_from_map(map.release());
+  ptr = res;
+}
+union_map::union_map(ctx ctx, const std::string &str)
+{
+  auto res = isl_union_map_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+union_map &union_map::operator=(union_map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_map::~union_map() {
+  if (ptr)
+    isl_union_map_free(ptr);
+}
+
+__isl_give isl_union_map *union_map::copy() const & {
+  return isl_union_map_copy(ptr);
+}
+
+__isl_keep isl_union_map *union_map::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_map *union_map::release() {
+  isl_union_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_map::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_map::get_ctx() const {
+  return ctx(isl_union_map_get_ctx(ptr));
+}
+
+union_map union_map::affine_hull() const
+{
+  auto res = isl_union_map_affine_hull(copy());
+  return manage(res);
+}
+
+union_map union_map::apply_domain(union_map umap2) const
+{
+  auto res = isl_union_map_apply_domain(copy(), umap2.release());
+  return manage(res);
+}
+
+union_map union_map::apply_range(union_map umap2) const
+{
+  auto res = isl_union_map_apply_range(copy(), umap2.release());
+  return manage(res);
+}
+
+union_map union_map::coalesce() const
+{
+  auto res = isl_union_map_coalesce(copy());
+  return manage(res);
+}
+
+union_map union_map::compute_divs() const
+{
+  auto res = isl_union_map_compute_divs(copy());
+  return manage(res);
+}
+
+union_set union_map::deltas() const
+{
+  auto res = isl_union_map_deltas(copy());
+  return manage(res);
+}
+
+union_map union_map::detect_equalities() const
+{
+  auto res = isl_union_map_detect_equalities(copy());
+  return manage(res);
+}
+
+union_set union_map::domain() const
+{
+  auto res = isl_union_map_domain(copy());
+  return manage(res);
+}
+
+union_map union_map::domain_factor_domain() const
+{
+  auto res = isl_union_map_domain_factor_domain(copy());
+  return manage(res);
+}
+
+union_map union_map::domain_factor_range() const
+{
+  auto res = isl_union_map_domain_factor_range(copy());
+  return manage(res);
+}
+
+union_map union_map::domain_map() const
+{
+  auto res = isl_union_map_domain_map(copy());
+  return manage(res);
+}
+
+union_pw_multi_aff union_map::domain_map_union_pw_multi_aff() const
+{
+  auto res = isl_union_map_domain_map_union_pw_multi_aff(copy());
+  return manage(res);
+}
+
+union_map union_map::domain_product(union_map umap2) const
+{
+  auto res = isl_union_map_domain_product(copy(), umap2.release());
+  return manage(res);
+}
+
+union_map union_map::eq_at(multi_union_pw_aff mupa) const
+{
+  auto res = isl_union_map_eq_at_multi_union_pw_aff(copy(), mupa.release());
+  return manage(res);
+}
+
+union_map union_map::factor_domain() const
+{
+  auto res = isl_union_map_factor_domain(copy());
+  return manage(res);
+}
+
+union_map union_map::factor_range() const
+{
+  auto res = isl_union_map_factor_range(copy());
+  return manage(res);
+}
+
+union_map union_map::fixed_power(val exp) const
+{
+  auto res = isl_union_map_fixed_power_val(copy(), exp.release());
+  return manage(res);
+}
+
+stat union_map::foreach_map(const std::function<stat(map)> &fn) const
+{
+  struct fn_data {
+    const std::function<stat(map)> *func;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_map *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    stat ret = (*data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_union_map_foreach_map(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+union_map union_map::from(union_pw_multi_aff upma)
+{
+  auto res = isl_union_map_from_union_pw_multi_aff(upma.release());
+  return manage(res);
+}
+
+union_map union_map::from(multi_union_pw_aff mupa)
+{
+  auto res = isl_union_map_from_multi_union_pw_aff(mupa.release());
+  return manage(res);
+}
+
+union_map union_map::from_domain(union_set uset)
+{
+  auto res = isl_union_map_from_domain(uset.release());
+  return manage(res);
+}
+
+union_map union_map::from_domain_and_range(union_set domain, union_set range)
+{
+  auto res = isl_union_map_from_domain_and_range(domain.release(), range.release());
+  return manage(res);
+}
+
+union_map union_map::from_range(union_set uset)
+{
+  auto res = isl_union_map_from_range(uset.release());
+  return manage(res);
+}
+
+union_map union_map::gist(union_map context) const
+{
+  auto res = isl_union_map_gist(copy(), context.release());
+  return manage(res);
+}
+
+union_map union_map::gist_domain(union_set uset) const
+{
+  auto res = isl_union_map_gist_domain(copy(), uset.release());
+  return manage(res);
+}
+
+union_map union_map::gist_params(set set) const
+{
+  auto res = isl_union_map_gist_params(copy(), set.release());
+  return manage(res);
+}
+
+union_map union_map::gist_range(union_set uset) const
+{
+  auto res = isl_union_map_gist_range(copy(), uset.release());
+  return manage(res);
+}
+
+union_map union_map::intersect(union_map umap2) const
+{
+  auto res = isl_union_map_intersect(copy(), umap2.release());
+  return manage(res);
+}
+
+union_map union_map::intersect_domain(union_set uset) const
+{
+  auto res = isl_union_map_intersect_domain(copy(), uset.release());
+  return manage(res);
+}
+
+union_map union_map::intersect_params(set set) const
+{
+  auto res = isl_union_map_intersect_params(copy(), set.release());
+  return manage(res);
+}
+
+union_map union_map::intersect_range(union_set uset) const
+{
+  auto res = isl_union_map_intersect_range(copy(), uset.release());
+  return manage(res);
+}
+
+boolean union_map::is_bijective() const
+{
+  auto res = isl_union_map_is_bijective(get());
+  return manage(res);
+}
+
+boolean union_map::is_empty() const
+{
+  auto res = isl_union_map_is_empty(get());
+  return manage(res);
+}
+
+boolean union_map::is_equal(const union_map &umap2) const
+{
+  auto res = isl_union_map_is_equal(get(), umap2.get());
+  return manage(res);
+}
+
+boolean union_map::is_injective() const
+{
+  auto res = isl_union_map_is_injective(get());
+  return manage(res);
+}
+
+boolean union_map::is_single_valued() const
+{
+  auto res = isl_union_map_is_single_valued(get());
+  return manage(res);
+}
+
+boolean union_map::is_strict_subset(const union_map &umap2) const
+{
+  auto res = isl_union_map_is_strict_subset(get(), umap2.get());
+  return manage(res);
+}
+
+boolean union_map::is_subset(const union_map &umap2) const
+{
+  auto res = isl_union_map_is_subset(get(), umap2.get());
+  return manage(res);
+}
+
+union_map union_map::lexmax() const
+{
+  auto res = isl_union_map_lexmax(copy());
+  return manage(res);
+}
+
+union_map union_map::lexmin() const
+{
+  auto res = isl_union_map_lexmin(copy());
+  return manage(res);
+}
+
+union_map union_map::polyhedral_hull() const
+{
+  auto res = isl_union_map_polyhedral_hull(copy());
+  return manage(res);
+}
+
+union_map union_map::product(union_map umap2) const
+{
+  auto res = isl_union_map_product(copy(), umap2.release());
+  return manage(res);
+}
+
+union_map union_map::project_out_all_params() const
+{
+  auto res = isl_union_map_project_out_all_params(copy());
+  return manage(res);
+}
+
+union_set union_map::range() const
+{
+  auto res = isl_union_map_range(copy());
+  return manage(res);
+}
+
+union_map union_map::range_factor_domain() const
+{
+  auto res = isl_union_map_range_factor_domain(copy());
+  return manage(res);
+}
+
+union_map union_map::range_factor_range() const
+{
+  auto res = isl_union_map_range_factor_range(copy());
+  return manage(res);
+}
+
+union_map union_map::range_map() const
+{
+  auto res = isl_union_map_range_map(copy());
+  return manage(res);
+}
+
+union_map union_map::range_product(union_map umap2) const
+{
+  auto res = isl_union_map_range_product(copy(), umap2.release());
+  return manage(res);
+}
+
+union_map union_map::reverse() const
+{
+  auto res = isl_union_map_reverse(copy());
+  return manage(res);
+}
+
+union_map union_map::subtract(union_map umap2) const
+{
+  auto res = isl_union_map_subtract(copy(), umap2.release());
+  return manage(res);
+}
+
+union_map union_map::subtract_domain(union_set dom) const
+{
+  auto res = isl_union_map_subtract_domain(copy(), dom.release());
+  return manage(res);
+}
+
+union_map union_map::subtract_range(union_set dom) const
+{
+  auto res = isl_union_map_subtract_range(copy(), dom.release());
+  return manage(res);
+}
+
+union_map union_map::unite(union_map umap2) const
+{
+  auto res = isl_union_map_union(copy(), umap2.release());
+  return manage(res);
+}
+
+union_set union_map::wrap() const
+{
+  auto res = isl_union_map_wrap(copy());
+  return manage(res);
+}
+
+union_map union_map::zip() const
+{
+  auto res = isl_union_map_zip(copy());
+  return manage(res);
+}
+
+// implementations for isl::union_pw_aff
+union_pw_aff manage(__isl_take isl_union_pw_aff *ptr) {
+  return union_pw_aff(ptr);
+}
+union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr) {
+  ptr = isl_union_pw_aff_copy(ptr);
+  return union_pw_aff(ptr);
+}
+
+union_pw_aff::union_pw_aff()
+    : ptr(nullptr) {}
+
+union_pw_aff::union_pw_aff(const union_pw_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+union_pw_aff::union_pw_aff(__isl_take isl_union_pw_aff *ptr)
+    : ptr(ptr) {}
+
+union_pw_aff::union_pw_aff(pw_aff pa)
+{
+  auto res = isl_union_pw_aff_from_pw_aff(pa.release());
+  ptr = res;
+}
+union_pw_aff::union_pw_aff(ctx ctx, const std::string &str)
+{
+  auto res = isl_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+union_pw_aff &union_pw_aff::operator=(union_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_pw_aff::~union_pw_aff() {
+  if (ptr)
+    isl_union_pw_aff_free(ptr);
+}
+
+__isl_give isl_union_pw_aff *union_pw_aff::copy() const & {
+  return isl_union_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_union_pw_aff *union_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_pw_aff *union_pw_aff::release() {
+  isl_union_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_pw_aff::get_ctx() const {
+  return ctx(isl_union_pw_aff_get_ctx(ptr));
+}
+
+union_pw_aff union_pw_aff::add(union_pw_aff upa2) const
+{
+  auto res = isl_union_pw_aff_add(copy(), upa2.release());
+  return manage(res);
+}
+
+union_pw_aff union_pw_aff::pullback(union_pw_multi_aff upma) const
+{
+  auto res = isl_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
+  return manage(res);
+}
+
+union_pw_aff union_pw_aff::union_add(union_pw_aff upa2) const
+{
+  auto res = isl_union_pw_aff_union_add(copy(), upa2.release());
+  return manage(res);
+}
+
+// implementations for isl::union_pw_multi_aff
+union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr) {
+  return union_pw_multi_aff(ptr);
+}
+union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr) {
+  ptr = isl_union_pw_multi_aff_copy(ptr);
+  return union_pw_multi_aff(ptr);
+}
+
+union_pw_multi_aff::union_pw_multi_aff()
+    : ptr(nullptr) {}
+
+union_pw_multi_aff::union_pw_multi_aff(const union_pw_multi_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+union_pw_multi_aff::union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr)
+    : ptr(ptr) {}
+
+union_pw_multi_aff::union_pw_multi_aff(pw_multi_aff pma)
+{
+  auto res = isl_union_pw_multi_aff_from_pw_multi_aff(pma.release());
+  ptr = res;
+}
+union_pw_multi_aff::union_pw_multi_aff(ctx ctx, const std::string &str)
+{
+  auto res = isl_union_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+union_pw_multi_aff::union_pw_multi_aff(union_pw_aff upa)
+{
+  auto res = isl_union_pw_multi_aff_from_union_pw_aff(upa.release());
+  ptr = res;
+}
+
+union_pw_multi_aff &union_pw_multi_aff::operator=(union_pw_multi_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_pw_multi_aff::~union_pw_multi_aff() {
+  if (ptr)
+    isl_union_pw_multi_aff_free(ptr);
+}
+
+__isl_give isl_union_pw_multi_aff *union_pw_multi_aff::copy() const & {
+  return isl_union_pw_multi_aff_copy(ptr);
+}
+
+__isl_keep isl_union_pw_multi_aff *union_pw_multi_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_pw_multi_aff *union_pw_multi_aff::release() {
+  isl_union_pw_multi_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_pw_multi_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_pw_multi_aff::get_ctx() const {
+  return ctx(isl_union_pw_multi_aff_get_ctx(ptr));
+}
+
+union_pw_multi_aff union_pw_multi_aff::add(union_pw_multi_aff upma2) const
+{
+  auto res = isl_union_pw_multi_aff_add(copy(), upma2.release());
+  return manage(res);
+}
+
+union_pw_multi_aff union_pw_multi_aff::flat_range_product(union_pw_multi_aff upma2) const
+{
+  auto res = isl_union_pw_multi_aff_flat_range_product(copy(), upma2.release());
+  return manage(res);
+}
+
+union_pw_multi_aff union_pw_multi_aff::pullback(union_pw_multi_aff upma2) const
+{
+  auto res = isl_union_pw_multi_aff_pullback_union_pw_multi_aff(copy(), upma2.release());
+  return manage(res);
+}
+
+union_pw_multi_aff union_pw_multi_aff::union_add(union_pw_multi_aff upma2) const
+{
+  auto res = isl_union_pw_multi_aff_union_add(copy(), upma2.release());
+  return manage(res);
+}
+
+// implementations for isl::union_set
+union_set manage(__isl_take isl_union_set *ptr) {
+  return union_set(ptr);
+}
+union_set manage_copy(__isl_keep isl_union_set *ptr) {
+  ptr = isl_union_set_copy(ptr);
+  return union_set(ptr);
+}
+
+union_set::union_set()
+    : ptr(nullptr) {}
+
+union_set::union_set(const union_set &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+union_set::union_set(__isl_take isl_union_set *ptr)
+    : ptr(ptr) {}
+
+union_set::union_set(basic_set bset)
+{
+  auto res = isl_union_set_from_basic_set(bset.release());
+  ptr = res;
+}
+union_set::union_set(set set)
+{
+  auto res = isl_union_set_from_set(set.release());
+  ptr = res;
+}
+union_set::union_set(point pnt)
+{
+  auto res = isl_union_set_from_point(pnt.release());
+  ptr = res;
+}
+union_set::union_set(ctx ctx, const std::string &str)
+{
+  auto res = isl_union_set_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+union_set &union_set::operator=(union_set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_set::~union_set() {
+  if (ptr)
+    isl_union_set_free(ptr);
+}
+
+__isl_give isl_union_set *union_set::copy() const & {
+  return isl_union_set_copy(ptr);
+}
+
+__isl_keep isl_union_set *union_set::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_set *union_set::release() {
+  isl_union_set *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_set::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_set::get_ctx() const {
+  return ctx(isl_union_set_get_ctx(ptr));
+}
+
+union_set union_set::affine_hull() const
+{
+  auto res = isl_union_set_affine_hull(copy());
+  return manage(res);
+}
+
+union_set union_set::apply(union_map umap) const
+{
+  auto res = isl_union_set_apply(copy(), umap.release());
+  return manage(res);
+}
+
+union_set union_set::coalesce() const
+{
+  auto res = isl_union_set_coalesce(copy());
+  return manage(res);
+}
+
+union_set union_set::compute_divs() const
+{
+  auto res = isl_union_set_compute_divs(copy());
+  return manage(res);
+}
+
+union_set union_set::detect_equalities() const
+{
+  auto res = isl_union_set_detect_equalities(copy());
+  return manage(res);
+}
+
+stat union_set::foreach_point(const std::function<stat(point)> &fn) const
+{
+  struct fn_data {
+    const std::function<stat(point)> *func;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_point *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    stat ret = (*data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_union_set_foreach_point(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+stat union_set::foreach_set(const std::function<stat(set)> &fn) const
+{
+  struct fn_data {
+    const std::function<stat(set)> *func;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_set *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    stat ret = (*data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_union_set_foreach_set(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+union_set union_set::gist(union_set context) const
+{
+  auto res = isl_union_set_gist(copy(), context.release());
+  return manage(res);
+}
+
+union_set union_set::gist_params(set set) const
+{
+  auto res = isl_union_set_gist_params(copy(), set.release());
+  return manage(res);
+}
+
+union_map union_set::identity() const
+{
+  auto res = isl_union_set_identity(copy());
+  return manage(res);
+}
+
+union_set union_set::intersect(union_set uset2) const
+{
+  auto res = isl_union_set_intersect(copy(), uset2.release());
+  return manage(res);
+}
+
+union_set union_set::intersect_params(set set) const
+{
+  auto res = isl_union_set_intersect_params(copy(), set.release());
+  return manage(res);
+}
+
+boolean union_set::is_empty() const
+{
+  auto res = isl_union_set_is_empty(get());
+  return manage(res);
+}
+
+boolean union_set::is_equal(const union_set &uset2) const
+{
+  auto res = isl_union_set_is_equal(get(), uset2.get());
+  return manage(res);
+}
+
+boolean union_set::is_strict_subset(const union_set &uset2) const
+{
+  auto res = isl_union_set_is_strict_subset(get(), uset2.get());
+  return manage(res);
+}
+
+boolean union_set::is_subset(const union_set &uset2) const
+{
+  auto res = isl_union_set_is_subset(get(), uset2.get());
+  return manage(res);
+}
+
+union_set union_set::lexmax() const
+{
+  auto res = isl_union_set_lexmax(copy());
+  return manage(res);
+}
+
+union_set union_set::lexmin() const
+{
+  auto res = isl_union_set_lexmin(copy());
+  return manage(res);
+}
+
+union_set union_set::polyhedral_hull() const
+{
+  auto res = isl_union_set_polyhedral_hull(copy());
+  return manage(res);
+}
+
+union_set union_set::preimage(multi_aff ma) const
+{
+  auto res = isl_union_set_preimage_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+union_set union_set::preimage(pw_multi_aff pma) const
+{
+  auto res = isl_union_set_preimage_pw_multi_aff(copy(), pma.release());
+  return manage(res);
+}
+
+union_set union_set::preimage(union_pw_multi_aff upma) const
+{
+  auto res = isl_union_set_preimage_union_pw_multi_aff(copy(), upma.release());
+  return manage(res);
+}
+
+point union_set::sample_point() const
+{
+  auto res = isl_union_set_sample_point(copy());
+  return manage(res);
+}
+
+union_set union_set::subtract(union_set uset2) const
+{
+  auto res = isl_union_set_subtract(copy(), uset2.release());
+  return manage(res);
+}
+
+union_set union_set::unite(union_set uset2) const
+{
+  auto res = isl_union_set_union(copy(), uset2.release());
+  return manage(res);
+}
+
+union_map union_set::unwrap() const
+{
+  auto res = isl_union_set_unwrap(copy());
+  return manage(res);
+}
+
+// implementations for isl::val
+val manage(__isl_take isl_val *ptr) {
+  return val(ptr);
+}
+val manage_copy(__isl_keep isl_val *ptr) {
+  ptr = isl_val_copy(ptr);
+  return val(ptr);
+}
+
+val::val()
+    : ptr(nullptr) {}
+
+val::val(const val &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+val::val(__isl_take isl_val *ptr)
+    : ptr(ptr) {}
+
+val::val(ctx ctx, const std::string &str)
+{
+  auto res = isl_val_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+val::val(ctx ctx, long i)
+{
+  auto res = isl_val_int_from_si(ctx.release(), i);
+  ptr = res;
+}
+
+val &val::operator=(val obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+val::~val() {
+  if (ptr)
+    isl_val_free(ptr);
+}
+
+__isl_give isl_val *val::copy() const & {
+  return isl_val_copy(ptr);
+}
+
+__isl_keep isl_val *val::get() const {
+  return ptr;
+}
+
+__isl_give isl_val *val::release() {
+  isl_val *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool val::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx val::get_ctx() const {
+  return ctx(isl_val_get_ctx(ptr));
+}
+
+val val::abs() const
+{
+  auto res = isl_val_abs(copy());
+  return manage(res);
+}
+
+boolean val::abs_eq(const val &v2) const
+{
+  auto res = isl_val_abs_eq(get(), v2.get());
+  return manage(res);
+}
+
+val val::add(val v2) const
+{
+  auto res = isl_val_add(copy(), v2.release());
+  return manage(res);
+}
+
+val val::ceil() const
+{
+  auto res = isl_val_ceil(copy());
+  return manage(res);
+}
+
+int val::cmp_si(long i) const
+{
+  auto res = isl_val_cmp_si(get(), i);
+  return res;
+}
+
+val val::div(val v2) const
+{
+  auto res = isl_val_div(copy(), v2.release());
+  return manage(res);
+}
+
+boolean val::eq(const val &v2) const
+{
+  auto res = isl_val_eq(get(), v2.get());
+  return manage(res);
+}
+
+val val::floor() const
+{
+  auto res = isl_val_floor(copy());
+  return manage(res);
+}
+
+val val::gcd(val v2) const
+{
+  auto res = isl_val_gcd(copy(), v2.release());
+  return manage(res);
+}
+
+boolean val::ge(const val &v2) const
+{
+  auto res = isl_val_ge(get(), v2.get());
+  return manage(res);
+}
+
+boolean val::gt(const val &v2) const
+{
+  auto res = isl_val_gt(get(), v2.get());
+  return manage(res);
+}
+
+val val::infty(ctx ctx)
+{
+  auto res = isl_val_infty(ctx.release());
+  return manage(res);
+}
+
+val val::inv() const
+{
+  auto res = isl_val_inv(copy());
+  return manage(res);
+}
+
+boolean val::is_divisible_by(const val &v2) const
+{
+  auto res = isl_val_is_divisible_by(get(), v2.get());
+  return manage(res);
+}
+
+boolean val::is_infty() const
+{
+  auto res = isl_val_is_infty(get());
+  return manage(res);
+}
+
+boolean val::is_int() const
+{
+  auto res = isl_val_is_int(get());
+  return manage(res);
+}
+
+boolean val::is_nan() const
+{
+  auto res = isl_val_is_nan(get());
+  return manage(res);
+}
+
+boolean val::is_neg() const
+{
+  auto res = isl_val_is_neg(get());
+  return manage(res);
+}
+
+boolean val::is_neginfty() const
+{
+  auto res = isl_val_is_neginfty(get());
+  return manage(res);
+}
+
+boolean val::is_negone() const
+{
+  auto res = isl_val_is_negone(get());
+  return manage(res);
+}
+
+boolean val::is_nonneg() const
+{
+  auto res = isl_val_is_nonneg(get());
+  return manage(res);
+}
+
+boolean val::is_nonpos() const
+{
+  auto res = isl_val_is_nonpos(get());
+  return manage(res);
+}
+
+boolean val::is_one() const
+{
+  auto res = isl_val_is_one(get());
+  return manage(res);
+}
+
+boolean val::is_pos() const
+{
+  auto res = isl_val_is_pos(get());
+  return manage(res);
+}
+
+boolean val::is_rat() const
+{
+  auto res = isl_val_is_rat(get());
+  return manage(res);
+}
+
+boolean val::is_zero() const
+{
+  auto res = isl_val_is_zero(get());
+  return manage(res);
+}
+
+boolean val::le(const val &v2) const
+{
+  auto res = isl_val_le(get(), v2.get());
+  return manage(res);
+}
+
+boolean val::lt(const val &v2) const
+{
+  auto res = isl_val_lt(get(), v2.get());
+  return manage(res);
+}
+
+val val::max(val v2) const
+{
+  auto res = isl_val_max(copy(), v2.release());
+  return manage(res);
+}
+
+val val::min(val v2) const
+{
+  auto res = isl_val_min(copy(), v2.release());
+  return manage(res);
+}
+
+val val::mod(val v2) const
+{
+  auto res = isl_val_mod(copy(), v2.release());
+  return manage(res);
+}
+
+val val::mul(val v2) const
+{
+  auto res = isl_val_mul(copy(), v2.release());
+  return manage(res);
+}
+
+val val::nan(ctx ctx)
+{
+  auto res = isl_val_nan(ctx.release());
+  return manage(res);
+}
+
+boolean val::ne(const val &v2) const
+{
+  auto res = isl_val_ne(get(), v2.get());
+  return manage(res);
+}
+
+val val::neg() const
+{
+  auto res = isl_val_neg(copy());
+  return manage(res);
+}
+
+val val::neginfty(ctx ctx)
+{
+  auto res = isl_val_neginfty(ctx.release());
+  return manage(res);
+}
+
+val val::negone(ctx ctx)
+{
+  auto res = isl_val_negone(ctx.release());
+  return manage(res);
+}
+
+val val::one(ctx ctx)
+{
+  auto res = isl_val_one(ctx.release());
+  return manage(res);
+}
+
+int val::sgn() const
+{
+  auto res = isl_val_sgn(get());
+  return res;
+}
+
+val val::sub(val v2) const
+{
+  auto res = isl_val_sub(copy(), v2.release());
+  return manage(res);
+}
+
+val val::trunc() const
+{
+  auto res = isl_val_trunc(copy());
+  return manage(res);
+}
+
+val val::zero(ctx ctx)
+{
+  auto res = isl_val_zero(ctx.release());
+  return manage(res);
+}
+} // namespace checked
+} // namespace isl
+
+#endif /* ISL_CPP_CHECKED */
diff --git a/lib/External/isl/include/isl/cpp.h b/lib/External/isl/include/isl/cpp.h
new file mode 100644
index 0000000..2545b35
--- /dev/null
+++ b/lib/External/isl/include/isl/cpp.h
@@ -0,0 +1,7631 @@
+/// These are automatically generated C++ bindings for isl.
+///
+/// isl is a library for computing with integer sets and maps described by
+/// Presburger formulas. On top of this, isl provides various tools for
+/// polyhedral compilation, ranging from dependence analysis over scheduling
+/// to AST generation.
+
+#ifndef ISL_CPP
+#define ISL_CPP
+
+#include <isl/val.h>
+#include <isl/aff.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/ilp.h>
+#include <isl/union_set.h>
+#include <isl/union_map.h>
+#include <isl/flow.h>
+#include <isl/schedule.h>
+#include <isl/schedule_node.h>
+#include <isl/ast_build.h>
+
+#include <isl/ctx.h>
+#include <isl/options.h>
+
+#include <functional>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+/* ISL_USE_EXCEPTIONS should be defined to 1 if exceptions are available.
+ * gcc and clang define __cpp_exceptions; MSVC and xlC define _CPPUNWIND.
+ * If exceptions are not available, any error condition will result
+ * in an abort.
+ */
+#ifndef ISL_USE_EXCEPTIONS
+#if defined(__cpp_exceptions) || defined(_CPPUNWIND)
+#define ISL_USE_EXCEPTIONS	1
+#else
+#define ISL_USE_EXCEPTIONS	0
+#endif
+#endif
+
+namespace isl {
+
+class ctx {
+	isl_ctx *ptr;
+public:
+	/* implicit */ ctx(isl_ctx *ctx) : ptr(ctx) {}
+	isl_ctx *release() {
+		auto tmp = ptr;
+		ptr = nullptr;
+		return tmp;
+	}
+	isl_ctx *get() {
+		return ptr;
+	}
+};
+
+/* Macros hiding try/catch.
+ * If exceptions are not available, then no exceptions will be thrown and
+ * there is nothing to catch.
+ */
+#if ISL_USE_EXCEPTIONS
+#define ISL_CPP_TRY		try
+#define ISL_CPP_CATCH_ALL	catch (...)
+#else
+#define ISL_CPP_TRY		if (1)
+#define ISL_CPP_CATCH_ALL	if (0)
+#endif
+
+#if ISL_USE_EXCEPTIONS
+
+/* Class capturing isl errors.
+ *
+ * The what() return value is stored in a reference counted string
+ * to ensure that the copy constructor and the assignment operator
+ * do not throw any exceptions.
+ */
+class exception : public std::exception {
+	std::shared_ptr<std::string> what_str;
+
+protected:
+	inline exception(const char *what_arg, const char *msg,
+		const char *file, int line);
+public:
+	exception() {}
+	exception(const char *what_arg) {
+		what_str = std::make_shared<std::string>(what_arg);
+	}
+	static inline exception create(enum isl_error error, const char *msg,
+		const char *file, int line);
+	static inline exception create_from_last_error(ctx ctx);
+	virtual const char *what() const noexcept {
+		return what_str->c_str();
+	}
+
+	/* Default behavior on error conditions that occur inside isl calls
+	 * performed from inside the bindings.
+	 * In the case exceptions are available, isl should continue
+	 * without printing a warning since the warning message
+	 * will be included in the exception thrown from inside the bindings.
+	 */
+	static constexpr auto on_error = ISL_ON_ERROR_CONTINUE;
+	/* Wrapper for throwing an exception on NULL input.
+	 */
+	static void throw_NULL_input(const char *file, int line) {
+		throw create(isl_error_invalid, "NULL input", file, line);
+	}
+	/* Wrapper for throwing an exception corresponding to the last
+	 * error on "ctx".
+	 */
+	static void throw_last_error(ctx ctx) {
+		throw create_from_last_error(ctx);
+	}
+};
+
+/* Create an exception of a type described by "what_arg", with
+ * error message "msg" in line "line" of file "file".
+ *
+ * Create a string holding the what() return value that
+ * corresponds to what isl would have printed.
+ * If no error message or no error file was set, then use "what_arg" instead.
+ */
+exception::exception(const char *what_arg, const char *msg, const char *file,
+	int line)
+{
+	if (!msg || !file)
+		what_str = std::make_shared<std::string>(what_arg);
+	else
+		what_str = std::make_shared<std::string>(std::string(file) +
+				    ":" + std::to_string(line) + ": " + msg);
+}
+
+class exception_abort : public exception {
+	friend exception;
+	exception_abort(const char *msg, const char *file, int line) :
+		exception("execution aborted", msg, file, line) {}
+};
+
+class exception_alloc : public exception {
+	friend exception;
+	exception_alloc(const char *msg, const char *file, int line) :
+		exception("memory allocation failure", msg, file, line) {}
+};
+
+class exception_unknown : public exception {
+	friend exception;
+	exception_unknown(const char *msg, const char *file, int line) :
+		exception("unknown failure", msg, file, line) {}
+};
+
+class exception_internal : public exception {
+	friend exception;
+	exception_internal(const char *msg, const char *file, int line) :
+		exception("internal error", msg, file, line) {}
+};
+
+class exception_invalid : public exception {
+	friend exception;
+	exception_invalid(const char *msg, const char *file, int line) :
+		exception("invalid argument", msg, file, line) {}
+};
+
+class exception_quota : public exception {
+	friend exception;
+	exception_quota(const char *msg, const char *file, int line) :
+		exception("quota exceeded", msg, file, line) {}
+};
+
+class exception_unsupported : public exception {
+	friend exception;
+	exception_unsupported(const char *msg, const char *file, int line) :
+		exception("unsupported operation", msg, file, line) {}
+};
+
+/* Create an exception of the class that corresponds to "error", with
+ * error message "msg" in line "line" of file "file".
+ *
+ * isl_error_none is treated as an invalid error type.
+ */
+exception exception::create(enum isl_error error, const char *msg,
+	const char *file, int line)
+{
+	switch (error) {
+	case isl_error_none:
+		break;
+	case isl_error_abort: return exception_abort(msg, file, line);
+	case isl_error_alloc: return exception_alloc(msg, file, line);
+	case isl_error_unknown: return exception_unknown(msg, file, line);
+	case isl_error_internal: return exception_internal(msg, file, line);
+	case isl_error_invalid: return exception_invalid(msg, file, line);
+	case isl_error_quota: return exception_quota(msg, file, line);
+	case isl_error_unsupported:
+				return exception_unsupported(msg, file, line);
+	}
+
+	throw exception_invalid("invalid error type", file, line);
+}
+
+/* Create an exception from the last error that occurred on "ctx" and
+ * reset the error.
+ *
+ * If "ctx" is NULL or if it is not in an error state at the start,
+ * then an invalid argument exception is thrown.
+ */
+exception exception::create_from_last_error(ctx ctx)
+{
+	enum isl_error error;
+	const char *msg, *file;
+	int line;
+
+	error = isl_ctx_last_error(ctx.get());
+	msg = isl_ctx_last_error_msg(ctx.get());
+	file = isl_ctx_last_error_file(ctx.get());
+	line = isl_ctx_last_error_line(ctx.get());
+	isl_ctx_reset_error(ctx.get());
+
+	return create(error, msg, file, line);
+}
+
+#else
+
+#include <stdio.h>
+#include <stdlib.h>
+
+class exception {
+public:
+	/* Default behavior on error conditions that occur inside isl calls
+	 * performed from inside the bindings.
+	 * In the case exceptions are not available, isl should abort.
+	 */
+	static constexpr auto on_error = ISL_ON_ERROR_ABORT;
+	/* Wrapper for throwing an exception on NULL input.
+	 * In the case exceptions are not available, print an error and abort.
+	 */
+	static void throw_NULL_input(const char *file, int line) {
+		fprintf(stderr, "%s:%d: NULL input\n", file, line);
+		abort();
+	}
+	/* Wrapper for throwing an exception corresponding to the last
+	 * error on "ctx".
+	 * isl should already abort when an error condition occurs,
+	 * so this function should never be called.
+	 */
+	static void throw_last_error(ctx ctx) {
+		abort();
+	}
+};
+
+#endif
+
+/* Helper class for setting the on_error and resetting the option
+ * to the original value when leaving the scope.
+ */
+class options_scoped_set_on_error {
+	isl_ctx *ctx;
+	int saved_on_error;
+public:
+	options_scoped_set_on_error(class ctx ctx, int on_error) {
+		this->ctx = ctx.get();
+		saved_on_error = isl_options_get_on_error(this->ctx);
+		isl_options_set_on_error(this->ctx, on_error);
+	}
+	~options_scoped_set_on_error() {
+		isl_options_set_on_error(ctx, saved_on_error);
+	}
+};
+
+} // namespace isl
+
+namespace isl {
+
+// forward declarations
+class aff;
+class ast_build;
+class ast_expr;
+class ast_node;
+class basic_map;
+class basic_set;
+class map;
+class multi_aff;
+class multi_pw_aff;
+class multi_union_pw_aff;
+class multi_val;
+class point;
+class pw_aff;
+class pw_multi_aff;
+class schedule;
+class schedule_constraints;
+class schedule_node;
+class set;
+class union_access_info;
+class union_flow;
+class union_map;
+class union_pw_aff;
+class union_pw_multi_aff;
+class union_set;
+class val;
+
+// declarations for isl::aff
+inline aff manage(__isl_take isl_aff *ptr);
+inline aff manage_copy(__isl_keep isl_aff *ptr);
+
+class aff {
+  friend inline aff manage(__isl_take isl_aff *ptr);
+  friend inline aff manage_copy(__isl_keep isl_aff *ptr);
+
+  isl_aff *ptr = nullptr;
+
+  inline explicit aff(__isl_take isl_aff *ptr);
+
+public:
+  inline /* implicit */ aff();
+  inline /* implicit */ aff(const aff &obj);
+  inline explicit aff(ctx ctx, const std::string &str);
+  inline aff &operator=(aff obj);
+  inline ~aff();
+  inline __isl_give isl_aff *copy() const &;
+  inline __isl_give isl_aff *copy() && = delete;
+  inline __isl_keep isl_aff *get() const;
+  inline __isl_give isl_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline aff add(aff aff2) const;
+  inline aff ceil() const;
+  inline aff div(aff aff2) const;
+  inline set eq_set(aff aff2) const;
+  inline aff floor() const;
+  inline set ge_set(aff aff2) const;
+  inline set gt_set(aff aff2) const;
+  inline set le_set(aff aff2) const;
+  inline set lt_set(aff aff2) const;
+  inline aff mod(val mod) const;
+  inline aff mul(aff aff2) const;
+  inline set ne_set(aff aff2) const;
+  inline aff neg() const;
+  inline aff pullback(multi_aff ma) const;
+  inline aff scale(val v) const;
+  inline aff scale_down(val v) const;
+  inline aff sub(aff aff2) const;
+};
+
+// declarations for isl::ast_build
+inline ast_build manage(__isl_take isl_ast_build *ptr);
+inline ast_build manage_copy(__isl_keep isl_ast_build *ptr);
+
+class ast_build {
+  friend inline ast_build manage(__isl_take isl_ast_build *ptr);
+  friend inline ast_build manage_copy(__isl_keep isl_ast_build *ptr);
+
+  isl_ast_build *ptr = nullptr;
+
+  inline explicit ast_build(__isl_take isl_ast_build *ptr);
+
+public:
+  inline /* implicit */ ast_build();
+  inline /* implicit */ ast_build(const ast_build &obj);
+  inline explicit ast_build(ctx ctx);
+  inline ast_build &operator=(ast_build obj);
+  inline ~ast_build();
+  inline __isl_give isl_ast_build *copy() const &;
+  inline __isl_give isl_ast_build *copy() && = delete;
+  inline __isl_keep isl_ast_build *get() const;
+  inline __isl_give isl_ast_build *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline ast_expr access_from(pw_multi_aff pma) const;
+  inline ast_expr access_from(multi_pw_aff mpa) const;
+  inline ast_expr call_from(pw_multi_aff pma) const;
+  inline ast_expr call_from(multi_pw_aff mpa) const;
+  inline ast_expr expr_from(set set) const;
+  inline ast_expr expr_from(pw_aff pa) const;
+  static inline ast_build from_context(set set);
+  inline ast_node node_from_schedule_map(union_map schedule) const;
+};
+
+// declarations for isl::ast_expr
+inline ast_expr manage(__isl_take isl_ast_expr *ptr);
+inline ast_expr manage_copy(__isl_keep isl_ast_expr *ptr);
+
+class ast_expr {
+  friend inline ast_expr manage(__isl_take isl_ast_expr *ptr);
+  friend inline ast_expr manage_copy(__isl_keep isl_ast_expr *ptr);
+
+  isl_ast_expr *ptr = nullptr;
+
+  inline explicit ast_expr(__isl_take isl_ast_expr *ptr);
+
+public:
+  inline /* implicit */ ast_expr();
+  inline /* implicit */ ast_expr(const ast_expr &obj);
+  inline ast_expr &operator=(ast_expr obj);
+  inline ~ast_expr();
+  inline __isl_give isl_ast_expr *copy() const &;
+  inline __isl_give isl_ast_expr *copy() && = delete;
+  inline __isl_keep isl_ast_expr *get() const;
+  inline __isl_give isl_ast_expr *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline std::string to_C_str() const;
+};
+
+// declarations for isl::ast_node
+inline ast_node manage(__isl_take isl_ast_node *ptr);
+inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
+
+class ast_node {
+  friend inline ast_node manage(__isl_take isl_ast_node *ptr);
+  friend inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
+
+  isl_ast_node *ptr = nullptr;
+
+  inline explicit ast_node(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node();
+  inline /* implicit */ ast_node(const ast_node &obj);
+  inline ast_node &operator=(ast_node obj);
+  inline ~ast_node();
+  inline __isl_give isl_ast_node *copy() const &;
+  inline __isl_give isl_ast_node *copy() && = delete;
+  inline __isl_keep isl_ast_node *get() const;
+  inline __isl_give isl_ast_node *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline std::string to_C_str() const;
+};
+
+// declarations for isl::basic_map
+inline basic_map manage(__isl_take isl_basic_map *ptr);
+inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+
+class basic_map {
+  friend inline basic_map manage(__isl_take isl_basic_map *ptr);
+  friend inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+
+  isl_basic_map *ptr = nullptr;
+
+  inline explicit basic_map(__isl_take isl_basic_map *ptr);
+
+public:
+  inline /* implicit */ basic_map();
+  inline /* implicit */ basic_map(const basic_map &obj);
+  inline explicit basic_map(ctx ctx, const std::string &str);
+  inline basic_map &operator=(basic_map obj);
+  inline ~basic_map();
+  inline __isl_give isl_basic_map *copy() const &;
+  inline __isl_give isl_basic_map *copy() && = delete;
+  inline __isl_keep isl_basic_map *get() const;
+  inline __isl_give isl_basic_map *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline basic_map affine_hull() const;
+  inline basic_map apply_domain(basic_map bmap2) const;
+  inline basic_map apply_range(basic_map bmap2) const;
+  inline basic_set deltas() const;
+  inline basic_map detect_equalities() const;
+  inline basic_map flatten() const;
+  inline basic_map flatten_domain() const;
+  inline basic_map flatten_range() const;
+  inline basic_map gist(basic_map context) const;
+  inline basic_map intersect(basic_map bmap2) const;
+  inline basic_map intersect_domain(basic_set bset) const;
+  inline basic_map intersect_range(basic_set bset) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const basic_map &bmap2) const;
+  inline bool is_subset(const basic_map &bmap2) const;
+  inline map lexmax() const;
+  inline map lexmin() const;
+  inline basic_map reverse() const;
+  inline basic_map sample() const;
+  inline map unite(basic_map bmap2) const;
+};
+
+// declarations for isl::basic_set
+inline basic_set manage(__isl_take isl_basic_set *ptr);
+inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+
+class basic_set {
+  friend inline basic_set manage(__isl_take isl_basic_set *ptr);
+  friend inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+
+  isl_basic_set *ptr = nullptr;
+
+  inline explicit basic_set(__isl_take isl_basic_set *ptr);
+
+public:
+  inline /* implicit */ basic_set();
+  inline /* implicit */ basic_set(const basic_set &obj);
+  inline explicit basic_set(ctx ctx, const std::string &str);
+  inline /* implicit */ basic_set(point pnt);
+  inline basic_set &operator=(basic_set obj);
+  inline ~basic_set();
+  inline __isl_give isl_basic_set *copy() const &;
+  inline __isl_give isl_basic_set *copy() && = delete;
+  inline __isl_keep isl_basic_set *get() const;
+  inline __isl_give isl_basic_set *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline basic_set affine_hull() const;
+  inline basic_set apply(basic_map bmap) const;
+  inline basic_set detect_equalities() const;
+  inline val dim_max_val(int pos) const;
+  inline basic_set flatten() const;
+  inline basic_set gist(basic_set context) const;
+  inline basic_set intersect(basic_set bset2) const;
+  inline basic_set intersect_params(basic_set bset2) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const basic_set &bset2) const;
+  inline bool is_subset(const basic_set &bset2) const;
+  inline bool is_wrapping() const;
+  inline set lexmax() const;
+  inline set lexmin() const;
+  inline basic_set sample() const;
+  inline point sample_point() const;
+  inline set unite(basic_set bset2) const;
+};
+
+// declarations for isl::map
+inline map manage(__isl_take isl_map *ptr);
+inline map manage_copy(__isl_keep isl_map *ptr);
+
+class map {
+  friend inline map manage(__isl_take isl_map *ptr);
+  friend inline map manage_copy(__isl_keep isl_map *ptr);
+
+  isl_map *ptr = nullptr;
+
+  inline explicit map(__isl_take isl_map *ptr);
+
+public:
+  inline /* implicit */ map();
+  inline /* implicit */ map(const map &obj);
+  inline explicit map(ctx ctx, const std::string &str);
+  inline /* implicit */ map(basic_map bmap);
+  inline map &operator=(map obj);
+  inline ~map();
+  inline __isl_give isl_map *copy() const &;
+  inline __isl_give isl_map *copy() && = delete;
+  inline __isl_keep isl_map *get() const;
+  inline __isl_give isl_map *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline basic_map affine_hull() const;
+  inline map apply_domain(map map2) const;
+  inline map apply_range(map map2) const;
+  inline map coalesce() const;
+  inline map complement() const;
+  inline set deltas() const;
+  inline map detect_equalities() const;
+  inline map flatten() const;
+  inline map flatten_domain() const;
+  inline map flatten_range() const;
+  inline void foreach_basic_map(const std::function<void(basic_map)> &fn) const;
+  inline map gist(map context) const;
+  inline map gist_domain(set context) const;
+  inline map intersect(map map2) const;
+  inline map intersect_domain(set set) const;
+  inline map intersect_params(set params) const;
+  inline map intersect_range(set set) const;
+  inline bool is_bijective() const;
+  inline bool is_disjoint(const map &map2) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const map &map2) const;
+  inline bool is_injective() const;
+  inline bool is_single_valued() const;
+  inline bool is_strict_subset(const map &map2) const;
+  inline bool is_subset(const map &map2) const;
+  inline map lexmax() const;
+  inline map lexmin() const;
+  inline basic_map polyhedral_hull() const;
+  inline map reverse() const;
+  inline basic_map sample() const;
+  inline map subtract(map map2) const;
+  inline map unite(map map2) const;
+  inline basic_map unshifted_simple_hull() const;
+};
+
+// declarations for isl::multi_aff
+inline multi_aff manage(__isl_take isl_multi_aff *ptr);
+inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+
+class multi_aff {
+  friend inline multi_aff manage(__isl_take isl_multi_aff *ptr);
+  friend inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+
+  isl_multi_aff *ptr = nullptr;
+
+  inline explicit multi_aff(__isl_take isl_multi_aff *ptr);
+
+public:
+  inline /* implicit */ multi_aff();
+  inline /* implicit */ multi_aff(const multi_aff &obj);
+  inline /* implicit */ multi_aff(aff aff);
+  inline explicit multi_aff(ctx ctx, const std::string &str);
+  inline multi_aff &operator=(multi_aff obj);
+  inline ~multi_aff();
+  inline __isl_give isl_multi_aff *copy() const &;
+  inline __isl_give isl_multi_aff *copy() && = delete;
+  inline __isl_keep isl_multi_aff *get() const;
+  inline __isl_give isl_multi_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline multi_aff add(multi_aff multi2) const;
+  inline multi_aff flat_range_product(multi_aff multi2) const;
+  inline multi_aff product(multi_aff multi2) const;
+  inline multi_aff pullback(multi_aff ma2) const;
+  inline multi_aff range_product(multi_aff multi2) const;
+};
+
+// declarations for isl::multi_pw_aff
+inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
+inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+
+class multi_pw_aff {
+  friend inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
+  friend inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+
+  isl_multi_pw_aff *ptr = nullptr;
+
+  inline explicit multi_pw_aff(__isl_take isl_multi_pw_aff *ptr);
+
+public:
+  inline /* implicit */ multi_pw_aff();
+  inline /* implicit */ multi_pw_aff(const multi_pw_aff &obj);
+  inline /* implicit */ multi_pw_aff(multi_aff ma);
+  inline /* implicit */ multi_pw_aff(pw_aff pa);
+  inline /* implicit */ multi_pw_aff(pw_multi_aff pma);
+  inline explicit multi_pw_aff(ctx ctx, const std::string &str);
+  inline multi_pw_aff &operator=(multi_pw_aff obj);
+  inline ~multi_pw_aff();
+  inline __isl_give isl_multi_pw_aff *copy() const &;
+  inline __isl_give isl_multi_pw_aff *copy() && = delete;
+  inline __isl_keep isl_multi_pw_aff *get() const;
+  inline __isl_give isl_multi_pw_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline multi_pw_aff add(multi_pw_aff multi2) const;
+  inline multi_pw_aff flat_range_product(multi_pw_aff multi2) const;
+  inline multi_pw_aff product(multi_pw_aff multi2) const;
+  inline multi_pw_aff pullback(multi_aff ma) const;
+  inline multi_pw_aff pullback(pw_multi_aff pma) const;
+  inline multi_pw_aff pullback(multi_pw_aff mpa2) const;
+  inline multi_pw_aff range_product(multi_pw_aff multi2) const;
+};
+
+// declarations for isl::multi_union_pw_aff
+inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
+inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+
+class multi_union_pw_aff {
+  friend inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
+  friend inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+
+  isl_multi_union_pw_aff *ptr = nullptr;
+
+  inline explicit multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr);
+
+public:
+  inline /* implicit */ multi_union_pw_aff();
+  inline /* implicit */ multi_union_pw_aff(const multi_union_pw_aff &obj);
+  inline /* implicit */ multi_union_pw_aff(union_pw_aff upa);
+  inline /* implicit */ multi_union_pw_aff(multi_pw_aff mpa);
+  inline explicit multi_union_pw_aff(ctx ctx, const std::string &str);
+  inline multi_union_pw_aff &operator=(multi_union_pw_aff obj);
+  inline ~multi_union_pw_aff();
+  inline __isl_give isl_multi_union_pw_aff *copy() const &;
+  inline __isl_give isl_multi_union_pw_aff *copy() && = delete;
+  inline __isl_keep isl_multi_union_pw_aff *get() const;
+  inline __isl_give isl_multi_union_pw_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline multi_union_pw_aff add(multi_union_pw_aff multi2) const;
+  inline multi_union_pw_aff flat_range_product(multi_union_pw_aff multi2) const;
+  inline multi_union_pw_aff pullback(union_pw_multi_aff upma) const;
+  inline multi_union_pw_aff range_product(multi_union_pw_aff multi2) const;
+  inline multi_union_pw_aff union_add(multi_union_pw_aff mupa2) const;
+};
+
+// declarations for isl::multi_val
+inline multi_val manage(__isl_take isl_multi_val *ptr);
+inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+
+class multi_val {
+  friend inline multi_val manage(__isl_take isl_multi_val *ptr);
+  friend inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+
+  isl_multi_val *ptr = nullptr;
+
+  inline explicit multi_val(__isl_take isl_multi_val *ptr);
+
+public:
+  inline /* implicit */ multi_val();
+  inline /* implicit */ multi_val(const multi_val &obj);
+  inline multi_val &operator=(multi_val obj);
+  inline ~multi_val();
+  inline __isl_give isl_multi_val *copy() const &;
+  inline __isl_give isl_multi_val *copy() && = delete;
+  inline __isl_keep isl_multi_val *get() const;
+  inline __isl_give isl_multi_val *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline multi_val add(multi_val multi2) const;
+  inline multi_val flat_range_product(multi_val multi2) const;
+  inline multi_val product(multi_val multi2) const;
+  inline multi_val range_product(multi_val multi2) const;
+};
+
+// declarations for isl::point
+inline point manage(__isl_take isl_point *ptr);
+inline point manage_copy(__isl_keep isl_point *ptr);
+
+class point {
+  friend inline point manage(__isl_take isl_point *ptr);
+  friend inline point manage_copy(__isl_keep isl_point *ptr);
+
+  isl_point *ptr = nullptr;
+
+  inline explicit point(__isl_take isl_point *ptr);
+
+public:
+  inline /* implicit */ point();
+  inline /* implicit */ point(const point &obj);
+  inline point &operator=(point obj);
+  inline ~point();
+  inline __isl_give isl_point *copy() const &;
+  inline __isl_give isl_point *copy() && = delete;
+  inline __isl_keep isl_point *get() const;
+  inline __isl_give isl_point *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+};
+
+// declarations for isl::pw_aff
+inline pw_aff manage(__isl_take isl_pw_aff *ptr);
+inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+
+class pw_aff {
+  friend inline pw_aff manage(__isl_take isl_pw_aff *ptr);
+  friend inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+
+  isl_pw_aff *ptr = nullptr;
+
+  inline explicit pw_aff(__isl_take isl_pw_aff *ptr);
+
+public:
+  inline /* implicit */ pw_aff();
+  inline /* implicit */ pw_aff(const pw_aff &obj);
+  inline /* implicit */ pw_aff(aff aff);
+  inline explicit pw_aff(ctx ctx, const std::string &str);
+  inline pw_aff &operator=(pw_aff obj);
+  inline ~pw_aff();
+  inline __isl_give isl_pw_aff *copy() const &;
+  inline __isl_give isl_pw_aff *copy() && = delete;
+  inline __isl_keep isl_pw_aff *get() const;
+  inline __isl_give isl_pw_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline pw_aff add(pw_aff pwaff2) const;
+  inline pw_aff ceil() const;
+  inline pw_aff cond(pw_aff pwaff_true, pw_aff pwaff_false) const;
+  inline pw_aff div(pw_aff pa2) const;
+  inline set eq_set(pw_aff pwaff2) const;
+  inline pw_aff floor() const;
+  inline set ge_set(pw_aff pwaff2) const;
+  inline set gt_set(pw_aff pwaff2) const;
+  inline set le_set(pw_aff pwaff2) const;
+  inline set lt_set(pw_aff pwaff2) const;
+  inline pw_aff max(pw_aff pwaff2) const;
+  inline pw_aff min(pw_aff pwaff2) const;
+  inline pw_aff mod(val mod) const;
+  inline pw_aff mul(pw_aff pwaff2) const;
+  inline set ne_set(pw_aff pwaff2) const;
+  inline pw_aff neg() const;
+  inline pw_aff pullback(multi_aff ma) const;
+  inline pw_aff pullback(pw_multi_aff pma) const;
+  inline pw_aff pullback(multi_pw_aff mpa) const;
+  inline pw_aff scale(val v) const;
+  inline pw_aff scale_down(val f) const;
+  inline pw_aff sub(pw_aff pwaff2) const;
+  inline pw_aff tdiv_q(pw_aff pa2) const;
+  inline pw_aff tdiv_r(pw_aff pa2) const;
+  inline pw_aff union_add(pw_aff pwaff2) const;
+};
+
+// declarations for isl::pw_multi_aff
+inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
+inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+
+class pw_multi_aff {
+  friend inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
+  friend inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+
+  isl_pw_multi_aff *ptr = nullptr;
+
+  inline explicit pw_multi_aff(__isl_take isl_pw_multi_aff *ptr);
+
+public:
+  inline /* implicit */ pw_multi_aff();
+  inline /* implicit */ pw_multi_aff(const pw_multi_aff &obj);
+  inline /* implicit */ pw_multi_aff(multi_aff ma);
+  inline /* implicit */ pw_multi_aff(pw_aff pa);
+  inline explicit pw_multi_aff(ctx ctx, const std::string &str);
+  inline pw_multi_aff &operator=(pw_multi_aff obj);
+  inline ~pw_multi_aff();
+  inline __isl_give isl_pw_multi_aff *copy() const &;
+  inline __isl_give isl_pw_multi_aff *copy() && = delete;
+  inline __isl_keep isl_pw_multi_aff *get() const;
+  inline __isl_give isl_pw_multi_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline pw_multi_aff add(pw_multi_aff pma2) const;
+  inline pw_multi_aff flat_range_product(pw_multi_aff pma2) const;
+  inline pw_multi_aff product(pw_multi_aff pma2) const;
+  inline pw_multi_aff pullback(multi_aff ma) const;
+  inline pw_multi_aff pullback(pw_multi_aff pma2) const;
+  inline pw_multi_aff range_product(pw_multi_aff pma2) const;
+  inline pw_multi_aff union_add(pw_multi_aff pma2) const;
+};
+
+// declarations for isl::schedule
+inline schedule manage(__isl_take isl_schedule *ptr);
+inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+
+class schedule {
+  friend inline schedule manage(__isl_take isl_schedule *ptr);
+  friend inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+
+  isl_schedule *ptr = nullptr;
+
+  inline explicit schedule(__isl_take isl_schedule *ptr);
+
+public:
+  inline /* implicit */ schedule();
+  inline /* implicit */ schedule(const schedule &obj);
+  inline explicit schedule(ctx ctx, const std::string &str);
+  inline schedule &operator=(schedule obj);
+  inline ~schedule();
+  inline __isl_give isl_schedule *copy() const &;
+  inline __isl_give isl_schedule *copy() && = delete;
+  inline __isl_keep isl_schedule *get() const;
+  inline __isl_give isl_schedule *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_map get_map() const;
+  inline schedule_node get_root() const;
+  inline schedule pullback(union_pw_multi_aff upma) const;
+};
+
+// declarations for isl::schedule_constraints
+inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
+inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+
+class schedule_constraints {
+  friend inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
+  friend inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+
+  isl_schedule_constraints *ptr = nullptr;
+
+  inline explicit schedule_constraints(__isl_take isl_schedule_constraints *ptr);
+
+public:
+  inline /* implicit */ schedule_constraints();
+  inline /* implicit */ schedule_constraints(const schedule_constraints &obj);
+  inline explicit schedule_constraints(ctx ctx, const std::string &str);
+  inline schedule_constraints &operator=(schedule_constraints obj);
+  inline ~schedule_constraints();
+  inline __isl_give isl_schedule_constraints *copy() const &;
+  inline __isl_give isl_schedule_constraints *copy() && = delete;
+  inline __isl_keep isl_schedule_constraints *get() const;
+  inline __isl_give isl_schedule_constraints *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline schedule compute_schedule() const;
+  inline union_map get_coincidence() const;
+  inline union_map get_conditional_validity() const;
+  inline union_map get_conditional_validity_condition() const;
+  inline set get_context() const;
+  inline union_set get_domain() const;
+  inline union_map get_proximity() const;
+  inline union_map get_validity() const;
+  static inline schedule_constraints on_domain(union_set domain);
+  inline schedule_constraints set_coincidence(union_map coincidence) const;
+  inline schedule_constraints set_conditional_validity(union_map condition, union_map validity) const;
+  inline schedule_constraints set_context(set context) const;
+  inline schedule_constraints set_proximity(union_map proximity) const;
+  inline schedule_constraints set_validity(union_map validity) const;
+};
+
+// declarations for isl::schedule_node
+inline schedule_node manage(__isl_take isl_schedule_node *ptr);
+inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+
+class schedule_node {
+  friend inline schedule_node manage(__isl_take isl_schedule_node *ptr);
+  friend inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+
+  isl_schedule_node *ptr = nullptr;
+
+  inline explicit schedule_node(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node();
+  inline /* implicit */ schedule_node(const schedule_node &obj);
+  inline schedule_node &operator=(schedule_node obj);
+  inline ~schedule_node();
+  inline __isl_give isl_schedule_node *copy() const &;
+  inline __isl_give isl_schedule_node *copy() && = delete;
+  inline __isl_keep isl_schedule_node *get() const;
+  inline __isl_give isl_schedule_node *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline bool band_member_get_coincident(int pos) const;
+  inline schedule_node band_member_set_coincident(int pos, int coincident) const;
+  inline schedule_node child(int pos) const;
+  inline multi_union_pw_aff get_prefix_schedule_multi_union_pw_aff() const;
+  inline union_map get_prefix_schedule_union_map() const;
+  inline union_pw_multi_aff get_prefix_schedule_union_pw_multi_aff() const;
+  inline schedule get_schedule() const;
+  inline schedule_node parent() const;
+};
+
+// declarations for isl::set
+inline set manage(__isl_take isl_set *ptr);
+inline set manage_copy(__isl_keep isl_set *ptr);
+
+class set {
+  friend inline set manage(__isl_take isl_set *ptr);
+  friend inline set manage_copy(__isl_keep isl_set *ptr);
+
+  isl_set *ptr = nullptr;
+
+  inline explicit set(__isl_take isl_set *ptr);
+
+public:
+  inline /* implicit */ set();
+  inline /* implicit */ set(const set &obj);
+  inline explicit set(ctx ctx, const std::string &str);
+  inline /* implicit */ set(basic_set bset);
+  inline /* implicit */ set(point pnt);
+  inline set &operator=(set obj);
+  inline ~set();
+  inline __isl_give isl_set *copy() const &;
+  inline __isl_give isl_set *copy() && = delete;
+  inline __isl_keep isl_set *get() const;
+  inline __isl_give isl_set *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline basic_set affine_hull() const;
+  inline set apply(map map) const;
+  inline set coalesce() const;
+  inline set complement() const;
+  inline set detect_equalities() const;
+  inline set flatten() const;
+  inline void foreach_basic_set(const std::function<void(basic_set)> &fn) const;
+  inline val get_stride(int pos) const;
+  inline set gist(set context) const;
+  inline map identity() const;
+  inline set intersect(set set2) const;
+  inline set intersect_params(set params) const;
+  inline bool is_disjoint(const set &set2) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const set &set2) const;
+  inline bool is_strict_subset(const set &set2) const;
+  inline bool is_subset(const set &set2) const;
+  inline bool is_wrapping() const;
+  inline set lexmax() const;
+  inline set lexmin() const;
+  inline val max_val(const aff &obj) const;
+  inline val min_val(const aff &obj) const;
+  inline basic_set polyhedral_hull() const;
+  inline basic_set sample() const;
+  inline point sample_point() const;
+  inline set subtract(set set2) const;
+  inline set unite(set set2) const;
+  inline basic_set unshifted_simple_hull() const;
+};
+
+// declarations for isl::union_access_info
+inline union_access_info manage(__isl_take isl_union_access_info *ptr);
+inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+
+class union_access_info {
+  friend inline union_access_info manage(__isl_take isl_union_access_info *ptr);
+  friend inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+
+  isl_union_access_info *ptr = nullptr;
+
+  inline explicit union_access_info(__isl_take isl_union_access_info *ptr);
+
+public:
+  inline /* implicit */ union_access_info();
+  inline /* implicit */ union_access_info(const union_access_info &obj);
+  inline explicit union_access_info(union_map sink);
+  inline union_access_info &operator=(union_access_info obj);
+  inline ~union_access_info();
+  inline __isl_give isl_union_access_info *copy() const &;
+  inline __isl_give isl_union_access_info *copy() && = delete;
+  inline __isl_keep isl_union_access_info *get() const;
+  inline __isl_give isl_union_access_info *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_flow compute_flow() const;
+  inline union_access_info set_kill(union_map kill) const;
+  inline union_access_info set_may_source(union_map may_source) const;
+  inline union_access_info set_must_source(union_map must_source) const;
+  inline union_access_info set_schedule(schedule schedule) const;
+  inline union_access_info set_schedule_map(union_map schedule_map) const;
+};
+
+// declarations for isl::union_flow
+inline union_flow manage(__isl_take isl_union_flow *ptr);
+inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+
+class union_flow {
+  friend inline union_flow manage(__isl_take isl_union_flow *ptr);
+  friend inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+
+  isl_union_flow *ptr = nullptr;
+
+  inline explicit union_flow(__isl_take isl_union_flow *ptr);
+
+public:
+  inline /* implicit */ union_flow();
+  inline /* implicit */ union_flow(const union_flow &obj);
+  inline union_flow &operator=(union_flow obj);
+  inline ~union_flow();
+  inline __isl_give isl_union_flow *copy() const &;
+  inline __isl_give isl_union_flow *copy() && = delete;
+  inline __isl_keep isl_union_flow *get() const;
+  inline __isl_give isl_union_flow *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_map get_full_may_dependence() const;
+  inline union_map get_full_must_dependence() const;
+  inline union_map get_may_dependence() const;
+  inline union_map get_may_no_source() const;
+  inline union_map get_must_dependence() const;
+  inline union_map get_must_no_source() const;
+};
+
+// declarations for isl::union_map
+inline union_map manage(__isl_take isl_union_map *ptr);
+inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+
+class union_map {
+  friend inline union_map manage(__isl_take isl_union_map *ptr);
+  friend inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+
+  isl_union_map *ptr = nullptr;
+
+  inline explicit union_map(__isl_take isl_union_map *ptr);
+
+public:
+  inline /* implicit */ union_map();
+  inline /* implicit */ union_map(const union_map &obj);
+  inline /* implicit */ union_map(basic_map bmap);
+  inline /* implicit */ union_map(map map);
+  inline explicit union_map(ctx ctx, const std::string &str);
+  inline union_map &operator=(union_map obj);
+  inline ~union_map();
+  inline __isl_give isl_union_map *copy() const &;
+  inline __isl_give isl_union_map *copy() && = delete;
+  inline __isl_keep isl_union_map *get() const;
+  inline __isl_give isl_union_map *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_map affine_hull() const;
+  inline union_map apply_domain(union_map umap2) const;
+  inline union_map apply_range(union_map umap2) const;
+  inline union_map coalesce() const;
+  inline union_map compute_divs() const;
+  inline union_set deltas() const;
+  inline union_map detect_equalities() const;
+  inline union_set domain() const;
+  inline union_map domain_factor_domain() const;
+  inline union_map domain_factor_range() const;
+  inline union_map domain_map() const;
+  inline union_pw_multi_aff domain_map_union_pw_multi_aff() const;
+  inline union_map domain_product(union_map umap2) const;
+  inline union_map eq_at(multi_union_pw_aff mupa) const;
+  inline union_map factor_domain() const;
+  inline union_map factor_range() const;
+  inline union_map fixed_power(val exp) const;
+  inline void foreach_map(const std::function<void(map)> &fn) const;
+  static inline union_map from(union_pw_multi_aff upma);
+  static inline union_map from(multi_union_pw_aff mupa);
+  static inline union_map from_domain(union_set uset);
+  static inline union_map from_domain_and_range(union_set domain, union_set range);
+  static inline union_map from_range(union_set uset);
+  inline union_map gist(union_map context) const;
+  inline union_map gist_domain(union_set uset) const;
+  inline union_map gist_params(set set) const;
+  inline union_map gist_range(union_set uset) const;
+  inline union_map intersect(union_map umap2) const;
+  inline union_map intersect_domain(union_set uset) const;
+  inline union_map intersect_params(set set) const;
+  inline union_map intersect_range(union_set uset) const;
+  inline bool is_bijective() const;
+  inline bool is_empty() const;
+  inline bool is_equal(const union_map &umap2) const;
+  inline bool is_injective() const;
+  inline bool is_single_valued() const;
+  inline bool is_strict_subset(const union_map &umap2) const;
+  inline bool is_subset(const union_map &umap2) const;
+  inline union_map lexmax() const;
+  inline union_map lexmin() const;
+  inline union_map polyhedral_hull() const;
+  inline union_map product(union_map umap2) const;
+  inline union_map project_out_all_params() const;
+  inline union_set range() const;
+  inline union_map range_factor_domain() const;
+  inline union_map range_factor_range() const;
+  inline union_map range_map() const;
+  inline union_map range_product(union_map umap2) const;
+  inline union_map reverse() const;
+  inline union_map subtract(union_map umap2) const;
+  inline union_map subtract_domain(union_set dom) const;
+  inline union_map subtract_range(union_set dom) const;
+  inline union_map unite(union_map umap2) const;
+  inline union_set wrap() const;
+  inline union_map zip() const;
+};
+
+// declarations for isl::union_pw_aff
+inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
+inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+
+class union_pw_aff {
+  friend inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
+  friend inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+
+  isl_union_pw_aff *ptr = nullptr;
+
+  inline explicit union_pw_aff(__isl_take isl_union_pw_aff *ptr);
+
+public:
+  inline /* implicit */ union_pw_aff();
+  inline /* implicit */ union_pw_aff(const union_pw_aff &obj);
+  inline /* implicit */ union_pw_aff(pw_aff pa);
+  inline explicit union_pw_aff(ctx ctx, const std::string &str);
+  inline union_pw_aff &operator=(union_pw_aff obj);
+  inline ~union_pw_aff();
+  inline __isl_give isl_union_pw_aff *copy() const &;
+  inline __isl_give isl_union_pw_aff *copy() && = delete;
+  inline __isl_keep isl_union_pw_aff *get() const;
+  inline __isl_give isl_union_pw_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_pw_aff add(union_pw_aff upa2) const;
+  inline union_pw_aff pullback(union_pw_multi_aff upma) const;
+  inline union_pw_aff union_add(union_pw_aff upa2) const;
+};
+
+// declarations for isl::union_pw_multi_aff
+inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
+inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+
+class union_pw_multi_aff {
+  friend inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
+  friend inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+
+  isl_union_pw_multi_aff *ptr = nullptr;
+
+  inline explicit union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr);
+
+public:
+  inline /* implicit */ union_pw_multi_aff();
+  inline /* implicit */ union_pw_multi_aff(const union_pw_multi_aff &obj);
+  inline /* implicit */ union_pw_multi_aff(pw_multi_aff pma);
+  inline explicit union_pw_multi_aff(ctx ctx, const std::string &str);
+  inline /* implicit */ union_pw_multi_aff(union_pw_aff upa);
+  inline union_pw_multi_aff &operator=(union_pw_multi_aff obj);
+  inline ~union_pw_multi_aff();
+  inline __isl_give isl_union_pw_multi_aff *copy() const &;
+  inline __isl_give isl_union_pw_multi_aff *copy() && = delete;
+  inline __isl_keep isl_union_pw_multi_aff *get() const;
+  inline __isl_give isl_union_pw_multi_aff *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_pw_multi_aff add(union_pw_multi_aff upma2) const;
+  inline union_pw_multi_aff flat_range_product(union_pw_multi_aff upma2) const;
+  inline union_pw_multi_aff pullback(union_pw_multi_aff upma2) const;
+  inline union_pw_multi_aff union_add(union_pw_multi_aff upma2) const;
+};
+
+// declarations for isl::union_set
+inline union_set manage(__isl_take isl_union_set *ptr);
+inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+
+class union_set {
+  friend inline union_set manage(__isl_take isl_union_set *ptr);
+  friend inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+
+  isl_union_set *ptr = nullptr;
+
+  inline explicit union_set(__isl_take isl_union_set *ptr);
+
+public:
+  inline /* implicit */ union_set();
+  inline /* implicit */ union_set(const union_set &obj);
+  inline /* implicit */ union_set(basic_set bset);
+  inline /* implicit */ union_set(set set);
+  inline /* implicit */ union_set(point pnt);
+  inline explicit union_set(ctx ctx, const std::string &str);
+  inline union_set &operator=(union_set obj);
+  inline ~union_set();
+  inline __isl_give isl_union_set *copy() const &;
+  inline __isl_give isl_union_set *copy() && = delete;
+  inline __isl_keep isl_union_set *get() const;
+  inline __isl_give isl_union_set *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline union_set affine_hull() const;
+  inline union_set apply(union_map umap) const;
+  inline union_set coalesce() const;
+  inline union_set compute_divs() const;
+  inline union_set detect_equalities() const;
+  inline void foreach_point(const std::function<void(point)> &fn) const;
+  inline void foreach_set(const std::function<void(set)> &fn) const;
+  inline union_set gist(union_set context) const;
+  inline union_set gist_params(set set) const;
+  inline union_map identity() const;
+  inline union_set intersect(union_set uset2) const;
+  inline union_set intersect_params(set set) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const union_set &uset2) const;
+  inline bool is_strict_subset(const union_set &uset2) const;
+  inline bool is_subset(const union_set &uset2) const;
+  inline union_set lexmax() const;
+  inline union_set lexmin() const;
+  inline union_set polyhedral_hull() const;
+  inline union_set preimage(multi_aff ma) const;
+  inline union_set preimage(pw_multi_aff pma) const;
+  inline union_set preimage(union_pw_multi_aff upma) const;
+  inline point sample_point() const;
+  inline union_set subtract(union_set uset2) const;
+  inline union_set unite(union_set uset2) const;
+  inline union_map unwrap() const;
+};
+
+// declarations for isl::val
+inline val manage(__isl_take isl_val *ptr);
+inline val manage_copy(__isl_keep isl_val *ptr);
+
+class val {
+  friend inline val manage(__isl_take isl_val *ptr);
+  friend inline val manage_copy(__isl_keep isl_val *ptr);
+
+  isl_val *ptr = nullptr;
+
+  inline explicit val(__isl_take isl_val *ptr);
+
+public:
+  inline /* implicit */ val();
+  inline /* implicit */ val(const val &obj);
+  inline explicit val(ctx ctx, const std::string &str);
+  inline explicit val(ctx ctx, long i);
+  inline val &operator=(val obj);
+  inline ~val();
+  inline __isl_give isl_val *copy() const &;
+  inline __isl_give isl_val *copy() && = delete;
+  inline __isl_keep isl_val *get() const;
+  inline __isl_give isl_val *release();
+  inline bool is_null() const;
+  inline ctx get_ctx() const;
+
+  inline val abs() const;
+  inline bool abs_eq(const val &v2) const;
+  inline val add(val v2) const;
+  inline val ceil() const;
+  inline int cmp_si(long i) const;
+  inline val div(val v2) const;
+  inline bool eq(const val &v2) const;
+  inline val floor() const;
+  inline val gcd(val v2) const;
+  inline bool ge(const val &v2) const;
+  inline bool gt(const val &v2) const;
+  static inline val infty(ctx ctx);
+  inline val inv() const;
+  inline bool is_divisible_by(const val &v2) const;
+  inline bool is_infty() const;
+  inline bool is_int() const;
+  inline bool is_nan() const;
+  inline bool is_neg() const;
+  inline bool is_neginfty() const;
+  inline bool is_negone() const;
+  inline bool is_nonneg() const;
+  inline bool is_nonpos() const;
+  inline bool is_one() const;
+  inline bool is_pos() const;
+  inline bool is_rat() const;
+  inline bool is_zero() const;
+  inline bool le(const val &v2) const;
+  inline bool lt(const val &v2) const;
+  inline val max(val v2) const;
+  inline val min(val v2) const;
+  inline val mod(val v2) const;
+  inline val mul(val v2) const;
+  static inline val nan(ctx ctx);
+  inline bool ne(const val &v2) const;
+  inline val neg() const;
+  static inline val neginfty(ctx ctx);
+  static inline val negone(ctx ctx);
+  static inline val one(ctx ctx);
+  inline int sgn() const;
+  inline val sub(val v2) const;
+  inline val trunc() const;
+  static inline val zero(ctx ctx);
+};
+
+// implementations for isl::aff
+aff manage(__isl_take isl_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return aff(ptr);
+}
+aff manage_copy(__isl_keep isl_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return aff(ptr);
+}
+
+aff::aff()
+    : ptr(nullptr) {}
+
+aff::aff(const aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+aff::aff(__isl_take isl_aff *ptr)
+    : ptr(ptr) {}
+
+aff::aff(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+aff &aff::operator=(aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+aff::~aff() {
+  if (ptr)
+    isl_aff_free(ptr);
+}
+
+__isl_give isl_aff *aff::copy() const & {
+  return isl_aff_copy(ptr);
+}
+
+__isl_keep isl_aff *aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_aff *aff::release() {
+  isl_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx aff::get_ctx() const {
+  return ctx(isl_aff_get_ctx(ptr));
+}
+
+aff aff::add(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_add(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::ceil() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_ceil(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::div(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_div(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set aff::eq_set(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_eq_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::floor() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_floor(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set aff::ge_set(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_ge_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set aff::gt_set(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_gt_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set aff::le_set(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_le_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set aff::lt_set(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_lt_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::mod(val mod) const
+{
+  if (!ptr || mod.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_mod_val(copy(), mod.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::mul(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_mul(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set aff::ne_set(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_ne_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::neg() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_neg(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::pullback(multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_pullback_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::scale(val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_scale_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::scale_down(val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_scale_down_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+aff aff::sub(aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_aff_sub(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::ast_build
+ast_build manage(__isl_take isl_ast_build *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return ast_build(ptr);
+}
+ast_build manage_copy(__isl_keep isl_ast_build *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_ast_build_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_ast_build_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return ast_build(ptr);
+}
+
+ast_build::ast_build()
+    : ptr(nullptr) {}
+
+ast_build::ast_build(const ast_build &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_ast_build_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+ast_build::ast_build(__isl_take isl_ast_build *ptr)
+    : ptr(ptr) {}
+
+ast_build::ast_build(ctx ctx)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_build_alloc(ctx.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+ast_build &ast_build::operator=(ast_build obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_build::~ast_build() {
+  if (ptr)
+    isl_ast_build_free(ptr);
+}
+
+__isl_give isl_ast_build *ast_build::copy() const & {
+  return isl_ast_build_copy(ptr);
+}
+
+__isl_keep isl_ast_build *ast_build::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_build *ast_build::release() {
+  isl_ast_build *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_build::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx ast_build::get_ctx() const {
+  return ctx(isl_ast_build_get_ctx(ptr));
+}
+
+ast_expr ast_build::access_from(pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_build_access_from_pw_multi_aff(get(), pma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+ast_expr ast_build::access_from(multi_pw_aff mpa) const
+{
+  if (!ptr || mpa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_build_access_from_multi_pw_aff(get(), mpa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+ast_expr ast_build::call_from(pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_build_call_from_pw_multi_aff(get(), pma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+ast_expr ast_build::call_from(multi_pw_aff mpa) const
+{
+  if (!ptr || mpa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_build_call_from_multi_pw_aff(get(), mpa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+ast_expr ast_build::expr_from(set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_build_expr_from_set(get(), set.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+ast_expr ast_build::expr_from(pw_aff pa) const
+{
+  if (!ptr || pa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_build_expr_from_pw_aff(get(), pa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+ast_build ast_build::from_context(set set)
+{
+  if (set.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = set.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_build_from_context(set.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+ast_node ast_build::node_from_schedule_map(union_map schedule) const
+{
+  if (!ptr || schedule.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_build_node_from_schedule_map(get(), schedule.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::ast_expr
+ast_expr manage(__isl_take isl_ast_expr *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return ast_expr(ptr);
+}
+ast_expr manage_copy(__isl_keep isl_ast_expr *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_ast_expr_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_ast_expr_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return ast_expr(ptr);
+}
+
+ast_expr::ast_expr()
+    : ptr(nullptr) {}
+
+ast_expr::ast_expr(const ast_expr &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_ast_expr_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+ast_expr::ast_expr(__isl_take isl_ast_expr *ptr)
+    : ptr(ptr) {}
+
+
+ast_expr &ast_expr::operator=(ast_expr obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_expr::~ast_expr() {
+  if (ptr)
+    isl_ast_expr_free(ptr);
+}
+
+__isl_give isl_ast_expr *ast_expr::copy() const & {
+  return isl_ast_expr_copy(ptr);
+}
+
+__isl_keep isl_ast_expr *ast_expr::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_expr *ast_expr::release() {
+  isl_ast_expr *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_expr::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx ast_expr::get_ctx() const {
+  return ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+std::string ast_expr::to_C_str() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_expr_to_C_str(get());
+  std::string tmp(res);
+  free(res);
+  return tmp;
+}
+
+// implementations for isl::ast_node
+ast_node manage(__isl_take isl_ast_node *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return ast_node(ptr);
+}
+ast_node manage_copy(__isl_keep isl_ast_node *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_ast_node_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_ast_node_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return ast_node(ptr);
+}
+
+ast_node::ast_node()
+    : ptr(nullptr) {}
+
+ast_node::ast_node(const ast_node &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_ast_node_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+ast_node::ast_node(__isl_take isl_ast_node *ptr)
+    : ptr(ptr) {}
+
+
+ast_node &ast_node::operator=(ast_node obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_node::~ast_node() {
+  if (ptr)
+    isl_ast_node_free(ptr);
+}
+
+__isl_give isl_ast_node *ast_node::copy() const & {
+  return isl_ast_node_copy(ptr);
+}
+
+__isl_keep isl_ast_node *ast_node::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_node *ast_node::release() {
+  isl_ast_node *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_node::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx ast_node::get_ctx() const {
+  return ctx(isl_ast_node_get_ctx(ptr));
+}
+
+std::string ast_node::to_C_str() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_ast_node_to_C_str(get());
+  std::string tmp(res);
+  free(res);
+  return tmp;
+}
+
+// implementations for isl::basic_map
+basic_map manage(__isl_take isl_basic_map *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return basic_map(ptr);
+}
+basic_map manage_copy(__isl_keep isl_basic_map *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_basic_map_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_basic_map_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return basic_map(ptr);
+}
+
+basic_map::basic_map()
+    : ptr(nullptr) {}
+
+basic_map::basic_map(const basic_map &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_basic_map_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+basic_map::basic_map(__isl_take isl_basic_map *ptr)
+    : ptr(ptr) {}
+
+basic_map::basic_map(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+basic_map &basic_map::operator=(basic_map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+basic_map::~basic_map() {
+  if (ptr)
+    isl_basic_map_free(ptr);
+}
+
+__isl_give isl_basic_map *basic_map::copy() const & {
+  return isl_basic_map_copy(ptr);
+}
+
+__isl_keep isl_basic_map *basic_map::get() const {
+  return ptr;
+}
+
+__isl_give isl_basic_map *basic_map::release() {
+  isl_basic_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool basic_map::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx basic_map::get_ctx() const {
+  return ctx(isl_basic_map_get_ctx(ptr));
+}
+
+basic_map basic_map::affine_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_affine_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::apply_domain(basic_map bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_apply_domain(copy(), bmap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::apply_range(basic_map bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_apply_range(copy(), bmap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set basic_map::deltas() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_deltas(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::detect_equalities() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::flatten() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_flatten(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::flatten_domain() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_flatten_domain(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::flatten_range() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_flatten_range(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::gist(basic_map context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::intersect(basic_map bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_intersect(copy(), bmap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::intersect_domain(basic_set bset) const
+{
+  if (!ptr || bset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_intersect_domain(copy(), bset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::intersect_range(basic_set bset) const
+{
+  if (!ptr || bset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_intersect_range(copy(), bset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool basic_map::is_empty() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool basic_map::is_equal(const basic_map &bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_is_equal(get(), bmap2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool basic_map::is_subset(const basic_map &bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_is_subset(get(), bmap2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+map basic_map::lexmax() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map basic_map::lexmin() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::reverse() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_reverse(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map basic_map::sample() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_sample(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map basic_map::unite(basic_map bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_map_union(copy(), bmap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::basic_set
+basic_set manage(__isl_take isl_basic_set *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return basic_set(ptr);
+}
+basic_set manage_copy(__isl_keep isl_basic_set *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_basic_set_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_basic_set_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return basic_set(ptr);
+}
+
+basic_set::basic_set()
+    : ptr(nullptr) {}
+
+basic_set::basic_set(const basic_set &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_basic_set_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+basic_set::basic_set(__isl_take isl_basic_set *ptr)
+    : ptr(ptr) {}
+
+basic_set::basic_set(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+basic_set::basic_set(point pnt)
+{
+  if (pnt.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = pnt.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_from_point(pnt.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+basic_set &basic_set::operator=(basic_set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+basic_set::~basic_set() {
+  if (ptr)
+    isl_basic_set_free(ptr);
+}
+
+__isl_give isl_basic_set *basic_set::copy() const & {
+  return isl_basic_set_copy(ptr);
+}
+
+__isl_keep isl_basic_set *basic_set::get() const {
+  return ptr;
+}
+
+__isl_give isl_basic_set *basic_set::release() {
+  isl_basic_set *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool basic_set::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx basic_set::get_ctx() const {
+  return ctx(isl_basic_set_get_ctx(ptr));
+}
+
+basic_set basic_set::affine_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_affine_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set basic_set::apply(basic_map bmap) const
+{
+  if (!ptr || bmap.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_apply(copy(), bmap.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set basic_set::detect_equalities() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val basic_set::dim_max_val(int pos) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_dim_max_val(copy(), pos);
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set basic_set::flatten() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_flatten(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set basic_set::gist(basic_set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set basic_set::intersect(basic_set bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_intersect(copy(), bset2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set basic_set::intersect_params(basic_set bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_intersect_params(copy(), bset2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool basic_set::is_empty() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool basic_set::is_equal(const basic_set &bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_is_equal(get(), bset2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool basic_set::is_subset(const basic_set &bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_is_subset(get(), bset2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool basic_set::is_wrapping() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_is_wrapping(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+set basic_set::lexmax() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set basic_set::lexmin() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set basic_set::sample() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_sample(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+point basic_set::sample_point() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_sample_point(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set basic_set::unite(basic_set bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_basic_set_union(copy(), bset2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::map
+map manage(__isl_take isl_map *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return map(ptr);
+}
+map manage_copy(__isl_keep isl_map *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_map_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_map_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return map(ptr);
+}
+
+map::map()
+    : ptr(nullptr) {}
+
+map::map(const map &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_map_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+map::map(__isl_take isl_map *ptr)
+    : ptr(ptr) {}
+
+map::map(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+map::map(basic_map bmap)
+{
+  if (bmap.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = bmap.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_from_basic_map(bmap.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+map &map::operator=(map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+map::~map() {
+  if (ptr)
+    isl_map_free(ptr);
+}
+
+__isl_give isl_map *map::copy() const & {
+  return isl_map_copy(ptr);
+}
+
+__isl_keep isl_map *map::get() const {
+  return ptr;
+}
+
+__isl_give isl_map *map::release() {
+  isl_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool map::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx map::get_ctx() const {
+  return ctx(isl_map_get_ctx(ptr));
+}
+
+basic_map map::affine_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_affine_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::apply_domain(map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_apply_domain(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::apply_range(map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_apply_range(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::coalesce() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_coalesce(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::complement() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_complement(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set map::deltas() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_deltas(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::detect_equalities() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::flatten() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_flatten(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::flatten_domain() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_flatten_domain(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::flatten_range() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_flatten_range(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+void map::foreach_basic_map(const std::function<void(basic_map)> &fn) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  struct fn_data {
+    const std::function<void(basic_map)> *func;
+    std::exception_ptr eptr;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_basic_map *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (*data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_map_foreach_basic_map(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return void(res);
+}
+
+map map::gist(map context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::gist_domain(set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_gist_domain(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::intersect(map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_intersect(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::intersect_domain(set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_intersect_domain(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::intersect_params(set params) const
+{
+  if (!ptr || params.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_intersect_params(copy(), params.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::intersect_range(set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_intersect_range(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool map::is_bijective() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_is_bijective(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool map::is_disjoint(const map &map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_is_disjoint(get(), map2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool map::is_empty() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool map::is_equal(const map &map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_is_equal(get(), map2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool map::is_injective() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_is_injective(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool map::is_single_valued() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_is_single_valued(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool map::is_strict_subset(const map &map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_is_strict_subset(get(), map2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool map::is_subset(const map &map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_is_subset(get(), map2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+map map::lexmax() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::lexmin() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map map::polyhedral_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_polyhedral_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::reverse() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_reverse(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map map::sample() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_sample(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::subtract(map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_subtract(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map map::unite(map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_union(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_map map::unshifted_simple_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_map_unshifted_simple_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::multi_aff
+multi_aff manage(__isl_take isl_multi_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return multi_aff(ptr);
+}
+multi_aff manage_copy(__isl_keep isl_multi_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_multi_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_multi_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return multi_aff(ptr);
+}
+
+multi_aff::multi_aff()
+    : ptr(nullptr) {}
+
+multi_aff::multi_aff(const multi_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_multi_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+multi_aff::multi_aff(__isl_take isl_multi_aff *ptr)
+    : ptr(ptr) {}
+
+multi_aff::multi_aff(aff aff)
+{
+  if (aff.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = aff.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_aff_from_aff(aff.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+multi_aff::multi_aff(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+multi_aff &multi_aff::operator=(multi_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_aff::~multi_aff() {
+  if (ptr)
+    isl_multi_aff_free(ptr);
+}
+
+__isl_give isl_multi_aff *multi_aff::copy() const & {
+  return isl_multi_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_aff *multi_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_aff *multi_aff::release() {
+  isl_multi_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx multi_aff::get_ctx() const {
+  return ctx(isl_multi_aff_get_ctx(ptr));
+}
+
+multi_aff multi_aff::add(multi_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_aff_add(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_aff multi_aff::flat_range_product(multi_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_aff_flat_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_aff multi_aff::product(multi_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_aff_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_aff multi_aff::pullback(multi_aff ma2) const
+{
+  if (!ptr || ma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_aff_pullback_multi_aff(copy(), ma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_aff multi_aff::range_product(multi_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_aff_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::multi_pw_aff
+multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return multi_pw_aff(ptr);
+}
+multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_multi_pw_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_multi_pw_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return multi_pw_aff(ptr);
+}
+
+multi_pw_aff::multi_pw_aff()
+    : ptr(nullptr) {}
+
+multi_pw_aff::multi_pw_aff(const multi_pw_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_multi_pw_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+multi_pw_aff::multi_pw_aff(__isl_take isl_multi_pw_aff *ptr)
+    : ptr(ptr) {}
+
+multi_pw_aff::multi_pw_aff(multi_aff ma)
+{
+  if (ma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = ma.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_from_multi_aff(ma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+multi_pw_aff::multi_pw_aff(pw_aff pa)
+{
+  if (pa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = pa.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_from_pw_aff(pa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+multi_pw_aff::multi_pw_aff(pw_multi_aff pma)
+{
+  if (pma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = pma.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_from_pw_multi_aff(pma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+multi_pw_aff::multi_pw_aff(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+multi_pw_aff &multi_pw_aff::operator=(multi_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_pw_aff::~multi_pw_aff() {
+  if (ptr)
+    isl_multi_pw_aff_free(ptr);
+}
+
+__isl_give isl_multi_pw_aff *multi_pw_aff::copy() const & {
+  return isl_multi_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_pw_aff *multi_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_pw_aff *multi_pw_aff::release() {
+  isl_multi_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx multi_pw_aff::get_ctx() const {
+  return ctx(isl_multi_pw_aff_get_ctx(ptr));
+}
+
+multi_pw_aff multi_pw_aff::add(multi_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_add(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::flat_range_product(multi_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_flat_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::product(multi_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::pullback(multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_pullback_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::pullback(pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::pullback(multi_pw_aff mpa2) const
+{
+  if (!ptr || mpa2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_pullback_multi_pw_aff(copy(), mpa2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_pw_aff multi_pw_aff::range_product(multi_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::multi_union_pw_aff
+multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return multi_union_pw_aff(ptr);
+}
+multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_multi_union_pw_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_multi_union_pw_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return multi_union_pw_aff(ptr);
+}
+
+multi_union_pw_aff::multi_union_pw_aff()
+    : ptr(nullptr) {}
+
+multi_union_pw_aff::multi_union_pw_aff(const multi_union_pw_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_multi_union_pw_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+multi_union_pw_aff::multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr)
+    : ptr(ptr) {}
+
+multi_union_pw_aff::multi_union_pw_aff(union_pw_aff upa)
+{
+  if (upa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = upa.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_from_union_pw_aff(upa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+multi_union_pw_aff::multi_union_pw_aff(multi_pw_aff mpa)
+{
+  if (mpa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = mpa.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_from_multi_pw_aff(mpa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+multi_union_pw_aff::multi_union_pw_aff(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+multi_union_pw_aff &multi_union_pw_aff::operator=(multi_union_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_union_pw_aff::~multi_union_pw_aff() {
+  if (ptr)
+    isl_multi_union_pw_aff_free(ptr);
+}
+
+__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::copy() const & {
+  return isl_multi_union_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_union_pw_aff *multi_union_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::release() {
+  isl_multi_union_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_union_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx multi_union_pw_aff::get_ctx() const {
+  return ctx(isl_multi_union_pw_aff_get_ctx(ptr));
+}
+
+multi_union_pw_aff multi_union_pw_aff::add(multi_union_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_add(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_union_pw_aff multi_union_pw_aff::flat_range_product(multi_union_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_flat_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_union_pw_aff multi_union_pw_aff::pullback(union_pw_multi_aff upma) const
+{
+  if (!ptr || upma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_union_pw_aff multi_union_pw_aff::range_product(multi_union_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_union_pw_aff multi_union_pw_aff::union_add(multi_union_pw_aff mupa2) const
+{
+  if (!ptr || mupa2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_union_add(copy(), mupa2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::multi_val
+multi_val manage(__isl_take isl_multi_val *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return multi_val(ptr);
+}
+multi_val manage_copy(__isl_keep isl_multi_val *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_multi_val_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_multi_val_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return multi_val(ptr);
+}
+
+multi_val::multi_val()
+    : ptr(nullptr) {}
+
+multi_val::multi_val(const multi_val &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_multi_val_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+multi_val::multi_val(__isl_take isl_multi_val *ptr)
+    : ptr(ptr) {}
+
+
+multi_val &multi_val::operator=(multi_val obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_val::~multi_val() {
+  if (ptr)
+    isl_multi_val_free(ptr);
+}
+
+__isl_give isl_multi_val *multi_val::copy() const & {
+  return isl_multi_val_copy(ptr);
+}
+
+__isl_keep isl_multi_val *multi_val::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_val *multi_val::release() {
+  isl_multi_val *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_val::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx multi_val::get_ctx() const {
+  return ctx(isl_multi_val_get_ctx(ptr));
+}
+
+multi_val multi_val::add(multi_val multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_val_add(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_val multi_val::flat_range_product(multi_val multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_val_flat_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_val multi_val::product(multi_val multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_val_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_val multi_val::range_product(multi_val multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_multi_val_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::point
+point manage(__isl_take isl_point *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return point(ptr);
+}
+point manage_copy(__isl_keep isl_point *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_point_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_point_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return point(ptr);
+}
+
+point::point()
+    : ptr(nullptr) {}
+
+point::point(const point &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_point_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+point::point(__isl_take isl_point *ptr)
+    : ptr(ptr) {}
+
+
+point &point::operator=(point obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+point::~point() {
+  if (ptr)
+    isl_point_free(ptr);
+}
+
+__isl_give isl_point *point::copy() const & {
+  return isl_point_copy(ptr);
+}
+
+__isl_keep isl_point *point::get() const {
+  return ptr;
+}
+
+__isl_give isl_point *point::release() {
+  isl_point *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool point::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx point::get_ctx() const {
+  return ctx(isl_point_get_ctx(ptr));
+}
+
+
+// implementations for isl::pw_aff
+pw_aff manage(__isl_take isl_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return pw_aff(ptr);
+}
+pw_aff manage_copy(__isl_keep isl_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_pw_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_pw_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return pw_aff(ptr);
+}
+
+pw_aff::pw_aff()
+    : ptr(nullptr) {}
+
+pw_aff::pw_aff(const pw_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_pw_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+pw_aff::pw_aff(__isl_take isl_pw_aff *ptr)
+    : ptr(ptr) {}
+
+pw_aff::pw_aff(aff aff)
+{
+  if (aff.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = aff.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_from_aff(aff.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+pw_aff::pw_aff(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+pw_aff &pw_aff::operator=(pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+pw_aff::~pw_aff() {
+  if (ptr)
+    isl_pw_aff_free(ptr);
+}
+
+__isl_give isl_pw_aff *pw_aff::copy() const & {
+  return isl_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_pw_aff *pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_pw_aff *pw_aff::release() {
+  isl_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx pw_aff::get_ctx() const {
+  return ctx(isl_pw_aff_get_ctx(ptr));
+}
+
+pw_aff pw_aff::add(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_add(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::ceil() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_ceil(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::cond(pw_aff pwaff_true, pw_aff pwaff_false) const
+{
+  if (!ptr || pwaff_true.is_null() || pwaff_false.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_cond(copy(), pwaff_true.release(), pwaff_false.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::div(pw_aff pa2) const
+{
+  if (!ptr || pa2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_div(copy(), pa2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set pw_aff::eq_set(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_eq_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::floor() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_floor(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set pw_aff::ge_set(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_ge_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set pw_aff::gt_set(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_gt_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set pw_aff::le_set(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_le_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set pw_aff::lt_set(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_lt_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::max(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_max(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::min(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_min(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::mod(val mod) const
+{
+  if (!ptr || mod.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_mod_val(copy(), mod.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::mul(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_mul(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set pw_aff::ne_set(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_ne_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::neg() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_neg(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::pullback(multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_pullback_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::pullback(pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::pullback(multi_pw_aff mpa) const
+{
+  if (!ptr || mpa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_pullback_multi_pw_aff(copy(), mpa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::scale(val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_scale_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::scale_down(val f) const
+{
+  if (!ptr || f.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_scale_down_val(copy(), f.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::sub(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_sub(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::tdiv_q(pw_aff pa2) const
+{
+  if (!ptr || pa2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_tdiv_q(copy(), pa2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::tdiv_r(pw_aff pa2) const
+{
+  if (!ptr || pa2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_tdiv_r(copy(), pa2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_aff pw_aff::union_add(pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_aff_union_add(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::pw_multi_aff
+pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return pw_multi_aff(ptr);
+}
+pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_pw_multi_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_pw_multi_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return pw_multi_aff(ptr);
+}
+
+pw_multi_aff::pw_multi_aff()
+    : ptr(nullptr) {}
+
+pw_multi_aff::pw_multi_aff(const pw_multi_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_pw_multi_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+pw_multi_aff::pw_multi_aff(__isl_take isl_pw_multi_aff *ptr)
+    : ptr(ptr) {}
+
+pw_multi_aff::pw_multi_aff(multi_aff ma)
+{
+  if (ma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = ma.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_from_multi_aff(ma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+pw_multi_aff::pw_multi_aff(pw_aff pa)
+{
+  if (pa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = pa.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_from_pw_aff(pa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+pw_multi_aff::pw_multi_aff(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+pw_multi_aff &pw_multi_aff::operator=(pw_multi_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+pw_multi_aff::~pw_multi_aff() {
+  if (ptr)
+    isl_pw_multi_aff_free(ptr);
+}
+
+__isl_give isl_pw_multi_aff *pw_multi_aff::copy() const & {
+  return isl_pw_multi_aff_copy(ptr);
+}
+
+__isl_keep isl_pw_multi_aff *pw_multi_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_pw_multi_aff *pw_multi_aff::release() {
+  isl_pw_multi_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool pw_multi_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx pw_multi_aff::get_ctx() const {
+  return ctx(isl_pw_multi_aff_get_ctx(ptr));
+}
+
+pw_multi_aff pw_multi_aff::add(pw_multi_aff pma2) const
+{
+  if (!ptr || pma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_add(copy(), pma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::flat_range_product(pw_multi_aff pma2) const
+{
+  if (!ptr || pma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_flat_range_product(copy(), pma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::product(pw_multi_aff pma2) const
+{
+  if (!ptr || pma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_product(copy(), pma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::pullback(multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_pullback_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::pullback(pw_multi_aff pma2) const
+{
+  if (!ptr || pma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_pullback_pw_multi_aff(copy(), pma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::range_product(pw_multi_aff pma2) const
+{
+  if (!ptr || pma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_range_product(copy(), pma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+pw_multi_aff pw_multi_aff::union_add(pw_multi_aff pma2) const
+{
+  if (!ptr || pma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_union_add(copy(), pma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::schedule
+schedule manage(__isl_take isl_schedule *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return schedule(ptr);
+}
+schedule manage_copy(__isl_keep isl_schedule *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_schedule_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_schedule_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return schedule(ptr);
+}
+
+schedule::schedule()
+    : ptr(nullptr) {}
+
+schedule::schedule(const schedule &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_schedule_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+schedule::schedule(__isl_take isl_schedule *ptr)
+    : ptr(ptr) {}
+
+schedule::schedule(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+schedule &schedule::operator=(schedule obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+schedule::~schedule() {
+  if (ptr)
+    isl_schedule_free(ptr);
+}
+
+__isl_give isl_schedule *schedule::copy() const & {
+  return isl_schedule_copy(ptr);
+}
+
+__isl_keep isl_schedule *schedule::get() const {
+  return ptr;
+}
+
+__isl_give isl_schedule *schedule::release() {
+  isl_schedule *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool schedule::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx schedule::get_ctx() const {
+  return ctx(isl_schedule_get_ctx(ptr));
+}
+
+union_map schedule::get_map() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_get_map(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule_node schedule::get_root() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_get_root(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule schedule::pullback(union_pw_multi_aff upma) const
+{
+  if (!ptr || upma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_pullback_union_pw_multi_aff(copy(), upma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::schedule_constraints
+schedule_constraints manage(__isl_take isl_schedule_constraints *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return schedule_constraints(ptr);
+}
+schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_schedule_constraints_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_schedule_constraints_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return schedule_constraints(ptr);
+}
+
+schedule_constraints::schedule_constraints()
+    : ptr(nullptr) {}
+
+schedule_constraints::schedule_constraints(const schedule_constraints &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_schedule_constraints_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+schedule_constraints::schedule_constraints(__isl_take isl_schedule_constraints *ptr)
+    : ptr(ptr) {}
+
+schedule_constraints::schedule_constraints(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+schedule_constraints &schedule_constraints::operator=(schedule_constraints obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+schedule_constraints::~schedule_constraints() {
+  if (ptr)
+    isl_schedule_constraints_free(ptr);
+}
+
+__isl_give isl_schedule_constraints *schedule_constraints::copy() const & {
+  return isl_schedule_constraints_copy(ptr);
+}
+
+__isl_keep isl_schedule_constraints *schedule_constraints::get() const {
+  return ptr;
+}
+
+__isl_give isl_schedule_constraints *schedule_constraints::release() {
+  isl_schedule_constraints *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool schedule_constraints::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx schedule_constraints::get_ctx() const {
+  return ctx(isl_schedule_constraints_get_ctx(ptr));
+}
+
+schedule schedule_constraints::compute_schedule() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_compute_schedule(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map schedule_constraints::get_coincidence() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_coincidence(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map schedule_constraints::get_conditional_validity() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_conditional_validity(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map schedule_constraints::get_conditional_validity_condition() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_conditional_validity_condition(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set schedule_constraints::get_context() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_context(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set schedule_constraints::get_domain() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_domain(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map schedule_constraints::get_proximity() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_proximity(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map schedule_constraints::get_validity() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_validity(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::on_domain(union_set domain)
+{
+  if (domain.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = domain.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_on_domain(domain.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_coincidence(union_map coincidence) const
+{
+  if (!ptr || coincidence.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_coincidence(copy(), coincidence.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_conditional_validity(union_map condition, union_map validity) const
+{
+  if (!ptr || condition.is_null() || validity.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_conditional_validity(copy(), condition.release(), validity.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_context(set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_context(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_proximity(union_map proximity) const
+{
+  if (!ptr || proximity.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_proximity(copy(), proximity.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule_constraints schedule_constraints::set_validity(union_map validity) const
+{
+  if (!ptr || validity.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_validity(copy(), validity.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::schedule_node
+schedule_node manage(__isl_take isl_schedule_node *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return schedule_node(ptr);
+}
+schedule_node manage_copy(__isl_keep isl_schedule_node *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_schedule_node_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_schedule_node_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return schedule_node(ptr);
+}
+
+schedule_node::schedule_node()
+    : ptr(nullptr) {}
+
+schedule_node::schedule_node(const schedule_node &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_schedule_node_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+schedule_node::schedule_node(__isl_take isl_schedule_node *ptr)
+    : ptr(ptr) {}
+
+
+schedule_node &schedule_node::operator=(schedule_node obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+schedule_node::~schedule_node() {
+  if (ptr)
+    isl_schedule_node_free(ptr);
+}
+
+__isl_give isl_schedule_node *schedule_node::copy() const & {
+  return isl_schedule_node_copy(ptr);
+}
+
+__isl_keep isl_schedule_node *schedule_node::get() const {
+  return ptr;
+}
+
+__isl_give isl_schedule_node *schedule_node::release() {
+  isl_schedule_node *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool schedule_node::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx schedule_node::get_ctx() const {
+  return ctx(isl_schedule_node_get_ctx(ptr));
+}
+
+bool schedule_node::band_member_get_coincident(int pos) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_node_band_member_get_coincident(get(), pos);
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+schedule_node schedule_node::band_member_set_coincident(int pos, int coincident) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_node_band_member_set_coincident(copy(), pos, coincident);
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule_node schedule_node::child(int pos) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_node_child(copy(), pos);
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+multi_union_pw_aff schedule_node::get_prefix_schedule_multi_union_pw_aff() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map schedule_node::get_prefix_schedule_union_map() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_node_get_prefix_schedule_union_map(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_pw_multi_aff schedule_node::get_prefix_schedule_union_pw_multi_aff() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule schedule_node::get_schedule() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_node_get_schedule(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+schedule_node schedule_node::parent() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_schedule_node_parent(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::set
+set manage(__isl_take isl_set *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return set(ptr);
+}
+set manage_copy(__isl_keep isl_set *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_set_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_set_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return set(ptr);
+}
+
+set::set()
+    : ptr(nullptr) {}
+
+set::set(const set &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_set_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+set::set(__isl_take isl_set *ptr)
+    : ptr(ptr) {}
+
+set::set(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+set::set(basic_set bset)
+{
+  if (bset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = bset.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_from_basic_set(bset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+set::set(point pnt)
+{
+  if (pnt.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = pnt.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_from_point(pnt.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+set &set::operator=(set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+set::~set() {
+  if (ptr)
+    isl_set_free(ptr);
+}
+
+__isl_give isl_set *set::copy() const & {
+  return isl_set_copy(ptr);
+}
+
+__isl_keep isl_set *set::get() const {
+  return ptr;
+}
+
+__isl_give isl_set *set::release() {
+  isl_set *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool set::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx set::get_ctx() const {
+  return ctx(isl_set_get_ctx(ptr));
+}
+
+basic_set set::affine_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_affine_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::apply(map map) const
+{
+  if (!ptr || map.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_apply(copy(), map.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::coalesce() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_coalesce(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::complement() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_complement(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::detect_equalities() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::flatten() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_flatten(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+void set::foreach_basic_set(const std::function<void(basic_set)> &fn) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  struct fn_data {
+    const std::function<void(basic_set)> *func;
+    std::exception_ptr eptr;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_basic_set *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (*data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_set_foreach_basic_set(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return void(res);
+}
+
+val set::get_stride(int pos) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_get_stride(get(), pos);
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::gist(set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+map set::identity() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_identity(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::intersect(set set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_intersect(copy(), set2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::intersect_params(set params) const
+{
+  if (!ptr || params.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_intersect_params(copy(), params.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool set::is_disjoint(const set &set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_is_disjoint(get(), set2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool set::is_empty() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool set::is_equal(const set &set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_is_equal(get(), set2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool set::is_strict_subset(const set &set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_is_strict_subset(get(), set2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool set::is_subset(const set &set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_is_subset(get(), set2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool set::is_wrapping() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_is_wrapping(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+set set::lexmax() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::lexmin() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val set::max_val(const aff &obj) const
+{
+  if (!ptr || obj.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_max_val(get(), obj.get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val set::min_val(const aff &obj) const
+{
+  if (!ptr || obj.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_min_val(get(), obj.get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set set::polyhedral_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_polyhedral_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set set::sample() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_sample(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+point set::sample_point() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_sample_point(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::subtract(set set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_subtract(copy(), set2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+set set::unite(set set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_union(copy(), set2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+basic_set set::unshifted_simple_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_set_unshifted_simple_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::union_access_info
+union_access_info manage(__isl_take isl_union_access_info *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return union_access_info(ptr);
+}
+union_access_info manage_copy(__isl_keep isl_union_access_info *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_access_info_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_union_access_info_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return union_access_info(ptr);
+}
+
+union_access_info::union_access_info()
+    : ptr(nullptr) {}
+
+union_access_info::union_access_info(const union_access_info &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_access_info_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+union_access_info::union_access_info(__isl_take isl_union_access_info *ptr)
+    : ptr(ptr) {}
+
+union_access_info::union_access_info(union_map sink)
+{
+  if (sink.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = sink.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_access_info_from_sink(sink.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+union_access_info &union_access_info::operator=(union_access_info obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_access_info::~union_access_info() {
+  if (ptr)
+    isl_union_access_info_free(ptr);
+}
+
+__isl_give isl_union_access_info *union_access_info::copy() const & {
+  return isl_union_access_info_copy(ptr);
+}
+
+__isl_keep isl_union_access_info *union_access_info::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_access_info *union_access_info::release() {
+  isl_union_access_info *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_access_info::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_access_info::get_ctx() const {
+  return ctx(isl_union_access_info_get_ctx(ptr));
+}
+
+union_flow union_access_info::compute_flow() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_access_info_compute_flow(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_access_info union_access_info::set_kill(union_map kill) const
+{
+  if (!ptr || kill.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_access_info_set_kill(copy(), kill.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_access_info union_access_info::set_may_source(union_map may_source) const
+{
+  if (!ptr || may_source.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_access_info_set_may_source(copy(), may_source.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_access_info union_access_info::set_must_source(union_map must_source) const
+{
+  if (!ptr || must_source.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_access_info_set_must_source(copy(), must_source.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_access_info union_access_info::set_schedule(schedule schedule) const
+{
+  if (!ptr || schedule.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_access_info_set_schedule(copy(), schedule.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_access_info union_access_info::set_schedule_map(union_map schedule_map) const
+{
+  if (!ptr || schedule_map.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_access_info_set_schedule_map(copy(), schedule_map.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::union_flow
+union_flow manage(__isl_take isl_union_flow *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return union_flow(ptr);
+}
+union_flow manage_copy(__isl_keep isl_union_flow *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_flow_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_union_flow_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return union_flow(ptr);
+}
+
+union_flow::union_flow()
+    : ptr(nullptr) {}
+
+union_flow::union_flow(const union_flow &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_flow_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+union_flow::union_flow(__isl_take isl_union_flow *ptr)
+    : ptr(ptr) {}
+
+
+union_flow &union_flow::operator=(union_flow obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_flow::~union_flow() {
+  if (ptr)
+    isl_union_flow_free(ptr);
+}
+
+__isl_give isl_union_flow *union_flow::copy() const & {
+  return isl_union_flow_copy(ptr);
+}
+
+__isl_keep isl_union_flow *union_flow::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_flow *union_flow::release() {
+  isl_union_flow *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_flow::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_flow::get_ctx() const {
+  return ctx(isl_union_flow_get_ctx(ptr));
+}
+
+union_map union_flow::get_full_may_dependence() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_flow_get_full_may_dependence(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_flow::get_full_must_dependence() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_flow_get_full_must_dependence(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_flow::get_may_dependence() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_flow_get_may_dependence(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_flow::get_may_no_source() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_flow_get_may_no_source(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_flow::get_must_dependence() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_flow_get_must_dependence(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_flow::get_must_no_source() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_flow_get_must_no_source(get());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::union_map
+union_map manage(__isl_take isl_union_map *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return union_map(ptr);
+}
+union_map manage_copy(__isl_keep isl_union_map *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_map_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_union_map_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return union_map(ptr);
+}
+
+union_map::union_map()
+    : ptr(nullptr) {}
+
+union_map::union_map(const union_map &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_map_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+union_map::union_map(__isl_take isl_union_map *ptr)
+    : ptr(ptr) {}
+
+union_map::union_map(basic_map bmap)
+{
+  if (bmap.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = bmap.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_from_basic_map(bmap.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+union_map::union_map(map map)
+{
+  if (map.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = map.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_from_map(map.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+union_map::union_map(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+union_map &union_map::operator=(union_map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_map::~union_map() {
+  if (ptr)
+    isl_union_map_free(ptr);
+}
+
+__isl_give isl_union_map *union_map::copy() const & {
+  return isl_union_map_copy(ptr);
+}
+
+__isl_keep isl_union_map *union_map::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_map *union_map::release() {
+  isl_union_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_map::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_map::get_ctx() const {
+  return ctx(isl_union_map_get_ctx(ptr));
+}
+
+union_map union_map::affine_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_affine_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::apply_domain(union_map umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_apply_domain(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::apply_range(union_map umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_apply_range(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::coalesce() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_coalesce(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::compute_divs() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_compute_divs(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_map::deltas() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_deltas(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::detect_equalities() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_map::domain() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_domain(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::domain_factor_domain() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_domain_factor_domain(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::domain_factor_range() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_domain_factor_range(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::domain_map() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_domain_map(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_pw_multi_aff union_map::domain_map_union_pw_multi_aff() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_domain_map_union_pw_multi_aff(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::domain_product(union_map umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_domain_product(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::eq_at(multi_union_pw_aff mupa) const
+{
+  if (!ptr || mupa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_eq_at_multi_union_pw_aff(copy(), mupa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::factor_domain() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_factor_domain(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::factor_range() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_factor_range(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::fixed_power(val exp) const
+{
+  if (!ptr || exp.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_fixed_power_val(copy(), exp.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+void union_map::foreach_map(const std::function<void(map)> &fn) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  struct fn_data {
+    const std::function<void(map)> *func;
+    std::exception_ptr eptr;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_map *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (*data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_union_map_foreach_map(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return void(res);
+}
+
+union_map union_map::from(union_pw_multi_aff upma)
+{
+  if (upma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = upma.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_from_union_pw_multi_aff(upma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::from(multi_union_pw_aff mupa)
+{
+  if (mupa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = mupa.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_from_multi_union_pw_aff(mupa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::from_domain(union_set uset)
+{
+  if (uset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = uset.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_from_domain(uset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::from_domain_and_range(union_set domain, union_set range)
+{
+  if (domain.is_null() || range.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = domain.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_from_domain_and_range(domain.release(), range.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::from_range(union_set uset)
+{
+  if (uset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = uset.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_from_range(uset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::gist(union_map context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::gist_domain(union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_gist_domain(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::gist_params(set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_gist_params(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::gist_range(union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_gist_range(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::intersect(union_map umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_intersect(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::intersect_domain(union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_intersect_domain(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::intersect_params(set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_intersect_params(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::intersect_range(union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_intersect_range(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool union_map::is_bijective() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_is_bijective(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool union_map::is_empty() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool union_map::is_equal(const union_map &umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_is_equal(get(), umap2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool union_map::is_injective() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_is_injective(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool union_map::is_single_valued() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_is_single_valued(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool union_map::is_strict_subset(const union_map &umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_is_strict_subset(get(), umap2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool union_map::is_subset(const union_map &umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_is_subset(get(), umap2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+union_map union_map::lexmax() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::lexmin() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::polyhedral_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_polyhedral_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::product(union_map umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_product(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::project_out_all_params() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_project_out_all_params(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_map::range() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_range(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::range_factor_domain() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_range_factor_domain(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::range_factor_range() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_range_factor_range(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::range_map() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_range_map(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::range_product(union_map umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_range_product(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::reverse() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_reverse(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::subtract(union_map umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_subtract(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::subtract_domain(union_set dom) const
+{
+  if (!ptr || dom.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_subtract_domain(copy(), dom.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::subtract_range(union_set dom) const
+{
+  if (!ptr || dom.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_subtract_range(copy(), dom.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::unite(union_map umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_union(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_map::wrap() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_wrap(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_map::zip() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_map_zip(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::union_pw_aff
+union_pw_aff manage(__isl_take isl_union_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return union_pw_aff(ptr);
+}
+union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_pw_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_union_pw_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return union_pw_aff(ptr);
+}
+
+union_pw_aff::union_pw_aff()
+    : ptr(nullptr) {}
+
+union_pw_aff::union_pw_aff(const union_pw_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_pw_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+union_pw_aff::union_pw_aff(__isl_take isl_union_pw_aff *ptr)
+    : ptr(ptr) {}
+
+union_pw_aff::union_pw_aff(pw_aff pa)
+{
+  if (pa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = pa.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_aff_from_pw_aff(pa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+union_pw_aff::union_pw_aff(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+union_pw_aff &union_pw_aff::operator=(union_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_pw_aff::~union_pw_aff() {
+  if (ptr)
+    isl_union_pw_aff_free(ptr);
+}
+
+__isl_give isl_union_pw_aff *union_pw_aff::copy() const & {
+  return isl_union_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_union_pw_aff *union_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_pw_aff *union_pw_aff::release() {
+  isl_union_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_pw_aff::get_ctx() const {
+  return ctx(isl_union_pw_aff_get_ctx(ptr));
+}
+
+union_pw_aff union_pw_aff::add(union_pw_aff upa2) const
+{
+  if (!ptr || upa2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_aff_add(copy(), upa2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_pw_aff union_pw_aff::pullback(union_pw_multi_aff upma) const
+{
+  if (!ptr || upma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_pw_aff union_pw_aff::union_add(union_pw_aff upa2) const
+{
+  if (!ptr || upa2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_aff_union_add(copy(), upa2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::union_pw_multi_aff
+union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return union_pw_multi_aff(ptr);
+}
+union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_pw_multi_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_union_pw_multi_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return union_pw_multi_aff(ptr);
+}
+
+union_pw_multi_aff::union_pw_multi_aff()
+    : ptr(nullptr) {}
+
+union_pw_multi_aff::union_pw_multi_aff(const union_pw_multi_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_pw_multi_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+union_pw_multi_aff::union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr)
+    : ptr(ptr) {}
+
+union_pw_multi_aff::union_pw_multi_aff(pw_multi_aff pma)
+{
+  if (pma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = pma.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_from_pw_multi_aff(pma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+union_pw_multi_aff::union_pw_multi_aff(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+union_pw_multi_aff::union_pw_multi_aff(union_pw_aff upa)
+{
+  if (upa.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = upa.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_from_union_pw_aff(upa.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+union_pw_multi_aff &union_pw_multi_aff::operator=(union_pw_multi_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_pw_multi_aff::~union_pw_multi_aff() {
+  if (ptr)
+    isl_union_pw_multi_aff_free(ptr);
+}
+
+__isl_give isl_union_pw_multi_aff *union_pw_multi_aff::copy() const & {
+  return isl_union_pw_multi_aff_copy(ptr);
+}
+
+__isl_keep isl_union_pw_multi_aff *union_pw_multi_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_pw_multi_aff *union_pw_multi_aff::release() {
+  isl_union_pw_multi_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_pw_multi_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_pw_multi_aff::get_ctx() const {
+  return ctx(isl_union_pw_multi_aff_get_ctx(ptr));
+}
+
+union_pw_multi_aff union_pw_multi_aff::add(union_pw_multi_aff upma2) const
+{
+  if (!ptr || upma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_add(copy(), upma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_pw_multi_aff union_pw_multi_aff::flat_range_product(union_pw_multi_aff upma2) const
+{
+  if (!ptr || upma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_flat_range_product(copy(), upma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_pw_multi_aff union_pw_multi_aff::pullback(union_pw_multi_aff upma2) const
+{
+  if (!ptr || upma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_pullback_union_pw_multi_aff(copy(), upma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_pw_multi_aff union_pw_multi_aff::union_add(union_pw_multi_aff upma2) const
+{
+  if (!ptr || upma2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_union_add(copy(), upma2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::union_set
+union_set manage(__isl_take isl_union_set *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return union_set(ptr);
+}
+union_set manage_copy(__isl_keep isl_union_set *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_set_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_union_set_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return union_set(ptr);
+}
+
+union_set::union_set()
+    : ptr(nullptr) {}
+
+union_set::union_set(const union_set &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_union_set_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+union_set::union_set(__isl_take isl_union_set *ptr)
+    : ptr(ptr) {}
+
+union_set::union_set(basic_set bset)
+{
+  if (bset.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = bset.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_from_basic_set(bset.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+union_set::union_set(set set)
+{
+  if (set.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = set.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_from_set(set.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+union_set::union_set(point pnt)
+{
+  if (pnt.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = pnt.get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_from_point(pnt.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+union_set::union_set(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+union_set &union_set::operator=(union_set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_set::~union_set() {
+  if (ptr)
+    isl_union_set_free(ptr);
+}
+
+__isl_give isl_union_set *union_set::copy() const & {
+  return isl_union_set_copy(ptr);
+}
+
+__isl_keep isl_union_set *union_set::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_set *union_set::release() {
+  isl_union_set *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_set::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx union_set::get_ctx() const {
+  return ctx(isl_union_set_get_ctx(ptr));
+}
+
+union_set union_set::affine_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_affine_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::apply(union_map umap) const
+{
+  if (!ptr || umap.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_apply(copy(), umap.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::coalesce() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_coalesce(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::compute_divs() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_compute_divs(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::detect_equalities() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+void union_set::foreach_point(const std::function<void(point)> &fn) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  struct fn_data {
+    const std::function<void(point)> *func;
+    std::exception_ptr eptr;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_point *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (*data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_union_set_foreach_point(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return void(res);
+}
+
+void union_set::foreach_set(const std::function<void(set)> &fn) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  struct fn_data {
+    const std::function<void(set)> *func;
+    std::exception_ptr eptr;
+  } fn_data = { &fn };
+  auto fn_lambda = [](isl_set *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (*data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_union_set_foreach_set(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return void(res);
+}
+
+union_set union_set::gist(union_set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::gist_params(set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_gist_params(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_set::identity() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_identity(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::intersect(union_set uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_intersect(copy(), uset2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::intersect_params(set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_intersect_params(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool union_set::is_empty() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool union_set::is_equal(const union_set &uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_is_equal(get(), uset2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool union_set::is_strict_subset(const union_set &uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_is_strict_subset(get(), uset2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool union_set::is_subset(const union_set &uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_is_subset(get(), uset2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+union_set union_set::lexmax() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::lexmin() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::polyhedral_hull() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_polyhedral_hull(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::preimage(multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_preimage_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::preimage(pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_preimage_pw_multi_aff(copy(), pma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::preimage(union_pw_multi_aff upma) const
+{
+  if (!ptr || upma.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_preimage_union_pw_multi_aff(copy(), upma.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+point union_set::sample_point() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_sample_point(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::subtract(union_set uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_subtract(copy(), uset2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_set union_set::unite(union_set uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_union(copy(), uset2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+union_map union_set::unwrap() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_union_set_unwrap(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+// implementations for isl::val
+val manage(__isl_take isl_val *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  return val(ptr);
+}
+val manage_copy(__isl_keep isl_val *ptr) {
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_val_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = isl_val_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(ctx);
+  return val(ptr);
+}
+
+val::val()
+    : ptr(nullptr) {}
+
+val::val(const val &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = isl_val_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  ptr = obj.copy();
+  if (obj.ptr && !ptr)
+    exception::throw_last_error(ctx);
+}
+
+val::val(__isl_take isl_val *ptr)
+    : ptr(ptr) {}
+
+val::val(ctx ctx, const std::string &str)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+val::val(ctx ctx, long i)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_int_from_si(ctx.release(), i);
+  if (!res)
+    exception::throw_last_error(ctx);
+  ptr = res;
+}
+
+val &val::operator=(val obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+val::~val() {
+  if (ptr)
+    isl_val_free(ptr);
+}
+
+__isl_give isl_val *val::copy() const & {
+  return isl_val_copy(ptr);
+}
+
+__isl_keep isl_val *val::get() const {
+  return ptr;
+}
+
+__isl_give isl_val *val::release() {
+  isl_val *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool val::is_null() const {
+  return ptr == nullptr;
+}
+
+ctx val::get_ctx() const {
+  return ctx(isl_val_get_ctx(ptr));
+}
+
+val val::abs() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_abs(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool val::abs_eq(const val &v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_abs_eq(get(), v2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+val val::add(val v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_add(copy(), v2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::ceil() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_ceil(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+int val::cmp_si(long i) const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_cmp_si(get(), i);
+  return res;
+}
+
+val val::div(val v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_div(copy(), v2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool val::eq(const val &v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_eq(get(), v2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+val val::floor() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_floor(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::gcd(val v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_gcd(copy(), v2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool val::ge(const val &v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_ge(get(), v2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::gt(const val &v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_gt(get(), v2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+val val::infty(ctx ctx)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_infty(ctx.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::inv() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_inv(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool val::is_divisible_by(const val &v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_divisible_by(get(), v2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_infty() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_infty(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_int() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_int(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_nan() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_nan(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_neg() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_neg(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_neginfty() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_neginfty(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_negone() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_negone(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_nonneg() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_nonneg(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_nonpos() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_nonpos(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_one() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_one(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_pos() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_pos(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_rat() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_rat(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::is_zero() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_is_zero(get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::le(const val &v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_le(get(), v2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+bool val::lt(const val &v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_lt(get(), v2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+val val::max(val v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_max(copy(), v2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::min(val v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_min(copy(), v2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::mod(val v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_mod(copy(), v2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::mul(val v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_mul(copy(), v2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::nan(ctx ctx)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_nan(ctx.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+bool val::ne(const val &v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_ne(get(), v2.get());
+  if (res < 0)
+    exception::throw_last_error(ctx);
+  return res;
+}
+
+val val::neg() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_neg(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::neginfty(ctx ctx)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_neginfty(ctx.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::negone(ctx ctx)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_negone(ctx.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::one(ctx ctx)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_one(ctx.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+int val::sgn() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_sgn(get());
+  return res;
+}
+
+val val::sub(val v2) const
+{
+  if (!ptr || v2.is_null())
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_sub(copy(), v2.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::trunc() const
+{
+  if (!ptr)
+    exception::throw_NULL_input(__FILE__, __LINE__);
+  auto ctx = get_ctx();
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_trunc(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
+val val::zero(ctx ctx)
+{
+  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto res = isl_val_zero(ctx.release());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+} // namespace isl
+
+#endif /* ISL_CPP */
diff --git a/lib/External/isl/interface/Makefile.am b/lib/External/isl/interface/Makefile.am
new file mode 100644
index 0000000..fa09ce4
--- /dev/null
+++ b/lib/External/isl/interface/Makefile.am
@@ -0,0 +1,26 @@
+AUTOMAKE_OPTIONS = nostdinc
+
+noinst_PROGRAMS = extract_interface
+
+includes = -I$(top_builddir) -I$(top_srcdir) \
+	-I$(top_builddir)/include -I$(top_srcdir)/include
+
+extract_interface_CPPFLAGS = $(includes)
+extract_interface_CXXFLAGS = $(CLANG_CXXFLAGS)
+extract_interface_SOURCES = \
+	generator.h \
+	generator.cc \
+	python.h \
+	python.cc \
+	cpp.h \
+	cpp.cc \
+	cpp_conversion.h \
+	cpp_conversion.cc \
+	extract_interface.h \
+	extract_interface.cc
+extract_interface_LDFLAGS = $(CLANG_LDFLAGS)
+extract_interface_LDADD = \
+	-lclangFrontend -lclangSerialization -lclangParse -lclangSema \
+	$(LIB_CLANG_EDIT) \
+	-lclangAnalysis -lclangAST -lclangLex -lclangBasic -lclangDriver \
+	$(CLANG_LIBS) $(CLANG_LDFLAGS)
diff --git a/lib/External/isl/interface/Makefile.in b/lib/External/isl/interface/Makefile.in
new file mode 100644
index 0000000..f34c851
--- /dev/null
+++ b/lib/External/isl/interface/Makefile.in
@@ -0,0 +1,759 @@
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = extract_interface$(EXEEXT)
+subdir = interface
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
+	$(top_srcdir)/m4/ax_cc_maxopt.m4 \
+	$(top_srcdir)/m4/ax_check_compiler_flags.m4 \
+	$(top_srcdir)/m4/ax_compiler_vendor.m4 \
+	$(top_srcdir)/m4/ax_create_pkgconfig_info.m4 \
+	$(top_srcdir)/m4/ax_create_stdint_h.m4 \
+	$(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+	$(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
+	$(top_srcdir)/m4/ax_detect_clang.m4 \
+	$(top_srcdir)/m4/ax_detect_git_head.m4 \
+	$(top_srcdir)/m4/ax_detect_gmp.m4 \
+	$(top_srcdir)/m4/ax_detect_imath.m4 \
+	$(top_srcdir)/m4/ax_gcc_archflag.m4 \
+	$(top_srcdir)/m4/ax_gcc_warn_unused_result.m4 \
+	$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
+	$(top_srcdir)/m4/ax_set_warning_flags.m4 \
+	$(top_srcdir)/m4/ax_submodule.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/isl_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_extract_interface_OBJECTS = extract_interface-generator.$(OBJEXT) \
+	extract_interface-python.$(OBJEXT) \
+	extract_interface-cpp.$(OBJEXT) \
+	extract_interface-cpp_conversion.$(OBJEXT) \
+	extract_interface-extract_interface.$(OBJEXT)
+extract_interface_OBJECTS = $(am_extract_interface_OBJECTS)
+am__DEPENDENCIES_1 =
+extract_interface_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+extract_interface_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(extract_interface_CXXFLAGS) $(CXXFLAGS) \
+	$(extract_interface_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = 
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo "  CXX     " $@;
+am__v_CXX_1 = 
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo "  CXXLD   " $@;
+am__v_CXXLD_1 = 
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(extract_interface_SOURCES)
+DIST_SOURCES = $(extract_interface_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CLANG_CXXFLAGS = @CLANG_CXXFLAGS@
+CLANG_LDFLAGS = @CLANG_LDFLAGS@
+CLANG_LIBS = @CLANG_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXX11FLAGS = @CXX11FLAGS@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GIT_HEAD = @GIT_HEAD@
+GIT_HEAD_ID = @GIT_HEAD_ID@
+GIT_HEAD_VERSION = @GIT_HEAD_VERSION@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_CLANG_EDIT = @LIB_CLANG_EDIT@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MP_CPPFLAGS = @MP_CPPFLAGS@
+MP_LDFLAGS = @MP_LDFLAGS@
+MP_LIBS = @MP_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PDFLATEX = @PDFLATEX@
+PERL = @PERL@
+POD2HTML = @POD2HTML@
+PRTDIAG = @PRTDIAG@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARNING_FLAGS = @WARNING_FLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+llvm_config_found = @llvm_config_found@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfig_libdir = @pkgconfig_libdir@
+pkgconfig_libfile = @pkgconfig_libfile@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+versioninfo = @versioninfo@
+AUTOMAKE_OPTIONS = nostdinc
+includes = -I$(top_builddir) -I$(top_srcdir) \
+	-I$(top_builddir)/include -I$(top_srcdir)/include
+
+extract_interface_CPPFLAGS = $(includes)
+extract_interface_CXXFLAGS = $(CLANG_CXXFLAGS)
+extract_interface_SOURCES = \
+	generator.h \
+	generator.cc \
+	python.h \
+	python.cc \
+	cpp.h \
+	cpp.cc \
+	cpp_conversion.h \
+	cpp_conversion.cc \
+	extract_interface.h \
+	extract_interface.cc
+
+extract_interface_LDFLAGS = $(CLANG_LDFLAGS)
+extract_interface_LDADD = \
+	-lclangFrontend -lclangSerialization -lclangParse -lclangSema \
+	$(LIB_CLANG_EDIT) \
+	-lclangAnalysis -lclangAST -lclangLex -lclangBasic -lclangDriver \
+	$(CLANG_LIBS) $(CLANG_LDFLAGS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign interface/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign interface/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+	@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+
+extract_interface$(EXEEXT): $(extract_interface_OBJECTS) $(extract_interface_DEPENDENCIES) $(EXTRA_extract_interface_DEPENDENCIES) 
+	@rm -f extract_interface$(EXEEXT)
+	$(AM_V_CXXLD)$(extract_interface_LINK) $(extract_interface_OBJECTS) $(extract_interface_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract_interface-cpp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract_interface-cpp_conversion.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract_interface-extract_interface.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract_interface-generator.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract_interface-python.Po@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+extract_interface-generator.o: generator.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-generator.o -MD -MP -MF $(DEPDIR)/extract_interface-generator.Tpo -c -o extract_interface-generator.o `test -f 'generator.cc' || echo '$(srcdir)/'`generator.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-generator.Tpo $(DEPDIR)/extract_interface-generator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='generator.cc' object='extract_interface-generator.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-generator.o `test -f 'generator.cc' || echo '$(srcdir)/'`generator.cc
+
+extract_interface-generator.obj: generator.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-generator.obj -MD -MP -MF $(DEPDIR)/extract_interface-generator.Tpo -c -o extract_interface-generator.obj `if test -f 'generator.cc'; then $(CYGPATH_W) 'generator.cc'; else $(CYGPATH_W) '$(srcdir)/generator.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-generator.Tpo $(DEPDIR)/extract_interface-generator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='generator.cc' object='extract_interface-generator.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-generator.obj `if test -f 'generator.cc'; then $(CYGPATH_W) 'generator.cc'; else $(CYGPATH_W) '$(srcdir)/generator.cc'; fi`
+
+extract_interface-python.o: python.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-python.o -MD -MP -MF $(DEPDIR)/extract_interface-python.Tpo -c -o extract_interface-python.o `test -f 'python.cc' || echo '$(srcdir)/'`python.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-python.Tpo $(DEPDIR)/extract_interface-python.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='python.cc' object='extract_interface-python.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-python.o `test -f 'python.cc' || echo '$(srcdir)/'`python.cc
+
+extract_interface-python.obj: python.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-python.obj -MD -MP -MF $(DEPDIR)/extract_interface-python.Tpo -c -o extract_interface-python.obj `if test -f 'python.cc'; then $(CYGPATH_W) 'python.cc'; else $(CYGPATH_W) '$(srcdir)/python.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-python.Tpo $(DEPDIR)/extract_interface-python.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='python.cc' object='extract_interface-python.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-python.obj `if test -f 'python.cc'; then $(CYGPATH_W) 'python.cc'; else $(CYGPATH_W) '$(srcdir)/python.cc'; fi`
+
+extract_interface-cpp.o: cpp.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-cpp.o -MD -MP -MF $(DEPDIR)/extract_interface-cpp.Tpo -c -o extract_interface-cpp.o `test -f 'cpp.cc' || echo '$(srcdir)/'`cpp.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-cpp.Tpo $(DEPDIR)/extract_interface-cpp.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='cpp.cc' object='extract_interface-cpp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-cpp.o `test -f 'cpp.cc' || echo '$(srcdir)/'`cpp.cc
+
+extract_interface-cpp.obj: cpp.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-cpp.obj -MD -MP -MF $(DEPDIR)/extract_interface-cpp.Tpo -c -o extract_interface-cpp.obj `if test -f 'cpp.cc'; then $(CYGPATH_W) 'cpp.cc'; else $(CYGPATH_W) '$(srcdir)/cpp.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-cpp.Tpo $(DEPDIR)/extract_interface-cpp.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='cpp.cc' object='extract_interface-cpp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-cpp.obj `if test -f 'cpp.cc'; then $(CYGPATH_W) 'cpp.cc'; else $(CYGPATH_W) '$(srcdir)/cpp.cc'; fi`
+
+extract_interface-cpp_conversion.o: cpp_conversion.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-cpp_conversion.o -MD -MP -MF $(DEPDIR)/extract_interface-cpp_conversion.Tpo -c -o extract_interface-cpp_conversion.o `test -f 'cpp_conversion.cc' || echo '$(srcdir)/'`cpp_conversion.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-cpp_conversion.Tpo $(DEPDIR)/extract_interface-cpp_conversion.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='cpp_conversion.cc' object='extract_interface-cpp_conversion.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-cpp_conversion.o `test -f 'cpp_conversion.cc' || echo '$(srcdir)/'`cpp_conversion.cc
+
+extract_interface-cpp_conversion.obj: cpp_conversion.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-cpp_conversion.obj -MD -MP -MF $(DEPDIR)/extract_interface-cpp_conversion.Tpo -c -o extract_interface-cpp_conversion.obj `if test -f 'cpp_conversion.cc'; then $(CYGPATH_W) 'cpp_conversion.cc'; else $(CYGPATH_W) '$(srcdir)/cpp_conversion.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-cpp_conversion.Tpo $(DEPDIR)/extract_interface-cpp_conversion.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='cpp_conversion.cc' object='extract_interface-cpp_conversion.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-cpp_conversion.obj `if test -f 'cpp_conversion.cc'; then $(CYGPATH_W) 'cpp_conversion.cc'; else $(CYGPATH_W) '$(srcdir)/cpp_conversion.cc'; fi`
+
+extract_interface-extract_interface.o: extract_interface.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-extract_interface.o -MD -MP -MF $(DEPDIR)/extract_interface-extract_interface.Tpo -c -o extract_interface-extract_interface.o `test -f 'extract_interface.cc' || echo '$(srcdir)/'`extract_interface.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-extract_interface.Tpo $(DEPDIR)/extract_interface-extract_interface.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='extract_interface.cc' object='extract_interface-extract_interface.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-extract_interface.o `test -f 'extract_interface.cc' || echo '$(srcdir)/'`extract_interface.cc
+
+extract_interface-extract_interface.obj: extract_interface.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -MT extract_interface-extract_interface.obj -MD -MP -MF $(DEPDIR)/extract_interface-extract_interface.Tpo -c -o extract_interface-extract_interface.obj `if test -f 'extract_interface.cc'; then $(CYGPATH_W) 'extract_interface.cc'; else $(CYGPATH_W) '$(srcdir)/extract_interface.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/extract_interface-extract_interface.Tpo $(DEPDIR)/extract_interface-extract_interface.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='extract_interface.cc' object='extract_interface-extract_interface.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(extract_interface_CPPFLAGS) $(CPPFLAGS) $(extract_interface_CXXFLAGS) $(CXXFLAGS) -c -o extract_interface-extract_interface.obj `if test -f 'extract_interface.cc'; then $(CYGPATH_W) 'extract_interface.cc'; else $(CYGPATH_W) '$(srcdir)/extract_interface.cc'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \
+	ctags-am distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/External/isl/interface/cpp.cc b/lib/External/isl/interface/cpp.cc
new file mode 100644
index 0000000..955f944
--- /dev/null
+++ b/lib/External/isl/interface/cpp.cc
@@ -0,0 +1,1457 @@
+/*
+ * Copyright 2016, 2017 Tobias Grosser. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOBIAS GROSSER ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as
+ * representing official policies, either expressed or implied, of
+ * Tobias Grosser.
+ */
+
+#include <cstdarg>
+#include <cstdio>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "cpp.h"
+#include "isl_config.h"
+
+/* Print string formatted according to "fmt" to ostream "os".
+ *
+ * This osprintf method allows us to use printf style formatting constructs when
+ * writing to an ostream.
+ */
+static void osprintf(ostream &os, const char *format, ...)
+{
+	va_list arguments;
+	char *string_pointer;
+	size_t size;
+
+	va_start(arguments, format);
+	size = vsnprintf(NULL, 0, format, arguments);
+	string_pointer = new char[size + 1];
+	va_end(arguments);
+	va_start(arguments, format);
+	vsnprintf(string_pointer, size + 1, format, arguments);
+	va_end(arguments);
+	os << string_pointer;
+	delete[] string_pointer;
+}
+
+/* Convert "l" to a string.
+ */
+static std::string to_string(long l)
+{
+	std::ostringstream strm;
+	strm << l;
+	return strm.str();
+}
+
+/* Generate a cpp interface based on the extracted types and functions.
+ *
+ * Print first a set of forward declarations for all isl wrapper
+ * classes, then the declarations of the classes, and at the end all
+ * implementations.
+ *
+ * If checked C++ bindings are being generated,
+ * then wrap them in a namespace to avoid conflicts
+ * with the default C++ bindings (with automatic checks using exceptions).
+ */
+void cpp_generator::generate()
+{
+	ostream &os = cout;
+
+	osprintf(os, "\n");
+	osprintf(os, "namespace isl {\n\n");
+	if (checked)
+		osprintf(os, "namespace checked {\n\n");
+
+	print_forward_declarations(os);
+	osprintf(os, "\n");
+	print_declarations(os);
+	osprintf(os, "\n");
+	print_implementations(os);
+
+	if (checked)
+		osprintf(os, "} // namespace checked\n");
+	osprintf(os, "} // namespace isl\n");
+}
+
+/* Print forward declarations for all classes to "os".
+*/
+void cpp_generator::print_forward_declarations(ostream &os)
+{
+	map<string, isl_class>::iterator ci;
+
+	osprintf(os, "// forward declarations\n");
+
+	for (ci = classes.begin(); ci != classes.end(); ++ci)
+		print_class_forward_decl(os, ci->second);
+}
+
+/* Print all declarations to "os".
+ */
+void cpp_generator::print_declarations(ostream &os)
+{
+	map<string, isl_class>::iterator ci;
+	bool first = true;
+
+	for (ci = classes.begin(); ci != classes.end(); ++ci) {
+		if (first)
+			first = false;
+		else
+			osprintf(os, "\n");
+
+		print_class(os, ci->second);
+	}
+}
+
+/* Print all implementations to "os".
+ */
+void cpp_generator::print_implementations(ostream &os)
+{
+	map<string, isl_class>::iterator ci;
+	bool first = true;
+
+	for (ci = classes.begin(); ci != classes.end(); ++ci) {
+		if (first)
+			first = false;
+		else
+			osprintf(os, "\n");
+
+		print_class_impl(os, ci->second);
+	}
+}
+
+/* Print declarations for class "clazz" to "os".
+ */
+void cpp_generator::print_class(ostream &os, const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "// declarations for isl::%s\n", cppname);
+
+	print_class_factory_decl(os, clazz);
+	osprintf(os, "\n");
+	osprintf(os, "class %s {\n", cppname);
+	print_class_factory_decl(os, clazz, "  friend ");
+	osprintf(os, "\n");
+	osprintf(os, "  %s *ptr = nullptr;\n", name);
+	osprintf(os, "\n");
+	print_private_constructors_decl(os, clazz);
+	osprintf(os, "\n");
+	osprintf(os, "public:\n");
+	print_public_constructors_decl(os, clazz);
+	print_constructors_decl(os, clazz);
+	print_copy_assignment_decl(os, clazz);
+	print_destructor_decl(os, clazz);
+	print_ptr_decl(os, clazz);
+	print_get_ctx_decl(os);
+	osprintf(os, "\n");
+	print_methods_decl(os, clazz);
+
+	osprintf(os, "};\n");
+}
+
+/* Print forward declaration of class "clazz" to "os".
+ */
+void cpp_generator::print_class_forward_decl(ostream &os,
+	const isl_class &clazz)
+{
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "class %s;\n", cppname);
+}
+
+/* Print global factory functions to "os".
+ *
+ * Each class has two global factory functions:
+ *
+ * 	set manage(__isl_take isl_set *ptr);
+ * 	set manage_copy(__isl_keep isl_set *ptr);
+ *
+ * A user can construct isl C++ objects from a raw pointer and indicate whether
+ * they intend to take the ownership of the object or not through these global
+ * factory functions. This ensures isl object creation is very explicit and
+ * pointers are not converted by accident. Thanks to overloading, manage() and
+ * manage_copy() can be called on any isl raw pointer and the corresponding
+ * object is automatically created, without the user having to choose the right
+ * isl object type.
+ */
+void cpp_generator::print_class_factory_decl(ostream &os,
+	const isl_class &clazz, const std::string &prefix)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	os << prefix;
+	osprintf(os, "inline %s manage(__isl_take %s *ptr);\n", cppname, name);
+	os << prefix;
+	osprintf(os, "inline %s manage_copy(__isl_keep %s *ptr);\n",
+		cppname, name);
+}
+
+/* Print declarations of private constructors for class "clazz" to "os".
+ *
+ * Each class has currently one private constructor:
+ *
+ * 	1) Constructor from a plain isl_* C pointer
+ *
+ * Example:
+ *
+ * 	set(__isl_take isl_set *ptr);
+ *
+ * The raw pointer constructor is kept private. Object creation is only
+ * possible through manage() or manage_copy().
+ */
+void cpp_generator::print_private_constructors_decl(ostream &os,
+	const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "  inline explicit %s(__isl_take %s *ptr);\n", cppname,
+		 name);
+}
+
+/* Print declarations of public constructors for class "clazz" to "os".
+ *
+ * Each class currently has two public constructors:
+ *
+ * 	1) A default constructor
+ * 	2) A copy constructor
+ *
+ * Example:
+ *
+ *	set();
+ *	set(const set &set);
+ */
+void cpp_generator::print_public_constructors_decl(ostream &os,
+	const isl_class &clazz)
+{
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+	osprintf(os, "  inline /* implicit */ %s();\n", cppname);
+
+	osprintf(os, "  inline /* implicit */ %s(const %s &obj);\n",
+		 cppname, cppname);
+}
+
+/* Print declarations for constructors for class "class" to "os".
+ *
+ * For each isl function that is marked as __isl_constructor,
+ * add a corresponding C++ constructor.
+ *
+ * Example:
+ *
+ * 	inline /\* implicit *\/ union_set(basic_set bset);
+ * 	inline /\* implicit *\/ union_set(set set);
+ * 	inline explicit val(ctx ctx, long i);
+ * 	inline explicit val(ctx ctx, const std::string &str);
+ */
+void cpp_generator::print_constructors_decl(ostream &os,
+       const isl_class &clazz)
+{
+	set<FunctionDecl *>::const_iterator in;
+	const set<FunctionDecl *> &constructors = clazz.constructors;
+
+	for (in = constructors.begin(); in != constructors.end(); ++in) {
+		FunctionDecl *cons = *in;
+		string fullname = cons->getName();
+		function_kind kind = function_kind_constructor;
+
+		print_method_decl(os, clazz, fullname, cons, kind);
+	}
+}
+
+/* Print declarations of copy assignment operator for class "clazz"
+ * to "os".
+ *
+ * Each class has one assignment operator.
+ *
+ * 	isl:set &set::operator=(set obj)
+ *
+ */
+void cpp_generator::print_copy_assignment_decl(ostream &os,
+	const isl_class &clazz)
+{
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "  inline %s &operator=(%s obj);\n", cppname, cppname);
+}
+
+/* Print declaration of destructor for class "clazz" to "os".
+ */
+void cpp_generator::print_destructor_decl(ostream &os, const isl_class &clazz)
+{
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "  inline ~%s();\n", cppname);
+}
+
+/* Print declaration of pointer functions for class "clazz" to "os".
+ *
+ * To obtain a raw pointer three functions are provided:
+ *
+ * 	1) __isl_give isl_set *copy()
+ *
+ * 	  Returns a pointer to a _copy_ of the internal object
+ *
+ * 	2) __isl_keep isl_set *get()
+ *
+ * 	  Returns a pointer to the internal object
+ *
+ * 	3) __isl_give isl_set *release()
+ *
+ * 	  Returns a pointer to the internal object and resets the
+ * 	  internal pointer to nullptr.
+ *
+ * We also provide functionality to explicitly check if a pointer is
+ * currently managed by this object.
+ *
+ * 	4) bool is_null()
+ *
+ * 	  Check if the current object is a null pointer.
+ *
+ * The functions get() and release() model the value_ptr proposed in
+ * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3339.pdf.
+ * The copy() function is an extension to allow the user to explicitly
+ * copy the underlying object.
+ *
+ * Also generate a declaration to delete copy() for r-values, for
+ * r-values release() should be used to avoid unnecessary copies.
+ */
+void cpp_generator::print_ptr_decl(ostream &os, const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+
+	osprintf(os, "  inline __isl_give %s *copy() const &;\n", name);
+	osprintf(os, "  inline __isl_give %s *copy() && = delete;\n", name);
+	osprintf(os, "  inline __isl_keep %s *get() const;\n", name);
+	osprintf(os, "  inline __isl_give %s *release();\n", name);
+	osprintf(os, "  inline bool is_null() const;\n");
+}
+
+/* Print the declaration of the get_ctx method.
+ */
+void cpp_generator::print_get_ctx_decl(ostream &os)
+{
+	osprintf(os, "  inline ctx get_ctx() const;\n");
+}
+
+/* Print declarations for methods in class "clazz" to "os".
+ */
+void cpp_generator::print_methods_decl(ostream &os, const isl_class &clazz)
+{
+	map<string, set<FunctionDecl *> >::const_iterator it;
+
+	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
+		print_method_group_decl(os, clazz, it->first, it->second);
+}
+
+/* Print declarations for methods "methods" of name "fullname" in class "clazz"
+ * to "os".
+ *
+ * "fullname" is the name of the generated C++ method.  It commonly corresponds
+ * to the isl name, with the object type prefix dropped.
+ * In case of overloaded methods, the result type suffix has also been removed.
+ */
+void cpp_generator::print_method_group_decl(ostream &os, const isl_class &clazz,
+	const string &fullname, const set<FunctionDecl *> &methods)
+{
+	set<FunctionDecl *>::const_iterator it;
+
+	for (it = methods.begin(); it != methods.end(); ++it) {
+		function_kind kind = get_method_kind(clazz, *it);
+		print_method_decl(os, clazz, fullname, *it, kind);
+	}
+}
+
+/* Print declarations for "method" in class "clazz" to "os".
+ *
+ * "fullname" is the name of the generated C++ method.  It commonly corresponds
+ * to the isl name, with the object type prefix dropped.
+ * In case of overloaded methods, the result type suffix has also been removed.
+ *
+ * "kind" specifies the kind of method that should be generated.
+ */
+void cpp_generator::print_method_decl(ostream &os, const isl_class &clazz,
+	const string &fullname, FunctionDecl *method, function_kind kind)
+{
+	print_method_header(os, clazz, method, fullname, true, kind);
+}
+
+/* Print implementations for class "clazz" to "os".
+ */
+void cpp_generator::print_class_impl(ostream &os, const isl_class &clazz)
+{
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "// implementations for isl::%s\n", cppname);
+
+	print_class_factory_impl(os, clazz);
+	osprintf(os, "\n");
+	print_public_constructors_impl(os, clazz);
+	osprintf(os, "\n");
+	print_private_constructors_impl(os, clazz);
+	osprintf(os, "\n");
+	print_constructors_impl(os, clazz);
+	osprintf(os, "\n");
+	print_copy_assignment_impl(os, clazz);
+	osprintf(os, "\n");
+	print_destructor_impl(os, clazz);
+	osprintf(os, "\n");
+	print_ptr_impl(os, clazz);
+	osprintf(os, "\n");
+	print_get_ctx_impl(os, clazz);
+	osprintf(os, "\n");
+	print_methods_impl(os, clazz);
+}
+
+/* Print code for throwing an exception corresponding to the last error
+ * that occurred on "ctx".
+ * This assumes that a valid isl::ctx is available in the "ctx" variable,
+ * e.g., through a prior call to print_save_ctx.
+ */
+static void print_throw_last_error(ostream &os)
+{
+	osprintf(os, "    exception::throw_last_error(ctx);\n");
+}
+
+/* Print code for throwing an exception on NULL input.
+ */
+static void print_throw_NULL_input(ostream &os)
+{
+	osprintf(os, "    exception::throw_NULL_input(__FILE__, __LINE__);\n");
+}
+
+/* Print implementation of global factory functions to "os".
+ *
+ * Each class has two global factory functions:
+ *
+ * 	set manage(__isl_take isl_set *ptr);
+ * 	set manage_copy(__isl_keep isl_set *ptr);
+ *
+ * Unless checked C++ bindings are being generated,
+ * both functions require the argument to be non-NULL.
+ * An exception is thrown if anything went wrong during the copying
+ * in manage_copy.
+ * During the copying, isl is made not to print any error message
+ * because the error message is included in the exception.
+ */
+void cpp_generator::print_class_factory_impl(ostream &os,
+	const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "%s manage(__isl_take %s *ptr) {\n", cppname, name);
+	if (!checked) {
+		osprintf(os, "  if (!ptr)\n");
+		print_throw_NULL_input(os);
+	}
+	osprintf(os, "  return %s(ptr);\n", cppname);
+	osprintf(os, "}\n");
+
+	osprintf(os, "%s manage_copy(__isl_keep %s *ptr) {\n", cppname,
+		name);
+	if (!checked) {
+		osprintf(os, "  if (!ptr)\n");
+		print_throw_NULL_input(os);
+		osprintf(os, "  auto ctx = %s_get_ctx(ptr);\n", name);
+		print_on_error_continue(os);
+	}
+	osprintf(os, "  ptr = %s_copy(ptr);\n", name);
+	if (!checked) {
+		osprintf(os, "  if (!ptr)\n");
+		print_throw_last_error(os);
+	}
+	osprintf(os, "  return %s(ptr);\n", cppname);
+	osprintf(os, "}\n");
+}
+
+/* Print implementations of private constructors for class "clazz" to "os".
+ */
+void cpp_generator::print_private_constructors_impl(ostream &os,
+	const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "%s::%s(__isl_take %s *ptr)\n    : ptr(ptr) {}\n",
+		 cppname, cppname, name);
+}
+
+/* Print implementations of public constructors for class "clazz" to "os".
+ *
+ * Throw an exception from the copy constructor if anything went wrong
+ * during the copying or if the input is NULL.
+ * During the copying, isl is made not to print any error message
+ * because the error message is included in the exception.
+ * No exceptions are thrown if checked C++ bindings
+ * are being generated,
+ */
+void cpp_generator::print_public_constructors_impl(ostream &os,
+	const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "%s::%s()\n    : ptr(nullptr) {}\n\n", cppname, cppname);
+	osprintf(os, "%s::%s(const %s &obj)\n    : ptr(nullptr)\n",
+		 cppname, cppname, cppname);
+	osprintf(os, "{\n");
+	if (!checked) {
+		osprintf(os, "  if (!obj.ptr)\n");
+		print_throw_NULL_input(os);
+		osprintf(os, "  auto ctx = %s_get_ctx(obj.ptr);\n", name);
+		print_on_error_continue(os);
+	}
+	osprintf(os, "  ptr = obj.copy();\n");
+	if (!checked) {
+		osprintf(os, "  if (obj.ptr && !ptr)\n");
+		print_throw_last_error(os);
+	}
+	osprintf(os, "}\n");
+}
+
+/* Print implementations of constructors for class "clazz" to "os".
+ */
+void cpp_generator::print_constructors_impl(ostream &os,
+       const isl_class &clazz)
+{
+	set<FunctionDecl *>::const_iterator in;
+	const set<FunctionDecl *> constructors = clazz.constructors;
+
+	for (in = constructors.begin(); in != constructors.end(); ++in) {
+		FunctionDecl *cons = *in;
+		string fullname = cons->getName();
+		function_kind kind = function_kind_constructor;
+
+		print_method_impl(os, clazz, fullname, cons, kind);
+	}
+}
+
+/* Print implementation of copy assignment operator for class "clazz" to "os".
+ */
+void cpp_generator::print_copy_assignment_impl(ostream &os,
+	const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "%s &%s::operator=(%s obj) {\n", cppname,
+		 cppname, cppname);
+	osprintf(os, "  std::swap(this->ptr, obj.ptr);\n", name);
+	osprintf(os, "  return *this;\n");
+	osprintf(os, "}\n");
+}
+
+/* Print implementation of destructor for class "clazz" to "os".
+ */
+void cpp_generator::print_destructor_impl(ostream &os,
+	const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "%s::~%s() {\n", cppname, cppname);
+	osprintf(os, "  if (ptr)\n");
+	osprintf(os, "    %s_free(ptr);\n", name);
+	osprintf(os, "}\n");
+}
+
+/* Print implementation of ptr() functions for class "clazz" to "os".
+ */
+void cpp_generator::print_ptr_impl(ostream &os, const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "__isl_give %s *%s::copy() const & {\n", name, cppname);
+	osprintf(os, "  return %s_copy(ptr);\n", name);
+	osprintf(os, "}\n\n");
+	osprintf(os, "__isl_keep %s *%s::get() const {\n", name, cppname);
+	osprintf(os, "  return ptr;\n");
+	osprintf(os, "}\n\n");
+	osprintf(os, "__isl_give %s *%s::release() {\n", name, cppname);
+	osprintf(os, "  %s *tmp = ptr;\n", name);
+	osprintf(os, "  ptr = nullptr;\n");
+	osprintf(os, "  return tmp;\n");
+	osprintf(os, "}\n\n");
+	osprintf(os, "bool %s::is_null() const {\n", cppname);
+	osprintf(os, "  return ptr == nullptr;\n");
+	osprintf(os, "}\n");
+}
+
+/* Print the implementation of the get_ctx method.
+ */
+void cpp_generator::print_get_ctx_impl(ostream &os, const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	osprintf(os, "ctx %s::get_ctx() const {\n", cppname);
+	osprintf(os, "  return ctx(%s_get_ctx(ptr));\n", name);
+	osprintf(os, "}\n");
+}
+
+/* Print definitions for methods of class "clazz" to "os".
+ */
+void cpp_generator::print_methods_impl(ostream &os, const isl_class &clazz)
+{
+	map<string, set<FunctionDecl *> >::const_iterator it;
+	bool first = true;
+
+	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it) {
+		if (first)
+			first = false;
+		else
+			osprintf(os, "\n");
+		print_method_group_impl(os, clazz, it->first, it->second);
+	}
+}
+
+/* Print definitions for methods "methods" of name "fullname" in class "clazz"
+ * to "os".
+ *
+ * "fullname" is the name of the generated C++ method.  It commonly corresponds
+ * to the isl name, with the object type prefix dropped.
+ * In case of overloaded methods, the result type suffix has also been removed.
+ *
+ * "kind" specifies the kind of method that should be generated.
+ */
+void cpp_generator::print_method_group_impl(ostream &os, const isl_class &clazz,
+	const string &fullname, const set<FunctionDecl *> &methods)
+{
+	set<FunctionDecl *>::const_iterator it;
+	bool first = true;
+
+	for (it = methods.begin(); it != methods.end(); ++it) {
+		function_kind kind;
+		if (first)
+			first = false;
+		else
+			osprintf(os, "\n");
+		kind = get_method_kind(clazz, *it);
+		print_method_impl(os, clazz, fullname, *it, kind);
+	}
+}
+
+/* Print the use of "param" to "os".
+ *
+ * "load_from_this_ptr" specifies whether the parameter should be loaded from
+ * the this-ptr.  In case a value is loaded from a this pointer, the original
+ * value must be preserved and must consequently be copied.  Values that are
+ * loaded from parameters do not need to be preserved, as such values will
+ * already be copies of the actual parameters.  It is consequently possible
+ * to directly take the pointer from these values, which saves
+ * an unnecessary copy.
+ *
+ * In case the parameter is a callback function, two parameters get printed,
+ * a wrapper for the callback function and a pointer to the actual
+ * callback function.  The wrapper is expected to be available
+ * in a previously declared variable <name>_lambda, while
+ * the actual callback function is expected to be stored
+ * in a structure called <name>_data.
+ * The caller of this function must ensure that these variables exist.
+ */
+void cpp_generator::print_method_param_use(ostream &os, ParmVarDecl *param,
+	bool load_from_this_ptr)
+{
+	string name = param->getName().str();
+	const char *name_str = name.c_str();
+	QualType type = param->getOriginalType();
+
+	if (type->isIntegerType()) {
+		osprintf(os, "%s", name_str);
+		return;
+	}
+
+	if (is_string(type)) {
+		osprintf(os, "%s.c_str()", name_str);
+		return;
+	}
+
+	if (is_callback(type)) {
+		osprintf(os, "%s_lambda, ", name_str);
+		osprintf(os, "&%s_data", name_str);
+		return;
+	}
+
+	if (!load_from_this_ptr && !is_callback(type))
+		osprintf(os, "%s.", name_str);
+
+	if (keeps(param)) {
+		osprintf(os, "get()");
+	} else {
+		if (load_from_this_ptr)
+			osprintf(os, "copy()");
+		else
+			osprintf(os, "release()");
+	}
+}
+
+/* Print code that checks that all isl object arguments to "method" are valid
+ * (not NULL) and throws an exception if they are not.
+ * "kind" specifies the kind of method that is being generated.
+ *
+ * If checked bindings are being generated,
+ * then no such check is performed.
+ */
+void cpp_generator::print_argument_validity_check(ostream &os,
+	FunctionDecl *method, function_kind kind)
+{
+	int n;
+	bool first = true;
+
+	if (checked)
+		return;
+
+	n = method->getNumParams();
+	for (int i = 0; i < n; ++i) {
+		bool is_this;
+		ParmVarDecl *param = method->getParamDecl(i);
+		string name = param->getName().str();
+		const char *name_str = name.c_str();
+		QualType type = param->getOriginalType();
+
+		is_this = i == 0 && kind == function_kind_member_method;
+		if (!is_this && (is_isl_ctx(type) || !is_isl_type(type)))
+			continue;
+
+		if (first)
+			osprintf(os, "  if (");
+		else
+			osprintf(os, " || ");
+
+		if (is_this)
+			osprintf(os, "!ptr");
+		else
+			osprintf(os, "%s.is_null()", name_str);
+
+		first = false;
+	}
+	if (first)
+		return;
+	osprintf(os, ")\n");
+	print_throw_NULL_input(os);
+}
+
+/* Print code for saving a copy of the isl::ctx available at the start
+ * of the method "method" in a "ctx" variable, for use in exception handling.
+ * "kind" specifies what kind of method "method" is.
+ *
+ * If checked bindings are being generated,
+ * then the "ctx" variable is not needed.
+ * If "method" is a member function, then obtain the isl_ctx from
+ * the "this" object.
+ * If the first argument of the method is an isl::ctx, then use that one,
+ * assuming it is not already called "ctx".
+ * Otherwise, save a copy of the isl::ctx associated to the first argument
+ * of isl object type.
+ */
+void cpp_generator::print_save_ctx(ostream &os, FunctionDecl *method,
+	function_kind kind)
+{
+	int n;
+	ParmVarDecl *param = method->getParamDecl(0);
+	QualType type = param->getOriginalType();
+
+	if (checked)
+		return;
+	if (kind == function_kind_member_method) {
+		osprintf(os, "  auto ctx = get_ctx();\n");
+		return;
+	}
+	if (is_isl_ctx(type)) {
+		const char *name;
+
+		name = param->getName().str().c_str();
+		if (strcmp(name, "ctx") != 0)
+			osprintf(os, "  auto ctx = %s;\n", name);
+		return;
+	}
+	n = method->getNumParams();
+	for (int i = 0; i < n; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		QualType type = param->getOriginalType();
+
+		if (!is_isl_type(type))
+			continue;
+		osprintf(os, "  auto ctx = %s.get_ctx();\n",
+			param->getName().str().c_str());
+		return;
+	}
+}
+
+/* Print code to make isl not print an error message when an error occurs
+ * within the current scope (if exceptions are available),
+ * since the error message will be included in the exception.
+ * If exceptions are not available, then exception::on_error
+ * is set to ISL_ON_ERROR_ABORT and isl is therefore made to abort instead.
+ *
+ * If checked bindings are being generated,
+ * then leave it to the user to decide what isl should do on error.
+ * Otherwise, assume that a valid isl::ctx is available in the "ctx" variable,
+ * e.g., through a prior call to print_save_ctx.
+ */
+void cpp_generator::print_on_error_continue(ostream &os)
+{
+	if (checked)
+		return;
+	osprintf(os, "  options_scoped_set_on_error saved_on_error(ctx, "
+		     "exception::on_error);\n");
+}
+
+/* Print code that checks whether the execution of the core of "method"
+ * was successful.
+ *
+ * If checked bindings are being generated,
+ * then no checks are performed.
+ *
+ * Otherwise, first check if any of the callbacks failed with
+ * an exception.  If so, the "eptr" in the corresponding data structure
+ * contains the exception that was caught and that needs to be rethrown.
+ * Then check if the function call failed in any other way and throw
+ * the appropriate exception.
+ * In particular, if the return type is isl_stat or isl_bool,
+ * then a negative value indicates a failure.  If the return type
+ * is an isl type, then a NULL value indicates a failure.
+ * Assume print_save_ctx has made sure that a valid isl::ctx
+ * is available in the "ctx" variable.
+ */
+void cpp_generator::print_exceptional_execution_check(ostream &os,
+	FunctionDecl *method)
+{
+	int n;
+	bool check_null, check_neg;
+	QualType return_type = method->getReturnType();
+
+	if (checked)
+		return;
+
+	n = method->getNumParams();
+	for (int i = 0; i < n; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		const char *name;
+
+		if (!is_callback(param->getOriginalType()))
+			continue;
+		name = param->getName().str().c_str();
+		osprintf(os, "  if (%s_data.eptr)\n", name);
+		osprintf(os, "    std::rethrow_exception(%s_data.eptr);\n",
+			name);
+	}
+
+	check_neg = is_isl_stat(return_type) || is_isl_bool(return_type);
+	check_null = is_isl_type(return_type);
+	if (!check_null && !check_neg)
+		return;
+
+	if (check_neg)
+		osprintf(os, "  if (res < 0)\n");
+	else
+		osprintf(os, "  if (!res)\n");
+	print_throw_last_error(os);
+}
+
+/* Print definition for "method" in class "clazz" to "os".
+ *
+ * "fullname" is the name of the generated C++ method.  It commonly corresponds
+ * to the isl name, with the object type prefix dropped.
+ * In case of overloaded methods, the result type suffix has also been removed.
+ *
+ * "kind" specifies the kind of method that should be generated.
+ *
+ * This method distinguishes three kinds of methods: member methods, static
+ * methods, and constructors.
+ *
+ * Member methods call "method" by passing to the underlying isl function the
+ * isl object belonging to "this" as first argument and the remaining arguments
+ * as subsequent arguments. The result of the isl function is returned as a new
+ * object if the underlying isl function returns an isl_* ptr, as a bool
+ * if the isl function returns an isl_bool, as void if the isl functions
+ * returns an isl_stat,
+ * as std::string if the isl function returns 'const char *', and as
+ * unmodified return value otherwise.
+ * If checked C++ bindings are being generated,
+ * then an isl_bool return type is transformed into a boolean and
+ * an isl_stat into a stat since no exceptions can be generated
+ * on negative results from the isl function.
+ *
+ * Static methods call "method" by passing all arguments to the underlying isl
+ * function, as no this-pointer is available. The result is a newly managed
+ * isl C++ object.
+ *
+ * Constructors create a new object from a given set of input parameters. They
+ * do not return a value, but instead update the pointer stored inside the
+ * newly created object.
+ *
+ * If the method has a callback argument, we reduce the number of parameters
+ * that are exposed by one to hide the user pointer from the interface. On
+ * the C++ side no user pointer is needed, as arguments can be forwarded
+ * as part of the std::function argument which specifies the callback function.
+ *
+ * Unless checked C++ bindings are being generated,
+ * the inputs of the method are first checked for being valid isl objects and
+ * a copy of the associated isl::ctx is saved (if needed).
+ * If any failure occurs, either during the check for the inputs or
+ * during the isl function call, an exception is thrown.
+ * During the function call, isl is made not to print any error message
+ * because the error message is included in the exception.
+ */
+void cpp_generator::print_method_impl(ostream &os, const isl_class &clazz,
+	const string &fullname, FunctionDecl *method, function_kind kind)
+{
+	string methodname = method->getName();
+	int num_params = method->getNumParams();
+	QualType return_type = method->getReturnType();
+	string rettype_str = type2cpp(return_type);
+	bool has_callback = false;
+
+	print_method_header(os, clazz, method, fullname, false, kind);
+	osprintf(os, "{\n");
+	print_argument_validity_check(os, method, kind);
+	print_save_ctx(os, method, kind);
+	print_on_error_continue(os);
+
+	for (int i = 0; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		if (is_callback(param->getType())) {
+			has_callback = true;
+			num_params -= 1;
+			print_callback_local(os, param);
+		}
+	}
+
+	osprintf(os, "  auto res = %s(", methodname.c_str());
+
+	for (int i = 0; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		bool load_from_this_ptr = false;
+
+		if (i == 0 && kind == function_kind_member_method)
+			load_from_this_ptr = true;
+
+		print_method_param_use(os, param, load_from_this_ptr);
+
+		if (i != num_params - 1)
+			osprintf(os, ", ");
+	}
+	osprintf(os, ");\n");
+
+	print_exceptional_execution_check(os, method);
+	if (kind == function_kind_constructor) {
+		osprintf(os, "  ptr = res;\n");
+	} else if (is_isl_type(return_type) ||
+		    (checked &&
+		     (is_isl_bool(return_type) || is_isl_stat(return_type)))) {
+		osprintf(os, "  return manage(res);\n");
+	} else if (has_callback) {
+		osprintf(os, "  return %s(res);\n", rettype_str.c_str());
+	} else if (is_string(return_type)) {
+		osprintf(os, "  std::string tmp(res);\n");
+		if (gives(method))
+			osprintf(os, "  free(res);\n");
+		osprintf(os, "  return tmp;\n");
+	} else {
+		osprintf(os, "  return res;\n");
+	}
+
+	osprintf(os, "}\n");
+}
+
+/* Print the header for "method" in class "clazz" to "os".
+ *
+ * Print the header of a declaration if "is_declaration" is set, otherwise print
+ * the header of a method definition.
+ *
+ * "fullname" is the name of the generated C++ method.  It commonly corresponds
+ * to the isl name, with the object type prefix dropped.
+ * In case of overloaded methods, the result type suffix has also been removed.
+ *
+ * "kind" specifies the kind of method that should be generated.
+ *
+ * This function prints headers for member methods, static methods, and
+ * constructors, either for their declaration or definition.
+ *
+ * Member functions are declared as "const", as they do not change the current
+ * object, but instead create a new object. They always retrieve the first
+ * parameter of the original isl function from the this-pointer of the object,
+ * such that only starting at the second parameter the parameters of the
+ * original function become part of the method's interface.
+ *
+ * A function
+ *
+ * 	__isl_give isl_set *isl_set_intersect(__isl_take isl_set *s1,
+ * 		__isl_take isl_set *s2);
+ *
+ * is translated into:
+ *
+ * 	inline set intersect(set set2) const;
+ *
+ * For static functions and constructors all parameters of the original isl
+ * function are exposed.
+ *
+ * Parameters that are defined as __isl_keep or are of type string, are passed
+ * as const reference, which allows the compiler to optimize the parameter
+ * transfer.
+ *
+ * Constructors are marked as explicit using the C++ keyword 'explicit' or as
+ * implicit using a comment in place of the explicit keyword. By annotating
+ * implicit constructors with a comment, users of the interface are made
+ * aware of the potential danger that implicit construction is possible
+ * for these constructors, whereas without a comment not every user would
+ * know that implicit construction is allowed in absence of an explicit keyword.
+ */
+void cpp_generator::print_method_header(ostream &os, const isl_class &clazz,
+	FunctionDecl *method, const string &fullname, bool is_declaration,
+	function_kind kind)
+{
+	string cname = fullname.substr(clazz.name.length() + 1);
+	string rettype_str = type2cpp(method->getReturnType());
+	string classname = type2cpp(clazz);
+	int num_params = method->getNumParams();
+	int first_param = 0;
+
+	cname = rename_method(cname);
+	if (kind == function_kind_member_method)
+		first_param = 1;
+
+	if (is_declaration) {
+		osprintf(os, "  ");
+
+		if (kind == function_kind_static_method)
+			osprintf(os, "static ");
+
+		osprintf(os, "inline ");
+
+		if (kind == function_kind_constructor) {
+			if (is_implicit_conversion(clazz, method))
+				osprintf(os, "/* implicit */ ");
+			else
+				osprintf(os, "explicit ");
+		}
+	}
+
+	if (kind != function_kind_constructor)
+		osprintf(os, "%s ", rettype_str.c_str());
+
+	if (!is_declaration)
+		osprintf(os, "%s::", classname.c_str());
+
+	if (kind != function_kind_constructor)
+		osprintf(os, "%s", cname.c_str());
+	else
+		osprintf(os, "%s", classname.c_str());
+
+	osprintf(os, "(");
+
+	for (int i = first_param; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		string cpptype = type2cpp(type);
+
+		if (is_callback(type))
+			num_params--;
+
+		if (keeps(param) || is_string(type) || is_callback(type))
+			osprintf(os, "const %s &%s", cpptype.c_str(),
+				 param->getName().str().c_str());
+		else
+			osprintf(os, "%s %s", cpptype.c_str(),
+				 param->getName().str().c_str());
+
+		if (i != num_params - 1)
+			osprintf(os, ", ");
+	}
+
+	osprintf(os, ")");
+
+	if (kind == function_kind_member_method)
+		osprintf(os, " const");
+
+	if (is_declaration)
+		osprintf(os, ";");
+	osprintf(os, "\n");
+}
+
+/* Generate the list of argument types for a callback function of
+ * type "type".  If "cpp" is set, then generate the C++ type list, otherwise
+ * the C type list.
+ *
+ * For a callback of type
+ *
+ *      isl_stat (*)(__isl_take isl_map *map, void *user)
+ *
+ * the following C++ argument list is generated:
+ *
+ *      map
+ */
+string cpp_generator::generate_callback_args(QualType type, bool cpp)
+{
+	std::string type_str;
+	const FunctionProtoType *callback;
+	int num_params;
+
+	callback = type->getPointeeType()->getAs<FunctionProtoType>();
+	num_params = callback->getNumArgs();
+	if (cpp)
+		num_params--;
+
+	for (long i = 0; i < num_params; i++) {
+		QualType type = callback->getArgType(i);
+
+		if (cpp)
+			type_str += type2cpp(type);
+		else
+			type_str += type.getAsString();
+
+		if (!cpp)
+			type_str += "arg_" + ::to_string(i);
+
+		if (i != num_params - 1)
+			type_str += ", ";
+	}
+
+	return type_str;
+}
+
+/* Generate the full cpp type of a callback function of type "type".
+ *
+ * For a callback of type
+ *
+ *      isl_stat (*)(__isl_take isl_map *map, void *user)
+ *
+ * the following type is generated:
+ *
+ *      std::function<stat(map)>
+ */
+string cpp_generator::generate_callback_type(QualType type)
+{
+	std::string type_str;
+	const FunctionProtoType *callback = type->getPointeeType()->getAs<FunctionProtoType>();
+	QualType return_type = callback->getReturnType();
+	string rettype_str = type2cpp(return_type);
+
+	type_str = "std::function<";
+	type_str += rettype_str;
+	type_str += "(";
+	type_str += generate_callback_args(type, true);
+	type_str += ")>";
+
+	return type_str;
+}
+
+/* Print the call to the C++ callback function "call", wrapped
+ * for use inside the lambda function that is used as the C callback function,
+ * in the case where checked C++ bindings are being generated.
+ *
+ * In particular, print
+ *
+ *        stat ret = @call@;
+ *        return ret.release();
+ */
+void cpp_generator::print_wrapped_call_checked(ostream &os,
+	const string &call)
+{
+	osprintf(os, "    stat ret = %s;\n", call.c_str());
+	osprintf(os, "    return ret.release();\n");
+}
+
+/* Print the call to the C++ callback function "call", wrapped
+ * for use inside the lambda function that is used as the C callback function.
+ *
+ * In particular, print
+ *
+ *        ISL_CPP_TRY {
+ *          @call@;
+ *          return isl_stat_ok;
+ *        } ISL_CPP_CATCH_ALL {
+ *          data->eptr = std::current_exception();
+ *          return isl_stat_error;
+ *        }
+ *
+ * where ISL_CPP_TRY is defined to "try" and ISL_CPP_CATCH_ALL to "catch (...)"
+ * (if exceptions are available).
+ *
+ * If checked C++ bindings are being generated, then
+ * the call is wrapped differently.
+ */
+void cpp_generator::print_wrapped_call(ostream &os, const string &call)
+{
+	if (checked)
+		return print_wrapped_call_checked(os, call);
+
+	osprintf(os, "    ISL_CPP_TRY {\n");
+	osprintf(os, "      %s;\n", call.c_str());
+	osprintf(os, "      return isl_stat_ok;\n");
+	osprintf(os, "    } ISL_CPP_CATCH_ALL {\n"
+		     "      data->eptr = std::current_exception();\n");
+	osprintf(os, "      return isl_stat_error;\n");
+	osprintf(os, "    }\n");
+}
+
+/* Print the local variables that are needed for a callback argument,
+ * in particular, print a lambda function that wraps the callback and
+ * a pointer to the actual C++ callback function.
+ *
+ * For a callback of the form
+ *
+ *      isl_stat (*fn)(__isl_take isl_map *map, void *user)
+ *
+ * the following lambda function is generated:
+ *
+ *      auto fn_lambda = [](isl_map *arg_0, void *arg_1) -> isl_stat {
+ *        auto *data = static_cast<struct fn_data *>(arg_1);
+ *        try {
+ *          stat ret = (*data->func)(manage(arg_0));
+ *          return isl_stat_ok;
+ *        } catch (...) {
+ *          data->eptr = std::current_exception();
+ *          return isl_stat_error;
+ *        }
+ *      };
+ *
+ * The pointer to the std::function C++ callback function is stored in
+ * a fn_data data structure for passing to the C callback function,
+ * along with an std::exception_ptr that is used to store any
+ * exceptions thrown in the C++ callback.
+ *
+ *      struct fn_data {
+ *        const std::function<stat(map)> *func;
+ *        std::exception_ptr eptr;
+ *      } fn_data = { &fn };
+ *
+ * This std::function object represents the actual user
+ * callback function together with the locally captured state at the caller.
+ *
+ * The lambda function is expected to be used as a C callback function
+ * where the lambda itself is provided as the function pointer and
+ * where the user void pointer is a pointer to fn_data.
+ * The std::function object is extracted from the pointer to fn_data
+ * inside the lambda function.
+ *
+ * The std::exception_ptr object is not added to fn_data
+ * if checked C++ bindings are being generated.
+ * The body of the generated lambda function then is as follows:
+ *
+ *        stat ret = (*data->func)(manage(arg_0));
+ *        return isl_stat(ret);
+ */
+void cpp_generator::print_callback_local(ostream &os, ParmVarDecl *param)
+{
+	string pname;
+	QualType ptype;
+	string call, c_args, cpp_args, rettype, last_idx;
+	const FunctionProtoType *callback;
+	int num_params;
+
+	pname = param->getName().str();
+	ptype = param->getType();
+
+	c_args = generate_callback_args(ptype, false);
+	cpp_args = generate_callback_type(ptype);
+
+	callback = ptype->getPointeeType()->getAs<FunctionProtoType>();
+	rettype = callback->getReturnType().getAsString();
+	num_params = callback->getNumArgs();
+
+	last_idx = ::to_string(num_params - 1);
+
+	call = "(*data->func)(";
+	for (long i = 0; i < num_params - 1; i++) {
+		call += "manage(arg_" + ::to_string(i) + ")";
+		if (i != num_params - 2)
+			call += ", ";
+	}
+	call += ")";
+
+	osprintf(os, "  struct %s_data {\n", pname.c_str());
+	osprintf(os, "    const %s *func;\n", cpp_args.c_str());
+	if (!checked)
+		osprintf(os, "    std::exception_ptr eptr;\n");
+	osprintf(os, "  } %s_data = { &%s };\n", pname.c_str(), pname.c_str());
+	osprintf(os, "  auto %s_lambda = [](%s) -> %s {\n",
+		 pname.c_str(), c_args.c_str(), rettype.c_str());
+	osprintf(os,
+		 "    auto *data = static_cast<struct %s_data *>(arg_%s);\n",
+		 pname.c_str(), last_idx.c_str());
+	print_wrapped_call(os, call);
+	osprintf(os, "  };\n");
+}
+
+/* An array listing functions that must be renamed and the function name they
+ * should be renamed to. We currently rename functions in case their name would
+ * match a reserved C++ keyword, which is not allowed in C++.
+ */
+static const char *rename_map[][2] = {
+	{ "union", "unite" },
+};
+
+/* Rename method "name" in case the method name in the C++ bindings should not
+ * match the name in the C bindings. We do this for example to avoid
+ * C++ keywords.
+ */
+std::string cpp_generator::rename_method(std::string name)
+{
+	for (size_t i = 0; i < sizeof(rename_map) / sizeof(rename_map[0]); i++)
+		if (name.compare(rename_map[i][0]) == 0)
+			return rename_map[i][1];
+
+	return name;
+}
+
+/* Translate isl class "clazz" to its corresponding C++ type.
+ */
+string cpp_generator::type2cpp(const isl_class &clazz)
+{
+	return type2cpp(clazz.name);
+}
+
+/* Translate type string "type_str" to its C++ name counterpart.
+*/
+string cpp_generator::type2cpp(string type_str)
+{
+	return type_str.substr(4);
+}
+
+/* Translate QualType "type" to its C++ name counterpart.
+ *
+ * An isl_bool return type is translated into "bool",
+ * while an isl_stat is translated into "void".
+ * The exceptional cases are handled through exceptions.
+ * If checked C++ bindings are being generated, then
+ * C++ counterparts of isl_bool and isl_stat need to be used instead.
+ */
+string cpp_generator::type2cpp(QualType type)
+{
+	if (is_isl_type(type))
+		return type2cpp(type->getPointeeType().getAsString());
+
+	if (is_isl_bool(type))
+		return checked ? "boolean" : "bool";
+
+	if (is_isl_stat(type))
+		return checked ? "stat" : "void";
+
+	if (type->isIntegerType())
+		return type.getAsString();
+
+	if (is_string(type))
+		return "std::string";
+
+	if (is_callback(type))
+		return generate_callback_type(type);
+
+	die("Cannot convert type to C++ type");
+}
+
+/* Check if "subclass_type" is a subclass of "class_type".
+ */
+bool cpp_generator::is_subclass(QualType subclass_type,
+	const isl_class &class_type)
+{
+	std::string type_str = subclass_type->getPointeeType().getAsString();
+	std::vector<std::string> superclasses;
+	std::vector<const isl_class *> parents;
+	std::vector<std::string>::iterator ci;
+
+	superclasses = generator::find_superclasses(classes[type_str].type);
+
+	for (ci = superclasses.begin(); ci < superclasses.end(); ci++)
+		parents.push_back(&classes[*ci]);
+
+	while (!parents.empty()) {
+		const isl_class *candidate = parents.back();
+
+		parents.pop_back();
+
+		if (&class_type == candidate)
+			return true;
+
+		superclasses = generator::find_superclasses(candidate->type);
+
+		for (ci = superclasses.begin(); ci < superclasses.end(); ci++)
+			parents.push_back(&classes[*ci]);
+	}
+
+	return false;
+}
+
+/* Check if "cons" is an implicit conversion constructor of class "clazz".
+ *
+ * An implicit conversion constructor is generated in case "cons" has a single
+ * parameter, where the parameter type is a subclass of the class that is
+ * currently being generated.
+ */
+bool cpp_generator::is_implicit_conversion(const isl_class &clazz,
+	FunctionDecl *cons)
+{
+	ParmVarDecl *param = cons->getParamDecl(0);
+	QualType type = param->getOriginalType();
+
+	int num_params = cons->getNumParams();
+	if (num_params != 1)
+		return false;
+
+	if (is_isl_type(type) && !is_isl_ctx(type) && is_subclass(type, clazz))
+		return true;
+
+	return false;
+}
+
+/* Get kind of "method" in "clazz".
+ *
+ * Given the declaration of a static or member method, returns its kind.
+ */
+cpp_generator::function_kind cpp_generator::get_method_kind(
+	const isl_class &clazz, FunctionDecl *method)
+{
+	if (is_static(clazz, method))
+		return function_kind_static_method;
+	else
+		return function_kind_member_method;
+}
diff --git a/lib/External/isl/interface/cpp.h b/lib/External/isl/interface/cpp.h
new file mode 100644
index 0000000..32a378d
--- /dev/null
+++ b/lib/External/isl/interface/cpp.h
@@ -0,0 +1,97 @@
+#include "generator.h"
+
+using namespace std;
+using namespace clang;
+
+/* Generator for C++ bindings.
+ *
+ * "checked" is set if C++ bindings should be generated
+ * that rely on the user to check for error conditions.
+ */
+class cpp_generator : public generator {
+protected:
+	bool checked;
+public:
+	cpp_generator(set<RecordDecl *> &exported_types,
+		set<FunctionDecl *> exported_functions,
+		set<FunctionDecl *> functions,
+		bool checked = false) :
+		generator(exported_types, exported_functions, functions),
+		checked(checked) {}
+
+	enum function_kind {
+		function_kind_static_method,
+		function_kind_member_method,
+		function_kind_constructor,
+	};
+
+	virtual void generate();
+private:
+	void print_file(ostream &os, std::string filename);
+	void print_forward_declarations(ostream &os);
+	void print_declarations(ostream &os);
+	void print_class(ostream &os, const isl_class &clazz);
+	void print_class_forward_decl(ostream &os, const isl_class &clazz);
+	void print_class_factory_decl(ostream &os, const isl_class &clazz,
+		const std::string &prefix = std::string());
+	void print_private_constructors_decl(ostream &os,
+		const isl_class &clazz);
+	void print_copy_assignment_decl(ostream &os, const isl_class &clazz);
+	void print_public_constructors_decl(ostream &os,
+		const isl_class &clazz);
+	void print_constructors_decl(ostream &os, const isl_class &clazz);
+	void print_destructor_decl(ostream &os, const isl_class &clazz);
+	void print_ptr_decl(ostream &os, const isl_class &clazz);
+	void print_get_ctx_decl(ostream &os);
+	void print_methods_decl(ostream &os, const isl_class &clazz);
+	void print_method_group_decl(ostream &os, const isl_class &clazz,
+		const string &fullname, const set<FunctionDecl *> &methods);
+	void print_method_decl(ostream &os, const isl_class &clazz,
+		const string &fullname, FunctionDecl *method,
+		function_kind kind);
+	void print_implementations(ostream &os);
+	void print_class_impl(ostream &os, const isl_class &clazz);
+	void print_class_factory_impl(ostream &os, const isl_class &clazz);
+	void print_private_constructors_impl(ostream &os,
+		const isl_class &clazz);
+	void print_public_constructors_impl(ostream &os,
+		const isl_class &clazz);
+	void print_constructors_impl(ostream &os, const isl_class &clazz);
+	void print_copy_assignment_impl(ostream &os, const isl_class &clazz);
+	void print_destructor_impl(ostream &os, const isl_class &clazz);
+	void print_ptr_impl(ostream &os, const isl_class &clazz);
+	void print_get_ctx_impl(ostream &os, const isl_class &clazz);
+	void print_methods_impl(ostream &os, const isl_class &clazz);
+	void print_method_group_impl(ostream &os, const isl_class &clazz,
+		const string &fullname, const set<FunctionDecl *> &methods);
+	void print_argument_validity_check(ostream &os, FunctionDecl *method,
+		function_kind kind);
+	void print_save_ctx(ostream &os, FunctionDecl *method,
+		function_kind kind);
+	void print_on_error_continue(ostream &os);
+	void print_exceptional_execution_check(ostream &os,
+		FunctionDecl *method);
+	void print_method_impl(ostream &os, const isl_class &clazz,
+		const string &fullname,	FunctionDecl *method,
+		function_kind kind);
+	void print_method_param_use(ostream &os, ParmVarDecl *param,
+		bool load_from_this_ptr);
+	void print_method_header(ostream &os, const isl_class &clazz,
+		FunctionDecl *method, const string &fullname,
+		bool is_declaration, function_kind kind);
+	string generate_callback_args(QualType type, bool cpp);
+	string generate_callback_type(QualType type);
+	void print_wrapped_call_checked(std::ostream &os,
+		const std::string &call);
+	void print_wrapped_call(std::ostream &os, const std::string &call);
+	void print_callback_local(ostream &os, ParmVarDecl *param);
+	std::string rename_method(std::string name);
+	string type2cpp(const isl_class &clazz);
+	string type2cpp(QualType type);
+	bool is_implicit_conversion(const isl_class &clazz, FunctionDecl *cons);
+	bool is_subclass(QualType subclass_type, const isl_class &class_type);
+	function_kind get_method_kind(const isl_class &clazz,
+		FunctionDecl *method);
+public:
+	static string type2cpp(string type_string);
+};
diff --git a/lib/External/isl/interface/cpp_conversion.cc b/lib/External/isl/interface/cpp_conversion.cc
new file mode 100644
index 0000000..abdfcaf
--- /dev/null
+++ b/lib/External/isl/interface/cpp_conversion.cc
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2018      Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege.
+ */
+
+#include "cpp.h"
+#include "cpp_conversion.h"
+
+/* Print a function called "function" for converting objects of
+ * type "name" from the "from" bindings to the "to" bindings.
+ */
+static void convert(const char *name, const char *from, const char *to,
+	const char *function)
+{
+	printf("%s%s %s(%s%s obj) {\n", to, name, function, from, name);
+	printf("\t""return %s""manage(obj.copy());\n", to);
+	printf("}\n");
+	printf("\n");
+}
+
+/* Print functions for converting objects of "clazz"
+ * between the default and the checked C++ bindings.
+ *
+ * The conversion from default to checked is called "check".
+ * The inverse conversion is called "uncheck".
+ * For example, to "set", the following two functions are generated:
+ *
+ *	checked::set check(set obj) {
+ *		return checked::manage(obj.copy());
+ *	}
+ *
+ *	set uncheck(checked::set obj) {
+ *		return manage(obj.copy());
+ *	}
+ */
+static void print(const isl_class &clazz)
+{
+	string name = cpp_generator::type2cpp(clazz.name);
+
+	convert(name.c_str(), "", "checked::", "check");
+	convert(name.c_str(), "checked::", "", "uncheck");
+}
+
+/* Generate conversion functions for converting objects between
+ * the default and the checked C++ bindings.
+ * Do this for each exported class.
+ */
+void cpp_conversion_generator::generate()
+{
+	map<string, isl_class>::iterator ci;
+
+	printf("namespace isl {\n\n");
+	for (ci = classes.begin(); ci != classes.end(); ++ci)
+		print(ci->second);
+	printf("} // namespace isl\n");
+}
diff --git a/lib/External/isl/interface/cpp_conversion.h b/lib/External/isl/interface/cpp_conversion.h
new file mode 100644
index 0000000..8e10db7
--- /dev/null
+++ b/lib/External/isl/interface/cpp_conversion.h
@@ -0,0 +1,10 @@
+#include "generator.h"
+
+class cpp_conversion_generator : public generator {
+public:
+	cpp_conversion_generator(set<RecordDecl *> &exported_types,
+		set<FunctionDecl *> exported_functions,
+		set<FunctionDecl *> functions) :
+		generator(exported_types, exported_functions, functions) {}
+	virtual void generate();
+};
diff --git a/lib/External/isl/interface/extract_interface.cc b/lib/External/isl/interface/extract_interface.cc
new file mode 100644
index 0000000..51e2387
--- /dev/null
+++ b/lib/External/isl/interface/extract_interface.cc
@@ -0,0 +1,486 @@
+/*
+ * Copyright 2011 Sven Verdoolaege. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as
+ * representing official policies, either expressed or implied, of
+ * Sven Verdoolaege.
+ */ 
+
+#include "isl_config.h"
+
+#include <assert.h>
+#include <iostream>
+#include <stdlib.h>
+#ifdef HAVE_ADT_OWNINGPTR_H
+#include <llvm/ADT/OwningPtr.h>
+#else
+#include <memory>
+#endif
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Support/Host.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <clang/AST/ASTContext.h>
+#include <clang/AST/ASTConsumer.h>
+#include <clang/Basic/FileSystemOptions.h>
+#include <clang/Basic/FileManager.h>
+#include <clang/Basic/TargetOptions.h>
+#include <clang/Basic/TargetInfo.h>
+#include <clang/Basic/Version.h>
+#include <clang/Driver/Compilation.h>
+#include <clang/Driver/Driver.h>
+#include <clang/Driver/Tool.h>
+#include <clang/Frontend/CompilerInstance.h>
+#include <clang/Frontend/CompilerInvocation.h>
+#ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
+#include <clang/Basic/DiagnosticOptions.h>
+#else
+#include <clang/Frontend/DiagnosticOptions.h>
+#endif
+#include <clang/Frontend/TextDiagnosticPrinter.h>
+#include <clang/Frontend/Utils.h>
+#include <clang/Lex/HeaderSearch.h>
+#ifdef HAVE_LEX_PREPROCESSOROPTIONS_H
+#include <clang/Lex/PreprocessorOptions.h>
+#else
+#include <clang/Frontend/PreprocessorOptions.h>
+#endif
+#include <clang/Lex/Preprocessor.h>
+#include <clang/Parse/ParseAST.h>
+#include <clang/Sema/Sema.h>
+
+#include "extract_interface.h"
+#include "generator.h"
+#include "python.h"
+#include "cpp.h"
+#include "cpp_conversion.h"
+
+using namespace std;
+using namespace clang;
+using namespace clang::driver;
+
+#ifdef HAVE_ADT_OWNINGPTR_H
+#define unique_ptr	llvm::OwningPtr
+#endif
+
+static llvm::cl::opt<string> InputFilename(llvm::cl::Positional,
+			llvm::cl::Required, llvm::cl::desc("<input file>"));
+static llvm::cl::list<string> Includes("I",
+			llvm::cl::desc("Header search path"),
+			llvm::cl::value_desc("path"), llvm::cl::Prefix);
+
+static llvm::cl::opt<string> Language(llvm::cl::Required,
+	llvm::cl::ValueRequired, "language",
+	llvm::cl::desc("Bindings to generate"),
+	llvm::cl::value_desc("name"));
+
+static const char *ResourceDir =
+	CLANG_PREFIX "/lib/clang/" CLANG_VERSION_STRING;
+
+/* Does decl have an attribute of the following form?
+ *
+ *	__attribute__((annotate("name")))
+ */
+bool has_annotation(Decl *decl, const char *name)
+{
+	if (!decl->hasAttrs())
+		return false;
+
+	AttrVec attrs = decl->getAttrs();
+	for (AttrVec::const_iterator i = attrs.begin() ; i != attrs.end(); ++i) {
+		const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
+		if (!ann)
+			continue;
+		if (ann->getAnnotation().str() == name)
+			return true;
+	}
+
+	return false;
+}
+
+/* Is decl marked as exported?
+ */
+static bool is_exported(Decl *decl)
+{
+	return has_annotation(decl, "isl_export");
+}
+
+/* Collect all types and functions that are annotated "isl_export"
+ * in "exported_types" and "exported_function".  Collect all function
+ * declarations in "functions".
+ *
+ * We currently only consider single declarations.
+ */
+struct MyASTConsumer : public ASTConsumer {
+	set<RecordDecl *> exported_types;
+	set<FunctionDecl *> exported_functions;
+	set<FunctionDecl *> functions;
+
+	virtual HandleTopLevelDeclReturn HandleTopLevelDecl(DeclGroupRef D) {
+		Decl *decl;
+
+		if (!D.isSingleDecl())
+			return HandleTopLevelDeclContinue;
+		decl = D.getSingleDecl();
+		if (isa<FunctionDecl>(decl))
+			functions.insert(cast<FunctionDecl>(decl));
+		if (!is_exported(decl))
+			return HandleTopLevelDeclContinue;
+		switch (decl->getKind()) {
+		case Decl::Record:
+			exported_types.insert(cast<RecordDecl>(decl));
+			break;
+		case Decl::Function:
+			exported_functions.insert(cast<FunctionDecl>(decl));
+			break;
+		default:
+			break;
+		}
+		return HandleTopLevelDeclContinue;
+	}
+};
+
+#ifdef USE_ARRAYREF
+
+#ifdef HAVE_CXXISPRODUCTION
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
+			    "", false, false, Diags);
+}
+#elif defined(HAVE_ISPRODUCTION)
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
+			    "", false, Diags);
+}
+#elif defined(DRIVER_CTOR_TAKES_DEFAULTIMAGENAME)
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
+			    "", Diags);
+}
+#else
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+	return new Driver(binary, llvm::sys::getDefaultTargetTriple(), Diags);
+}
+#endif
+
+namespace clang { namespace driver { class Job; } }
+
+/* Clang changed its API from 3.5 to 3.6 and once more in 3.7.
+ * We fix this with a simple overloaded function here.
+ */
+struct ClangAPI {
+	static Job *command(Job *J) { return J; }
+	static Job *command(Job &J) { return &J; }
+	static Command *command(Command &C) { return &C; }
+};
+
+/* Create a CompilerInvocation object that stores the command line
+ * arguments constructed by the driver.
+ * The arguments are mainly useful for setting up the system include
+ * paths on newer clangs and on some platforms.
+ */
+static CompilerInvocation *construct_invocation(const char *filename,
+	DiagnosticsEngine &Diags)
+{
+	const char *binary = CLANG_PREFIX"/bin/clang";
+	const unique_ptr<Driver> driver(construct_driver(binary, Diags));
+	std::vector<const char *> Argv;
+	Argv.push_back(binary);
+	Argv.push_back(filename);
+	const unique_ptr<Compilation> compilation(
+		driver->BuildCompilation(llvm::ArrayRef<const char *>(Argv)));
+	JobList &Jobs = compilation->getJobs();
+
+	Command *cmd = cast<Command>(ClangAPI::command(*Jobs.begin()));
+	if (strcmp(cmd->getCreator().getName(), "clang"))
+		return NULL;
+
+	const ArgStringList *args = &cmd->getArguments();
+
+	CompilerInvocation *invocation = new CompilerInvocation;
+	CompilerInvocation::CreateFromArgs(*invocation, args->data() + 1,
+						args->data() + args->size(),
+						Diags);
+	return invocation;
+}
+
+#else
+
+static CompilerInvocation *construct_invocation(const char *filename,
+	DiagnosticsEngine &Diags)
+{
+	return NULL;
+}
+
+#endif
+
+#ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
+
+static TextDiagnosticPrinter *construct_printer(void)
+{
+	return new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
+}
+
+#else
+
+static TextDiagnosticPrinter *construct_printer(void)
+{
+	DiagnosticOptions DO;
+	return new TextDiagnosticPrinter(llvm::errs(), DO);
+}
+
+#endif
+
+#ifdef CREATETARGETINFO_TAKES_SHARED_PTR
+
+static TargetInfo *create_target_info(CompilerInstance *Clang,
+	DiagnosticsEngine &Diags)
+{
+	shared_ptr<TargetOptions> TO = Clang->getInvocation().TargetOpts;
+	TO->Triple = llvm::sys::getDefaultTargetTriple();
+	return TargetInfo::CreateTargetInfo(Diags, TO);
+}
+
+#elif defined(CREATETARGETINFO_TAKES_POINTER)
+
+static TargetInfo *create_target_info(CompilerInstance *Clang,
+	DiagnosticsEngine &Diags)
+{
+	TargetOptions &TO = Clang->getTargetOpts();
+	TO.Triple = llvm::sys::getDefaultTargetTriple();
+	return TargetInfo::CreateTargetInfo(Diags, &TO);
+}
+
+#else
+
+static TargetInfo *create_target_info(CompilerInstance *Clang,
+	DiagnosticsEngine &Diags)
+{
+	TargetOptions &TO = Clang->getTargetOpts();
+	TO.Triple = llvm::sys::getDefaultTargetTriple();
+	return TargetInfo::CreateTargetInfo(Diags, TO);
+}
+
+#endif
+
+#ifdef CREATEDIAGNOSTICS_TAKES_ARG
+
+static void create_diagnostics(CompilerInstance *Clang)
+{
+	Clang->createDiagnostics(0, NULL, construct_printer());
+}
+
+#else
+
+static void create_diagnostics(CompilerInstance *Clang)
+{
+	Clang->createDiagnostics(construct_printer());
+}
+
+#endif
+
+#ifdef CREATEPREPROCESSOR_TAKES_TUKIND
+
+static void create_preprocessor(CompilerInstance *Clang)
+{
+	Clang->createPreprocessor(TU_Complete);
+}
+
+#else
+
+static void create_preprocessor(CompilerInstance *Clang)
+{
+	Clang->createPreprocessor();
+}
+
+#endif
+
+#ifdef ADDPATH_TAKES_4_ARGUMENTS
+
+void add_path(HeaderSearchOptions &HSO, string Path)
+{
+	HSO.AddPath(Path, frontend::Angled, false, false);
+}
+
+#else
+
+void add_path(HeaderSearchOptions &HSO, string Path)
+{
+	HSO.AddPath(Path, frontend::Angled, true, false, false);
+}
+
+#endif
+
+#ifdef HAVE_SETMAINFILEID
+
+static void create_main_file_id(SourceManager &SM, const FileEntry *file)
+{
+	SM.setMainFileID(SM.createFileID(file, SourceLocation(),
+					SrcMgr::C_User));
+}
+
+#else
+
+static void create_main_file_id(SourceManager &SM, const FileEntry *file)
+{
+	SM.createMainFileID(file);
+}
+
+#endif
+
+#ifdef SETLANGDEFAULTS_TAKES_5_ARGUMENTS
+
+static void set_lang_defaults(CompilerInstance *Clang)
+{
+	PreprocessorOptions &PO = Clang->getPreprocessorOpts();
+	TargetOptions &TO = Clang->getTargetOpts();
+	llvm::Triple T(TO.Triple);
+	CompilerInvocation::setLangDefaults(Clang->getLangOpts(), IK_C, T, PO,
+					    LangStandard::lang_unspecified);
+}
+
+#else
+
+static void set_lang_defaults(CompilerInstance *Clang)
+{
+	CompilerInvocation::setLangDefaults(Clang->getLangOpts(), IK_C,
+					    LangStandard::lang_unspecified);
+}
+
+#endif
+
+#ifdef SETINVOCATION_TAKES_SHARED_PTR
+
+static void set_invocation(CompilerInstance *Clang,
+	CompilerInvocation *invocation)
+{
+	Clang->setInvocation(std::make_shared<CompilerInvocation>(*invocation));
+}
+
+#else
+
+static void set_invocation(CompilerInstance *Clang,
+	CompilerInvocation *invocation)
+{
+	Clang->setInvocation(invocation);
+}
+
+#endif
+
+/* Create an interface generator for the selected language and
+ * then use it to generate the interface.
+ */
+static void generate(MyASTConsumer &consumer)
+{
+	generator *gen;
+
+	if (Language.compare("python") == 0) {
+		gen = new python_generator(consumer.exported_types,
+			consumer.exported_functions, consumer.functions);
+	} else if (Language.compare("cpp") == 0) {
+		gen = new cpp_generator(consumer.exported_types,
+			consumer.exported_functions, consumer.functions);
+	} else if (Language.compare("cpp-checked") == 0) {
+		gen = new cpp_generator(consumer.exported_types,
+			consumer.exported_functions, consumer.functions, true);
+	} else if (Language.compare("cpp-checked-conversion") == 0) {
+		gen = new cpp_conversion_generator(consumer.exported_types,
+			consumer.exported_functions, consumer.functions);
+	} else {
+		cerr << "Language '" << Language << "' not recognized." << endl
+		     << "Not generating bindings." << endl;
+		exit(EXIT_FAILURE);
+	}
+
+	gen->generate();
+}
+
+int main(int argc, char *argv[])
+{
+	llvm::cl::ParseCommandLineOptions(argc, argv);
+
+	CompilerInstance *Clang = new CompilerInstance();
+	create_diagnostics(Clang);
+	DiagnosticsEngine &Diags = Clang->getDiagnostics();
+	Diags.setSuppressSystemWarnings(true);
+	CompilerInvocation *invocation =
+		construct_invocation(InputFilename.c_str(), Diags);
+	if (invocation)
+		set_invocation(Clang, invocation);
+	Clang->createFileManager();
+	Clang->createSourceManager(Clang->getFileManager());
+	TargetInfo *target = create_target_info(Clang, Diags);
+	Clang->setTarget(target);
+	set_lang_defaults(Clang);
+	HeaderSearchOptions &HSO = Clang->getHeaderSearchOpts();
+	LangOptions &LO = Clang->getLangOpts();
+	PreprocessorOptions &PO = Clang->getPreprocessorOpts();
+	HSO.ResourceDir = ResourceDir;
+
+	for (llvm::cl::list<string>::size_type i = 0; i < Includes.size(); ++i)
+		add_path(HSO, Includes[i]);
+
+	PO.addMacroDef("__isl_give=__attribute__((annotate(\"isl_give\")))");
+	PO.addMacroDef("__isl_keep=__attribute__((annotate(\"isl_keep\")))");
+	PO.addMacroDef("__isl_take=__attribute__((annotate(\"isl_take\")))");
+	PO.addMacroDef("__isl_export=__attribute__((annotate(\"isl_export\")))");
+	PO.addMacroDef("__isl_overload="
+	    "__attribute__((annotate(\"isl_overload\"))) "
+	    "__attribute__((annotate(\"isl_export\")))");
+	PO.addMacroDef("__isl_constructor=__attribute__((annotate(\"isl_constructor\"))) __attribute__((annotate(\"isl_export\")))");
+	PO.addMacroDef("__isl_subclass(super)=__attribute__((annotate(\"isl_subclass(\" #super \")\"))) __attribute__((annotate(\"isl_export\")))");
+
+	create_preprocessor(Clang);
+	Preprocessor &PP = Clang->getPreprocessor();
+
+	PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), LO);
+
+	const FileEntry *file = Clang->getFileManager().getFile(InputFilename);
+	assert(file);
+	create_main_file_id(Clang->getSourceManager(), file);
+
+	Clang->createASTContext();
+	MyASTConsumer consumer;
+	Sema *sema = new Sema(PP, Clang->getASTContext(), consumer);
+
+	Diags.getClient()->BeginSourceFile(LO, &PP);
+	ParseAST(*sema);
+	Diags.getClient()->EndSourceFile();
+
+	generate(consumer);
+
+	delete sema;
+	delete Clang;
+	llvm::llvm_shutdown();
+
+	return EXIT_SUCCESS;
+}
diff --git a/lib/External/isl/interface/extract_interface.h b/lib/External/isl/interface/extract_interface.h
new file mode 100644
index 0000000..b6788f1
--- /dev/null
+++ b/lib/External/isl/interface/extract_interface.h
@@ -0,0 +1,3 @@
+#include <clang/AST/Decl.h>
+
+bool has_annotation(clang::Decl *decl, const char *name);
diff --git a/lib/External/isl/interface/generator.cc b/lib/External/isl/interface/generator.cc
new file mode 100644
index 0000000..01704f8
--- /dev/null
+++ b/lib/External/isl/interface/generator.cc
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2011,2015 Sven Verdoolaege. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as
+ * representing official policies, either expressed or implied, of
+ * Sven Verdoolaege.
+ */
+
+#include <stdio.h>
+#include <iostream>
+
+#include <clang/AST/Attr.h>
+
+#include "isl_config.h"
+#include "extract_interface.h"
+#include "generator.h"
+
+/* Should "method" be considered to be a static method?
+ * That is, is the first argument something other than
+ * an instance of the class?
+ */
+bool generator::is_static(const isl_class &clazz, FunctionDecl *method)
+{
+	ParmVarDecl *param = method->getParamDecl(0);
+	QualType type = param->getOriginalType();
+
+	if (!is_isl_type(type))
+		return true;
+	return extract_type(type) != clazz.name;
+}
+
+/* Find the FunctionDecl with name "name",
+ * returning NULL if there is no such FunctionDecl.
+ * If "required" is set, then error out if no FunctionDecl can be found.
+ */
+FunctionDecl *generator::find_by_name(const string &name, bool required)
+{
+	map<string, FunctionDecl *>::iterator i;
+
+	i = functions_by_name.find(name);
+	if (i != functions_by_name.end())
+		return i->second;
+	if (required)
+		die("No " + name + " function found");
+	return NULL;
+}
+
+/* Collect all functions that belong to a certain type, separating
+ * constructors from regular methods and keeping track of the _to_str,
+ * _copy and _free functions, if any, separately.  If there are any overloaded
+ * functions, then they are grouped based on their name after removing the
+ * argument type suffix.
+ */
+generator::generator(set<RecordDecl *> &exported_types,
+	set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions)
+{
+	map<string, isl_class>::iterator ci;
+
+	set<FunctionDecl *>::iterator in;
+	for (in = functions.begin(); in != functions.end(); ++in) {
+		FunctionDecl *decl = *in;
+		functions_by_name[decl->getName()] = decl;
+	}
+
+	set<RecordDecl *>::iterator it;
+	for (it = exported_types.begin(); it != exported_types.end(); ++it) {
+		RecordDecl *decl = *it;
+		string name = decl->getName();
+		classes[name].name = name;
+		classes[name].type = decl;
+		classes[name].fn_to_str = find_by_name(name + "_to_str", false);
+		classes[name].fn_copy = find_by_name(name + "_copy", true);
+		classes[name].fn_free = find_by_name(name + "_free", true);
+	}
+
+	for (in = exported_functions.begin(); in != exported_functions.end();
+	     ++in) {
+		isl_class *c = method2class(*in);
+		if (!c)
+			continue;
+		if (is_constructor(*in)) {
+			c->constructors.insert(*in);
+		} else {
+			FunctionDecl *method = *in;
+			string fullname = method->getName();
+			fullname = drop_type_suffix(fullname, method);
+			c->methods[fullname].insert(method);
+		}
+	}
+}
+
+/* Print error message "msg" and abort.
+ */
+void generator::die(const char *msg)
+{
+	fprintf(stderr, "%s\n", msg);
+	abort();
+}
+
+/* Print error message "msg" and abort.
+ */
+void generator::die(string msg)
+{
+	die(msg.c_str());
+}
+
+/* Return a sequence of the types of which the given type declaration is
+ * marked as being a subtype.
+ * The order of the types is the opposite of the order in which they
+ * appear in the source.  In particular, the first annotation
+ * is the one that is closest to the annotated type and the corresponding
+ * type is then also the first that will appear in the sequence of types.
+ */
+std::vector<string> generator::find_superclasses(RecordDecl *decl)
+{
+	vector<string> super;
+
+	if (!decl->hasAttrs())
+		return super;
+
+	string sub = "isl_subclass";
+	size_t len = sub.length();
+	AttrVec attrs = decl->getAttrs();
+	for (AttrVec::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
+		const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
+		if (!ann)
+			continue;
+		string s = ann->getAnnotation().str();
+		if (s.substr(0, len) == sub) {
+			s = s.substr(len + 1, s.length() - len  - 2);
+			super.push_back(s);
+		}
+	}
+
+	return super;
+}
+
+/* Is decl marked as being part of an overloaded method?
+ */
+bool generator::is_overload(Decl *decl)
+{
+	return has_annotation(decl, "isl_overload");
+}
+
+/* Is decl marked as a constructor?
+ */
+bool generator::is_constructor(Decl *decl)
+{
+	return has_annotation(decl, "isl_constructor");
+}
+
+/* Is decl marked as consuming a reference?
+ */
+bool generator::takes(Decl *decl)
+{
+	return has_annotation(decl, "isl_take");
+}
+
+/* Is decl marked as preserving a reference?
+ */
+bool generator::keeps(Decl *decl)
+{
+	return has_annotation(decl, "isl_keep");
+}
+
+/* Is decl marked as returning a reference that is required to be freed.
+ */
+bool generator::gives(Decl *decl)
+{
+	return has_annotation(decl, "isl_give");
+}
+
+/* Return the class that has a name that matches the initial part
+ * of the name of function "fd" or NULL if no such class could be found.
+ */
+isl_class *generator::method2class(FunctionDecl *fd)
+{
+	string best;
+	map<string, isl_class>::iterator ci;
+	string name = fd->getNameAsString();
+
+	for (ci = classes.begin(); ci != classes.end(); ++ci) {
+		if (name.substr(0, ci->first.length()) == ci->first)
+			best = ci->first;
+	}
+
+	if (classes.find(best) == classes.end()) {
+		cerr << "Unable to find class of " << name << endl;
+		return NULL;
+	}
+
+	return &classes[best];
+}
+
+/* Is "type" the type "isl_ctx *"?
+ */
+bool generator::is_isl_ctx(QualType type)
+{
+	if (!type->isPointerType())
+		return 0;
+	type = type->getPointeeType();
+	if (type.getAsString() != "isl_ctx")
+		return false;
+
+	return true;
+}
+
+/* Is the first argument of "fd" of type "isl_ctx *"?
+ */
+bool generator::first_arg_is_isl_ctx(FunctionDecl *fd)
+{
+	ParmVarDecl *param;
+
+	if (fd->getNumParams() < 1)
+		return false;
+
+	param = fd->getParamDecl(0);
+	return is_isl_ctx(param->getOriginalType());
+}
+
+/* Is "type" that of a pointer to an isl_* structure?
+ */
+bool generator::is_isl_type(QualType type)
+{
+	if (type->isPointerType()) {
+		string s;
+
+		type = type->getPointeeType();
+		if (type->isFunctionType())
+			return false;
+		s = type.getAsString();
+		return s.substr(0, 4) == "isl_";
+	}
+
+	return false;
+}
+
+/* Is "type" the type isl_bool?
+ */
+bool generator::is_isl_bool(QualType type)
+{
+	string s;
+
+	if (type->isPointerType())
+		return false;
+
+	s = type.getAsString();
+	return s == "isl_bool";
+}
+
+/* Is "type" the type isl_stat?
+ */
+bool generator::is_isl_stat(QualType type)
+{
+	string s;
+
+	if (type->isPointerType())
+		return false;
+
+	s = type.getAsString();
+	return s == "isl_stat";
+}
+
+
+/* Is "type" that of a pointer to a function?
+ */
+bool generator::is_callback(QualType type)
+{
+	if (!type->isPointerType())
+		return false;
+	type = type->getPointeeType();
+	return type->isFunctionType();
+}
+
+/* Is "type" that of "char *" of "const char *"?
+ */
+bool generator::is_string(QualType type)
+{
+	if (type->isPointerType()) {
+		string s = type->getPointeeType().getAsString();
+		return s == "const char" || s == "char";
+	}
+
+	return false;
+}
+
+/* Is "type" that of "long"?
+ */
+bool generator::is_long(QualType type)
+{
+	const BuiltinType *builtin = type->getAs<BuiltinType>();
+	return builtin && builtin->getKind() == BuiltinType::Long;
+}
+
+/* Return the name of the type that "type" points to.
+ * The input "type" is assumed to be a pointer type.
+ */
+string generator::extract_type(QualType type)
+{
+	if (type->isPointerType())
+		return type->getPointeeType().getAsString();
+	die("Cannot extract type from non-pointer type");
+}
+
+/* If "method" is overloaded, then drop the suffix of "name"
+ * corresponding to the type of the final argument and
+ * return the modified name (or the original name if
+ * no modifications were made).
+ */
+string generator::drop_type_suffix(string name, FunctionDecl *method)
+{
+	int num_params;
+	ParmVarDecl *param;
+	string type;
+	size_t name_len, type_len;
+
+	if (!is_overload(method))
+		return name;
+
+	num_params = method->getNumParams();
+	param = method->getParamDecl(num_params - 1);
+	type = extract_type(param->getOriginalType());
+	type = type.substr(4);
+	name_len = name.length();
+	type_len = type.length();
+
+	if (name_len > type_len && name.substr(name_len - type_len) == type)
+		name = name.substr(0, name_len - type_len - 1);
+
+	return name;
+}
diff --git a/lib/External/isl/interface/generator.h b/lib/External/isl/interface/generator.h
new file mode 100644
index 0000000..6376084
--- /dev/null
+++ b/lib/External/isl/interface/generator.h
@@ -0,0 +1,72 @@
+#ifndef ISL_INTERFACE_GENERATOR_H
+#define ISL_INTERFACE_GENERATOR_H
+
+#include <map>
+#include <set>
+#include <string>
+
+#include <clang/AST/Decl.h>
+
+using namespace std;
+using namespace clang;
+
+/* isl_class collects all constructors and methods for an isl "class".
+ * "name" is the name of the class.
+ * "type" is the declaration that introduces the type.
+ * "methods" contains the set of methods, grouped by method name.
+ * "fn_to_str" is a reference to the *_to_str method of this class, if any.
+ * "fn_copy" is a reference to the *_copy method of this class, if any.
+ * "fn_free" is a reference to the *_free method of this class, if any.
+ */
+struct isl_class {
+	string name;
+	RecordDecl *type;
+	set<FunctionDecl *> constructors;
+	map<string, set<FunctionDecl *> > methods;
+	FunctionDecl *fn_to_str;
+	FunctionDecl *fn_copy;
+	FunctionDecl *fn_free;
+};
+
+/* Base class for interface generators.
+ */
+class generator {
+protected:
+	map<string,isl_class> classes;
+	map<string, FunctionDecl *> functions_by_name;
+
+public:
+	generator(set<RecordDecl *> &exported_types,
+		set<FunctionDecl *> exported_functions,
+		set<FunctionDecl *> functions);
+
+	virtual void generate() = 0;
+	virtual ~generator() {};
+
+protected:
+	void print_class_header(const isl_class &clazz, const string &name,
+		const vector<string> &super);
+	string drop_type_suffix(string name, FunctionDecl *method);
+	void die(const char *msg) __attribute__((noreturn));
+	void die(string msg) __attribute__((noreturn));
+	vector<string> find_superclasses(RecordDecl *decl);
+	bool is_overload(Decl *decl);
+	bool is_constructor(Decl *decl);
+	bool takes(Decl *decl);
+	bool keeps(Decl *decl);
+	bool gives(Decl *decl);
+	isl_class *method2class(FunctionDecl *fd);
+	bool is_isl_ctx(QualType type);
+	bool first_arg_is_isl_ctx(FunctionDecl *fd);
+	bool is_isl_type(QualType type);
+	bool is_isl_bool(QualType type);
+	bool is_isl_stat(QualType type);
+	bool is_long(QualType type);
+	bool is_callback(QualType type);
+	bool is_string(QualType type);
+	bool is_static(const isl_class &clazz, FunctionDecl *method);
+	string extract_type(QualType type);
+	FunctionDecl *find_by_name(const string &name, bool required);
+};
+
+#endif /* ISL_INTERFACE_GENERATOR_H */
diff --git a/lib/External/isl/interface/isl.py b/lib/External/isl/interface/isl.py
new file mode 100644
index 0000000..b660772
--- /dev/null
+++ b/lib/External/isl/interface/isl.py
@@ -0,0 +1,5655 @@
+from ctypes import *
+
+isl = cdll.LoadLibrary("libisl.so")
+libc = cdll.LoadLibrary("libc.so.6")
+
+class Error(Exception):
+    pass
+
+class Context:
+    defaultInstance = None
+
+    def __init__(self):
+        ptr = isl.isl_ctx_alloc()
+        self.ptr = ptr
+
+    def __del__(self):
+        isl.isl_ctx_free(self)
+
+    def from_param(self):
+        return c_void_p(self.ptr)
+
+    @staticmethod
+    def getDefaultInstance():
+        if Context.defaultInstance == None:
+            Context.defaultInstance = Context()
+        return Context.defaultInstance
+
+isl.isl_ctx_alloc.restype = c_void_p
+isl.isl_ctx_free.argtypes = [Context]
+
+class union_pw_multi_aff(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is pw_multi_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_pw_multi_aff_from_pw_multi_aff(isl.isl_pw_multi_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_pw_multi_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        if len(args) == 1 and args[0].__class__ is union_pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_pw_multi_aff_from_union_pw_aff(isl.isl_union_pw_aff_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_union_pw_multi_aff_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        ptr = isl.isl_union_pw_multi_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.union_pw_multi_aff("""%s""")' % s
+        else:
+            return 'isl.union_pw_multi_aff("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_pw_multi_aff:
+                arg1 = union_pw_multi_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_add(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
+        return union_pw_multi_aff(ctx=ctx, ptr=res)
+    def flat_range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_pw_multi_aff:
+                arg1 = union_pw_multi_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_flat_range_product(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
+        return union_pw_multi_aff(ctx=ctx, ptr=res)
+    def pullback(arg0, arg1):
+        if arg1.__class__ is union_pw_multi_aff:
+            res = isl.isl_union_pw_multi_aff_pullback_union_pw_multi_aff(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
+            return union_pw_multi_aff(ctx=arg0.ctx, ptr=res)
+    def union_add(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_pw_multi_aff:
+                arg1 = union_pw_multi_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_union_add(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
+        return union_pw_multi_aff(ctx=ctx, ptr=res)
+
+isl.isl_union_pw_multi_aff_from_pw_multi_aff.restype = c_void_p
+isl.isl_union_pw_multi_aff_from_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_read_from_str.restype = c_void_p
+isl.isl_union_pw_multi_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_union_pw_multi_aff_from_union_pw_aff.restype = c_void_p
+isl.isl_union_pw_multi_aff_from_union_pw_aff.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_add.restype = c_void_p
+isl.isl_union_pw_multi_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_flat_range_product.restype = c_void_p
+isl.isl_union_pw_multi_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_pullback_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_pw_multi_aff_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_union_add.restype = c_void_p
+isl.isl_union_pw_multi_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_copy.restype = c_void_p
+isl.isl_union_pw_multi_aff_copy.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_free.restype = c_void_p
+isl.isl_union_pw_multi_aff_free.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_to_str.restype = POINTER(c_char)
+isl.isl_union_pw_multi_aff_to_str.argtypes = [c_void_p]
+
+class multi_union_pw_aff(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is union_pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_union_pw_aff_from_union_pw_aff(isl.isl_union_pw_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is multi_pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_union_pw_aff_from_multi_pw_aff(isl.isl_multi_pw_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_union_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_multi_union_pw_aff_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
+        except:
+            raise
+        ptr = isl.isl_multi_union_pw_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.multi_union_pw_aff("""%s""")' % s
+        else:
+            return 'isl.multi_union_pw_aff("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_add(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        return multi_union_pw_aff(ctx=ctx, ptr=res)
+    def flat_range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_flat_range_product(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        return multi_union_pw_aff(ctx=ctx, ptr=res)
+    def pullback(arg0, arg1):
+        if arg1.__class__ is union_pw_multi_aff:
+            res = isl.isl_multi_union_pw_aff_pullback_union_pw_multi_aff(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
+            return multi_union_pw_aff(ctx=arg0.ctx, ptr=res)
+    def range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_range_product(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        return multi_union_pw_aff(ctx=ctx, ptr=res)
+    def union_add(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_union_add(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        return multi_union_pw_aff(ctx=ctx, ptr=res)
+
+isl.isl_multi_union_pw_aff_from_union_pw_aff.restype = c_void_p
+isl.isl_multi_union_pw_aff_from_union_pw_aff.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_from_multi_pw_aff.restype = c_void_p
+isl.isl_multi_union_pw_aff_from_multi_pw_aff.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_read_from_str.restype = c_void_p
+isl.isl_multi_union_pw_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_multi_union_pw_aff_add.restype = c_void_p
+isl.isl_multi_union_pw_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_flat_range_product.restype = c_void_p
+isl.isl_multi_union_pw_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_pullback_union_pw_multi_aff.restype = c_void_p
+isl.isl_multi_union_pw_aff_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_range_product.restype = c_void_p
+isl.isl_multi_union_pw_aff_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_union_add.restype = c_void_p
+isl.isl_multi_union_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_copy.restype = c_void_p
+isl.isl_multi_union_pw_aff_copy.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_free.restype = c_void_p
+isl.isl_multi_union_pw_aff_free.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_to_str.restype = POINTER(c_char)
+isl.isl_multi_union_pw_aff_to_str.argtypes = [c_void_p]
+
+class union_pw_aff(union_pw_multi_aff, multi_union_pw_aff):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_pw_aff_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_union_pw_aff_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
+        except:
+            raise
+        ptr = isl.isl_union_pw_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.union_pw_aff("""%s""")' % s
+        else:
+            return 'isl.union_pw_aff("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_pw_aff:
+                arg1 = union_pw_aff(arg1)
+        except:
+            return union_pw_multi_aff(arg0).add(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_add(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_aff_copy(arg1.ptr))
+        return union_pw_aff(ctx=ctx, ptr=res)
+    def pullback(arg0, arg1):
+        if arg1.__class__ is union_pw_multi_aff:
+            res = isl.isl_union_pw_aff_pullback_union_pw_multi_aff(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
+            return union_pw_aff(ctx=arg0.ctx, ptr=res)
+    def union_add(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_pw_aff:
+                arg1 = union_pw_aff(arg1)
+        except:
+            return union_pw_multi_aff(arg0).union_add(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_union_add(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_aff_copy(arg1.ptr))
+        return union_pw_aff(ctx=ctx, ptr=res)
+
+isl.isl_union_pw_aff_from_pw_aff.restype = c_void_p
+isl.isl_union_pw_aff_from_pw_aff.argtypes = [c_void_p]
+isl.isl_union_pw_aff_read_from_str.restype = c_void_p
+isl.isl_union_pw_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_union_pw_aff_add.restype = c_void_p
+isl.isl_union_pw_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_pullback_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_pw_aff_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_union_add.restype = c_void_p
+isl.isl_union_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_copy.restype = c_void_p
+isl.isl_union_pw_aff_copy.argtypes = [c_void_p]
+isl.isl_union_pw_aff_free.restype = c_void_p
+isl.isl_union_pw_aff_free.argtypes = [c_void_p]
+isl.isl_union_pw_aff_to_str.restype = POINTER(c_char)
+isl.isl_union_pw_aff_to_str.argtypes = [c_void_p]
+
+class multi_pw_aff(multi_union_pw_aff):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is multi_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_pw_aff_from_multi_aff(isl.isl_multi_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_pw_aff_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is pw_multi_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_pw_aff_from_pw_multi_aff(isl.isl_pw_multi_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_multi_pw_aff_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
+        except:
+            raise
+        ptr = isl.isl_multi_pw_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.multi_pw_aff("""%s""")' % s
+        else:
+            return 'isl.multi_pw_aff("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
+        except:
+            return multi_union_pw_aff(arg0).add(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_pw_aff_add(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+        return multi_pw_aff(ctx=ctx, ptr=res)
+    def flat_range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
+        except:
+            return multi_union_pw_aff(arg0).flat_range_product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_pw_aff_flat_range_product(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+        return multi_pw_aff(ctx=ctx, ptr=res)
+    def product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
+        except:
+            return multi_union_pw_aff(arg0).product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_pw_aff_product(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+        return multi_pw_aff(ctx=ctx, ptr=res)
+    def pullback(arg0, arg1):
+        if arg1.__class__ is multi_aff:
+            res = isl.isl_multi_pw_aff_pullback_multi_aff(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+            return multi_pw_aff(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is pw_multi_aff:
+            res = isl.isl_multi_pw_aff_pullback_pw_multi_aff(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+            return multi_pw_aff(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is multi_pw_aff:
+            res = isl.isl_multi_pw_aff_pullback_multi_pw_aff(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+            return multi_pw_aff(ctx=arg0.ctx, ptr=res)
+    def range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
+        except:
+            return multi_union_pw_aff(arg0).range_product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_pw_aff_range_product(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+        return multi_pw_aff(ctx=ctx, ptr=res)
+
+isl.isl_multi_pw_aff_from_multi_aff.restype = c_void_p
+isl.isl_multi_pw_aff_from_multi_aff.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_from_pw_aff.restype = c_void_p
+isl.isl_multi_pw_aff_from_pw_aff.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_from_pw_multi_aff.restype = c_void_p
+isl.isl_multi_pw_aff_from_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_read_from_str.restype = c_void_p
+isl.isl_multi_pw_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_multi_pw_aff_add.restype = c_void_p
+isl.isl_multi_pw_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_flat_range_product.restype = c_void_p
+isl.isl_multi_pw_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_product.restype = c_void_p
+isl.isl_multi_pw_aff_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_multi_pw_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_pullback_pw_multi_aff.restype = c_void_p
+isl.isl_multi_pw_aff_pullback_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_pullback_multi_pw_aff.restype = c_void_p
+isl.isl_multi_pw_aff_pullback_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_range_product.restype = c_void_p
+isl.isl_multi_pw_aff_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_copy.restype = c_void_p
+isl.isl_multi_pw_aff_copy.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_free.restype = c_void_p
+isl.isl_multi_pw_aff_free.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_to_str.restype = POINTER(c_char)
+isl.isl_multi_pw_aff_to_str.argtypes = [c_void_p]
+
+class pw_multi_aff(union_pw_multi_aff, multi_pw_aff):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is multi_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_multi_aff_from_multi_aff(isl.isl_multi_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_multi_aff_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_multi_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_pw_multi_aff_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
+        except:
+            raise
+        ptr = isl.isl_pw_multi_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.pw_multi_aff("""%s""")' % s
+        else:
+            return 'isl.pw_multi_aff("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
+        except:
+            return union_pw_multi_aff(arg0).add(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_add(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        return pw_multi_aff(ctx=ctx, ptr=res)
+    def flat_range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
+        except:
+            return union_pw_multi_aff(arg0).flat_range_product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_flat_range_product(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        return pw_multi_aff(ctx=ctx, ptr=res)
+    def product(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
+        except:
+            return union_pw_multi_aff(arg0).product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_product(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        return pw_multi_aff(ctx=ctx, ptr=res)
+    def pullback(arg0, arg1):
+        if arg1.__class__ is multi_aff:
+            res = isl.isl_pw_multi_aff_pullback_multi_aff(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+            return pw_multi_aff(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is pw_multi_aff:
+            res = isl.isl_pw_multi_aff_pullback_pw_multi_aff(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+            return pw_multi_aff(ctx=arg0.ctx, ptr=res)
+    def range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
+        except:
+            return union_pw_multi_aff(arg0).range_product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_range_product(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        return pw_multi_aff(ctx=ctx, ptr=res)
+    def union_add(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
+        except:
+            return union_pw_multi_aff(arg0).union_add(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_union_add(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        return pw_multi_aff(ctx=ctx, ptr=res)
+
+isl.isl_pw_multi_aff_from_multi_aff.restype = c_void_p
+isl.isl_pw_multi_aff_from_multi_aff.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_from_pw_aff.restype = c_void_p
+isl.isl_pw_multi_aff_from_pw_aff.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_read_from_str.restype = c_void_p
+isl.isl_pw_multi_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_pw_multi_aff_add.restype = c_void_p
+isl.isl_pw_multi_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_flat_range_product.restype = c_void_p
+isl.isl_pw_multi_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_product.restype = c_void_p
+isl.isl_pw_multi_aff_product.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_pw_multi_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_pullback_pw_multi_aff.restype = c_void_p
+isl.isl_pw_multi_aff_pullback_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_range_product.restype = c_void_p
+isl.isl_pw_multi_aff_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_union_add.restype = c_void_p
+isl.isl_pw_multi_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_copy.restype = c_void_p
+isl.isl_pw_multi_aff_copy.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_free.restype = c_void_p
+isl.isl_pw_multi_aff_free.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_to_str.restype = POINTER(c_char)
+isl.isl_pw_multi_aff_to_str.argtypes = [c_void_p]
+
+class pw_aff(union_pw_aff, pw_multi_aff, multi_pw_aff):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_aff_from_aff(isl.isl_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_pw_aff_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        ptr = isl.isl_pw_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.pw_aff("""%s""")' % s
+        else:
+            return 'isl.pw_aff("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).add(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_add(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def ceil(arg0):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_ceil(isl.isl_pw_aff_copy(arg0.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def cond(arg0, arg1, arg2):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).cond(arg1, arg2)
+        try:
+            if not arg2.__class__ is pw_aff:
+                arg2 = pw_aff(arg2)
+        except:
+            return union_pw_aff(arg0).cond(arg1, arg2)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_cond(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr), isl.isl_pw_aff_copy(arg2.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def div(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).div(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_div(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def eq_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).eq_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_eq_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def floor(arg0):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_floor(isl.isl_pw_aff_copy(arg0.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def ge_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).ge_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_ge_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def gt_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).gt_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_gt_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def le_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).le_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_le_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def lt_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).lt_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_lt_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def max(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).max(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_max(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def min(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).min(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_min(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def mod(arg0, arg1):
+        if arg1.__class__ is val:
+            res = isl.isl_pw_aff_mod_val(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+            return pw_aff(ctx=arg0.ctx, ptr=res)
+    def mul(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).mul(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_mul(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def ne_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).ne_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_ne_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def neg(arg0):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_neg(isl.isl_pw_aff_copy(arg0.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def pullback(arg0, arg1):
+        if arg1.__class__ is multi_aff:
+            res = isl.isl_pw_aff_pullback_multi_aff(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+            return pw_aff(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is pw_multi_aff:
+            res = isl.isl_pw_aff_pullback_pw_multi_aff(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+            return pw_aff(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is multi_pw_aff:
+            res = isl.isl_pw_aff_pullback_multi_pw_aff(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+            return pw_aff(ctx=arg0.ctx, ptr=res)
+    def scale(arg0, arg1):
+        if arg1.__class__ is val:
+            res = isl.isl_pw_aff_scale_val(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+            return pw_aff(ctx=arg0.ctx, ptr=res)
+    def scale_down(arg0, arg1):
+        if arg1.__class__ is val:
+            res = isl.isl_pw_aff_scale_down_val(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+            return pw_aff(ctx=arg0.ctx, ptr=res)
+    def sub(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).sub(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_sub(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def tdiv_q(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).tdiv_q(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_tdiv_q(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def tdiv_r(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).tdiv_r(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_tdiv_r(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+    def union_add(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).union_add(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_union_add(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        return pw_aff(ctx=ctx, ptr=res)
+
+isl.isl_pw_aff_from_aff.restype = c_void_p
+isl.isl_pw_aff_from_aff.argtypes = [c_void_p]
+isl.isl_pw_aff_read_from_str.restype = c_void_p
+isl.isl_pw_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_pw_aff_add.restype = c_void_p
+isl.isl_pw_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_ceil.restype = c_void_p
+isl.isl_pw_aff_ceil.argtypes = [c_void_p]
+isl.isl_pw_aff_cond.restype = c_void_p
+isl.isl_pw_aff_cond.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_pw_aff_div.restype = c_void_p
+isl.isl_pw_aff_div.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_eq_set.restype = c_void_p
+isl.isl_pw_aff_eq_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_floor.restype = c_void_p
+isl.isl_pw_aff_floor.argtypes = [c_void_p]
+isl.isl_pw_aff_ge_set.restype = c_void_p
+isl.isl_pw_aff_ge_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_gt_set.restype = c_void_p
+isl.isl_pw_aff_gt_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_le_set.restype = c_void_p
+isl.isl_pw_aff_le_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_lt_set.restype = c_void_p
+isl.isl_pw_aff_lt_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_max.restype = c_void_p
+isl.isl_pw_aff_max.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_min.restype = c_void_p
+isl.isl_pw_aff_min.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_mod_val.restype = c_void_p
+isl.isl_pw_aff_mod_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_mul.restype = c_void_p
+isl.isl_pw_aff_mul.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_ne_set.restype = c_void_p
+isl.isl_pw_aff_ne_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_neg.restype = c_void_p
+isl.isl_pw_aff_neg.argtypes = [c_void_p]
+isl.isl_pw_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_pw_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_pullback_pw_multi_aff.restype = c_void_p
+isl.isl_pw_aff_pullback_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_pullback_multi_pw_aff.restype = c_void_p
+isl.isl_pw_aff_pullback_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_scale_val.restype = c_void_p
+isl.isl_pw_aff_scale_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_scale_down_val.restype = c_void_p
+isl.isl_pw_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_sub.restype = c_void_p
+isl.isl_pw_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_tdiv_q.restype = c_void_p
+isl.isl_pw_aff_tdiv_q.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_tdiv_r.restype = c_void_p
+isl.isl_pw_aff_tdiv_r.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_union_add.restype = c_void_p
+isl.isl_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_copy.restype = c_void_p
+isl.isl_pw_aff_copy.argtypes = [c_void_p]
+isl.isl_pw_aff_free.restype = c_void_p
+isl.isl_pw_aff_free.argtypes = [c_void_p]
+isl.isl_pw_aff_to_str.restype = POINTER(c_char)
+isl.isl_pw_aff_to_str.argtypes = [c_void_p]
+
+class multi_aff(pw_multi_aff, multi_pw_aff):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_aff_from_aff(isl.isl_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_multi_aff_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
+        except:
+            raise
+        ptr = isl.isl_multi_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.multi_aff("""%s""")' % s
+        else:
+            return 'isl.multi_aff("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
+        except:
+            return pw_multi_aff(arg0).add(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_aff_add(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+        return multi_aff(ctx=ctx, ptr=res)
+    def flat_range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
+        except:
+            return pw_multi_aff(arg0).flat_range_product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_aff_flat_range_product(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+        return multi_aff(ctx=ctx, ptr=res)
+    def product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
+        except:
+            return pw_multi_aff(arg0).product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_aff_product(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+        return multi_aff(ctx=ctx, ptr=res)
+    def pullback(arg0, arg1):
+        if arg1.__class__ is multi_aff:
+            res = isl.isl_multi_aff_pullback_multi_aff(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+            return multi_aff(ctx=arg0.ctx, ptr=res)
+    def range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
+        except:
+            return pw_multi_aff(arg0).range_product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_aff_range_product(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+        return multi_aff(ctx=ctx, ptr=res)
+
+isl.isl_multi_aff_from_aff.restype = c_void_p
+isl.isl_multi_aff_from_aff.argtypes = [c_void_p]
+isl.isl_multi_aff_read_from_str.restype = c_void_p
+isl.isl_multi_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_multi_aff_add.restype = c_void_p
+isl.isl_multi_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_flat_range_product.restype = c_void_p
+isl.isl_multi_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_product.restype = c_void_p
+isl.isl_multi_aff_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_multi_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_range_product.restype = c_void_p
+isl.isl_multi_aff_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_copy.restype = c_void_p
+isl.isl_multi_aff_copy.argtypes = [c_void_p]
+isl.isl_multi_aff_free.restype = c_void_p
+isl.isl_multi_aff_free.argtypes = [c_void_p]
+isl.isl_multi_aff_to_str.restype = POINTER(c_char)
+isl.isl_multi_aff_to_str.argtypes = [c_void_p]
+
+class aff(pw_aff, multi_aff):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_aff_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        ptr = isl.isl_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.aff("""%s""")' % s
+        else:
+            return 'isl.aff("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).add(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_add(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return aff(ctx=ctx, ptr=res)
+    def ceil(arg0):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_ceil(isl.isl_aff_copy(arg0.ptr))
+        return aff(ctx=ctx, ptr=res)
+    def div(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).div(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_div(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return aff(ctx=ctx, ptr=res)
+    def eq_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).eq_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_eq_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def floor(arg0):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_floor(isl.isl_aff_copy(arg0.ptr))
+        return aff(ctx=ctx, ptr=res)
+    def ge_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).ge_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_ge_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def gt_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).gt_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_gt_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def le_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).le_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_le_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def lt_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).lt_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_lt_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def mod(arg0, arg1):
+        if arg1.__class__ is val:
+            res = isl.isl_aff_mod_val(isl.isl_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+            return aff(ctx=arg0.ctx, ptr=res)
+    def mul(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).mul(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_mul(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return aff(ctx=ctx, ptr=res)
+    def ne_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).ne_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_ne_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def neg(arg0):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_neg(isl.isl_aff_copy(arg0.ptr))
+        return aff(ctx=ctx, ptr=res)
+    def pullback(arg0, arg1):
+        if arg1.__class__ is multi_aff:
+            res = isl.isl_aff_pullback_multi_aff(isl.isl_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+            return aff(ctx=arg0.ctx, ptr=res)
+    def scale(arg0, arg1):
+        if arg1.__class__ is val:
+            res = isl.isl_aff_scale_val(isl.isl_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+            return aff(ctx=arg0.ctx, ptr=res)
+    def scale_down(arg0, arg1):
+        if arg1.__class__ is val:
+            res = isl.isl_aff_scale_down_val(isl.isl_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+            return aff(ctx=arg0.ctx, ptr=res)
+    def sub(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).sub(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_sub(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        return aff(ctx=ctx, ptr=res)
+
+isl.isl_aff_read_from_str.restype = c_void_p
+isl.isl_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_aff_add.restype = c_void_p
+isl.isl_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_ceil.restype = c_void_p
+isl.isl_aff_ceil.argtypes = [c_void_p]
+isl.isl_aff_div.restype = c_void_p
+isl.isl_aff_div.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_eq_set.restype = c_void_p
+isl.isl_aff_eq_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_floor.restype = c_void_p
+isl.isl_aff_floor.argtypes = [c_void_p]
+isl.isl_aff_ge_set.restype = c_void_p
+isl.isl_aff_ge_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_gt_set.restype = c_void_p
+isl.isl_aff_gt_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_le_set.restype = c_void_p
+isl.isl_aff_le_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_lt_set.restype = c_void_p
+isl.isl_aff_lt_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_mod_val.restype = c_void_p
+isl.isl_aff_mod_val.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_mul.restype = c_void_p
+isl.isl_aff_mul.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_ne_set.restype = c_void_p
+isl.isl_aff_ne_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_neg.restype = c_void_p
+isl.isl_aff_neg.argtypes = [c_void_p]
+isl.isl_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_scale_val.restype = c_void_p
+isl.isl_aff_scale_val.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_scale_down_val.restype = c_void_p
+isl.isl_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_sub.restype = c_void_p
+isl.isl_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_copy.restype = c_void_p
+isl.isl_aff_copy.argtypes = [c_void_p]
+isl.isl_aff_free.restype = c_void_p
+isl.isl_aff_free.argtypes = [c_void_p]
+isl.isl_aff_to_str.restype = POINTER(c_char)
+isl.isl_aff_to_str.argtypes = [c_void_p]
+
+class ast_build(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 0:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_ast_build_alloc(self.ctx)
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_build_free(self.ptr)
+    def access_from(arg0, arg1):
+        if arg1.__class__ is pw_multi_aff:
+            res = isl.isl_ast_build_access_from_pw_multi_aff(arg0.ptr, isl.isl_pw_multi_aff_copy(arg1.ptr))
+            return ast_expr(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is multi_pw_aff:
+            res = isl.isl_ast_build_access_from_multi_pw_aff(arg0.ptr, isl.isl_multi_pw_aff_copy(arg1.ptr))
+            return ast_expr(ctx=arg0.ctx, ptr=res)
+    def call_from(arg0, arg1):
+        if arg1.__class__ is pw_multi_aff:
+            res = isl.isl_ast_build_call_from_pw_multi_aff(arg0.ptr, isl.isl_pw_multi_aff_copy(arg1.ptr))
+            return ast_expr(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is multi_pw_aff:
+            res = isl.isl_ast_build_call_from_multi_pw_aff(arg0.ptr, isl.isl_multi_pw_aff_copy(arg1.ptr))
+            return ast_expr(ctx=arg0.ctx, ptr=res)
+    def expr_from(arg0, arg1):
+        if arg1.__class__ is set:
+            res = isl.isl_ast_build_expr_from_set(arg0.ptr, isl.isl_set_copy(arg1.ptr))
+            return ast_expr(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is pw_aff:
+            res = isl.isl_ast_build_expr_from_pw_aff(arg0.ptr, isl.isl_pw_aff_copy(arg1.ptr))
+            return ast_expr(ctx=arg0.ctx, ptr=res)
+    @staticmethod
+    def from_context(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_build_from_context(isl.isl_set_copy(arg0.ptr))
+        return ast_build(ctx=ctx, ptr=res)
+    def node_from_schedule_map(arg0, arg1):
+        try:
+            if not arg0.__class__ is ast_build:
+                arg0 = ast_build(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_build_node_from_schedule_map(arg0.ptr, isl.isl_union_map_copy(arg1.ptr))
+        return ast_node(ctx=ctx, ptr=res)
+
+isl.isl_ast_build_alloc.restype = c_void_p
+isl.isl_ast_build_alloc.argtypes = [Context]
+isl.isl_ast_build_access_from_pw_multi_aff.restype = c_void_p
+isl.isl_ast_build_access_from_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_access_from_multi_pw_aff.restype = c_void_p
+isl.isl_ast_build_access_from_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_call_from_pw_multi_aff.restype = c_void_p
+isl.isl_ast_build_call_from_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_call_from_multi_pw_aff.restype = c_void_p
+isl.isl_ast_build_call_from_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_expr_from_set.restype = c_void_p
+isl.isl_ast_build_expr_from_set.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_expr_from_pw_aff.restype = c_void_p
+isl.isl_ast_build_expr_from_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_from_context.restype = c_void_p
+isl.isl_ast_build_from_context.argtypes = [c_void_p]
+isl.isl_ast_build_node_from_schedule_map.restype = c_void_p
+isl.isl_ast_build_node_from_schedule_map.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_copy.restype = c_void_p
+isl.isl_ast_build_copy.argtypes = [c_void_p]
+isl.isl_ast_build_free.restype = c_void_p
+isl.isl_ast_build_free.argtypes = [c_void_p]
+
+class ast_expr(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr:
+                arg0 = ast_expr(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr("""%s""")' % s
+        else:
+            return 'isl.ast_expr("%s")' % s
+    def to_C_str(arg0):
+        try:
+            if not arg0.__class__ is ast_expr:
+                arg0 = ast_expr(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_expr_to_C_str(arg0.ptr)
+        if res == 0:
+            raise
+        string = cast(res, c_char_p).value.decode('ascii')
+        libc.free(res)
+        return string
+
+isl.isl_ast_expr_to_C_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_C_str.argtypes = [c_void_p]
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_node(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_node_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_node("""%s""")' % s
+        else:
+            return 'isl.ast_node("%s")' % s
+    def to_C_str(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_to_C_str(arg0.ptr)
+        if res == 0:
+            raise
+        string = cast(res, c_char_p).value.decode('ascii')
+        libc.free(res)
+        return string
+
+isl.isl_ast_node_to_C_str.restype = POINTER(c_char)
+isl.isl_ast_node_to_C_str.argtypes = [c_void_p]
+isl.isl_ast_node_copy.restype = c_void_p
+isl.isl_ast_node_copy.argtypes = [c_void_p]
+isl.isl_ast_node_free.restype = c_void_p
+isl.isl_ast_node_free.argtypes = [c_void_p]
+isl.isl_ast_node_to_str.restype = POINTER(c_char)
+isl.isl_ast_node_to_str.argtypes = [c_void_p]
+
+class union_map(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is basic_map:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_map_from_basic_map(isl.isl_basic_map_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is map:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_map_from_map(isl.isl_map_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_map_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_union_map_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ptr = isl.isl_union_map_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.union_map("""%s""")' % s
+        else:
+            return 'isl.union_map("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_affine_hull(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def apply_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_apply_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def apply_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_apply_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_coalesce(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def compute_divs(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_compute_divs(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def deltas(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_deltas(isl.isl_union_map_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_detect_equalities(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def domain(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain(isl.isl_union_map_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def domain_factor_domain(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_factor_domain(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def domain_factor_range(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_factor_range(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def domain_map(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_map(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def domain_map_union_pw_multi_aff(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_map_union_pw_multi_aff(isl.isl_union_map_copy(arg0.ptr))
+        return union_pw_multi_aff(ctx=ctx, ptr=res)
+    def domain_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_product(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def eq_at(arg0, arg1):
+        if arg1.__class__ is multi_union_pw_aff:
+            res = isl.isl_union_map_eq_at_multi_union_pw_aff(isl.isl_union_map_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+            return union_map(ctx=arg0.ctx, ptr=res)
+    def factor_domain(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_factor_domain(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def factor_range(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_factor_range(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def fixed_power(arg0, arg1):
+        if arg1.__class__ is val:
+            res = isl.isl_union_map_fixed_power_val(isl.isl_union_map_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+            return union_map(ctx=arg0.ctx, ptr=res)
+    def foreach_map(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = map(ctx=arg0.ctx, ptr=cb_arg0)
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_union_map_foreach_map(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        return res
+    @staticmethod
+    def convert_from(arg0):
+        if arg0.__class__ is union_pw_multi_aff:
+            res = isl.isl_union_map_from_union_pw_multi_aff(isl.isl_union_pw_multi_aff_copy(arg0.ptr))
+            return union_map(ctx=arg0.ctx, ptr=res)
+        if arg0.__class__ is multi_union_pw_aff:
+            res = isl.isl_union_map_from_multi_union_pw_aff(isl.isl_multi_union_pw_aff_copy(arg0.ptr))
+            return union_map(ctx=arg0.ctx, ptr=res)
+    @staticmethod
+    def from_domain(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_from_domain(isl.isl_union_set_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    @staticmethod
+    def from_domain_and_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_from_domain_and_range(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    @staticmethod
+    def from_range(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_from_range(isl.isl_union_set_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_gist(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def gist_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_gist_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def gist_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_gist_params(isl.isl_union_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def gist_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_gist_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_intersect(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def intersect_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_intersect_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_intersect_params(isl.isl_union_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def intersect_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_intersect_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def is_bijective(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_bijective(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_injective(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_injective(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_single_valued(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_single_valued(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_strict_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_strict_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_lexmax(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_lexmin(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def polyhedral_hull(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_polyhedral_hull(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def product(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_product(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def project_out_all_params(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_project_out_all_params(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def range(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range(isl.isl_union_map_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def range_factor_domain(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range_factor_domain(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def range_factor_range(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range_factor_range(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def range_map(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range_map(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range_product(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def reverse(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_reverse(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def subtract(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_subtract(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def subtract_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_subtract_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def subtract_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_subtract_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_union(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def wrap(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_wrap(isl.isl_union_map_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def zip(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_zip(isl.isl_union_map_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+
+isl.isl_union_map_from_basic_map.restype = c_void_p
+isl.isl_union_map_from_basic_map.argtypes = [c_void_p]
+isl.isl_union_map_from_map.restype = c_void_p
+isl.isl_union_map_from_map.argtypes = [c_void_p]
+isl.isl_union_map_read_from_str.restype = c_void_p
+isl.isl_union_map_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_union_map_affine_hull.restype = c_void_p
+isl.isl_union_map_affine_hull.argtypes = [c_void_p]
+isl.isl_union_map_apply_domain.restype = c_void_p
+isl.isl_union_map_apply_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_apply_range.restype = c_void_p
+isl.isl_union_map_apply_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_coalesce.restype = c_void_p
+isl.isl_union_map_coalesce.argtypes = [c_void_p]
+isl.isl_union_map_compute_divs.restype = c_void_p
+isl.isl_union_map_compute_divs.argtypes = [c_void_p]
+isl.isl_union_map_deltas.restype = c_void_p
+isl.isl_union_map_deltas.argtypes = [c_void_p]
+isl.isl_union_map_detect_equalities.restype = c_void_p
+isl.isl_union_map_detect_equalities.argtypes = [c_void_p]
+isl.isl_union_map_domain.restype = c_void_p
+isl.isl_union_map_domain.argtypes = [c_void_p]
+isl.isl_union_map_domain_factor_domain.restype = c_void_p
+isl.isl_union_map_domain_factor_domain.argtypes = [c_void_p]
+isl.isl_union_map_domain_factor_range.restype = c_void_p
+isl.isl_union_map_domain_factor_range.argtypes = [c_void_p]
+isl.isl_union_map_domain_map.restype = c_void_p
+isl.isl_union_map_domain_map.argtypes = [c_void_p]
+isl.isl_union_map_domain_map_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_map_domain_map_union_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_union_map_domain_product.restype = c_void_p
+isl.isl_union_map_domain_product.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_eq_at_multi_union_pw_aff.restype = c_void_p
+isl.isl_union_map_eq_at_multi_union_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_factor_domain.restype = c_void_p
+isl.isl_union_map_factor_domain.argtypes = [c_void_p]
+isl.isl_union_map_factor_range.restype = c_void_p
+isl.isl_union_map_factor_range.argtypes = [c_void_p]
+isl.isl_union_map_fixed_power_val.restype = c_void_p
+isl.isl_union_map_fixed_power_val.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_foreach_map.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_map_from_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_map_from_union_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_union_map_from_multi_union_pw_aff.restype = c_void_p
+isl.isl_union_map_from_multi_union_pw_aff.argtypes = [c_void_p]
+isl.isl_union_map_from_domain.restype = c_void_p
+isl.isl_union_map_from_domain.argtypes = [c_void_p]
+isl.isl_union_map_from_domain_and_range.restype = c_void_p
+isl.isl_union_map_from_domain_and_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_from_range.restype = c_void_p
+isl.isl_union_map_from_range.argtypes = [c_void_p]
+isl.isl_union_map_gist.restype = c_void_p
+isl.isl_union_map_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_gist_domain.restype = c_void_p
+isl.isl_union_map_gist_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_gist_params.restype = c_void_p
+isl.isl_union_map_gist_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_gist_range.restype = c_void_p
+isl.isl_union_map_gist_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_intersect.restype = c_void_p
+isl.isl_union_map_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_intersect_domain.restype = c_void_p
+isl.isl_union_map_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_intersect_params.restype = c_void_p
+isl.isl_union_map_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_intersect_range.restype = c_void_p
+isl.isl_union_map_intersect_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_is_bijective.restype = c_bool
+isl.isl_union_map_is_bijective.argtypes = [c_void_p]
+isl.isl_union_map_is_empty.restype = c_bool
+isl.isl_union_map_is_empty.argtypes = [c_void_p]
+isl.isl_union_map_is_equal.restype = c_bool
+isl.isl_union_map_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_is_injective.restype = c_bool
+isl.isl_union_map_is_injective.argtypes = [c_void_p]
+isl.isl_union_map_is_single_valued.restype = c_bool
+isl.isl_union_map_is_single_valued.argtypes = [c_void_p]
+isl.isl_union_map_is_strict_subset.restype = c_bool
+isl.isl_union_map_is_strict_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_is_subset.restype = c_bool
+isl.isl_union_map_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_lexmax.restype = c_void_p
+isl.isl_union_map_lexmax.argtypes = [c_void_p]
+isl.isl_union_map_lexmin.restype = c_void_p
+isl.isl_union_map_lexmin.argtypes = [c_void_p]
+isl.isl_union_map_polyhedral_hull.restype = c_void_p
+isl.isl_union_map_polyhedral_hull.argtypes = [c_void_p]
+isl.isl_union_map_product.restype = c_void_p
+isl.isl_union_map_product.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_project_out_all_params.restype = c_void_p
+isl.isl_union_map_project_out_all_params.argtypes = [c_void_p]
+isl.isl_union_map_range.restype = c_void_p
+isl.isl_union_map_range.argtypes = [c_void_p]
+isl.isl_union_map_range_factor_domain.restype = c_void_p
+isl.isl_union_map_range_factor_domain.argtypes = [c_void_p]
+isl.isl_union_map_range_factor_range.restype = c_void_p
+isl.isl_union_map_range_factor_range.argtypes = [c_void_p]
+isl.isl_union_map_range_map.restype = c_void_p
+isl.isl_union_map_range_map.argtypes = [c_void_p]
+isl.isl_union_map_range_product.restype = c_void_p
+isl.isl_union_map_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_reverse.restype = c_void_p
+isl.isl_union_map_reverse.argtypes = [c_void_p]
+isl.isl_union_map_subtract.restype = c_void_p
+isl.isl_union_map_subtract.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_subtract_domain.restype = c_void_p
+isl.isl_union_map_subtract_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_subtract_range.restype = c_void_p
+isl.isl_union_map_subtract_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_union.restype = c_void_p
+isl.isl_union_map_union.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_wrap.restype = c_void_p
+isl.isl_union_map_wrap.argtypes = [c_void_p]
+isl.isl_union_map_zip.restype = c_void_p
+isl.isl_union_map_zip.argtypes = [c_void_p]
+isl.isl_union_map_copy.restype = c_void_p
+isl.isl_union_map_copy.argtypes = [c_void_p]
+isl.isl_union_map_free.restype = c_void_p
+isl.isl_union_map_free.argtypes = [c_void_p]
+isl.isl_union_map_to_str.restype = POINTER(c_char)
+isl.isl_union_map_to_str.argtypes = [c_void_p]
+
+class map(union_map):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_map_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        if len(args) == 1 and args[0].__class__ is basic_map:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_map_from_basic_map(isl.isl_basic_map_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_map_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ptr = isl.isl_map_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.map("""%s""")' % s
+        else:
+            return 'isl.map("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_affine_hull(isl.isl_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def apply_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).apply_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_apply_domain(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def apply_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).apply_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_apply_range(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_coalesce(isl.isl_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def complement(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_complement(isl.isl_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def deltas(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_deltas(isl.isl_map_copy(arg0.ptr))
+        return set(ctx=ctx, ptr=res)
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_detect_equalities(isl.isl_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def flatten(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_flatten(isl.isl_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def flatten_domain(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_flatten_domain(isl.isl_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def flatten_range(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_flatten_range(isl.isl_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def foreach_basic_map(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = basic_map(ctx=arg0.ctx, ptr=cb_arg0)
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_map_foreach_basic_map(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        return res
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_gist(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def gist_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_map(arg0).gist_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_gist_domain(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).intersect(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_intersect(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def intersect_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_map(arg0).intersect_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_intersect_domain(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_map(arg0).intersect_params(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_intersect_params(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def intersect_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_map(arg0).intersect_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_intersect_range(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def is_bijective(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_is_bijective(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_disjoint(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).is_disjoint(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_is_disjoint(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).is_equal(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_injective(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_is_injective(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_single_valued(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_is_single_valued(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_strict_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).is_strict_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_is_strict_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).is_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_lexmax(isl.isl_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_lexmin(isl.isl_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def polyhedral_hull(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_polyhedral_hull(isl.isl_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def reverse(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_reverse(isl.isl_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def sample(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_sample(isl.isl_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def subtract(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).subtract(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_subtract(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).union(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_union(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+    def unshifted_simple_hull(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_unshifted_simple_hull(isl.isl_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+
+isl.isl_map_read_from_str.restype = c_void_p
+isl.isl_map_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_map_from_basic_map.restype = c_void_p
+isl.isl_map_from_basic_map.argtypes = [c_void_p]
+isl.isl_map_affine_hull.restype = c_void_p
+isl.isl_map_affine_hull.argtypes = [c_void_p]
+isl.isl_map_apply_domain.restype = c_void_p
+isl.isl_map_apply_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_map_apply_range.restype = c_void_p
+isl.isl_map_apply_range.argtypes = [c_void_p, c_void_p]
+isl.isl_map_coalesce.restype = c_void_p
+isl.isl_map_coalesce.argtypes = [c_void_p]
+isl.isl_map_complement.restype = c_void_p
+isl.isl_map_complement.argtypes = [c_void_p]
+isl.isl_map_deltas.restype = c_void_p
+isl.isl_map_deltas.argtypes = [c_void_p]
+isl.isl_map_detect_equalities.restype = c_void_p
+isl.isl_map_detect_equalities.argtypes = [c_void_p]
+isl.isl_map_flatten.restype = c_void_p
+isl.isl_map_flatten.argtypes = [c_void_p]
+isl.isl_map_flatten_domain.restype = c_void_p
+isl.isl_map_flatten_domain.argtypes = [c_void_p]
+isl.isl_map_flatten_range.restype = c_void_p
+isl.isl_map_flatten_range.argtypes = [c_void_p]
+isl.isl_map_foreach_basic_map.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_map_gist.restype = c_void_p
+isl.isl_map_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_map_gist_domain.restype = c_void_p
+isl.isl_map_gist_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_map_intersect.restype = c_void_p
+isl.isl_map_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_map_intersect_domain.restype = c_void_p
+isl.isl_map_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_map_intersect_params.restype = c_void_p
+isl.isl_map_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_map_intersect_range.restype = c_void_p
+isl.isl_map_intersect_range.argtypes = [c_void_p, c_void_p]
+isl.isl_map_is_bijective.restype = c_bool
+isl.isl_map_is_bijective.argtypes = [c_void_p]
+isl.isl_map_is_disjoint.restype = c_bool
+isl.isl_map_is_disjoint.argtypes = [c_void_p, c_void_p]
+isl.isl_map_is_empty.restype = c_bool
+isl.isl_map_is_empty.argtypes = [c_void_p]
+isl.isl_map_is_equal.restype = c_bool
+isl.isl_map_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_map_is_injective.restype = c_bool
+isl.isl_map_is_injective.argtypes = [c_void_p]
+isl.isl_map_is_single_valued.restype = c_bool
+isl.isl_map_is_single_valued.argtypes = [c_void_p]
+isl.isl_map_is_strict_subset.restype = c_bool
+isl.isl_map_is_strict_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_map_is_subset.restype = c_bool
+isl.isl_map_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_map_lexmax.restype = c_void_p
+isl.isl_map_lexmax.argtypes = [c_void_p]
+isl.isl_map_lexmin.restype = c_void_p
+isl.isl_map_lexmin.argtypes = [c_void_p]
+isl.isl_map_polyhedral_hull.restype = c_void_p
+isl.isl_map_polyhedral_hull.argtypes = [c_void_p]
+isl.isl_map_reverse.restype = c_void_p
+isl.isl_map_reverse.argtypes = [c_void_p]
+isl.isl_map_sample.restype = c_void_p
+isl.isl_map_sample.argtypes = [c_void_p]
+isl.isl_map_subtract.restype = c_void_p
+isl.isl_map_subtract.argtypes = [c_void_p, c_void_p]
+isl.isl_map_union.restype = c_void_p
+isl.isl_map_union.argtypes = [c_void_p, c_void_p]
+isl.isl_map_unshifted_simple_hull.restype = c_void_p
+isl.isl_map_unshifted_simple_hull.argtypes = [c_void_p]
+isl.isl_map_copy.restype = c_void_p
+isl.isl_map_copy.argtypes = [c_void_p]
+isl.isl_map_free.restype = c_void_p
+isl.isl_map_free.argtypes = [c_void_p]
+isl.isl_map_to_str.restype = POINTER(c_char)
+isl.isl_map_to_str.argtypes = [c_void_p]
+
+class basic_map(map):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_basic_map_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_basic_map_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ptr = isl.isl_basic_map_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.basic_map("""%s""")' % s
+        else:
+            return 'isl.basic_map("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_affine_hull(isl.isl_basic_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def apply_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).apply_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_apply_domain(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def apply_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).apply_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_apply_range(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def deltas(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_deltas(isl.isl_basic_map_copy(arg0.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_detect_equalities(isl.isl_basic_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def flatten(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_flatten(isl.isl_basic_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def flatten_domain(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_flatten_domain(isl.isl_basic_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def flatten_range(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_flatten_range(isl.isl_basic_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_gist(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).intersect(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_intersect(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def intersect_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return map(arg0).intersect_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_intersect_domain(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def intersect_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return map(arg0).intersect_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_intersect_range(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).is_equal(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).is_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_lexmax(isl.isl_basic_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_lexmin(isl.isl_basic_map_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def reverse(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_reverse(isl.isl_basic_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def sample(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_sample(isl.isl_basic_map_copy(arg0.ptr))
+        return basic_map(ctx=ctx, ptr=res)
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).union(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_union(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        return map(ctx=ctx, ptr=res)
+
+isl.isl_basic_map_read_from_str.restype = c_void_p
+isl.isl_basic_map_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_basic_map_affine_hull.restype = c_void_p
+isl.isl_basic_map_affine_hull.argtypes = [c_void_p]
+isl.isl_basic_map_apply_domain.restype = c_void_p
+isl.isl_basic_map_apply_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_apply_range.restype = c_void_p
+isl.isl_basic_map_apply_range.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_deltas.restype = c_void_p
+isl.isl_basic_map_deltas.argtypes = [c_void_p]
+isl.isl_basic_map_detect_equalities.restype = c_void_p
+isl.isl_basic_map_detect_equalities.argtypes = [c_void_p]
+isl.isl_basic_map_flatten.restype = c_void_p
+isl.isl_basic_map_flatten.argtypes = [c_void_p]
+isl.isl_basic_map_flatten_domain.restype = c_void_p
+isl.isl_basic_map_flatten_domain.argtypes = [c_void_p]
+isl.isl_basic_map_flatten_range.restype = c_void_p
+isl.isl_basic_map_flatten_range.argtypes = [c_void_p]
+isl.isl_basic_map_gist.restype = c_void_p
+isl.isl_basic_map_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_intersect.restype = c_void_p
+isl.isl_basic_map_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_intersect_domain.restype = c_void_p
+isl.isl_basic_map_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_intersect_range.restype = c_void_p
+isl.isl_basic_map_intersect_range.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_is_empty.restype = c_bool
+isl.isl_basic_map_is_empty.argtypes = [c_void_p]
+isl.isl_basic_map_is_equal.restype = c_bool
+isl.isl_basic_map_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_is_subset.restype = c_bool
+isl.isl_basic_map_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_lexmax.restype = c_void_p
+isl.isl_basic_map_lexmax.argtypes = [c_void_p]
+isl.isl_basic_map_lexmin.restype = c_void_p
+isl.isl_basic_map_lexmin.argtypes = [c_void_p]
+isl.isl_basic_map_reverse.restype = c_void_p
+isl.isl_basic_map_reverse.argtypes = [c_void_p]
+isl.isl_basic_map_sample.restype = c_void_p
+isl.isl_basic_map_sample.argtypes = [c_void_p]
+isl.isl_basic_map_union.restype = c_void_p
+isl.isl_basic_map_union.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_copy.restype = c_void_p
+isl.isl_basic_map_copy.argtypes = [c_void_p]
+isl.isl_basic_map_free.restype = c_void_p
+isl.isl_basic_map_free.argtypes = [c_void_p]
+isl.isl_basic_map_to_str.restype = POINTER(c_char)
+isl.isl_basic_map_to_str.argtypes = [c_void_p]
+
+class union_set(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is basic_set:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_from_basic_set(isl.isl_basic_set_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is set:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_from_set(isl.isl_set_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is point:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_from_point(isl.isl_point_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_union_set_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ptr = isl.isl_union_set_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.union_set("""%s""")' % s
+        else:
+            return 'isl.union_set("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_affine_hull(isl.isl_union_set_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def apply(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_apply(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_coalesce(isl.isl_union_set_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def compute_divs(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_compute_divs(isl.isl_union_set_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_detect_equalities(isl.isl_union_set_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def foreach_point(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = point(ctx=arg0.ctx, ptr=cb_arg0)
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_union_set_foreach_point(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        return res
+    def foreach_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = set(ctx=arg0.ctx, ptr=cb_arg0)
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_union_set_foreach_set(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        return res
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_gist(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def gist_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_gist_params(isl.isl_union_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def identity(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_identity(isl.isl_union_set_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_intersect(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_intersect_params(isl.isl_union_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_strict_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_is_strict_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_lexmax(isl.isl_union_set_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_lexmin(isl.isl_union_set_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def polyhedral_hull(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_polyhedral_hull(isl.isl_union_set_copy(arg0.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def preimage(arg0, arg1):
+        if arg1.__class__ is multi_aff:
+            res = isl.isl_union_set_preimage_multi_aff(isl.isl_union_set_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+            return union_set(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is pw_multi_aff:
+            res = isl.isl_union_set_preimage_pw_multi_aff(isl.isl_union_set_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+            return union_set(ctx=arg0.ctx, ptr=res)
+        if arg1.__class__ is union_pw_multi_aff:
+            res = isl.isl_union_set_preimage_union_pw_multi_aff(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
+            return union_set(ctx=arg0.ctx, ptr=res)
+    def sample_point(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_sample_point(isl.isl_union_set_copy(arg0.ptr))
+        return point(ctx=ctx, ptr=res)
+    def subtract(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_subtract(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_union(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        return union_set(ctx=ctx, ptr=res)
+    def unwrap(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_unwrap(isl.isl_union_set_copy(arg0.ptr))
+        return union_map(ctx=ctx, ptr=res)
+
+isl.isl_union_set_from_basic_set.restype = c_void_p
+isl.isl_union_set_from_basic_set.argtypes = [c_void_p]
+isl.isl_union_set_from_set.restype = c_void_p
+isl.isl_union_set_from_set.argtypes = [c_void_p]
+isl.isl_union_set_from_point.restype = c_void_p
+isl.isl_union_set_from_point.argtypes = [c_void_p]
+isl.isl_union_set_read_from_str.restype = c_void_p
+isl.isl_union_set_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_union_set_affine_hull.restype = c_void_p
+isl.isl_union_set_affine_hull.argtypes = [c_void_p]
+isl.isl_union_set_apply.restype = c_void_p
+isl.isl_union_set_apply.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_coalesce.restype = c_void_p
+isl.isl_union_set_coalesce.argtypes = [c_void_p]
+isl.isl_union_set_compute_divs.restype = c_void_p
+isl.isl_union_set_compute_divs.argtypes = [c_void_p]
+isl.isl_union_set_detect_equalities.restype = c_void_p
+isl.isl_union_set_detect_equalities.argtypes = [c_void_p]
+isl.isl_union_set_foreach_point.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_set_foreach_set.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_set_gist.restype = c_void_p
+isl.isl_union_set_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_gist_params.restype = c_void_p
+isl.isl_union_set_gist_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_identity.restype = c_void_p
+isl.isl_union_set_identity.argtypes = [c_void_p]
+isl.isl_union_set_intersect.restype = c_void_p
+isl.isl_union_set_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_intersect_params.restype = c_void_p
+isl.isl_union_set_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_is_empty.restype = c_bool
+isl.isl_union_set_is_empty.argtypes = [c_void_p]
+isl.isl_union_set_is_equal.restype = c_bool
+isl.isl_union_set_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_is_strict_subset.restype = c_bool
+isl.isl_union_set_is_strict_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_is_subset.restype = c_bool
+isl.isl_union_set_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_lexmax.restype = c_void_p
+isl.isl_union_set_lexmax.argtypes = [c_void_p]
+isl.isl_union_set_lexmin.restype = c_void_p
+isl.isl_union_set_lexmin.argtypes = [c_void_p]
+isl.isl_union_set_polyhedral_hull.restype = c_void_p
+isl.isl_union_set_polyhedral_hull.argtypes = [c_void_p]
+isl.isl_union_set_preimage_multi_aff.restype = c_void_p
+isl.isl_union_set_preimage_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_preimage_pw_multi_aff.restype = c_void_p
+isl.isl_union_set_preimage_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_preimage_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_set_preimage_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_sample_point.restype = c_void_p
+isl.isl_union_set_sample_point.argtypes = [c_void_p]
+isl.isl_union_set_subtract.restype = c_void_p
+isl.isl_union_set_subtract.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_union.restype = c_void_p
+isl.isl_union_set_union.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_unwrap.restype = c_void_p
+isl.isl_union_set_unwrap.argtypes = [c_void_p]
+isl.isl_union_set_copy.restype = c_void_p
+isl.isl_union_set_copy.argtypes = [c_void_p]
+isl.isl_union_set_free.restype = c_void_p
+isl.isl_union_set_free.argtypes = [c_void_p]
+isl.isl_union_set_to_str.restype = POINTER(c_char)
+isl.isl_union_set_to_str.argtypes = [c_void_p]
+
+class set(union_set):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_set_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        if len(args) == 1 and args[0].__class__ is basic_set:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_set_from_basic_set(isl.isl_basic_set_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is point:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_set_from_point(isl.isl_point_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_set_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ptr = isl.isl_set_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.set("""%s""")' % s
+        else:
+            return 'isl.set("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_affine_hull(isl.isl_set_copy(arg0.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def apply(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_set(arg0).apply(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_apply(isl.isl_set_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_coalesce(isl.isl_set_copy(arg0.ptr))
+        return set(ctx=ctx, ptr=res)
+    def complement(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_complement(isl.isl_set_copy(arg0.ptr))
+        return set(ctx=ctx, ptr=res)
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_detect_equalities(isl.isl_set_copy(arg0.ptr))
+        return set(ctx=ctx, ptr=res)
+    def flatten(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_flatten(isl.isl_set_copy(arg0.ptr))
+        return set(ctx=ctx, ptr=res)
+    def foreach_basic_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = basic_set(ctx=arg0.ctx, ptr=cb_arg0)
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_set_foreach_basic_set(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        return res
+    def get_stride(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_get_stride(arg0.ptr, arg1)
+        return val(ctx=ctx, ptr=res)
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_gist(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def identity(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_identity(isl.isl_set_copy(arg0.ptr))
+        return map(ctx=ctx, ptr=res)
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).intersect(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_intersect(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).intersect_params(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_intersect_params(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def is_disjoint(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).is_disjoint(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_is_disjoint(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).is_equal(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_strict_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).is_strict_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_is_strict_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).is_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_wrapping(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_is_wrapping(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_lexmax(isl.isl_set_copy(arg0.ptr))
+        return set(ctx=ctx, ptr=res)
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_lexmin(isl.isl_set_copy(arg0.ptr))
+        return set(ctx=ctx, ptr=res)
+    def max_val(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return union_set(arg0).max_val(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_max_val(arg0.ptr, arg1.ptr)
+        return val(ctx=ctx, ptr=res)
+    def min_val(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return union_set(arg0).min_val(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_min_val(arg0.ptr, arg1.ptr)
+        return val(ctx=ctx, ptr=res)
+    def polyhedral_hull(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_polyhedral_hull(isl.isl_set_copy(arg0.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def sample(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_sample(isl.isl_set_copy(arg0.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def sample_point(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_sample_point(isl.isl_set_copy(arg0.ptr))
+        return point(ctx=ctx, ptr=res)
+    def subtract(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).subtract(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_subtract(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).union(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_union(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+    def unshifted_simple_hull(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_unshifted_simple_hull(isl.isl_set_copy(arg0.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+
+isl.isl_set_read_from_str.restype = c_void_p
+isl.isl_set_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_set_from_basic_set.restype = c_void_p
+isl.isl_set_from_basic_set.argtypes = [c_void_p]
+isl.isl_set_from_point.restype = c_void_p
+isl.isl_set_from_point.argtypes = [c_void_p]
+isl.isl_set_affine_hull.restype = c_void_p
+isl.isl_set_affine_hull.argtypes = [c_void_p]
+isl.isl_set_apply.restype = c_void_p
+isl.isl_set_apply.argtypes = [c_void_p, c_void_p]
+isl.isl_set_coalesce.restype = c_void_p
+isl.isl_set_coalesce.argtypes = [c_void_p]
+isl.isl_set_complement.restype = c_void_p
+isl.isl_set_complement.argtypes = [c_void_p]
+isl.isl_set_detect_equalities.restype = c_void_p
+isl.isl_set_detect_equalities.argtypes = [c_void_p]
+isl.isl_set_flatten.restype = c_void_p
+isl.isl_set_flatten.argtypes = [c_void_p]
+isl.isl_set_foreach_basic_set.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_set_get_stride.restype = c_void_p
+isl.isl_set_get_stride.argtypes = [c_void_p, c_int]
+isl.isl_set_gist.restype = c_void_p
+isl.isl_set_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_set_identity.restype = c_void_p
+isl.isl_set_identity.argtypes = [c_void_p]
+isl.isl_set_intersect.restype = c_void_p
+isl.isl_set_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_set_intersect_params.restype = c_void_p
+isl.isl_set_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_disjoint.restype = c_bool
+isl.isl_set_is_disjoint.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_empty.restype = c_bool
+isl.isl_set_is_empty.argtypes = [c_void_p]
+isl.isl_set_is_equal.restype = c_bool
+isl.isl_set_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_strict_subset.restype = c_bool
+isl.isl_set_is_strict_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_subset.restype = c_bool
+isl.isl_set_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_wrapping.restype = c_bool
+isl.isl_set_is_wrapping.argtypes = [c_void_p]
+isl.isl_set_lexmax.restype = c_void_p
+isl.isl_set_lexmax.argtypes = [c_void_p]
+isl.isl_set_lexmin.restype = c_void_p
+isl.isl_set_lexmin.argtypes = [c_void_p]
+isl.isl_set_max_val.restype = c_void_p
+isl.isl_set_max_val.argtypes = [c_void_p, c_void_p]
+isl.isl_set_min_val.restype = c_void_p
+isl.isl_set_min_val.argtypes = [c_void_p, c_void_p]
+isl.isl_set_polyhedral_hull.restype = c_void_p
+isl.isl_set_polyhedral_hull.argtypes = [c_void_p]
+isl.isl_set_sample.restype = c_void_p
+isl.isl_set_sample.argtypes = [c_void_p]
+isl.isl_set_sample_point.restype = c_void_p
+isl.isl_set_sample_point.argtypes = [c_void_p]
+isl.isl_set_subtract.restype = c_void_p
+isl.isl_set_subtract.argtypes = [c_void_p, c_void_p]
+isl.isl_set_union.restype = c_void_p
+isl.isl_set_union.argtypes = [c_void_p, c_void_p]
+isl.isl_set_unshifted_simple_hull.restype = c_void_p
+isl.isl_set_unshifted_simple_hull.argtypes = [c_void_p]
+isl.isl_set_copy.restype = c_void_p
+isl.isl_set_copy.argtypes = [c_void_p]
+isl.isl_set_free.restype = c_void_p
+isl.isl_set_free.argtypes = [c_void_p]
+isl.isl_set_to_str.restype = POINTER(c_char)
+isl.isl_set_to_str.argtypes = [c_void_p]
+
+class basic_set(set):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_basic_set_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        if len(args) == 1 and args[0].__class__ is point:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_basic_set_from_point(isl.isl_point_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_basic_set_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ptr = isl.isl_basic_set_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.basic_set("""%s""")' % s
+        else:
+            return 'isl.basic_set("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_affine_hull(isl.isl_basic_set_copy(arg0.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def apply(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return set(arg0).apply(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_apply(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_detect_equalities(isl.isl_basic_set_copy(arg0.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def dim_max_val(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_dim_max_val(isl.isl_basic_set_copy(arg0.ptr), arg1)
+        return val(ctx=ctx, ptr=res)
+    def flatten(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_flatten(isl.isl_basic_set_copy(arg0.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return set(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_gist(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return set(arg0).intersect(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_intersect(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return set(arg0).intersect_params(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_intersect_params(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return set(arg0).is_equal(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return set(arg0).is_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_wrapping(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_is_wrapping(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_lexmax(isl.isl_basic_set_copy(arg0.ptr))
+        return set(ctx=ctx, ptr=res)
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_lexmin(isl.isl_basic_set_copy(arg0.ptr))
+        return set(ctx=ctx, ptr=res)
+    def sample(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_sample(isl.isl_basic_set_copy(arg0.ptr))
+        return basic_set(ctx=ctx, ptr=res)
+    def sample_point(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_sample_point(isl.isl_basic_set_copy(arg0.ptr))
+        return point(ctx=ctx, ptr=res)
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return set(arg0).union(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_union(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        return set(ctx=ctx, ptr=res)
+
+isl.isl_basic_set_read_from_str.restype = c_void_p
+isl.isl_basic_set_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_basic_set_from_point.restype = c_void_p
+isl.isl_basic_set_from_point.argtypes = [c_void_p]
+isl.isl_basic_set_affine_hull.restype = c_void_p
+isl.isl_basic_set_affine_hull.argtypes = [c_void_p]
+isl.isl_basic_set_apply.restype = c_void_p
+isl.isl_basic_set_apply.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_detect_equalities.restype = c_void_p
+isl.isl_basic_set_detect_equalities.argtypes = [c_void_p]
+isl.isl_basic_set_dim_max_val.restype = c_void_p
+isl.isl_basic_set_dim_max_val.argtypes = [c_void_p, c_int]
+isl.isl_basic_set_flatten.restype = c_void_p
+isl.isl_basic_set_flatten.argtypes = [c_void_p]
+isl.isl_basic_set_gist.restype = c_void_p
+isl.isl_basic_set_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_intersect.restype = c_void_p
+isl.isl_basic_set_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_intersect_params.restype = c_void_p
+isl.isl_basic_set_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_is_empty.restype = c_bool
+isl.isl_basic_set_is_empty.argtypes = [c_void_p]
+isl.isl_basic_set_is_equal.restype = c_bool
+isl.isl_basic_set_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_is_subset.restype = c_bool
+isl.isl_basic_set_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_is_wrapping.restype = c_bool
+isl.isl_basic_set_is_wrapping.argtypes = [c_void_p]
+isl.isl_basic_set_lexmax.restype = c_void_p
+isl.isl_basic_set_lexmax.argtypes = [c_void_p]
+isl.isl_basic_set_lexmin.restype = c_void_p
+isl.isl_basic_set_lexmin.argtypes = [c_void_p]
+isl.isl_basic_set_sample.restype = c_void_p
+isl.isl_basic_set_sample.argtypes = [c_void_p]
+isl.isl_basic_set_sample_point.restype = c_void_p
+isl.isl_basic_set_sample_point.argtypes = [c_void_p]
+isl.isl_basic_set_union.restype = c_void_p
+isl.isl_basic_set_union.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_copy.restype = c_void_p
+isl.isl_basic_set_copy.argtypes = [c_void_p]
+isl.isl_basic_set_free.restype = c_void_p
+isl.isl_basic_set_free.argtypes = [c_void_p]
+isl.isl_basic_set_to_str.restype = POINTER(c_char)
+isl.isl_basic_set_to_str.argtypes = [c_void_p]
+
+class multi_val(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_multi_val_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
+        except:
+            raise
+        ptr = isl.isl_multi_val_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.multi_val("""%s""")' % s
+        else:
+            return 'isl.multi_val("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_val_add(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        return multi_val(ctx=ctx, ptr=res)
+    def flat_range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_val_flat_range_product(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        return multi_val(ctx=ctx, ptr=res)
+    def product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_val_product(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        return multi_val(ctx=ctx, ptr=res)
+    def range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_val_range_product(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        return multi_val(ctx=ctx, ptr=res)
+
+isl.isl_multi_val_add.restype = c_void_p
+isl.isl_multi_val_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_flat_range_product.restype = c_void_p
+isl.isl_multi_val_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_product.restype = c_void_p
+isl.isl_multi_val_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_range_product.restype = c_void_p
+isl.isl_multi_val_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_copy.restype = c_void_p
+isl.isl_multi_val_copy.argtypes = [c_void_p]
+isl.isl_multi_val_free.restype = c_void_p
+isl.isl_multi_val_free.argtypes = [c_void_p]
+isl.isl_multi_val_to_str.restype = POINTER(c_char)
+isl.isl_multi_val_to_str.argtypes = [c_void_p]
+
+class point(basic_set):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_point_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is point:
+                arg0 = point(arg0)
+        except:
+            raise
+        ptr = isl.isl_point_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.point("""%s""")' % s
+        else:
+            return 'isl.point("%s")' % s
+
+isl.isl_point_copy.restype = c_void_p
+isl.isl_point_copy.argtypes = [c_void_p]
+isl.isl_point_free.restype = c_void_p
+isl.isl_point_free.argtypes = [c_void_p]
+isl.isl_point_to_str.restype = POINTER(c_char)
+isl.isl_point_to_str.argtypes = [c_void_p]
+
+class schedule(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_schedule_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is schedule:
+                arg0 = schedule(arg0)
+        except:
+            raise
+        ptr = isl.isl_schedule_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule("""%s""")' % s
+        else:
+            return 'isl.schedule("%s")' % s
+    def get_map(arg0):
+        try:
+            if not arg0.__class__ is schedule:
+                arg0 = schedule(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_get_map(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_root(arg0):
+        try:
+            if not arg0.__class__ is schedule:
+                arg0 = schedule(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_get_root(arg0.ptr)
+        return schedule_node(ctx=ctx, ptr=res)
+    def pullback(arg0, arg1):
+        if arg1.__class__ is union_pw_multi_aff:
+            res = isl.isl_schedule_pullback_union_pw_multi_aff(isl.isl_schedule_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
+            return schedule(ctx=arg0.ctx, ptr=res)
+
+isl.isl_schedule_read_from_str.restype = c_void_p
+isl.isl_schedule_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_schedule_get_map.restype = c_void_p
+isl.isl_schedule_get_map.argtypes = [c_void_p]
+isl.isl_schedule_get_root.restype = c_void_p
+isl.isl_schedule_get_root.argtypes = [c_void_p]
+isl.isl_schedule_pullback_union_pw_multi_aff.restype = c_void_p
+isl.isl_schedule_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_copy.restype = c_void_p
+isl.isl_schedule_copy.argtypes = [c_void_p]
+isl.isl_schedule_free.restype = c_void_p
+isl.isl_schedule_free.argtypes = [c_void_p]
+isl.isl_schedule_to_str.restype = POINTER(c_char)
+isl.isl_schedule_to_str.argtypes = [c_void_p]
+
+class schedule_constraints(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_schedule_constraints_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_constraints_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        ptr = isl.isl_schedule_constraints_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_constraints("""%s""")' % s
+        else:
+            return 'isl.schedule_constraints("%s")' % s
+    def compute_schedule(arg0):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_compute_schedule(isl.isl_schedule_constraints_copy(arg0.ptr))
+        return schedule(ctx=ctx, ptr=res)
+    def get_coincidence(arg0):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_get_coincidence(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_conditional_validity(arg0):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_get_conditional_validity(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_conditional_validity_condition(arg0):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_get_conditional_validity_condition(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_context(arg0):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_get_context(arg0.ptr)
+        return set(ctx=ctx, ptr=res)
+    def get_domain(arg0):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_get_domain(arg0.ptr)
+        return union_set(ctx=ctx, ptr=res)
+    def get_proximity(arg0):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_get_proximity(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_validity(arg0):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_get_validity(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    @staticmethod
+    def on_domain(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_on_domain(isl.isl_union_set_copy(arg0.ptr))
+        return schedule_constraints(ctx=ctx, ptr=res)
+    def set_coincidence(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_set_coincidence(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return schedule_constraints(ctx=ctx, ptr=res)
+    def set_conditional_validity(arg0, arg1, arg2):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        try:
+            if not arg2.__class__ is union_map:
+                arg2 = union_map(arg2)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_set_conditional_validity(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr), isl.isl_union_map_copy(arg2.ptr))
+        return schedule_constraints(ctx=ctx, ptr=res)
+    def set_context(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_set_context(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        return schedule_constraints(ctx=ctx, ptr=res)
+    def set_proximity(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_set_proximity(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return schedule_constraints(ctx=ctx, ptr=res)
+    def set_validity(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_set_validity(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return schedule_constraints(ctx=ctx, ptr=res)
+
+isl.isl_schedule_constraints_read_from_str.restype = c_void_p
+isl.isl_schedule_constraints_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_schedule_constraints_compute_schedule.restype = c_void_p
+isl.isl_schedule_constraints_compute_schedule.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_coincidence.restype = c_void_p
+isl.isl_schedule_constraints_get_coincidence.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_conditional_validity.restype = c_void_p
+isl.isl_schedule_constraints_get_conditional_validity.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_conditional_validity_condition.restype = c_void_p
+isl.isl_schedule_constraints_get_conditional_validity_condition.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_context.restype = c_void_p
+isl.isl_schedule_constraints_get_context.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_domain.restype = c_void_p
+isl.isl_schedule_constraints_get_domain.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_proximity.restype = c_void_p
+isl.isl_schedule_constraints_get_proximity.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_validity.restype = c_void_p
+isl.isl_schedule_constraints_get_validity.argtypes = [c_void_p]
+isl.isl_schedule_constraints_on_domain.restype = c_void_p
+isl.isl_schedule_constraints_on_domain.argtypes = [c_void_p]
+isl.isl_schedule_constraints_set_coincidence.restype = c_void_p
+isl.isl_schedule_constraints_set_coincidence.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_constraints_set_conditional_validity.restype = c_void_p
+isl.isl_schedule_constraints_set_conditional_validity.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_schedule_constraints_set_context.restype = c_void_p
+isl.isl_schedule_constraints_set_context.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_constraints_set_proximity.restype = c_void_p
+isl.isl_schedule_constraints_set_proximity.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_constraints_set_validity.restype = c_void_p
+isl.isl_schedule_constraints_set_validity.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_constraints_copy.restype = c_void_p
+isl.isl_schedule_constraints_copy.argtypes = [c_void_p]
+isl.isl_schedule_constraints_free.restype = c_void_p
+isl.isl_schedule_constraints_free.argtypes = [c_void_p]
+isl.isl_schedule_constraints_to_str.restype = POINTER(c_char)
+isl.isl_schedule_constraints_to_str.argtypes = [c_void_p]
+
+class schedule_node(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_node_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_node("""%s""")' % s
+        else:
+            return 'isl.schedule_node("%s")' % s
+    def band_member_get_coincident(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_band_member_get_coincident(arg0.ptr, arg1)
+        if res < 0:
+            raise
+        return bool(res)
+    def band_member_set_coincident(arg0, arg1, arg2):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_band_member_set_coincident(isl.isl_schedule_node_copy(arg0.ptr), arg1, arg2)
+        return schedule_node(ctx=ctx, ptr=res)
+    def child(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_child(isl.isl_schedule_node_copy(arg0.ptr), arg1)
+        return schedule_node(ctx=ctx, ptr=res)
+    def get_prefix_schedule_multi_union_pw_aff(arg0):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(arg0.ptr)
+        return multi_union_pw_aff(ctx=ctx, ptr=res)
+    def get_prefix_schedule_union_map(arg0):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_get_prefix_schedule_union_map(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_prefix_schedule_union_pw_multi_aff(arg0):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(arg0.ptr)
+        return union_pw_multi_aff(ctx=ctx, ptr=res)
+    def get_schedule(arg0):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_get_schedule(arg0.ptr)
+        return schedule(ctx=ctx, ptr=res)
+    def parent(arg0):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_parent(isl.isl_schedule_node_copy(arg0.ptr))
+        return schedule_node(ctx=ctx, ptr=res)
+
+isl.isl_schedule_node_band_member_get_coincident.restype = c_bool
+isl.isl_schedule_node_band_member_get_coincident.argtypes = [c_void_p, c_int]
+isl.isl_schedule_node_band_member_set_coincident.restype = c_void_p
+isl.isl_schedule_node_band_member_set_coincident.argtypes = [c_void_p, c_int, c_int]
+isl.isl_schedule_node_child.restype = c_void_p
+isl.isl_schedule_node_child.argtypes = [c_void_p, c_int]
+isl.isl_schedule_node_get_prefix_schedule_multi_union_pw_aff.restype = c_void_p
+isl.isl_schedule_node_get_prefix_schedule_multi_union_pw_aff.argtypes = [c_void_p]
+isl.isl_schedule_node_get_prefix_schedule_union_map.restype = c_void_p
+isl.isl_schedule_node_get_prefix_schedule_union_map.argtypes = [c_void_p]
+isl.isl_schedule_node_get_prefix_schedule_union_pw_multi_aff.restype = c_void_p
+isl.isl_schedule_node_get_prefix_schedule_union_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_schedule_node_get_schedule.restype = c_void_p
+isl.isl_schedule_node_get_schedule.argtypes = [c_void_p]
+isl.isl_schedule_node_parent.restype = c_void_p
+isl.isl_schedule_node_parent.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+
+class union_access_info(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is union_map:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_access_info_from_sink(isl.isl_union_map_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_union_access_info_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
+        except:
+            raise
+        ptr = isl.isl_union_access_info_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.union_access_info("""%s""")' % s
+        else:
+            return 'isl.union_access_info("%s")' % s
+    def compute_flow(arg0):
+        try:
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_access_info_compute_flow(isl.isl_union_access_info_copy(arg0.ptr))
+        return union_flow(ctx=ctx, ptr=res)
+    def set_kill(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_access_info_set_kill(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_access_info(ctx=ctx, ptr=res)
+    def set_may_source(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_access_info_set_may_source(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_access_info(ctx=ctx, ptr=res)
+    def set_must_source(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_access_info_set_must_source(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_access_info(ctx=ctx, ptr=res)
+    def set_schedule(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is schedule:
+                arg1 = schedule(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_access_info_set_schedule(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_schedule_copy(arg1.ptr))
+        return union_access_info(ctx=ctx, ptr=res)
+    def set_schedule_map(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_access_info_set_schedule_map(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        return union_access_info(ctx=ctx, ptr=res)
+
+isl.isl_union_access_info_from_sink.restype = c_void_p
+isl.isl_union_access_info_from_sink.argtypes = [c_void_p]
+isl.isl_union_access_info_compute_flow.restype = c_void_p
+isl.isl_union_access_info_compute_flow.argtypes = [c_void_p]
+isl.isl_union_access_info_set_kill.restype = c_void_p
+isl.isl_union_access_info_set_kill.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_set_may_source.restype = c_void_p
+isl.isl_union_access_info_set_may_source.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_set_must_source.restype = c_void_p
+isl.isl_union_access_info_set_must_source.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_set_schedule.restype = c_void_p
+isl.isl_union_access_info_set_schedule.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_set_schedule_map.restype = c_void_p
+isl.isl_union_access_info_set_schedule_map.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_copy.restype = c_void_p
+isl.isl_union_access_info_copy.argtypes = [c_void_p]
+isl.isl_union_access_info_free.restype = c_void_p
+isl.isl_union_access_info_free.argtypes = [c_void_p]
+isl.isl_union_access_info_to_str.restype = POINTER(c_char)
+isl.isl_union_access_info_to_str.argtypes = [c_void_p]
+
+class union_flow(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_union_flow_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
+        except:
+            raise
+        ptr = isl.isl_union_flow_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.union_flow("""%s""")' % s
+        else:
+            return 'isl.union_flow("%s")' % s
+    def get_full_may_dependence(arg0):
+        try:
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_flow_get_full_may_dependence(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_full_must_dependence(arg0):
+        try:
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_flow_get_full_must_dependence(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_may_dependence(arg0):
+        try:
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_flow_get_may_dependence(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_may_no_source(arg0):
+        try:
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_flow_get_may_no_source(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_must_dependence(arg0):
+        try:
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_flow_get_must_dependence(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+    def get_must_no_source(arg0):
+        try:
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_flow_get_must_no_source(arg0.ptr)
+        return union_map(ctx=ctx, ptr=res)
+
+isl.isl_union_flow_get_full_may_dependence.restype = c_void_p
+isl.isl_union_flow_get_full_may_dependence.argtypes = [c_void_p]
+isl.isl_union_flow_get_full_must_dependence.restype = c_void_p
+isl.isl_union_flow_get_full_must_dependence.argtypes = [c_void_p]
+isl.isl_union_flow_get_may_dependence.restype = c_void_p
+isl.isl_union_flow_get_may_dependence.argtypes = [c_void_p]
+isl.isl_union_flow_get_may_no_source.restype = c_void_p
+isl.isl_union_flow_get_may_no_source.argtypes = [c_void_p]
+isl.isl_union_flow_get_must_dependence.restype = c_void_p
+isl.isl_union_flow_get_must_dependence.argtypes = [c_void_p]
+isl.isl_union_flow_get_must_no_source.restype = c_void_p
+isl.isl_union_flow_get_must_no_source.argtypes = [c_void_p]
+isl.isl_union_flow_copy.restype = c_void_p
+isl.isl_union_flow_copy.argtypes = [c_void_p]
+isl.isl_union_flow_free.restype = c_void_p
+isl.isl_union_flow_free.argtypes = [c_void_p]
+isl.isl_union_flow_to_str.restype = POINTER(c_char)
+isl.isl_union_flow_to_str.argtypes = [c_void_p]
+
+class val(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_val_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        if len(args) == 1 and type(args[0]) == int:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_val_int_from_si(self.ctx, args[0])
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_val_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ptr = isl.isl_val_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.val("""%s""")' % s
+        else:
+            return 'isl.val("%s")' % s
+    def abs(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_abs(isl.isl_val_copy(arg0.ptr))
+        return val(ctx=ctx, ptr=res)
+    def abs_eq(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_abs_eq(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_add(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+        return val(ctx=ctx, ptr=res)
+    def ceil(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_ceil(isl.isl_val_copy(arg0.ptr))
+        return val(ctx=ctx, ptr=res)
+    def cmp_si(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_cmp_si(arg0.ptr, arg1)
+        return res
+    def div(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_div(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+        return val(ctx=ctx, ptr=res)
+    def eq(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_eq(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def floor(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_floor(isl.isl_val_copy(arg0.ptr))
+        return val(ctx=ctx, ptr=res)
+    def gcd(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_gcd(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+        return val(ctx=ctx, ptr=res)
+    def ge(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_ge(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def gt(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_gt(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    @staticmethod
+    def infty():
+        ctx = Context.getDefaultInstance()
+        res = isl.isl_val_infty(ctx)
+        return val(ctx=ctx, ptr=res)
+    def inv(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_inv(isl.isl_val_copy(arg0.ptr))
+        return val(ctx=ctx, ptr=res)
+    def is_divisible_by(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_divisible_by(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_infty(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_infty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_int(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_int(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_nan(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_nan(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_neg(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_neg(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_neginfty(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_neginfty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_negone(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_negone(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_nonneg(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_nonneg(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_nonpos(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_nonpos(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_one(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_one(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_pos(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_pos(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_rat(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_rat(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_zero(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_is_zero(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def le(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_le(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lt(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_lt(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def max(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_max(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+        return val(ctx=ctx, ptr=res)
+    def min(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_min(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+        return val(ctx=ctx, ptr=res)
+    def mod(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_mod(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+        return val(ctx=ctx, ptr=res)
+    def mul(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_mul(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+        return val(ctx=ctx, ptr=res)
+    @staticmethod
+    def nan():
+        ctx = Context.getDefaultInstance()
+        res = isl.isl_val_nan(ctx)
+        return val(ctx=ctx, ptr=res)
+    def ne(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_ne(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def neg(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_neg(isl.isl_val_copy(arg0.ptr))
+        return val(ctx=ctx, ptr=res)
+    @staticmethod
+    def neginfty():
+        ctx = Context.getDefaultInstance()
+        res = isl.isl_val_neginfty(ctx)
+        return val(ctx=ctx, ptr=res)
+    @staticmethod
+    def negone():
+        ctx = Context.getDefaultInstance()
+        res = isl.isl_val_negone(ctx)
+        return val(ctx=ctx, ptr=res)
+    @staticmethod
+    def one():
+        ctx = Context.getDefaultInstance()
+        res = isl.isl_val_one(ctx)
+        return val(ctx=ctx, ptr=res)
+    def sgn(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_sgn(arg0.ptr)
+        return res
+    def sub(arg0, arg1):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_sub(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+        return val(ctx=ctx, ptr=res)
+    def trunc(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_trunc(isl.isl_val_copy(arg0.ptr))
+        return val(ctx=ctx, ptr=res)
+    @staticmethod
+    def zero():
+        ctx = Context.getDefaultInstance()
+        res = isl.isl_val_zero(ctx)
+        return val(ctx=ctx, ptr=res)
+
+isl.isl_val_read_from_str.restype = c_void_p
+isl.isl_val_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_val_int_from_si.restype = c_void_p
+isl.isl_val_int_from_si.argtypes = [Context, c_long]
+isl.isl_val_abs.restype = c_void_p
+isl.isl_val_abs.argtypes = [c_void_p]
+isl.isl_val_abs_eq.restype = c_bool
+isl.isl_val_abs_eq.argtypes = [c_void_p, c_void_p]
+isl.isl_val_add.restype = c_void_p
+isl.isl_val_add.argtypes = [c_void_p, c_void_p]
+isl.isl_val_ceil.restype = c_void_p
+isl.isl_val_ceil.argtypes = [c_void_p]
+isl.isl_val_cmp_si.argtypes = [c_void_p, c_long]
+isl.isl_val_div.restype = c_void_p
+isl.isl_val_div.argtypes = [c_void_p, c_void_p]
+isl.isl_val_eq.restype = c_bool
+isl.isl_val_eq.argtypes = [c_void_p, c_void_p]
+isl.isl_val_floor.restype = c_void_p
+isl.isl_val_floor.argtypes = [c_void_p]
+isl.isl_val_gcd.restype = c_void_p
+isl.isl_val_gcd.argtypes = [c_void_p, c_void_p]
+isl.isl_val_ge.restype = c_bool
+isl.isl_val_ge.argtypes = [c_void_p, c_void_p]
+isl.isl_val_gt.restype = c_bool
+isl.isl_val_gt.argtypes = [c_void_p, c_void_p]
+isl.isl_val_infty.restype = c_void_p
+isl.isl_val_infty.argtypes = [Context]
+isl.isl_val_inv.restype = c_void_p
+isl.isl_val_inv.argtypes = [c_void_p]
+isl.isl_val_is_divisible_by.restype = c_bool
+isl.isl_val_is_divisible_by.argtypes = [c_void_p, c_void_p]
+isl.isl_val_is_infty.restype = c_bool
+isl.isl_val_is_infty.argtypes = [c_void_p]
+isl.isl_val_is_int.restype = c_bool
+isl.isl_val_is_int.argtypes = [c_void_p]
+isl.isl_val_is_nan.restype = c_bool
+isl.isl_val_is_nan.argtypes = [c_void_p]
+isl.isl_val_is_neg.restype = c_bool
+isl.isl_val_is_neg.argtypes = [c_void_p]
+isl.isl_val_is_neginfty.restype = c_bool
+isl.isl_val_is_neginfty.argtypes = [c_void_p]
+isl.isl_val_is_negone.restype = c_bool
+isl.isl_val_is_negone.argtypes = [c_void_p]
+isl.isl_val_is_nonneg.restype = c_bool
+isl.isl_val_is_nonneg.argtypes = [c_void_p]
+isl.isl_val_is_nonpos.restype = c_bool
+isl.isl_val_is_nonpos.argtypes = [c_void_p]
+isl.isl_val_is_one.restype = c_bool
+isl.isl_val_is_one.argtypes = [c_void_p]
+isl.isl_val_is_pos.restype = c_bool
+isl.isl_val_is_pos.argtypes = [c_void_p]
+isl.isl_val_is_rat.restype = c_bool
+isl.isl_val_is_rat.argtypes = [c_void_p]
+isl.isl_val_is_zero.restype = c_bool
+isl.isl_val_is_zero.argtypes = [c_void_p]
+isl.isl_val_le.restype = c_bool
+isl.isl_val_le.argtypes = [c_void_p, c_void_p]
+isl.isl_val_lt.restype = c_bool
+isl.isl_val_lt.argtypes = [c_void_p, c_void_p]
+isl.isl_val_max.restype = c_void_p
+isl.isl_val_max.argtypes = [c_void_p, c_void_p]
+isl.isl_val_min.restype = c_void_p
+isl.isl_val_min.argtypes = [c_void_p, c_void_p]
+isl.isl_val_mod.restype = c_void_p
+isl.isl_val_mod.argtypes = [c_void_p, c_void_p]
+isl.isl_val_mul.restype = c_void_p
+isl.isl_val_mul.argtypes = [c_void_p, c_void_p]
+isl.isl_val_nan.restype = c_void_p
+isl.isl_val_nan.argtypes = [Context]
+isl.isl_val_ne.restype = c_bool
+isl.isl_val_ne.argtypes = [c_void_p, c_void_p]
+isl.isl_val_neg.restype = c_void_p
+isl.isl_val_neg.argtypes = [c_void_p]
+isl.isl_val_neginfty.restype = c_void_p
+isl.isl_val_neginfty.argtypes = [Context]
+isl.isl_val_negone.restype = c_void_p
+isl.isl_val_negone.argtypes = [Context]
+isl.isl_val_one.restype = c_void_p
+isl.isl_val_one.argtypes = [Context]
+isl.isl_val_sgn.argtypes = [c_void_p]
+isl.isl_val_sub.restype = c_void_p
+isl.isl_val_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_val_trunc.restype = c_void_p
+isl.isl_val_trunc.argtypes = [c_void_p]
+isl.isl_val_zero.restype = c_void_p
+isl.isl_val_zero.argtypes = [Context]
+isl.isl_val_copy.restype = c_void_p
+isl.isl_val_copy.argtypes = [c_void_p]
+isl.isl_val_free.restype = c_void_p
+isl.isl_val_free.argtypes = [c_void_p]
+isl.isl_val_to_str.restype = POINTER(c_char)
+isl.isl_val_to_str.argtypes = [c_void_p]
diff --git a/lib/External/isl/interface/python.cc b/lib/External/isl/interface/python.cc
new file mode 100644
index 0000000..68fdbb8
--- /dev/null
+++ b/lib/External/isl/interface/python.cc
@@ -0,0 +1,675 @@
+/*
+ * Copyright 2011,2015 Sven Verdoolaege. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as
+ * representing official policies, either expressed or implied, of
+ * Sven Verdoolaege.
+ */ 
+
+#include "isl_config.h"
+
+#include <stdio.h>
+#include <iostream>
+#include <map>
+#include <vector>
+
+#include "python.h"
+#include "generator.h"
+
+/* Drop the "isl_" initial part of the type name "name".
+ */
+static string type2python(string name)
+{
+	return name.substr(4);
+}
+
+/* Print the header of the method "name" with "n_arg" arguments.
+ * If "is_static" is set, then mark the python method as static.
+ *
+ * If the method is called "from", then rename it to "convert_from"
+ * because "from" is a python keyword.
+ */
+void python_generator::print_method_header(bool is_static, const string &name,
+	int n_arg)
+{
+	const char *s;
+
+	if (is_static)
+		printf("    @staticmethod\n");
+
+	s = name.c_str();
+	if (name == "from")
+		s = "convert_from";
+
+	printf("    def %s(", s);
+	for (int i = 0; i < n_arg; ++i) {
+		if (i)
+			printf(", ");
+		printf("arg%d", i);
+	}
+	printf("):\n");
+}
+
+/* Print a check that the argument in position "pos" is of type "type".
+ * If this fails and if "upcast" is set, then convert the first
+ * argument to "super" and call the method "name" on it, passing
+ * the remaining of the "n" arguments.
+ * If the check fails and "upcast" is not set, then simply raise
+ * an exception.
+ * If "upcast" is not set, then the "super", "name" and "n" arguments
+ * to this function are ignored.
+ */
+void python_generator::print_type_check(const string &type, int pos,
+	bool upcast, const string &super, const string &name, int n)
+{
+	printf("        try:\n");
+	printf("            if not arg%d.__class__ is %s:\n",
+		pos, type.c_str());
+	printf("                arg%d = %s(arg%d)\n",
+		pos, type.c_str(), pos);
+	printf("        except:\n");
+	if (upcast) {
+		printf("            return %s(arg0).%s(",
+			type2python(super).c_str(), name.c_str());
+		for (int i = 1; i < n; ++i) {
+			if (i != 1)
+				printf(", ");
+			printf("arg%d", i);
+		}
+		printf(")\n");
+	} else
+		printf("            raise\n");
+}
+
+/* Construct a wrapper for a callback argument (at position "arg").
+ * Assign the wrapper to "cb".  We assume here that a function call
+ * has at most one callback argument.
+ *
+ * The wrapper converts the arguments of the callback to python types.
+ * If any exception is thrown, the wrapper keeps track of it in exc_info[0]
+ * and returns -1.  Otherwise the wrapper returns 0.
+ */
+void python_generator::print_callback(QualType type, int arg)
+{
+	const FunctionProtoType *fn = type->getAs<FunctionProtoType>();
+	unsigned n_arg = fn->getNumArgs();
+
+	printf("        exc_info = [None]\n");
+	printf("        fn = CFUNCTYPE(c_int");
+	for (unsigned i = 0; i < n_arg - 1; ++i) {
+		if (!is_isl_type(fn->getArgType(i)))
+			die("Argument has non-isl type");
+		printf(", c_void_p");
+	}
+	printf(", c_void_p)\n");
+	printf("        def cb_func(");
+	for (unsigned i = 0; i < n_arg; ++i) {
+		if (i)
+			printf(", ");
+		printf("cb_arg%d", i);
+	}
+	printf("):\n");
+	for (unsigned i = 0; i < n_arg - 1; ++i) {
+		string arg_type;
+		arg_type = type2python(extract_type(fn->getArgType(i)));
+		printf("            cb_arg%d = %s(ctx=arg0.ctx, "
+			"ptr=cb_arg%d)\n", i, arg_type.c_str(), i);
+	}
+	printf("            try:\n");
+	printf("                arg%d(", arg);
+	for (unsigned i = 0; i < n_arg - 1; ++i) {
+		if (i)
+			printf(", ");
+		printf("cb_arg%d", i);
+	}
+	printf(")\n");
+	printf("            except:\n");
+	printf("                import sys\n");
+	printf("                exc_info[0] = sys.exc_info()\n");
+	printf("                return -1\n");
+	printf("            return 0\n");
+	printf("        cb = fn(cb_func)\n");
+}
+
+/* Print the argument at position "arg" in call to "fd".
+ * "skip" is the number of initial arguments of "fd" that are
+ * skipped in the Python method.
+ *
+ * If the argument is a callback, then print a reference to
+ * the callback wrapper "cb".
+ * Otherwise, if the argument is marked as consuming a reference,
+ * then pass a copy of the pointer stored in the corresponding
+ * argument passed to the Python method.
+ * Otherwise, if the argument is a pointer, then pass this pointer itself.
+ * Otherwise, pass the argument directly.
+ */
+void python_generator::print_arg_in_call(FunctionDecl *fd, int arg, int skip)
+{
+	ParmVarDecl *param = fd->getParamDecl(arg);
+	QualType type = param->getOriginalType();
+	if (is_callback(type)) {
+		printf("cb");
+	} else if (takes(param)) {
+		string type_s = extract_type(type);
+		printf("isl.%s_copy(arg%d.ptr)", type_s.c_str(), arg - skip);
+	} else if (type->isPointerType()) {
+		printf("arg%d.ptr", arg - skip);
+	} else {
+		printf("arg%d", arg - skip);
+	}
+}
+
+/* Print the return statement of the python method corresponding
+ * to the C function "method".
+ *
+ * If the return type is a (const) char *, then convert the result
+ * to a Python string, raising an error on NULL and freeing
+ * the C string if needed.  For python 3 compatibility, the string returned
+ * by isl is explicitly decoded as an 'ascii' string.  This is correct
+ * as all strings returned by isl are expected to be 'ascii'.
+ *
+ * If the return type is isl_bool, then convert the result to
+ * a Python boolean, raising an error on isl_bool_error.
+ */
+void python_generator::print_method_return(FunctionDecl *method)
+{
+	QualType return_type = method->getReturnType();
+
+	if (is_isl_type(return_type)) {
+		string type;
+
+		type = type2python(extract_type(return_type));
+		printf("        return %s(ctx=ctx, ptr=res)\n", type.c_str());
+	} else if (is_string(return_type)) {
+		printf("        if res == 0:\n");
+		printf("            raise\n");
+		printf("        string = "
+		       "cast(res, c_char_p).value.decode('ascii')\n");
+
+		if (gives(method))
+			printf("        libc.free(res)\n");
+
+		printf("        return string\n");
+	} else if (is_isl_bool(return_type)) {
+		printf("        if res < 0:\n");
+		printf("            raise\n");
+		printf("        return bool(res)\n");
+	} else {
+		printf("        return res\n");
+	}
+}
+
+/* Print a python method corresponding to the C function "method".
+ * "super" contains the superclasses of the class to which the method belongs,
+ * with the first element corresponding to the annotation that appears
+ * closest to the annotated type.  This superclass is the least
+ * general extension of the annotated type in the linearization
+ * of the class hierarchy.
+ *
+ * If the first argument of "method" is something other than an instance
+ * of the class, then mark the python method as static.
+ * If, moreover, this first argument is an isl_ctx, then remove
+ * it from the arguments of the Python method.
+ *
+ * If the function has a callback argument, then it also has a "user"
+ * argument.  Since Python has closures, there is no need for such
+ * a user argument in the Python interface, so we simply drop it.
+ * We also create a wrapper ("cb") for the callback.
+ *
+ * For each argument of the function that refers to an isl structure,
+ * including the object on which the method is called,
+ * we check if the corresponding actual argument is of the right type.
+ * If not, we try to convert it to the right type.
+ * If that doesn't work and if "super" contains at least one element, we try
+ * to convert self to the type of the first superclass in "super" and
+ * call the corresponding method.
+ *
+ * If the function consumes a reference, then we pass it a copy of
+ * the actual argument.
+ */
+void python_generator::print_method(const isl_class &clazz,
+	FunctionDecl *method, vector<string> super)
+{
+	string fullname = method->getName();
+	string cname = fullname.substr(clazz.name.length() + 1);
+	int num_params = method->getNumParams();
+	int drop_user = 0;
+	int drop_ctx = first_arg_is_isl_ctx(method);
+
+	for (int i = 1; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		if (is_callback(type))
+			drop_user = 1;
+	}
+
+	print_method_header(is_static(clazz, method), cname,
+			    num_params - drop_ctx - drop_user);
+
+	for (int i = drop_ctx; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		string type;
+		if (!is_isl_type(param->getOriginalType()))
+			continue;
+		type = type2python(extract_type(param->getOriginalType()));
+		if (!drop_ctx && i > 0 && super.size() > 0)
+			print_type_check(type, i - drop_ctx, true, super[0],
+					cname, num_params - drop_user);
+		else
+			print_type_check(type, i - drop_ctx, false, "",
+					cname, -1);
+	}
+	for (int i = 1; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		if (!is_callback(type))
+			continue;
+		print_callback(type->getPointeeType(), i - drop_ctx);
+	}
+	if (drop_ctx)
+		printf("        ctx = Context.getDefaultInstance()\n");
+	else
+		printf("        ctx = arg0.ctx\n");
+	printf("        res = isl.%s(", fullname.c_str());
+	if (drop_ctx)
+		printf("ctx");
+	else
+		print_arg_in_call(method, 0, 0);
+	for (int i = 1; i < num_params - drop_user; ++i) {
+		printf(", ");
+		print_arg_in_call(method, i, drop_ctx);
+	}
+	if (drop_user)
+		printf(", None");
+	printf(")\n");
+
+	if (drop_user) {
+		printf("        if exc_info[0] != None:\n");
+		printf("            raise (exc_info[0][0], "
+			"exc_info[0][1], exc_info[0][2])\n");
+	}
+
+	print_method_return(method);
+}
+
+/* Print part of an overloaded python method corresponding to the C function
+ * "method".
+ *
+ * In particular, print code to test whether the arguments passed to
+ * the python method correspond to the arguments expected by "method"
+ * and to call "method" if they do.
+ */
+void python_generator::print_method_overload(const isl_class &clazz,
+	FunctionDecl *method)
+{
+	string fullname = method->getName();
+	int num_params = method->getNumParams();
+	int first;
+	string type;
+
+	first = is_static(clazz, method) ? 0 : 1;
+
+	printf("        if ");
+	for (int i = first; i < num_params; ++i) {
+		if (i > first)
+			printf(" and ");
+		ParmVarDecl *param = method->getParamDecl(i);
+		if (is_isl_type(param->getOriginalType())) {
+			string type;
+			type = extract_type(param->getOriginalType());
+			type = type2python(type);
+			printf("arg%d.__class__ is %s", i, type.c_str());
+		} else
+			printf("type(arg%d) == str", i);
+	}
+	printf(":\n");
+	printf("            res = isl.%s(", fullname.c_str());
+	print_arg_in_call(method, 0, 0);
+	for (int i = 1; i < num_params; ++i) {
+		printf(", ");
+		print_arg_in_call(method, i, 0);
+	}
+	printf(")\n");
+	type = type2python(extract_type(method->getReturnType()));
+	printf("            return %s(ctx=arg0.ctx, ptr=res)\n", type.c_str());
+}
+
+/* Print a python method with a name derived from "fullname"
+ * corresponding to the C functions "methods".
+ * "super" contains the superclasses of the class to which the method belongs.
+ *
+ * If "methods" consists of a single element that is not marked overloaded,
+ * the use print_method to print the method.
+ * Otherwise, print an overloaded method with pieces corresponding
+ * to each function in "methods".
+ */
+void python_generator::print_method(const isl_class &clazz,
+	const string &fullname, const set<FunctionDecl *> &methods,
+	vector<string> super)
+{
+	string cname;
+	set<FunctionDecl *>::const_iterator it;
+	int num_params;
+	FunctionDecl *any_method;
+
+	any_method = *methods.begin();
+	if (methods.size() == 1 && !is_overload(any_method)) {
+		print_method(clazz, any_method, super);
+		return;
+	}
+
+	cname = fullname.substr(clazz.name.length() + 1);
+	num_params = any_method->getNumParams();
+
+	print_method_header(is_static(clazz, any_method), cname, num_params);
+
+	for (it = methods.begin(); it != methods.end(); ++it)
+		print_method_overload(clazz, *it);
+}
+
+/* Print part of the constructor for this isl_class.
+ *
+ * In particular, check if the actual arguments correspond to the
+ * formal arguments of "cons" and if so call "cons" and put the
+ * result in self.ptr and a reference to the default context in self.ctx.
+ *
+ * If the function consumes a reference, then we pass it a copy of
+ * the actual argument.
+ *
+ * If the function takes a string argument, the python string is first
+ * encoded as a byte sequence, using 'ascii' as encoding.  This assumes
+ * that all strings passed to isl can be converted to 'ascii'.
+ */
+void python_generator::print_constructor(const isl_class &clazz,
+	FunctionDecl *cons)
+{
+	string fullname = cons->getName();
+	string cname = fullname.substr(clazz.name.length() + 1);
+	int num_params = cons->getNumParams();
+	int drop_ctx = first_arg_is_isl_ctx(cons);
+
+	printf("        if len(args) == %d", num_params - drop_ctx);
+	for (int i = drop_ctx; i < num_params; ++i) {
+		ParmVarDecl *param = cons->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		if (is_isl_type(type)) {
+			string s;
+			s = type2python(extract_type(type));
+			printf(" and args[%d].__class__ is %s",
+				i - drop_ctx, s.c_str());
+		} else if (type->isPointerType()) {
+			printf(" and type(args[%d]) == str", i - drop_ctx);
+		} else {
+			printf(" and type(args[%d]) == int", i - drop_ctx);
+		}
+	}
+	printf(":\n");
+	printf("            self.ctx = Context.getDefaultInstance()\n");
+	printf("            self.ptr = isl.%s(", fullname.c_str());
+	if (drop_ctx)
+		printf("self.ctx");
+	for (int i = drop_ctx; i < num_params; ++i) {
+		ParmVarDecl *param = cons->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		if (i)
+			printf(", ");
+		if (is_isl_type(type)) {
+			if (takes(param)) {
+				string type;
+				type = extract_type(param->getOriginalType());
+				printf("isl.%s_copy(args[%d].ptr)",
+					type.c_str(), i - drop_ctx);
+			} else
+				printf("args[%d].ptr", i - drop_ctx);
+		} else if (is_string(type)) {
+			printf("args[%d].encode('ascii')", i - drop_ctx);
+		} else {
+			printf("args[%d]", i - drop_ctx);
+		}
+	}
+	printf(")\n");
+	printf("            return\n");
+}
+
+/* Print the header of the class "name" with superclasses "super".
+ * The order of the superclasses is the opposite of the order
+ * in which the corresponding annotations appear in the source code.
+ */
+void python_generator::print_class_header(const isl_class &clazz,
+	const string &name, const vector<string> &super)
+{
+	printf("class %s", name.c_str());
+	if (super.size() > 0) {
+		printf("(");
+		for (unsigned i = 0; i < super.size(); ++i) {
+			if (i > 0)
+				printf(", ");
+			printf("%s", type2python(super[i]).c_str());
+		}
+		printf(")");
+	} else {
+		printf("(object)");
+	}
+	printf(":\n");
+}
+
+/* Tell ctypes about the return type of "fd".
+ * In particular, if "fd" returns a pointer to an isl object,
+ * then tell ctypes it returns a "c_void_p".
+ * Similarly, if "fd" returns an isl_bool,
+ * then tell ctypes it returns a "c_bool".
+ * If "fd" returns a char *, then simply tell ctypes.
+ */
+void python_generator::print_restype(FunctionDecl *fd)
+{
+	string fullname = fd->getName();
+	QualType type = fd->getReturnType();
+	if (is_isl_type(type))
+		printf("isl.%s.restype = c_void_p\n", fullname.c_str());
+	else if (is_isl_bool(type))
+		printf("isl.%s.restype = c_bool\n", fullname.c_str());
+	else if (is_string(type))
+		printf("isl.%s.restype = POINTER(c_char)\n", fullname.c_str());
+}
+
+/* Tell ctypes about the types of the arguments of the function "fd".
+ */
+void python_generator::print_argtypes(FunctionDecl *fd)
+{
+	string fullname = fd->getName();
+	int n = fd->getNumParams();
+	int drop_user = 0;
+
+	printf("isl.%s.argtypes = [", fullname.c_str());
+	for (int i = 0; i < n - drop_user; ++i) {
+		ParmVarDecl *param = fd->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		if (is_callback(type))
+			drop_user = 1;
+		if (i)
+			printf(", ");
+		if (is_isl_ctx(type))
+			printf("Context");
+		else if (is_isl_type(type) || is_callback(type))
+			printf("c_void_p");
+		else if (is_string(type))
+			printf("c_char_p");
+		else if (is_long(type))
+			printf("c_long");
+		else
+			printf("c_int");
+	}
+	if (drop_user)
+		printf(", c_void_p");
+	printf("]\n");
+}
+
+/* Print type definitions for the method 'fd'.
+ */
+void python_generator::print_method_type(FunctionDecl *fd)
+{
+	print_restype(fd);
+	print_argtypes(fd);
+}
+
+/* Print declarations for methods printing the class representation,
+ * provided there is a corresponding *_to_str function.
+ *
+ * In particular, provide an implementation of __str__ and __repr__ methods to
+ * override the default representation used by python. Python uses __str__ to
+ * pretty print the class (e.g., when calling print(obj)) and uses __repr__
+ * when printing a precise representation of an object (e.g., when dumping it
+ * in the REPL console).
+ *
+ * Check the type of the argument before calling the *_to_str function
+ * on it in case the method was called on an object from a subclass.
+ *
+ * The return value of the *_to_str function is decoded to a python string
+ * assuming an 'ascii' encoding.  This is necessary for python 3 compatibility.
+ */
+void python_generator::print_representation(const isl_class &clazz,
+	const string &python_name)
+{
+	if (!clazz.fn_to_str)
+		return;
+
+	printf("    def __str__(arg0):\n");
+	print_type_check(python_name, 0, false, "", "", -1);
+	printf("        ptr = isl.%s(arg0.ptr)\n",
+		string(clazz.fn_to_str->getName()).c_str());
+	printf("        res = cast(ptr, c_char_p).value.decode('ascii')\n");
+	printf("        libc.free(ptr)\n");
+	printf("        return res\n");
+	printf("    def __repr__(self):\n");
+	printf("        s = str(self)\n");
+	printf("        if '\"' in s:\n");
+	printf("            return 'isl.%s(\"\"\"%%s\"\"\")' %% s\n",
+		python_name.c_str());
+	printf("        else:\n");
+	printf("            return 'isl.%s(\"%%s\")' %% s\n",
+		python_name.c_str());
+}
+
+/* Print code to set method type signatures.
+ *
+ * To be able to call C functions it is necessary to explicitly set their
+ * argument and result types.  Do this for all exported constructors and
+ * methods, as well as for the *_to_str method, if it exists.
+ * Assuming each exported class has a *_copy and a *_free method,
+ * also unconditionally set the type of such methods.
+ */
+void python_generator::print_method_types(const isl_class &clazz)
+{
+	set<FunctionDecl *>::const_iterator in;
+	map<string, set<FunctionDecl *> >::const_iterator it;
+
+	for (in = clazz.constructors.begin(); in != clazz.constructors.end();
+		++in)
+		print_method_type(*in);
+
+	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
+		for (in = it->second.begin(); in != it->second.end(); ++in)
+			print_method_type(*in);
+
+	print_method_type(clazz.fn_copy);
+	print_method_type(clazz.fn_free);
+	if (clazz.fn_to_str)
+		print_method_type(clazz.fn_to_str);
+}
+
+/* Print out the definition of this isl_class.
+ *
+ * We first check if this isl_class is a subclass of one or more other classes.
+ * If it is, we make sure those superclasses are printed out first.
+ *
+ * Then we print a constructor with several cases, one for constructing
+ * a Python object from a return value and one for each function that
+ * was marked as a constructor.
+ *
+ * Next, we print out some common methods and the methods corresponding
+ * to functions that are not marked as constructors.
+ *
+ * Finally, we tell ctypes about the types of the arguments of the
+ * constructor functions and the return types of those function returning
+ * an isl object.
+ */
+void python_generator::print(const isl_class &clazz)
+{
+	string p_name = type2python(clazz.name);
+	set<FunctionDecl *>::const_iterator in;
+	map<string, set<FunctionDecl *> >::const_iterator it;
+	vector<string> super = find_superclasses(clazz.type);
+
+	for (unsigned i = 0; i < super.size(); ++i)
+		if (done.find(super[i]) == done.end())
+			print(classes[super[i]]);
+	done.insert(clazz.name);
+
+	printf("\n");
+	print_class_header(clazz, p_name, super);
+	printf("    def __init__(self, *args, **keywords):\n");
+
+	printf("        if \"ptr\" in keywords:\n");
+	printf("            self.ctx = keywords[\"ctx\"]\n");
+	printf("            self.ptr = keywords[\"ptr\"]\n");
+	printf("            return\n");
+
+	for (in = clazz.constructors.begin(); in != clazz.constructors.end();
+		++in)
+		print_constructor(clazz, *in);
+	printf("        raise Error\n");
+	printf("    def __del__(self):\n");
+	printf("        if hasattr(self, 'ptr'):\n");
+	printf("            isl.%s_free(self.ptr)\n", clazz.name.c_str());
+
+	print_representation(clazz, p_name);
+
+	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
+		print_method(clazz, it->first, it->second, super);
+
+	printf("\n");
+
+	print_method_types(clazz);
+}
+
+/* Generate a python interface based on the extracted types and
+ * functions.
+ *
+ * Print out each class in turn.  If one of these is a subclass of some
+ * other class, make sure the superclass is printed out first.
+ * functions.
+ */
+void python_generator::generate()
+{
+	map<string, isl_class>::iterator ci;
+
+	for (ci = classes.begin(); ci != classes.end(); ++ci) {
+		if (done.find(ci->first) == done.end())
+			print(ci->second);
+	}
+}
diff --git a/lib/External/isl/interface/python.h b/lib/External/isl/interface/python.h
new file mode 100644
index 0000000..554e52f
--- /dev/null
+++ b/lib/External/isl/interface/python.h
@@ -0,0 +1,45 @@
+#include <set>
+#include <clang/AST/Decl.h>
+#include "generator.h"
+
+using namespace std;
+using namespace clang;
+
+class python_generator : public generator {
+private:
+	set<string> done;
+
+public:
+	python_generator(set<RecordDecl *> &exported_types,
+		set<FunctionDecl *> exported_functions,
+		set<FunctionDecl *> functions) :
+		generator(exported_types, exported_functions, functions) {}
+
+	virtual void generate();
+
+private:
+	void print(const isl_class &clazz);
+	void print_method_header(bool is_static, const string &name, int n_arg);
+	void print_class_header(const isl_class &clazz, const string &name,
+		const vector<string> &super);
+	void print_type_check(const string &type, int pos, bool upcast,
+		const string &super, const string &name, int n);
+	void print_callback(QualType type, int arg);
+	void print_arg_in_call(FunctionDecl *fd, int arg, int skip);
+	void print_argtypes(FunctionDecl *fd);
+	void print_method_return(FunctionDecl *method);
+	void print_restype(FunctionDecl *fd);
+	void print(map<string, isl_class> &classes, set<string> &done);
+	void print_constructor(const isl_class &clazz, FunctionDecl *method);
+	void print_representation(const isl_class &clazz,
+		const string &python_name);
+	void print_method_type(FunctionDecl *fd);
+	void print_method_types(const isl_class &clazz);
+	void print_method(const isl_class &clazz, FunctionDecl *method,
+		vector<string> super);
+	void print_method_overload(const isl_class &clazz,
+		FunctionDecl *method);
+	void print_method(const isl_class &clazz, const string &fullname,
+		const set<FunctionDecl *> &methods, vector<string> super);
+
+};
diff --git a/lib/External/isl/isl_coalesce.c b/lib/External/isl/isl_coalesce.c
index 748d2f9..922c47f 100644
--- a/lib/External/isl/isl_coalesce.c
+++ b/lib/External/isl/isl_coalesce.c
@@ -1510,6 +1510,7 @@
 
 	isl_seq_cpy(bound->el, info[i].bmap->ineq[k], 1 + total);
 	isl_int_add_ui(bound->el[0], bound->el[0], 1);
+	isl_seq_normalize(ctx, bound->el, 1 + total);
 
 	isl_seq_cpy(wraps.mat->row[0], bound->el, 1 + total);
 	wraps.mat->n_row = 1;
diff --git a/lib/External/isl/isl_config.h.in b/lib/External/isl/isl_config.h.in
index e2ec2ea..27b6f94 100644
--- a/lib/External/isl/isl_config.h.in
+++ b/lib/External/isl/isl_config.h.in
@@ -34,6 +34,9 @@
 /* Define if clang/Basic/DiagnosticOptions.h exists */
 #undef HAVE_BASIC_DIAGNOSTICOPTIONS_H
 
+/* define if the compiler supports basic C++11 syntax */
+#undef HAVE_CXX11
+
 /* Define if Driver constructor takes CXXIsProduction argument */
 #undef HAVE_CXXISPRODUCTION
 
diff --git a/lib/External/isl/isl_output.c b/lib/External/isl/isl_output.c
index da54f43..338077b 100644
--- a/lib/External/isl/isl_output.c
+++ b/lib/External/isl/isl_output.c
@@ -268,6 +268,9 @@
 	enum isl_dim_type type;
 	int print_div_def;
 
+	if (!p || !space)
+		return isl_printer_free(p);
+
 	if (pos == 0)
 		return isl_printer_print_isl_int(p, c);
 
@@ -604,7 +607,7 @@
 	unsigned n_div;
 	enum isl_dim_type type;
 
-	if (!p)
+	if (!p || !space)
 		return -1;
 	n_div = isl_mat_rows(div);
 	if (p->output_format == ISL_FORMAT_C)
@@ -2080,11 +2083,14 @@
 }
 
 static __isl_give isl_printer *print_term_c(__isl_take isl_printer *p,
-	__isl_keep isl_space *dim,
+	__isl_keep isl_space *space,
 	__isl_keep isl_basic_set *bset, isl_int c, unsigned pos)
 {
 	enum isl_dim_type type;
 
+	if (!p || !space)
+		return isl_printer_free(p);
+
 	if (pos == 0)
 		return isl_printer_print_isl_int(p, c);
 
@@ -2096,8 +2102,8 @@
 		p = isl_printer_print_isl_int(p, c);
 		p = isl_printer_print_str(p, "*");
 	}
-	type = pos2type(dim, &pos);
-	p = print_name_c(p, dim, bset, type, pos);
+	type = pos2type(space, &pos);
+	p = print_name_c(p, space, bset, type, pos);
 	return p;
 }
 
@@ -2718,6 +2724,9 @@
 {
 	enum isl_dim_type type;
 
+	if (!p || !ls)
+		return isl_printer_free(p);
+
 	if (pos == 0)
 		return isl_printer_print_isl_int(p, c);
 
diff --git a/lib/External/isl/isl_test.c b/lib/External/isl/isl_test.c
index 3412e17..5633620 100644
--- a/lib/External/isl/isl_test.c
+++ b/lib/External/isl/isl_test.c
@@ -2112,6 +2112,7 @@
 		"(c = 4 + a and 4 * floor((a)/4) = a and a >= 0 and a <= 4) or "
 		"(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and "
 		    "a > 0 and a <= 5) }" },
+	{ 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" },
 };
 
 /* A specialized coalescing test case that would result
@@ -4436,109 +4437,6 @@
 	return 0;
 }
 
-/* Check that the dependence carrying step is not confused by
- * a bound on the coefficient size.
- * In particular, force the scheduler to move to a dependence carrying
- * step by demanding outer coincidence and bound the size of
- * the coefficients.  Earlier versions of isl would take this
- * bound into account while carrying dependences, breaking
- * fundamental assumptions.
- * On the other hand, the dependence carrying step now tries
- * to prevent loop coalescing by default, so check that indeed
- * no loop coalescing occurs by comparing the computed schedule
- * to the expected non-coalescing schedule.
- */
-static int test_bounded_coefficients_schedule(isl_ctx *ctx)
-{
-	const char *domain, *dep;
-	isl_union_set *I;
-	isl_union_map *D;
-	isl_schedule_constraints *sc;
-	isl_schedule *schedule;
-	isl_union_map *sched1, *sched2;
-	isl_bool equal;
-
-	domain = "{ C[i0, i1] : 2 <= i0 <= 3999 and 0 <= i1 <= -1 + i0 }";
-	dep = "{ C[i0, i1] -> C[i0, 1 + i1] : i0 <= 3999 and i1 >= 0 and "
-						"i1 <= -2 + i0; "
-		"C[i0, -1 + i0] -> C[1 + i0, 0] : i0 <= 3998 and i0 >= 1 }";
-	I = isl_union_set_read_from_str(ctx, domain);
-	D = isl_union_map_read_from_str(ctx, dep);
-	sc = isl_schedule_constraints_on_domain(I);
-	sc = isl_schedule_constraints_set_validity(sc, isl_union_map_copy(D));
-	sc = isl_schedule_constraints_set_coincidence(sc, D);
-	isl_options_set_schedule_outer_coincidence(ctx, 1);
-	isl_options_set_schedule_max_coefficient(ctx, 20);
-	schedule = isl_schedule_constraints_compute_schedule(sc);
-	isl_options_set_schedule_max_coefficient(ctx, -1);
-	isl_options_set_schedule_outer_coincidence(ctx, 0);
-	sched1 = isl_schedule_get_map(schedule);
-	isl_schedule_free(schedule);
-
-	sched2 = isl_union_map_read_from_str(ctx, "{ C[x,y] -> [x,y] }");
-	equal = isl_union_map_is_equal(sched1, sched2);
-	isl_union_map_free(sched1);
-	isl_union_map_free(sched2);
-
-	if (equal < 0)
-		return -1;
-	if (!equal)
-		isl_die(ctx, isl_error_unknown,
-			"unexpected schedule", return -1);
-
-	return 0;
-}
-
-/* Check that the bounds on the coefficients are respected.
- * This function checks for a particular output schedule,
- * but the exact output is not important, only that it does
- * not contain any coefficients greater than 4.
- * It is, however, easier to check for a particular output.
- * This test is only run for the whole component scheduler
- * because the incremental scheduler produces a slightly different schedule.
- */
-static int test_bounded_coefficients_schedule_whole(isl_ctx *ctx)
-{
-	const char *domain, *dep, *str;
-	isl_union_set *I;
-	isl_union_map *D;
-	isl_schedule_constraints *sc;
-	isl_schedule *schedule;
-	isl_union_map *sched1, *sched2;
-	isl_bool equal;
-
-	domain = "{ S_4[i, j, k] : 0 <= i < j <= 10 and 0 <= k <= 100; "
-	    "S_2[i, j] : 0 <= i < j <= 10; S_6[i, j] : 0 <= i < j <= 10 }";
-	dep = "{ S_2[0, j] -> S_4[0, j, 0] : 0 < j <= 10; "
-	    "S_4[0, j, 100] -> S_6[0, j] : 0 < j <= 10 }";
-	I = isl_union_set_read_from_str(ctx, domain);
-	D = isl_union_map_read_from_str(ctx, dep);
-	sc = isl_schedule_constraints_on_domain(I);
-	sc = isl_schedule_constraints_set_validity(sc, D);
-	isl_options_set_schedule_max_constant_term(ctx, 10);
-	isl_options_set_schedule_max_coefficient(ctx, 4);
-	schedule = isl_schedule_constraints_compute_schedule(sc);
-	isl_options_set_schedule_max_coefficient(ctx, -1);
-	isl_options_set_schedule_max_constant_term(ctx, -1);
-	sched1 = isl_schedule_get_map(schedule);
-	isl_schedule_free(schedule);
-
-	str = "{ S_4[i, j, k] -> [i, j, 10 - k]; "
-	    "S_2[i, j] -> [0, i, j]; S_6[i, j] -> [0, 10 + i, j] }";
-	sched2 = isl_union_map_read_from_str(ctx, str);
-	equal = isl_union_map_is_equal(sched1, sched2);
-	isl_union_map_free(sched1);
-	isl_union_map_free(sched2);
-
-	if (equal < 0)
-		return -1;
-	if (!equal)
-		isl_die(ctx, isl_error_unknown,
-			"unexpected schedule", return -1);
-
-	return 0;
-}
-
 /* Check that a set of schedule constraints that only allow for
  * a coalescing schedule still produces a schedule even if the user
  * request a non-coalescing schedule.  Earlier versions of isl
@@ -4894,8 +4792,6 @@
 	if (test_conflicting_context_schedule(ctx) < 0)
 		return -1;
 
-	if (test_bounded_coefficients_schedule(ctx) < 0)
-		return -1;
 	if (test_coalescing_schedule(ctx) < 0)
 		return -1;
 	if (test_skewing_schedule(ctx) < 0)
@@ -4914,8 +4810,6 @@
 	whole = isl_options_get_schedule_whole_component(ctx);
 	isl_options_set_schedule_whole_component(ctx, 1);
 	r = test_schedule(ctx);
-	if (r >= 0)
-		r = test_bounded_coefficients_schedule_whole(ctx);
 	isl_options_set_schedule_whole_component(ctx, whole);
 
 	return r;
diff --git a/lib/External/isl/isl_test_cpp-checked-conversion.cc b/lib/External/isl/isl_test_cpp-checked-conversion.cc
new file mode 100644
index 0000000..a4aeaf5
--- /dev/null
+++ b/lib/External/isl/isl_test_cpp-checked-conversion.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018      Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege.
+ */
+
+#include <stdlib.h>
+
+#include <isl/ctx.h>
+#include <isl/options.h>
+#include <isl/cpp-checked-conversion.h>
+
+/* Check that converting a NULL object from the checked C++ bindings
+ * (where the user is expected to check for NULL return values)
+ * to the default C++ bindings (where exceptions are raised
+ * instead of returning a NULL object) raises an exception.
+ */
+static void check_conversion_null(isl_ctx *ctx)
+{
+	isl::checked::set checked_set;
+	isl::set set;
+
+	bool caught = false;
+	try {
+		set = isl::uncheck(checked_set);
+		isl_die(ctx, isl_error_unknown, "no exception raised", return);
+	} catch (const isl::exception &e) {
+		caught = true;
+	}
+	if (!caught)
+		isl_die(ctx, isl_error_unknown, "no exception raised", return);
+}
+
+/* Dummy function on a set in the checked C++ bindings.
+ */
+static void f_checked(isl::checked::set set)
+{
+}
+
+/* Dummy function on a set in the default C++ bindings.
+ */
+static void f_unchecked(isl::set set)
+{
+}
+
+/* Check the conversion between C++ bindings in function calls.
+ * An incorrect call will result in a compiler error.
+ */
+static void check_conversion_call(isl_ctx *ctx)
+{
+	isl::set set(ctx, "{ S[i] : 0 <= i < 10 }");
+	isl::checked::set checked_set(ctx, "{ S[i] : 0 <= i < 10 }");
+
+	f_unchecked(set);
+	f_checked(isl::check(set));
+	f_unchecked(isl::uncheck(checked_set));
+	f_checked(checked_set);
+}
+
+/* Check that a double conversion results in the original set,
+ * or at least something that is equal to the original set.
+ */
+static void check_conversion_equal(isl_ctx *ctx)
+{
+	isl::set set(ctx, "{ S[i] : 0 <= i < 10 }");
+	isl::set set2;
+	isl::checked::set checked_set;
+
+	checked_set = isl::check(set);
+	set2 = isl::uncheck(checked_set);
+
+	if (!set.is_equal(set2))
+		isl_die(ctx, isl_error_unknown, "bad conversion", return);
+}
+
+/* Perform some tests on the conversion between the default C++ bindings and
+ * the checked C++ bindings.
+ */
+static void check_conversion(isl_ctx *ctx)
+{
+	check_conversion_null(ctx);
+	check_conversion_call(ctx);
+	check_conversion_equal(ctx);
+}
+
+int main()
+{
+	isl_ctx *ctx = isl_ctx_alloc();
+
+	isl_options_set_on_error(ctx, ISL_ON_ERROR_ABORT);
+
+	check_conversion(ctx);
+
+	isl_ctx_free(ctx);
+
+	return EXIT_SUCCESS;
+}
diff --git a/lib/External/isl/isl_test_cpp-checked.cc b/lib/External/isl/isl_test_cpp-checked.cc
new file mode 100644
index 0000000..fd49929
--- /dev/null
+++ b/lib/External/isl/isl_test_cpp-checked.cc
@@ -0,0 +1,176 @@
+/* Copyright 2016-2017 Tobias Grosser
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Tobias Grosser, Weststrasse 47, CH-8003, Zurich
+ */
+
+#include <vector>
+#include <string>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isl/options.h>
+#include <isl/cpp-checked.h>
+
+namespace isl { using namespace checked; }
+
+static void assert_impl(bool condition, const char *file, int line,
+	const char *message)
+{
+	if (condition)
+		return;
+
+	fprintf(stderr, "Assertion failed in %s:%d %s\n", file, line, message);
+	exit(EXIT_FAILURE);
+}
+
+static void assert_impl(isl::boolean condition, const char *file, int line,
+	const char *message)
+{
+	assert_impl(bool(condition), file, line, message);
+}
+
+#define assert(exp) assert_impl(exp, __FILE__, __LINE__, #exp)
+#define IS_TRUE(b)	(b).is_true()
+
+#include "isl_test_cpp-generic.cc"
+
+/* Test that isl_bool values are returned correctly.
+ *
+ * We check in detail the following parts of the isl::boolean class:
+ *  - The is_true, is_false, and is_error functions return true in case they
+ *    are called on a true, false, or error instance of isl::boolean,
+ *    respectively
+ *  - Explicit conversion to 'bool'
+ *  - Implicit conversion to 'bool'
+ *  - The complement operator
+ *  - Explicit construction from 'true' and 'false'
+ *  - Explicit construction form isl_bool
+ */
+void test_return_bool(isl::ctx ctx)
+{
+	isl::set empty(ctx, "{ : false }");
+	isl::set univ(ctx, "{ : }");
+	isl::set null;
+
+	isl::boolean b_true = empty.is_empty();
+	isl::boolean b_false = univ.is_empty();
+	isl::boolean b_error = null.is_empty();
+
+	assert(b_true.is_true());
+	assert(!b_true.is_false());
+	assert(!b_true.is_error());
+
+	assert(!b_false.is_true());
+	assert(b_false.is_false());
+	assert(!b_false.is_error());
+
+	assert(!b_error.is_true());
+	assert(!b_error.is_false());
+	assert(b_error.is_error());
+
+	assert(bool(b_true) == true);
+	assert(bool(b_false) == false);
+
+	assert(b_true);
+
+	assert((!b_false).is_true());
+	assert((!b_true).is_false());
+	assert((!b_error).is_error());
+
+	assert(isl::boolean(true).is_true());
+	assert(!isl::boolean(true).is_false());
+	assert(!isl::boolean(true).is_error());
+
+	assert(isl::boolean(false).is_false());
+	assert(!isl::boolean(false).is_true());
+	assert(!isl::boolean(false).is_error());
+
+	assert(isl::manage(isl_bool_true).is_true());
+	assert(!isl::manage(isl_bool_true).is_false());
+	assert(!isl::manage(isl_bool_true).is_error());
+
+	assert(isl::manage(isl_bool_false).is_false());
+	assert(!isl::manage(isl_bool_false).is_true());
+	assert(!isl::manage(isl_bool_false).is_error());
+
+	assert(isl::manage(isl_bool_error).is_error());
+	assert(!isl::manage(isl_bool_error).is_true());
+	assert(!isl::manage(isl_bool_error).is_false());
+}
+
+/* Test that return values are handled correctly.
+ *
+ * Test that isl C++ objects, integers, boolean values, and strings are
+ * returned correctly.
+ */
+void test_return(isl::ctx ctx)
+{
+	test_return_obj(ctx);
+	test_return_int(ctx);
+	test_return_bool(ctx);
+	test_return_string(ctx);
+}
+
+/* Test that foreach functions are modeled correctly.
+ *
+ * Verify that lambdas are correctly called as callback of a 'foreach'
+ * function and that variables captured by the lambda work correctly. Also
+ * check that the foreach function takes account of the return value of the
+ * lambda and aborts in case isl::stat::error is returned and then returns
+ * isl::stat::error itself.
+ */
+void test_foreach(isl::ctx ctx)
+{
+	isl::set s(ctx, "{ [0]; [1]; [2] }");
+
+	std::vector<isl::basic_set> basic_sets;
+
+	auto add_to_vector = [&] (isl::basic_set bs) {
+		basic_sets.push_back(bs);
+		return isl::stat::ok();
+	};
+
+	isl::stat ret1 = s.foreach_basic_set(add_to_vector);
+
+	assert(ret1.is_ok());
+	assert(basic_sets.size() == 3);
+	assert(isl::set(basic_sets[0]).is_subset(s).is_true());
+	assert(isl::set(basic_sets[1]).is_subset(s).is_true());
+	assert(isl::set(basic_sets[2]).is_subset(s).is_true());
+	assert(!basic_sets[0].is_equal(basic_sets[1]).is_true());
+
+	auto fail = [&] (isl::basic_set bs) {
+		return isl::stat::error();
+	};
+
+	isl::stat ret2 = s.foreach_basic_set(fail);
+
+	assert(ret2.is_error());
+}
+
+/* Test the isl checked C++ interface
+ *
+ * This includes:
+ *  - The isl C <-> C++ pointer interface
+ *  - Object construction
+ *  - Different parameter types
+ *  - Different return types
+ *  - Foreach functions
+ */
+int main()
+{
+	isl_ctx *ctx = isl_ctx_alloc();
+
+	isl_options_set_on_error(ctx, ISL_ON_ERROR_ABORT);
+
+	test_pointer(ctx);
+	test_constructors(ctx);
+	test_parameters(ctx);
+	test_return(ctx);
+	test_foreach(ctx);
+
+	isl_ctx_free(ctx);
+}
diff --git a/lib/External/isl/isl_test_cpp-generic.cc b/lib/External/isl/isl_test_cpp-generic.cc
new file mode 100644
index 0000000..c3ae55b
--- /dev/null
+++ b/lib/External/isl/isl_test_cpp-generic.cc
@@ -0,0 +1,185 @@
+/* Copyright 2016-2017 Tobias Grosser
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Tobias Grosser, Weststrasse 47, CH-8003, Zurich
+ */
+
+#ifndef IS_TRUE
+#define IS_TRUE(b)	(b)
+#endif
+
+/* Test the pointer interface for interaction between isl C and C++ types.
+ *
+ * This tests:
+ * - construction from an isl C object
+ * - check that constructed objects are non-null
+ * - get a non-owned C pointer from an isl C++ object usable in __isl_keep
+ *   methods
+ * - use copy to get an owned C pointer from an isl C++ object which is usable
+ *   in __isl_take methods. Verify that the original C++ object retains a valid
+ *   pointer.
+ * - use release to get an owned C pointer from an isl C++ object which is
+ *   usable in __isl_take methods. Verify that the original C++ object gave up
+ *   its pointer and now is null.
+ */
+void test_pointer(isl::ctx ctx)
+{
+	isl_set *c_empty = isl_set_read_from_str(ctx.get(), "{ : false }");
+	isl::set empty = isl::manage(c_empty);
+	assert(IS_TRUE(empty.is_empty()));
+	assert(isl_set_is_empty(empty.get()));
+
+	assert(!empty.is_null());
+	isl_set_free(empty.copy());
+	assert(!empty.is_null());
+	isl_set_free(empty.release());
+	assert(empty.is_null());
+}
+
+/* Test that isl objects can be constructed.
+ *
+ * This tests:
+ *  - construction of a null object
+ *  - construction from a string
+ *  - construction from an integer
+ *  - static constructor without a parameter
+ *  - conversion construction (implicit)
+ *  - conversion construction (explicit)
+ *
+ *  The tests to construct from integers and strings cover functionality that
+ *  is also tested in the parameter type tests, but here we verify that
+ *  multiple overloaded constructors are available and that overload resolution
+ *  works as expected.
+ *
+ *  Construction from an isl C pointer is tested in test_pointer.
+ */
+void test_constructors(isl::ctx ctx)
+{
+	isl::val null;
+	assert(null.is_null());
+
+	isl::val zero_from_str = isl::val(ctx, "0");
+	assert(IS_TRUE(zero_from_str.is_zero()));
+
+	isl::val zero_int_con = isl::val(ctx, 0);
+	assert(IS_TRUE(zero_int_con.is_zero()));
+
+	isl::val zero_static_con = isl::val::zero(ctx);
+	assert(IS_TRUE(zero_static_con.is_zero()));
+
+	isl::basic_set bs(ctx, "{ [1] }");
+	isl::set result(ctx, "{ [1] }");
+	isl::set s = bs;
+	assert(IS_TRUE(s.is_equal(result)));
+	isl::set s2(bs);
+	assert(IS_TRUE(s.unite(s2).is_equal(result)));
+}
+
+/* Test integer function parameters.
+ *
+ * Verify that extreme values and zero work.
+ */
+void test_parameters_int(isl::ctx ctx)
+{
+	isl::val long_max_str(ctx, std::to_string(LONG_MAX));
+	isl::val long_max_int(ctx, LONG_MAX);
+	assert(IS_TRUE(long_max_str.eq(long_max_int)));
+
+	isl::val long_min_str(ctx, std::to_string(LONG_MIN));
+	isl::val long_min_int(ctx, LONG_MIN);
+	assert(IS_TRUE(long_min_str.eq(long_min_int)));
+
+	isl::val long_zero_str = isl::val(ctx, std::to_string(0));
+	isl::val long_zero_int = isl::val(ctx, 0);
+	assert(IS_TRUE(long_zero_str.eq(long_zero_int)));
+}
+
+/* Test isl objects parameters.
+ *
+ * Verify that isl objects can be passed as lvalue and rvalue parameters.
+ * Also verify that isl object parameters are automatically type converted if
+ * there is an inheritance relation. Finally, test function calls without
+ * any additional parameters, apart from the isl object on which
+ * the method is called.
+ */
+void test_parameters_obj(isl::ctx ctx)
+{
+	isl::set a(ctx, "{ [0] }");
+	isl::set b(ctx, "{ [1] }");
+	isl::set c(ctx, "{ [2] }");
+	isl::set expected(ctx, "{ [i] : 0 <= i <= 2 }");
+
+	isl::set tmp = a.unite(b);
+	isl::set res_lvalue_param = tmp.unite(c);
+	assert(IS_TRUE(res_lvalue_param.is_equal(expected)));
+
+	isl::set res_rvalue_param = a.unite(b).unite(c);
+	assert(IS_TRUE(res_rvalue_param.is_equal(expected)));
+
+	isl::basic_set a2(ctx, "{ [0] }");
+	assert(IS_TRUE(a.is_equal(a2)));
+
+	isl::val two(ctx, 2);
+	isl::val half(ctx, "1/2");
+	isl::val res_only_this_param = two.inv();
+	assert(IS_TRUE(res_only_this_param.eq(half)));
+}
+
+/* Test different kinds of parameters to be passed to functions.
+ *
+ * This includes integer and isl C++ object parameters.
+ */
+void test_parameters(isl::ctx ctx)
+{
+	test_parameters_int(ctx);
+	test_parameters_obj(ctx);
+}
+
+/* Test that isl objects are returned correctly.
+ *
+ * This only tests that after combining two objects, the result is successfully
+ * returned.
+ */
+void test_return_obj(isl::ctx ctx)
+{
+	isl::val one(ctx, "1");
+	isl::val two(ctx, "2");
+	isl::val three(ctx, "3");
+
+	isl::val res = one.add(two);
+
+	assert(IS_TRUE(res.eq(three)));
+}
+
+/* Test that integer values are returned correctly.
+ */
+void test_return_int(isl::ctx ctx)
+{
+	isl::val one(ctx, "1");
+	isl::val neg_one(ctx, "-1");
+	isl::val zero(ctx, "0");
+
+	assert(one.sgn() > 0);
+	assert(neg_one.sgn() < 0);
+	assert(zero.sgn() == 0);
+}
+
+/* Test that strings are returned correctly.
+ * Do so by calling overloaded isl::ast_build::from_expr methods.
+ */
+void test_return_string(isl::ctx ctx)
+{
+	isl::set context(ctx, "[n] -> { : }");
+	isl::ast_build build = isl::ast_build::from_context(context);
+	isl::pw_aff pw_aff(ctx, "[n] -> { [n] }");
+	isl::set set(ctx, "[n] -> { : n >= 0 }");
+
+	isl::ast_expr expr = build.expr_from(pw_aff);
+	const char *expected_string = "n";
+	assert(expected_string == expr.to_C_str());
+
+	expr = build.expr_from(set);
+	expected_string = "n >= 0";
+	assert(expected_string == expr.to_C_str());
+}
diff --git a/lib/External/isl/isl_test_cpp.cc b/lib/External/isl/isl_test_cpp.cc
new file mode 100644
index 0000000..e5580b4
--- /dev/null
+++ b/lib/External/isl/isl_test_cpp.cc
@@ -0,0 +1,167 @@
+/* Copyright 2016-2017 Tobias Grosser
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Tobias Grosser, Weststrasse 47, CH-8003, Zurich
+ */
+
+#include <vector>
+#include <string>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isl/options.h>
+#include <isl/cpp.h>
+
+static void die_impl(const char *file, int line, const char *message)
+{
+	fprintf(stderr, "Assertion failed in %s:%d %s\n", file, line, message);
+	exit(EXIT_FAILURE);
+}
+
+static void assert_impl(bool condition, const char *file, int line,
+	const char *message)
+{
+	if (condition)
+		return;
+
+	return die_impl(file, line, message);
+}
+
+#define die(msg) die_impl(__FILE__, __LINE__, msg)
+#define assert(exp) assert_impl(exp, __FILE__, __LINE__, #exp)
+
+#include "isl_test_cpp-generic.cc"
+
+/* Test that isl_bool values are returned correctly.
+ *
+ * In particular, check the conversion to bool in case of true and false, and
+ * exception throwing in case of error.
+ */
+static void test_return_bool(isl::ctx ctx)
+{
+	isl::set empty(ctx, "{ : false }");
+	isl::set univ(ctx, "{ : }");
+	isl::set null;
+
+	bool b_true = empty.is_empty();
+	bool b_false = univ.is_empty();
+	bool caught = false;
+	try {
+		null.is_empty();
+		die("no exception raised");
+	} catch (const isl::exception &e) {
+		caught = true;
+	}
+
+	assert(b_true);
+	assert(!b_false);
+	assert(caught);
+}
+
+/* Test that return values are handled correctly.
+ *
+ * Test that isl C++ objects, integers, boolean values, and strings are
+ * returned correctly.
+ */
+static void test_return(isl::ctx ctx)
+{
+	test_return_obj(ctx);
+	test_return_int(ctx);
+	test_return_bool(ctx);
+	test_return_string(ctx);
+}
+
+/* Test that foreach functions are modeled correctly.
+ *
+ * Verify that lambdas are correctly called as callback of a 'foreach'
+ * function and that variables captured by the lambda work correctly. Also
+ * check that the foreach function handles exceptions thrown from
+ * the lambda and that it propagates the exception.
+ */
+static void test_foreach(isl::ctx ctx)
+{
+	isl::set s(ctx, "{ [0]; [1]; [2] }");
+
+	std::vector<isl::basic_set> basic_sets;
+
+	auto add_to_vector = [&] (isl::basic_set bs) {
+		basic_sets.push_back(bs);
+	};
+
+	s.foreach_basic_set(add_to_vector);
+
+	assert(basic_sets.size() == 3);
+	assert(isl::set(basic_sets[0]).is_subset(s));
+	assert(isl::set(basic_sets[1]).is_subset(s));
+	assert(isl::set(basic_sets[2]).is_subset(s));
+	assert(!basic_sets[0].is_equal(basic_sets[1]));
+
+	auto fail = [&] (isl::basic_set bs) {
+		throw "fail";
+	};
+
+	bool caught = false;
+	try {
+		s.foreach_basic_set(fail);
+		die("no exception raised");
+	} catch (char const *s) {
+		caught = true;
+	}
+	assert(caught);
+}
+
+/* Test that an exception is generated for an isl error and
+ * that the error message is captured by the exception.
+ * Also check that the exception can be copied and that copying
+ * does not throw any exceptions.
+ */
+static void test_exception(isl::ctx ctx)
+{
+	isl::multi_union_pw_aff mupa(ctx, "[]");
+	isl::exception copy;
+
+	static_assert(std::is_nothrow_copy_constructible<isl::exception>::value,
+		"exceptions must be nothrow-copy-constructible");
+	static_assert(std::is_nothrow_assignable<isl::exception,
+						isl::exception>::value,
+		"exceptions must be nothrow-assignable");
+
+	try {
+		auto umap = isl::union_map::from(mupa);
+	} catch (const isl::exception &error) {
+		assert(strstr(error.what(), "without explicit domain"));
+		copy = error;
+	}
+	assert(strstr(copy.what(), "without explicit domain"));
+}
+
+/* Test the (unchecked) isl C++ interface
+ *
+ * This includes:
+ *  - The isl C <-> C++ pointer interface
+ *  - Object construction
+ *  - Different parameter types
+ *  - Different return types
+ *  - Foreach functions
+ *  - Exceptions
+ */
+int main()
+{
+	isl_ctx *ctx = isl_ctx_alloc();
+
+	isl_options_set_on_error(ctx, ISL_ON_ERROR_ABORT);
+
+	test_pointer(ctx);
+	test_constructors(ctx);
+	test_parameters(ctx);
+	test_return(ctx);
+	test_foreach(ctx);
+	test_exception(ctx);
+
+	isl_ctx_free(ctx);
+
+	return EXIT_SUCCESS;
+}
diff --git a/lib/External/isl/interface/isl_test_python.py b/lib/External/isl/isl_test_python.py
similarity index 100%
rename from lib/External/isl/interface/isl_test_python.py
rename to lib/External/isl/isl_test_python.py
diff --git a/lib/External/isl/m4/ax_cxx_compile_stdcxx.m4 b/lib/External/isl/m4/ax_cxx_compile_stdcxx.m4
new file mode 100644
index 0000000..5032bba
--- /dev/null
+++ b/lib/External/isl/m4/ax_cxx_compile_stdcxx.m4
@@ -0,0 +1,982 @@
+# ===========================================================================
+#  https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the specified
+#   version of the C++ standard.  If necessary, add switches to CXX and
+#   CXXCPP to enable support.  VERSION may be '11' (for the C++11 standard)
+#   or '14' (for the C++14 standard).
+#
+#   The second argument, if specified, indicates whether you insist on an
+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+#   -std=c++11).  If neither is specified, you get whatever works, with
+#   preference for an extended mode.
+#
+#   The third argument, if specified 'mandatory' or if left unspecified,
+#   indicates that baseline support for the specified C++ standard is
+#   required and that the macro should error out if no mode with that
+#   support is found.  If specified 'optional', then configuration proceeds
+#   regardless, after defining HAVE_CXX${VERSION} if and only if a
+#   supporting mode is found.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
+#   Copyright (c) 2015 Paul Norman <penorman@mac.com>
+#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
+#   Copyright (c) 2016 Krzesimir Nowak <qdlacz@gmail.com>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.  This file is offered as-is, without any
+#   warranty.
+
+#serial 7
+
+dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
+dnl  (serial version number 13).
+
+AX_REQUIRE_DEFINED([AC_MSG_WARN])
+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
+  m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
+        [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
+        [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
+        [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$2], [], [],
+        [$2], [ext], [],
+        [$2], [noext], [],
+        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
+        [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
+  AC_LANG_PUSH([C++])dnl
+  ac_success=no
+  AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
+  ax_cv_cxx_compile_cxx$1,
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+    [ax_cv_cxx_compile_cxx$1=yes],
+    [ax_cv_cxx_compile_cxx$1=no])])
+  if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
+    ac_success=yes
+  fi
+
+  m4_if([$2], [noext], [], [dnl
+  if test x$ac_success = xno; then
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      switch="-std=gnu++${alternative}"
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                     $cachevar,
+        [ac_save_CXX="$CXX"
+         CXX="$CXX $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXX="$ac_save_CXX"])
+      if eval test x\$$cachevar = xyes; then
+        CXX="$CXX $switch"
+        if test -n "$CXXCPP" ; then
+          CXXCPP="$CXXCPP $switch"
+        fi
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+
+  m4_if([$2], [ext], [], [dnl
+  if test x$ac_success = xno; then
+    dnl HP's aCC needs +std=c++11 according to:
+    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+    dnl Cray's crayCC needs "-h std=c++11"
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
+        cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+        AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                       $cachevar,
+          [ac_save_CXX="$CXX"
+           CXX="$CXX $switch"
+           AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+            [eval $cachevar=yes],
+            [eval $cachevar=no])
+           CXX="$ac_save_CXX"])
+        if eval test x\$$cachevar = xyes; then
+          CXX="$CXX $switch"
+          if test -n "$CXXCPP" ; then
+            CXXCPP="$CXXCPP $switch"
+          fi
+          ac_success=yes
+          break
+        fi
+      done
+      if test x$ac_success = xyes; then
+        break
+      fi
+    done
+  fi])
+  AC_LANG_POP([C++])
+  if test x$ax_cxx_compile_cxx$1_required = xtrue; then
+    if test x$ac_success = xno; then
+      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
+    fi
+  fi
+  if test x$ac_success = xno; then
+    HAVE_CXX$1=0
+    AC_MSG_NOTICE([No compiler with C++$1 support was found])
+  else
+    HAVE_CXX$1=1
+    AC_DEFINE(HAVE_CXX$1,1,
+              [define if the compiler supports basic C++$1 syntax])
+  fi
+  AC_SUBST(HAVE_CXX$1)
+  m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
+])
+
+
+dnl  Test body for checking C++11 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+)
+
+
+dnl  Test body for checking C++14 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+)
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+)
+
+dnl  Tests for new features in C++11
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+]])
+
+
+dnl  Tests for new features in C++14
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
+
+// If the compiler admits that it is not ready for C++14, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201402L
+
+#error "This is not a C++14 compiler"
+
+#else
+
+namespace cxx14
+{
+
+  namespace test_polymorphic_lambdas
+  {
+
+    int
+    test()
+    {
+      const auto lambda = [](auto&&... args){
+        const auto istiny = [](auto x){
+          return (sizeof(x) == 1UL) ? 1 : 0;
+        };
+        const int aretiny[] = { istiny(args)... };
+        return aretiny[0];
+      };
+      return lambda(1, 1L, 1.0f, '1');
+    }
+
+  }
+
+  namespace test_binary_literals
+  {
+
+    constexpr auto ivii = 0b0000000000101010;
+    static_assert(ivii == 42, "wrong value");
+
+  }
+
+  namespace test_generalized_constexpr
+  {
+
+    template < typename CharT >
+    constexpr unsigned long
+    strlen_c(const CharT *const s) noexcept
+    {
+      auto length = 0UL;
+      for (auto p = s; *p; ++p)
+        ++length;
+      return length;
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("x") == 1UL, "");
+    static_assert(strlen_c("test") == 4UL, "");
+    static_assert(strlen_c("another\0test") == 7UL, "");
+
+  }
+
+  namespace test_lambda_init_capture
+  {
+
+    int
+    test()
+    {
+      auto x = 0;
+      const auto lambda1 = [a = x](int b){ return a + b; };
+      const auto lambda2 = [a = lambda1(x)](){ return a; };
+      return lambda2();
+    }
+
+  }
+
+  namespace test_digit_separators
+  {
+
+    constexpr auto ten_million = 100'000'000;
+    static_assert(ten_million == 100000000, "");
+
+  }
+
+  namespace test_return_type_deduction
+  {
+
+    auto f(int& x) { return x; }
+    decltype(auto) g(int& x) { return x; }
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static constexpr auto value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static constexpr auto value = true;
+    };
+
+    int
+    test()
+    {
+      auto x = 0;
+      static_assert(is_same<int, decltype(f(x))>::value, "");
+      static_assert(is_same<int&, decltype(g(x))>::value, "");
+      return x;
+    }
+
+  }
+
+}  // namespace cxx14
+
+#endif  // __cplusplus >= 201402L
+
+]])
+
+
+dnl  Tests for new features in C++17
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
+
+// If the compiler admits that it is not ready for C++17, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus <= 201402L
+
+#error "This is not a C++17 compiler"
+
+#else
+
+#if defined(__clang__)
+  #define REALLY_CLANG
+#else
+  #if defined(__GNUC__)
+    #define REALLY_GCC
+  #endif
+#endif
+
+#include <initializer_list>
+#include <utility>
+#include <type_traits>
+
+namespace cxx17
+{
+
+#if !defined(REALLY_CLANG)
+  namespace test_constexpr_lambdas
+  {
+
+    // TODO: test it with clang++ from git
+
+    constexpr int foo = [](){return 42;}();
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+  namespace test::nested_namespace::definitions
+  {
+
+  }
+
+  namespace test_fold_expression
+  {
+
+    template<typename... Args>
+    int multiply(Args... args)
+    {
+      return (args * ... * 1);
+    }
+
+    template<typename... Args>
+    bool all(Args... args)
+    {
+      return (args && ...);
+    }
+
+  }
+
+  namespace test_extended_static_assert
+  {
+
+    static_assert (true);
+
+  }
+
+  namespace test_auto_brace_init_list
+  {
+
+    auto foo = {5};
+    auto bar {5};
+
+    static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
+    static_assert(std::is_same<int, decltype(bar)>::value);
+  }
+
+  namespace test_typename_in_template_template_parameter
+  {
+
+    template<template<typename> typename X> struct D;
+
+  }
+
+  namespace test_fallthrough_nodiscard_maybe_unused_attributes
+  {
+
+    int f1()
+    {
+      return 42;
+    }
+
+    [[nodiscard]] int f2()
+    {
+      [[maybe_unused]] auto unused = f1();
+
+      switch (f1())
+      {
+      case 17:
+        f1();
+        [[fallthrough]];
+      case 42:
+        f1();
+      }
+      return f1();
+    }
+
+  }
+
+  namespace test_extended_aggregate_initialization
+  {
+
+    struct base1
+    {
+      int b1, b2 = 42;
+    };
+
+    struct base2
+    {
+      base2() {
+        b3 = 42;
+      }
+      int b3;
+    };
+
+    struct derived : base1, base2
+    {
+        int d;
+    };
+
+    derived d1 {{1, 2}, {}, 4};  // full initialization
+    derived d2 {{}, {}, 4};      // value-initialized bases
+
+  }
+
+  namespace test_general_range_based_for_loop
+  {
+
+    struct iter
+    {
+      int i;
+
+      int& operator* ()
+      {
+        return i;
+      }
+
+      const int& operator* () const
+      {
+        return i;
+      }
+
+      iter& operator++()
+      {
+        ++i;
+        return *this;
+      }
+    };
+
+    struct sentinel
+    {
+      int i;
+    };
+
+    bool operator== (const iter& i, const sentinel& s)
+    {
+      return i.i == s.i;
+    }
+
+    bool operator!= (const iter& i, const sentinel& s)
+    {
+      return !(i == s);
+    }
+
+    struct range
+    {
+      iter begin() const
+      {
+        return {0};
+      }
+
+      sentinel end() const
+      {
+        return {5};
+      }
+    };
+
+    void f()
+    {
+      range r {};
+
+      for (auto i : r)
+      {
+        [[maybe_unused]] auto v = i;
+      }
+    }
+
+  }
+
+  namespace test_lambda_capture_asterisk_this_by_value
+  {
+
+    struct t
+    {
+      int i;
+      int foo()
+      {
+        return [*this]()
+        {
+          return i;
+        }();
+      }
+    };
+
+  }
+
+  namespace test_enum_class_construction
+  {
+
+    enum class byte : unsigned char
+    {};
+
+    byte foo {42};
+
+  }
+
+  namespace test_constexpr_if
+  {
+
+    template <bool cond>
+    int f ()
+    {
+      if constexpr(cond)
+      {
+        return 13;
+      }
+      else
+      {
+        return 42;
+      }
+    }
+
+  }
+
+  namespace test_selection_statement_with_initializer
+  {
+
+    int f()
+    {
+      return 13;
+    }
+
+    int f2()
+    {
+      if (auto i = f(); i > 0)
+      {
+        return 3;
+      }
+
+      switch (auto i = f(); i + 4)
+      {
+      case 17:
+        return 2;
+
+      default:
+        return 1;
+      }
+    }
+
+  }
+
+#if !defined(REALLY_CLANG)
+  namespace test_template_argument_deduction_for_class_templates
+  {
+
+    // TODO: test it with clang++ from git
+
+    template <typename T1, typename T2>
+    struct pair
+    {
+      pair (T1 p1, T2 p2)
+        : m1 {p1},
+          m2 {p2}
+      {}
+
+      T1 m1;
+      T2 m2;
+    };
+
+    void f()
+    {
+      [[maybe_unused]] auto p = pair{13, 42u};
+    }
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+  namespace test_non_type_auto_template_parameters
+  {
+
+    template <auto n>
+    struct B
+    {};
+
+    B<5> b1;
+    B<'a'> b2;
+
+  }
+
+#if !defined(REALLY_CLANG)
+  namespace test_structured_bindings
+  {
+
+    // TODO: test it with clang++ from git
+
+    int arr[2] = { 1, 2 };
+    std::pair<int, int> pr = { 1, 2 };
+
+    auto f1() -> int(&)[2]
+    {
+      return arr;
+    }
+
+    auto f2() -> std::pair<int, int>&
+    {
+      return pr;
+    }
+
+    struct S
+    {
+      int x1 : 2;
+      volatile double y1;
+    };
+
+    S f3()
+    {
+      return {};
+    }
+
+    auto [ x1, y1 ] = f1();
+    auto& [ xr1, yr1 ] = f1();
+    auto [ x2, y2 ] = f2();
+    auto& [ xr2, yr2 ] = f2();
+    const auto [ x3, y3 ] = f3();
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+#if !defined(REALLY_CLANG)
+  namespace test_exception_spec_type_system
+  {
+
+    // TODO: test it with clang++ from git
+
+    struct Good {};
+    struct Bad {};
+
+    void g1() noexcept;
+    void g2();
+
+    template<typename T>
+    Bad
+    f(T*, T*);
+
+    template<typename T1, typename T2>
+    Good
+    f(T1*, T2*);
+
+    static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+  namespace test_inline_variables
+  {
+
+    template<class T> void f(T)
+    {}
+
+    template<class T> inline T g(T)
+    {
+      return T{};
+    }
+
+    template<> inline void f<>(int)
+    {}
+
+    template<> int g<>(int)
+    {
+      return 5;
+    }
+
+  }
+
+}  // namespace cxx17
+
+#endif  // __cplusplus <= 201402L
+
+]])
diff --git a/lib/External/isl/m4/ax_cxx_compile_stdcxx_11.m4 b/lib/External/isl/m4/ax_cxx_compile_stdcxx_11.m4
new file mode 100644
index 0000000..0aadeaf
--- /dev/null
+++ b/lib/External/isl/m4/ax_cxx_compile_stdcxx_11.m4
@@ -0,0 +1,39 @@
+# ============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX_11([ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the C++11
+#   standard; if necessary, add switches to CXX and CXXCPP to enable
+#   support.
+#
+#   This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX
+#   macro with the version set to C++11.  The two optional arguments are
+#   forwarded literally as the second and third argument respectively.
+#   Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for
+#   more information.  If you want to use this macro, you also need to
+#   download the ax_cxx_compile_stdcxx.m4 file.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
+#   Copyright (c) 2015 Paul Norman <penorman@mac.com>
+#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 17
+
+AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX])
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [AX_CXX_COMPILE_STDCXX([11], [$1], [$2])])
diff --git a/lib/External/isl/interface/isl.py.top b/lib/External/isl/python/isl.py.top
similarity index 100%
rename from lib/External/isl/interface/isl.py.top
rename to lib/External/isl/python/isl.py.top
diff --git a/lib/External/isl/schedule_test.sh.in b/lib/External/isl/schedule_test.sh.in
index afba802..16ae020 100644
--- a/lib/External/isl/schedule_test.sh.in
+++ b/lib/External/isl/schedule_test.sh.in
@@ -14,8 +14,14 @@
 	dir=`dirname $i`
 	ref=$dir/$base.st
 	options=`$GREP 'OPTIONS:' $i | $SED 's/.*://'`
-	(./isl_schedule$EXEEXT $options < $i > $test &&
-	./isl_schedule_cmp$EXEEXT $ref $test && rm $test) || failed=1
+	for o in --schedule-whole-component --no-schedule-whole-component; do
+		./isl_schedule$EXEEXT $o $options < $i > $test &&
+		    ./isl_schedule_cmp$EXEEXT $ref $test && rm $test
+		if [ $? -ne 0 ]; then
+			echo $o $options
+			failed=1
+		fi
+	done
 done
 
 test $failed -eq 0 || exit
diff --git a/lib/External/isl/test_inputs/schedule/bounded_coefficients.sc b/lib/External/isl/test_inputs/schedule/bounded_coefficients.sc
new file mode 100644
index 0000000..dd839e9
--- /dev/null
+++ b/lib/External/isl/test_inputs/schedule/bounded_coefficients.sc
@@ -0,0 +1,12 @@
+# Check that the bounds on the coefficients are respected.
+# This function checks for a particular output schedule,
+# but the exact output is not important, only that it does
+# not contain any coefficients greater than 4.
+# It is, however, easier to check for a particular output.
+# This test uses the whole component scheduler
+# because the incremental scheduler has no reason to fuse anything.
+# OPTIONS: --schedule-whole-component  --schedule-max-coefficient=4 --schedule-max-constant-term=10
+domain: { S_4[i, j, k] : 0 <= i < j <= 10 and 0 <= k <= 100;
+	  S_2[i, j] : 0 <= i < j <= 10; S_6[i, j] : 0 <= i < j <= 10 }
+validity: { S_2[0, j] -> S_4[0, j, 0] : 0 < j <= 10;
+	    S_4[0, j, 100] -> S_6[0, j] : 0 < j <= 10 }
diff --git a/lib/External/isl/test_inputs/schedule/bounded_coefficients.st b/lib/External/isl/test_inputs/schedule/bounded_coefficients.st
new file mode 100644
index 0000000..6ce339c
--- /dev/null
+++ b/lib/External/isl/test_inputs/schedule/bounded_coefficients.st
@@ -0,0 +1,5 @@
+domain: "{ S_6[i, j] : i >= 0 and i < j <= 10; S_4[i, j, k] : i >= 0 and i < j <= 10 and 0 <= k <= 100; S_2[i, j] : i >= 0 and i < j <= 10 }"
+child:
+  schedule: "[{ S_6[i, j] -> [(0)]; S_4[i, j, k] -> [(i)]; S_2[i, j] -> [(0)] }, { S_6[i, j] -> [(10 + i)]; S_4[i, j, k] -> [(j)]; S_2[i, j] -> [(i)] }, { S_6[i, j] -> [(j)]; S_4[i, j, k] -> [(10 - k)]; S_2[i, j] -> [(j)] }]"
+  permutable: 1
+  coincident: [ 1, 1, 1 ]
diff --git a/lib/External/isl/test_inputs/schedule/carry_bounded_coefficients.sc b/lib/External/isl/test_inputs/schedule/carry_bounded_coefficients.sc
new file mode 100644
index 0000000..70037c0
--- /dev/null
+++ b/lib/External/isl/test_inputs/schedule/carry_bounded_coefficients.sc
@@ -0,0 +1,19 @@
+# Check that the dependence carrying step is not confused by
+# a bound on the coefficient size.
+# In particular, force the scheduler to move to a dependence carrying
+# step by demanding outer coincidence and bound the size of
+# the coefficients.  Earlier versions of isl would take this
+# bound into account while carrying dependences, breaking
+# fundamental assumptions.
+# On the other hand, the dependence carrying step now tries
+# to prevent loop coalescing by default, so check that indeed
+# no loop coalescing occurs by comparing the computed schedule
+# to the expected non-coalescing schedule.
+# OPTIONS: --schedule-outer-coincidence --schedule-max-coefficient=20
+domain: { C[i0, i1] : 2 <= i0 <= 3999 and 0 <= i1 <= -1 + i0 }
+validity: { C[i0, i1] -> C[i0, 1 + i1] : i0 <= 3999 and i1 >= 0 and
+						i1 <= -2 + i0;
+		C[i0, -1 + i0] -> C[1 + i0, 0] : i0 <= 3998 and i0 >= 1 }
+coincidence: { C[i0, i1] -> C[i0, 1 + i1] : i0 <= 3999 and i1 >= 0 and
+						i1 <= -2 + i0;
+		C[i0, -1 + i0] -> C[1 + i0, 0] : i0 <= 3998 and i0 >= 1 }
diff --git a/lib/External/isl/test_inputs/schedule/carry_bounded_coefficients.st b/lib/External/isl/test_inputs/schedule/carry_bounded_coefficients.st
new file mode 100644
index 0000000..cdcf12c
--- /dev/null
+++ b/lib/External/isl/test_inputs/schedule/carry_bounded_coefficients.st
@@ -0,0 +1,5 @@
+domain: "{ C[i0, i1] : 2 <= i0 <= 3999 and 0 <= i1 < i0 }"
+child:
+  schedule: "[{ C[i0, i1] -> [(i0)] }]"
+  child:
+    schedule: "[{ C[i0, i1] -> [(i1)] }]"
diff --git a/lib/External/isl/test_inputs/schedule/max_coincidence.sc b/lib/External/isl/test_inputs/schedule/max_coincidence.sc
new file mode 100644
index 0000000..cabe9b4
--- /dev/null
+++ b/lib/External/isl/test_inputs/schedule/max_coincidence.sc
@@ -0,0 +1,7 @@
+# Check that nodes are not fused when maximizing coincidence.
+# This option is only effective for the incremental scheduler.
+# OPTIONS: --no-schedule-whole-component --schedule-maximize-coincidence
+domain: [n] -> { A[i,j,k] : 0 <= i,j,k < n; B[i,j,k] : 0 <= i,j,k < n }
+validity: { A[i,j,k] -> B[i,k,j] }
+proximity: { A[i,j,k] -> B[i,k,j] }
+coincidence: { A[i,j,k] -> A[i,j,k+1]; B[i,j,k] -> B[i,j,k+1] }
diff --git a/lib/External/isl/test_inputs/schedule/max_coincidence.st b/lib/External/isl/test_inputs/schedule/max_coincidence.st
new file mode 100644
index 0000000..2b29baf
--- /dev/null
+++ b/lib/External/isl/test_inputs/schedule/max_coincidence.st
@@ -0,0 +1,13 @@
+domain: "[n] -> { A[i, j, k] : 0 <= i < n and 0 <= j < n and 0 <= k < n; B[i, j, k] : 0 <= i < n and 0 <= j < n and 0 <= k < n }"
+child:
+  sequence:
+  - filter: "[n] -> { A[i, j, k] }"
+    child:
+      schedule: "[n] -> [{ A[i, j, k] -> [(i)] }, { A[i, j, k] -> [(j)] }, { A[i, j, k] -> [(k)] }]"
+      permutable: 1
+      coincident: [ 1, 1, 0 ]
+  - filter: "[n] -> { B[i, j, k] }"
+    child:
+      schedule: "[n] -> [{ B[i, j, k] -> [(i)] }, { B[i, j, k] -> [(j)] }, { B[i, j, k] -> [(k)] }]"
+      permutable: 1
+      coincident: [ 1, 1, 0 ]
diff --git a/lib/External/isl/test_inputs/schedule/nomax_coincidence.sc b/lib/External/isl/test_inputs/schedule/nomax_coincidence.sc
new file mode 100644
index 0000000..c37ad5b
--- /dev/null
+++ b/lib/External/isl/test_inputs/schedule/nomax_coincidence.sc
@@ -0,0 +1,7 @@
+# Check that nodes are fused when not maximizing coincidence.
+# This option is only effective for the incremental scheduler.
+# OPTIONS: --no-schedule-whole-component --no-schedule-maximize-coincidence
+domain: [n] -> { A[i,j,k] : 0 <= i,j,k < n; B[i,j,k] : 0 <= i,j,k < n }
+validity: { A[i,j,k] -> B[i,k,j] }
+proximity: { A[i,j,k] -> A[i,j,k+1]; A[i,j,k] -> B[i,k,j] }
+coincidence: { A[i,j,k] -> A[i,j,k+1]; B[i,j,k] -> B[i,j,k+1] }
diff --git a/lib/External/isl/test_inputs/schedule/nomax_coincidence.st b/lib/External/isl/test_inputs/schedule/nomax_coincidence.st
new file mode 100644
index 0000000..3d3af70
--- /dev/null
+++ b/lib/External/isl/test_inputs/schedule/nomax_coincidence.st
@@ -0,0 +1,9 @@
+domain: "[n] -> { A[i, j, k] : 0 <= i < n and 0 <= j < n and 0 <= k < n; B[i, j, k] : 0 <= i < n and 0 <= j < n and 0 <= k < n }"
+child:
+  schedule: "[n] -> [{ A[i, j, k] -> [(i)]; B[i, j, k] -> [(i)] }, { A[i, j, k] -> [(j)]; B[i, j, k] -> [(k)] }, { A[i, j, k] -> [(k)]; B[i, j, k] -> [(j)] }]"
+  permutable: 1
+  coincident: [ 1, 0, 0 ]
+  child:
+    sequence:
+    - filter: "[n] -> { A[i, j, k] }"
+    - filter: "[n] -> { B[i, j, k] }"