summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS3
-rw-r--r--ChangeLog9
-rw-r--r--GIT_HEAD_ID2
-rw-r--r--Makefile.am52
-rw-r--r--Makefile.in199
-rw-r--r--basis_reduction_tab.c39
-rwxr-xr-xconfigure245
-rw-r--r--configure.ac54
-rw-r--r--doc/Makefile.am13
-rw-r--r--doc/Makefile.in14
-rw-r--r--doc/manual.pdfbin488137 -> 496484 bytes
-rw-r--r--doc/user.pod282
-rw-r--r--include/isl/aff.h59
-rw-r--r--include/isl/aff_type.h20
-rw-r--r--include/isl/ctx.h5
-rw-r--r--include/isl/flow.h30
-rw-r--r--include/isl/map.h11
-rw-r--r--include/isl/multi.h9
-rw-r--r--include/isl/point.h2
-rw-r--r--include/isl/polynomial.h2
-rw-r--r--include/isl/schedule.h9
-rw-r--r--include/isl/schedule_node.h19
-rw-r--r--include/isl/schedule_type.h4
-rw-r--r--include/isl/set.h4
-rw-r--r--include/isl/space.h3
-rw-r--r--include/isl/union_map.h24
-rw-r--r--include/isl/union_set.h9
-rw-r--r--include/isl/val.h13
-rw-r--r--interface/Makefile.am2
-rw-r--r--interface/Makefile.in2
-rw-r--r--interface/all.h5
-rw-r--r--interface/extract_interface.cc13
-rw-r--r--interface/isl.py3416
-rw-r--r--interface/python.cc461
-rw-r--r--isl_aff.c444
-rw-r--r--isl_affine_hull.c12
-rw-r--r--isl_arg.c7
-rw-r--r--isl_ast.c1
-rw-r--r--isl_ast_build.c102
-rw-r--r--isl_ast_build_expr.c103
-rw-r--r--isl_ast_build_private.h6
-rw-r--r--isl_ast_codegen.c320
-rw-r--r--isl_ast_graft.c9
-rw-r--r--isl_coalesce.c77
-rw-r--r--isl_config.h.in34
-rw-r--r--isl_config_post.h25
-rw-r--r--isl_convex_hull.c202
-rw-r--r--isl_equalities.c32
-rw-r--r--isl_ffs.c24
-rw-r--r--isl_flow.c261
-rw-r--r--isl_fold.c21
-rw-r--r--isl_hash.c10
-rw-r--r--isl_hash_private.h8
-rw-r--r--isl_imath.c22
-rw-r--r--isl_input.c193
-rw-r--r--isl_int.h8
-rw-r--r--isl_int_sioimath.c221
-rw-r--r--isl_int_sioimath.h1223
-rw-r--r--isl_local_space.c10
-rw-r--r--isl_local_space_private.h2
-rw-r--r--isl_map.c565
-rw-r--r--isl_map_private.h25
-rw-r--r--isl_map_simplify.c1292
-rw-r--r--isl_mat.c2
-rw-r--r--isl_morph.c2
-rw-r--r--isl_multi_coalesce.c35
-rw-r--r--isl_multi_templ.c45
-rw-r--r--isl_output.c506
-rw-r--r--isl_output_private.h27
-rw-r--r--isl_point.c53
-rw-r--r--isl_polynomial.c26
-rw-r--r--isl_printer.c14
-rw-r--r--isl_printer_private.h11
-rw-r--r--isl_range.c81
-rw-r--r--isl_schedule.c50
-rw-r--r--isl_schedule_band.c55
-rw-r--r--isl_schedule_band.h5
-rw-r--r--isl_schedule_node.c262
-rw-r--r--isl_schedule_node_private.h6
-rw-r--r--isl_schedule_tree.c54
-rw-r--r--isl_schedule_tree.h5
-rw-r--r--isl_scheduler.c465
-rw-r--r--isl_space.c175
-rw-r--r--isl_space_private.h1
-rw-r--r--isl_stream.c1
-rw-r--r--isl_tab.c19
-rw-r--r--isl_test.c632
-rw-r--r--isl_test_imath.c79
-rw-r--r--isl_test_int.c623
-rw-r--r--isl_transitive_closure.c2
-rw-r--r--isl_union_eval.c58
-rw-r--r--isl_union_macro.h4
-rw-r--r--isl_union_map.c59
-rw-r--r--isl_union_multi.c465
-rw-r--r--isl_union_neg.c25
-rw-r--r--isl_union_single.c197
-rw-r--r--isl_union_templ.c750
-rw-r--r--isl_val.c46
-rw-r--r--isl_val_sioimath.c68
-rw-r--r--isl_version.c3
-rw-r--r--pip.c2
-rw-r--r--print_templ.c3
-rw-r--r--test_inputs/brisebarre.pip68
-rw-r--r--test_inputs/codegen/cloog/dealII.c26
-rw-r--r--test_inputs/codegen/cloog/faber.c23
-rw-r--r--test_inputs/codegen/cloog/jacobi-shared.c2
-rw-r--r--test_inputs/codegen/cloog/reservoir-liu-zhuge1.c4
-rw-r--r--test_inputs/codegen/isolate2.c14
-rw-r--r--test_inputs/codegen/isolate7.c27
-rw-r--r--test_inputs/codegen/isolate7.st16
-rw-r--r--test_inputs/codegen/omega/dagstuhl1-1.c2
-rw-r--r--test_inputs/codegen/omega/iter9-0.c2
-rw-r--r--test_inputs/codegen/omega/lefur03-0.c2
-rw-r--r--test_inputs/codegen/omega/lefur04-0.c6
-rw-r--r--test_inputs/codegen/omega/p.delft2-0.c4
-rw-r--r--test_inputs/codegen/omega/ts1d-check0-0.c2
-rw-r--r--test_inputs/codegen/pldi2012/figure8_b.c2
-rw-r--r--test_inputs/codegen/redundant.c18
-rw-r--r--test_inputs/codegen/redundant.st6
-rw-r--r--test_inputs/codegen/roman.c2
-rw-r--r--test_inputs/codegen/separate2.c17
-rw-r--r--test_inputs/codegen/separation_class2.c4
-rw-r--r--test_inputs/codegen/unroll3.c2
-rw-r--r--test_inputs/codegen/unroll4.c14
124 files changed, 12514 insertions, 2958 deletions
diff --git a/AUTHORS b/AUTHORS
index a6afd5a1..671a2413 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -19,10 +19,11 @@ isl was written by
2012-2014 Ecole Normale Superieure
45 rue d'Ulm, 75230 Paris
France
-2014 INRIA Rocquencourt
+2014-2015 INRIA Rocquencourt
Domaine de Voluceau - Rocquencourt, B.P. 105
78153 Le Chesnay
France
+2015 Polly Labs
Contributions by
diff --git a/ChangeLog b/ChangeLog
index 828bbe38..d63b67d0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+version: 0.16
+date: Tue Jan 12 09:56:16 CET 2016
+changes:
+ - add 32 bit integer optimization for IMath
+ - minor AST generator improvements
+ - add isl_union_flow_get_full_{may,must}_dependence
+ - minor improvements to Python bindings
+ - minor improvements to set and map printing
+---
version: 0.15
date: Thu Jun 11 12:45:33 CEST 2015
changes:
diff --git a/GIT_HEAD_ID b/GIT_HEAD_ID
index 48b92b54..afd4545b 100644
--- a/GIT_HEAD_ID
+++ b/GIT_HEAD_ID
@@ -1 +1 @@
-isl-0.15
+isl-0.16
diff --git a/Makefile.am b/Makefile.am
index 87655b19..887d2c2f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,8 +11,8 @@ lib_LTLIBRARIES = libisl.la
noinst_PROGRAMS = isl_test isl_polyhedron_sample isl_pip \
isl_polyhedron_minimize isl_polytope_scan \
isl_polyhedron_detect_equalities isl_cat \
- isl_closure isl_bound isl_codegen
-TESTS = isl_test codegen_test.sh pip_test.sh bound_test.sh
+ isl_closure isl_bound isl_codegen isl_test_int
+TESTS = isl_test codegen_test.sh pip_test.sh bound_test.sh isl_test_int
if IMATH_FOR_MP
@@ -21,7 +21,6 @@ MP_SRC = \
isl_imath.c \
isl_imath.h \
isl_int_imath.h \
- isl_val_imath.c \
imath_wrap/gmp_compat.h \
imath_wrap/imath.h \
imath_wrap/imrat.h \
@@ -30,6 +29,17 @@ MP_SRC = \
imath_wrap/imath.c \
imath_wrap/imrat.c
+noinst_PROGRAMS += isl_test_imath
+TESTS += isl_test_imath
+
+if SMALL_INT_OPT
+MP_SRC += isl_int_sioimath.h \
+ isl_int_sioimath.c \
+ isl_val_sioimath.c
+else
+MP_SRC += isl_val_imath.c
+endif
+
DEPRECATED_SRC =
MP_INCLUDE_H =
endif
@@ -92,9 +102,11 @@ libisl_la_SOURCES = \
isl_factorization.c \
isl_factorization.h \
isl_farkas.c \
+ isl_ffs.c \
isl_flow.c \
isl_fold.c \
isl_hash.c \
+ isl_hash_private.h \
isl_id_to_ast_expr.c \
isl_id_to_pw_aff.c \
isl_ilp.c \
@@ -121,6 +133,7 @@ libisl_la_SOURCES = \
isl_options.c \
isl_options_private.h \
isl_output.c \
+ isl_output_private.h \
isl_point_private.h \
isl_point.c \
isl_polynomial_private.h \
@@ -178,6 +191,14 @@ libisl_la_LDFLAGS = -version-info @versioninfo@ \
isl_test_LDFLAGS = @MP_LDFLAGS@
isl_test_LDADD = libisl.la @MP_LIBS@
+isl_test_int_LDFLAGS = @MP_LDFLAGS@
+isl_test_int_LDADD = libisl.la @MP_LIBS@
+
+if IMATH_FOR_MP
+isl_test_imath_LDFLAGS = @MP_LDFLAGS@
+isl_test_imath_LDADD = libisl.la @MP_LIBS@
+endif
+
isl_polyhedron_sample_LDADD = libisl.la
isl_polyhedron_sample_SOURCES = \
polyhedron_sample.c
@@ -283,6 +304,18 @@ deprecated_HEADERS = \
include/isl/deprecated/val_int.h \
include/isl/deprecated/vec_int.h
+BUILT_SOURCES = gitversion.h
+
+CLEANFILES = \
+ gitversion.h
+
+DISTCLEANFILES = \
+ isl-uninstalled.sh \
+ isl-uninstalled.pc \
+ isl.pc \
+ isl.pc.in \
+ include/isl/stdint.h
+
EXTRA_DIST = \
LICENSE \
isl_config_post.h \
@@ -297,13 +330,19 @@ EXTRA_DIST = \
isl_multi_apply_templ.c \
isl_multi_apply_set.c \
isl_multi_apply_union_set.c \
+ isl_multi_coalesce.c \
isl_multi_floor.c \
isl_multi_gist.c \
isl_multi_intersect.c \
print_templ.c \
isl_power_templ.c \
isl_pw_templ.c \
+ isl_union_macro.h \
isl_union_templ.c \
+ isl_union_single.c \
+ isl_union_multi.c \
+ isl_union_eval.c \
+ isl_union_neg.c \
isl.py \
doc/CodingStyle \
doc/SubmittingPatches \
@@ -344,3 +383,10 @@ install-data-local: $(srcdir)/isl.py
$(DESTDIR)$(libdir)/$$libisl-gdb.py; \
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"; \
$(INSTALL_DATA) $(srcdir)/isl.py $(DESTDIR)$(libdir)/$$libisl-gdb.py; esac
+
+uninstall-local:
+ @libisl=`sed -ne "/^library_names=/{s/.*='//;s/'$$//;s/ .*//;p;}" \
+ $(builddir)/libisl.la`; \
+ if test -n "$${libisl}"; then \
+ rm -f $(DESTDIR)$(libdir)/$$libisl-gdb.py; \
+ fi
diff --git a/Makefile.in b/Makefile.in
index 848a60dd..7e0b6540 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -85,8 +85,17 @@ noinst_PROGRAMS = isl_test$(EXEEXT) isl_polyhedron_sample$(EXEEXT) \
isl_pip$(EXEEXT) isl_polyhedron_minimize$(EXEEXT) \
isl_polytope_scan$(EXEEXT) \
isl_polyhedron_detect_equalities$(EXEEXT) isl_cat$(EXEEXT) \
- isl_closure$(EXEEXT) isl_bound$(EXEEXT) isl_codegen$(EXEEXT)
-TESTS = isl_test$(EXEEXT) codegen_test.sh pip_test.sh bound_test.sh
+ isl_closure$(EXEEXT) isl_bound$(EXEEXT) isl_codegen$(EXEEXT) \
+ isl_test_int$(EXEEXT) $(am__EXEEXT_1)
+TESTS = isl_test$(EXEEXT) codegen_test.sh pip_test.sh bound_test.sh \
+ isl_test_int$(EXEEXT) $(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 \
+@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
subdir = .
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
@@ -155,10 +164,11 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libisl_la_DEPENDENCIES =
am__libisl_la_SOURCES_DIST = mp_get_memory_functions.c isl_int_gmp.h \
isl_gmp.c isl_val_gmp.c isl_hide_deprecated.h isl_imath.c \
- isl_imath.h isl_int_imath.h isl_val_imath.c \
- imath_wrap/gmp_compat.h imath_wrap/imath.h imath_wrap/imrat.h \
- imath_wrap/wrap.h imath_wrap/gmp_compat.c imath_wrap/imath.c \
- imath_wrap/imrat.c isl_ast_int.c isl_aff.c isl_aff_private.h \
+ isl_imath.h isl_int_imath.h imath_wrap/gmp_compat.h \
+ imath_wrap/imath.h imath_wrap/imrat.h imath_wrap/wrap.h \
+ imath_wrap/gmp_compat.c imath_wrap/imath.c imath_wrap/imrat.c \
+ isl_int_sioimath.h isl_int_sioimath.c isl_val_sioimath.c \
+ isl_val_imath.c isl_ast_int.c isl_aff.c isl_aff_private.h \
isl_affine_hull.c isl_arg.c isl_ast.c isl_ast_private.h \
isl_ast_build.c isl_ast_build_private.h isl_ast_build_expr.c \
isl_ast_build_expr.h isl_ast_codegen.c isl_ast_graft.c \
@@ -168,16 +178,17 @@ am__libisl_la_SOURCES_DIST = mp_get_memory_functions.c isl_int_gmp.h \
isl_coalesce.c isl_constraint.c isl_constraint_private.h \
isl_convex_hull.c isl_ctx.c isl_ctx_private.h isl_deprecated.c \
isl_dim_map.h isl_dim_map.c isl_equalities.c isl_equalities.h \
- isl_factorization.c isl_factorization.h isl_farkas.c \
- isl_flow.c isl_fold.c isl_hash.c isl_id_to_ast_expr.c \
- isl_id_to_pw_aff.c isl_ilp.c isl_ilp_private.h isl_input.c \
- isl_int.h isl_local_space_private.h isl_local_space.c isl_lp.c \
+ isl_factorization.c isl_factorization.h isl_farkas.c isl_ffs.c \
+ isl_flow.c isl_fold.c isl_hash.c isl_hash_private.h \
+ isl_id_to_ast_expr.c isl_id_to_pw_aff.c isl_ilp.c \
+ isl_ilp_private.h isl_input.c isl_int.h \
+ isl_local_space_private.h isl_local_space.c isl_lp.c \
isl_lp_private.h isl_map.c isl_map_list.c isl_map_simplify.c \
isl_map_subtract.c isl_map_private.h isl_map_to_basic_set.c \
isl_mat.c isl_mat_private.h isl_morph.c isl_morph.h isl_id.c \
isl_id_private.h isl_obj.c isl_options.c isl_options_private.h \
- isl_output.c isl_point_private.h isl_point.c \
- isl_polynomial_private.h isl_polynomial.c \
+ isl_output.c isl_output_private.h isl_point_private.h \
+ isl_point.c isl_polynomial_private.h isl_polynomial.c \
isl_printer_private.h isl_printer.c print.c isl_range.c \
isl_range.h isl_reordering.c isl_reordering.h isl_sample.h \
isl_sample.c isl_scan.c isl_scan.h isl_schedule.c \
@@ -194,34 +205,41 @@ am__libisl_la_SOURCES_DIST = mp_get_memory_functions.c isl_int_gmp.h \
isl_vertices_private.h isl_vertices.c isl_yaml.h
@GMP_FOR_MP_TRUE@@NEED_GET_MEMORY_FUNCTIONS_TRUE@am__objects_1 = mp_get_memory_functions.lo
am__dirstamp = $(am__leading_dot)dirstamp
-@GMP_FOR_MP_FALSE@@IMATH_FOR_MP_TRUE@am__objects_2 = isl_imath.lo \
-@GMP_FOR_MP_FALSE@@IMATH_FOR_MP_TRUE@ isl_val_imath.lo \
+@IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_TRUE@am__objects_2 = \
+@IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_TRUE@ isl_int_sioimath.lo \
+@IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_TRUE@ isl_val_sioimath.lo
+@IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_FALSE@am__objects_3 = \
+@IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_FALSE@ isl_val_imath.lo
+@GMP_FOR_MP_FALSE@@IMATH_FOR_MP_TRUE@am__objects_4 = isl_imath.lo \
@GMP_FOR_MP_FALSE@@IMATH_FOR_MP_TRUE@ imath_wrap/gmp_compat.lo \
@GMP_FOR_MP_FALSE@@IMATH_FOR_MP_TRUE@ imath_wrap/imath.lo \
-@GMP_FOR_MP_FALSE@@IMATH_FOR_MP_TRUE@ imath_wrap/imrat.lo
-@GMP_FOR_MP_TRUE@am__objects_2 = $(am__objects_1) isl_gmp.lo \
+@GMP_FOR_MP_FALSE@@IMATH_FOR_MP_TRUE@ imath_wrap/imrat.lo \
+@GMP_FOR_MP_FALSE@@IMATH_FOR_MP_TRUE@ $(am__objects_2) \
+@GMP_FOR_MP_FALSE@@IMATH_FOR_MP_TRUE@ $(am__objects_3)
+@GMP_FOR_MP_TRUE@am__objects_4 = $(am__objects_1) isl_gmp.lo \
@GMP_FOR_MP_TRUE@ isl_val_gmp.lo
-@GMP_FOR_MP_TRUE@am__objects_3 = isl_ast_int.lo
-am_libisl_la_OBJECTS = $(am__objects_2) $(am__objects_3) isl_aff.lo \
+@GMP_FOR_MP_TRUE@am__objects_5 = isl_ast_int.lo
+am_libisl_la_OBJECTS = $(am__objects_4) $(am__objects_5) isl_aff.lo \
isl_affine_hull.lo isl_arg.lo isl_ast.lo isl_ast_build.lo \
isl_ast_build_expr.lo isl_ast_codegen.lo isl_ast_graft.lo \
isl_band.lo basis_reduction_tab.lo isl_bernstein.lo isl_blk.lo \
isl_bound.lo isl_coalesce.lo isl_constraint.lo \
isl_convex_hull.lo isl_ctx.lo isl_deprecated.lo isl_dim_map.lo \
isl_equalities.lo isl_factorization.lo isl_farkas.lo \
- isl_flow.lo isl_fold.lo isl_hash.lo isl_id_to_ast_expr.lo \
- isl_id_to_pw_aff.lo isl_ilp.lo isl_input.lo isl_local_space.lo \
- isl_lp.lo isl_map.lo isl_map_list.lo isl_map_simplify.lo \
- isl_map_subtract.lo isl_map_to_basic_set.lo isl_mat.lo \
- isl_morph.lo isl_id.lo isl_obj.lo isl_options.lo isl_output.lo \
- isl_point.lo isl_polynomial.lo isl_printer.lo print.lo \
- isl_range.lo isl_reordering.lo isl_sample.lo isl_scan.lo \
- isl_schedule.lo isl_schedule_band.lo isl_schedule_node.lo \
- isl_schedule_read.lo isl_schedule_tree.lo isl_scheduler.lo \
- isl_set_list.lo isl_sort.lo isl_space.lo isl_stream.lo \
- isl_seq.lo isl_tab.lo isl_tab_pip.lo isl_tarjan.lo \
- isl_transitive_closure.lo isl_union_map.lo isl_val.lo \
- isl_vec.lo isl_version.lo isl_vertices.lo
+ isl_ffs.lo isl_flow.lo isl_fold.lo isl_hash.lo \
+ isl_id_to_ast_expr.lo isl_id_to_pw_aff.lo isl_ilp.lo \
+ isl_input.lo isl_local_space.lo isl_lp.lo isl_map.lo \
+ isl_map_list.lo isl_map_simplify.lo isl_map_subtract.lo \
+ isl_map_to_basic_set.lo isl_mat.lo isl_morph.lo isl_id.lo \
+ isl_obj.lo isl_options.lo isl_output.lo isl_point.lo \
+ isl_polynomial.lo isl_printer.lo print.lo isl_range.lo \
+ isl_reordering.lo isl_sample.lo isl_scan.lo isl_schedule.lo \
+ isl_schedule_band.lo isl_schedule_node.lo isl_schedule_read.lo \
+ isl_schedule_tree.lo isl_scheduler.lo isl_set_list.lo \
+ isl_sort.lo isl_space.lo isl_stream.lo isl_seq.lo isl_tab.lo \
+ isl_tab_pip.lo isl_tarjan.lo isl_transitive_closure.lo \
+ isl_union_map.lo isl_val.lo isl_vec.lo isl_version.lo \
+ isl_vertices.lo
libisl_la_OBJECTS = $(am_libisl_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -230,6 +248,7 @@ am__v_lt_1 =
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)
PROGRAMS = $(noinst_PROGRAMS)
am_isl_bound_OBJECTS = bound.$(OBJEXT)
isl_bound_OBJECTS = $(am_isl_bound_OBJECTS)
@@ -280,6 +299,19 @@ isl_test_DEPENDENCIES = libisl.la
isl_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(isl_test_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
+isl_test_imath_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(isl_test_imath_LDFLAGS) $(LDFLAGS) -o \
+ $@
+isl_test_int_SOURCES = isl_test_int.c
+isl_test_int_OBJECTS = isl_test_int.$(OBJEXT)
+isl_test_int_DEPENDENCIES = libisl.la
+isl_test_int_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(isl_test_int_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
@@ -319,14 +351,14 @@ SOURCES = $(libisl_la_SOURCES) $(isl_bound_SOURCES) $(isl_cat_SOURCES) \
$(isl_pip_SOURCES) $(isl_polyhedron_detect_equalities_SOURCES) \
$(isl_polyhedron_minimize_SOURCES) \
$(isl_polyhedron_sample_SOURCES) $(isl_polytope_scan_SOURCES) \
- isl_test.c
+ 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) \
$(isl_codegen_SOURCES) $(isl_pip_SOURCES) \
$(isl_polyhedron_detect_equalities_SOURCES) \
$(isl_polyhedron_minimize_SOURCES) \
$(isl_polyhedron_sample_SOURCES) $(isl_polytope_scan_SOURCES) \
- isl_test.c
+ isl_test.c 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 \
@@ -760,20 +792,13 @@ lib_LTLIBRARIES = libisl.la
@GMP_FOR_MP_TRUE@ isl_gmp.c \
@GMP_FOR_MP_TRUE@ isl_val_gmp.c
-@IMATH_FOR_MP_TRUE@MP_SRC = \
-@IMATH_FOR_MP_TRUE@ isl_hide_deprecated.h \
-@IMATH_FOR_MP_TRUE@ isl_imath.c \
-@IMATH_FOR_MP_TRUE@ isl_imath.h \
-@IMATH_FOR_MP_TRUE@ isl_int_imath.h \
-@IMATH_FOR_MP_TRUE@ isl_val_imath.c \
-@IMATH_FOR_MP_TRUE@ imath_wrap/gmp_compat.h \
-@IMATH_FOR_MP_TRUE@ imath_wrap/imath.h \
-@IMATH_FOR_MP_TRUE@ imath_wrap/imrat.h \
-@IMATH_FOR_MP_TRUE@ imath_wrap/wrap.h \
-@IMATH_FOR_MP_TRUE@ imath_wrap/gmp_compat.c \
-@IMATH_FOR_MP_TRUE@ imath_wrap/imath.c \
-@IMATH_FOR_MP_TRUE@ imath_wrap/imrat.c
-
+@IMATH_FOR_MP_TRUE@MP_SRC = isl_hide_deprecated.h isl_imath.c \
+@IMATH_FOR_MP_TRUE@ isl_imath.h isl_int_imath.h \
+@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)
@GMP_FOR_MP_TRUE@DEPRECATED_SRC = isl_ast_int.c
@IMATH_FOR_MP_TRUE@DEPRECATED_SRC =
@GMP_FOR_MP_TRUE@MP_INCLUDE_H = include/isl/val_gmp.h
@@ -821,9 +846,11 @@ libisl_la_SOURCES = \
isl_factorization.c \
isl_factorization.h \
isl_farkas.c \
+ isl_ffs.c \
isl_flow.c \
isl_fold.c \
isl_hash.c \
+ isl_hash_private.h \
isl_id_to_ast_expr.c \
isl_id_to_pw_aff.c \
isl_ilp.c \
@@ -850,6 +877,7 @@ libisl_la_SOURCES = \
isl_options.c \
isl_options_private.h \
isl_output.c \
+ isl_output_private.h \
isl_point_private.h \
isl_point.c \
isl_polynomial_private.h \
@@ -907,6 +935,10 @@ libisl_la_LDFLAGS = -version-info @versioninfo@ \
isl_test_LDFLAGS = @MP_LDFLAGS@
isl_test_LDADD = libisl.la @MP_LIBS@
+isl_test_int_LDFLAGS = @MP_LDFLAGS@
+isl_test_int_LDADD = libisl.la @MP_LIBS@
+@IMATH_FOR_MP_TRUE@isl_test_imath_LDFLAGS = @MP_LDFLAGS@
+@IMATH_FOR_MP_TRUE@isl_test_imath_LDADD = libisl.la @MP_LIBS@
isl_polyhedron_sample_LDADD = libisl.la
isl_polyhedron_sample_SOURCES = \
polyhedron_sample.c
@@ -1014,6 +1046,17 @@ deprecated_HEADERS = \
include/isl/deprecated/val_int.h \
include/isl/deprecated/vec_int.h
+BUILT_SOURCES = gitversion.h
+CLEANFILES = \
+ gitversion.h
+
+DISTCLEANFILES = \
+ isl-uninstalled.sh \
+ isl-uninstalled.pc \
+ isl.pc \
+ isl.pc.in \
+ include/isl/stdint.h
+
EXTRA_DIST = \
LICENSE \
isl_config_post.h \
@@ -1028,13 +1071,19 @@ EXTRA_DIST = \
isl_multi_apply_templ.c \
isl_multi_apply_set.c \
isl_multi_apply_union_set.c \
+ isl_multi_coalesce.c \
isl_multi_floor.c \
isl_multi_gist.c \
isl_multi_intersect.c \
print_templ.c \
isl_power_templ.c \
isl_pw_templ.c \
+ isl_union_macro.h \
isl_union_templ.c \
+ isl_union_single.c \
+ isl_union_multi.c \
+ isl_union_eval.c \
+ isl_union_neg.c \
isl.py \
doc/CodingStyle \
doc/SubmittingPatches \
@@ -1057,7 +1106,7 @@ EXTRA_DIST = \
pkgconfigdir = $(pkgconfig_libdir)
pkgconfig_DATA = $(pkgconfig_libfile)
-all: isl_config.h
+all: $(BUILT_SOURCES) isl_config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
@@ -1217,6 +1266,14 @@ isl_test$(EXEEXT): $(isl_test_OBJECTS) $(isl_test_DEPENDENCIES) $(EXTRA_isl_test
@rm -f isl_test$(EXEEXT)
$(AM_V_CCLD)$(isl_test_LINK) $(isl_test_OBJECTS) $(isl_test_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)
+
+isl_test_int$(EXEEXT): $(isl_test_int_OBJECTS) $(isl_test_int_DEPENDENCIES) $(EXTRA_isl_test_int_DEPENDENCIES)
+ @rm -f isl_test_int$(EXEEXT)
+ $(AM_V_CCLD)$(isl_test_int_LINK) $(isl_test_int_OBJECTS) $(isl_test_int_LDADD) $(LIBS)
+
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f imath_wrap/*.$(OBJEXT)
@@ -1252,6 +1309,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_equalities.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_factorization.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_farkas.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_ffs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_flow.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_fold.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_gmp.Plo@am__quote@
@@ -1262,6 +1320,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_ilp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_imath.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_input.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_int_sioimath.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_local_space.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_lp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_map.Plo@am__quote@
@@ -1296,11 +1355,14 @@ distclean-compile:
@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_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@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_union_map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_val.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_val_gmp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_val_imath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_val_sioimath.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_vec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_version.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isl_vertices.Plo@am__quote@
@@ -1708,6 +1770,20 @@ bound_test.sh.log: bound_test.sh
--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_int.log: isl_test_int$(EXEEXT)
+ @p='isl_test_int$(EXEEXT)'; \
+ b='isl_test_int'; \
+ $(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'; \
+ $(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)
.test.log:
@p='$<'; \
$(am__set_b); \
@@ -1916,7 +1992,8 @@ distcleancheck: distclean
exit 1; } >&2
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
-check: check-recursive
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) \
isl_config.h
installdirs: installdirs-recursive
@@ -1924,7 +2001,8 @@ installdirs-am:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(deprecateddir)" "$(DESTDIR)$(pkgincludedir)" "$(DESTDIR)$(pkgincludedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
-install: install-recursive
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
@@ -1949,16 +2027,19 @@ mostlyclean-generic:
-test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
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)
-rm -f imath_wrap/$(DEPDIR)/$(am__dirstamp)
-rm -f imath_wrap/$(am__dirstamp)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-recursive
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
@@ -2034,10 +2115,11 @@ ps: ps-recursive
ps-am:
uninstall-am: uninstall-deprecatedHEADERS uninstall-libLTLIBRARIES \
- uninstall-nodist_pkgincludeHEADERS uninstall-pkgconfigDATA \
- uninstall-pkgincludeHEADERS
+ uninstall-local uninstall-nodist_pkgincludeHEADERS \
+ uninstall-pkgconfigDATA uninstall-pkgincludeHEADERS
-.MAKE: $(am__recursive_targets) all check-am install-am install-strip
+.MAKE: $(am__recursive_targets) all check check-am install install-am \
+ install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
am--refresh check check-TESTS check-am clean clean-cscope \
@@ -2061,8 +2143,8 @@ uninstall-am: uninstall-deprecatedHEADERS uninstall-libLTLIBRARIES \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
recheck tags tags-am uninstall uninstall-am \
uninstall-deprecatedHEADERS uninstall-libLTLIBRARIES \
- uninstall-nodist_pkgincludeHEADERS uninstall-pkgconfigDATA \
- uninstall-pkgincludeHEADERS
+ uninstall-local uninstall-nodist_pkgincludeHEADERS \
+ uninstall-pkgconfigDATA uninstall-pkgincludeHEADERS
dist-hook:
@@ -2083,6 +2165,13 @@ install-data-local: $(srcdir)/isl.py
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"; \
$(INSTALL_DATA) $(srcdir)/isl.py $(DESTDIR)$(libdir)/$$libisl-gdb.py; esac
+uninstall-local:
+ @libisl=`sed -ne "/^library_names=/{s/.*='//;s/'$$//;s/ .*//;p;}" \
+ $(builddir)/libisl.la`; \
+ if test -n "$${libisl}"; then \
+ rm -f $(DESTDIR)$(libdir)/$$libisl-gdb.py; \
+ fi
+
# 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/basis_reduction_tab.c b/basis_reduction_tab.c
index cd975485..b42f6773 100644
--- a/basis_reduction_tab.c
+++ b/basis_reduction_tab.c
@@ -45,6 +45,8 @@ struct tab_lp {
#define GBR_denref(a) mpq_denref(a)
#define GBR_floor(a,b) mpz_fdiv_q(a,GBR_numref(b),GBR_denref(b))
#define GBR_ceil(a,b) mpz_cdiv_q(a,GBR_numref(b),GBR_denref(b))
+#define GBR_set_num_neg(a, b) mpz_neg(GBR_numref(*a), b);
+#define GBR_set_den(a, b) mpz_set(GBR_denref(*a), b);
#endif /* USE_GMP_FOR_MP */
#ifdef USE_IMATH_FOR_MP
@@ -58,10 +60,31 @@ struct tab_lp {
#define GBR_mul(a,b,c) mp_rat_mul(b,c,a)
#define GBR_lt(a,b) (mp_rat_compare(a,b) < 0)
#define GBR_is_zero(a) (mp_rat_compare_zero(a) == 0)
-#define GBR_numref(a) mp_rat_numer_ref(a)
-#define GBR_denref(a) mp_rat_denom_ref(a)
-#define GBR_floor(a,b) impz_fdiv_q(a,GBR_numref(b),GBR_denref(b))
-#define GBR_ceil(a,b) impz_cdiv_q(a,GBR_numref(b),GBR_denref(b))
+#ifdef USE_SMALL_INT_OPT
+#define GBR_numref(a) isl_sioimath_encode_big(mp_rat_numer_ref(a))
+#define GBR_denref(a) isl_sioimath_encode_big(mp_rat_denom_ref(a))
+#define GBR_floor(a, b) isl_sioimath_fdiv_q((a), GBR_numref(b), GBR_denref(b))
+#define GBR_ceil(a, b) isl_sioimath_cdiv_q((a), GBR_numref(b), GBR_denref(b))
+#define GBR_set_num_neg(a, b) \
+ do { \
+ isl_sioimath_scratchspace_t scratch; \
+ impz_neg(mp_rat_numer_ref(*a), \
+ isl_sioimath_bigarg_src(*b, &scratch));\
+ } while (0)
+#define GBR_set_den(a, b) \
+ do { \
+ isl_sioimath_scratchspace_t scratch; \
+ impz_set(mp_rat_denom_ref(*a), \
+ isl_sioimath_bigarg_src(*b, &scratch));\
+ } while (0)
+#else /* USE_SMALL_INT_OPT */
+#define GBR_numref(a) mp_rat_numer_ref(a)
+#define GBR_denref(a) mp_rat_denom_ref(a)
+#define GBR_floor(a,b) impz_fdiv_q(a,GBR_numref(b),GBR_denref(b))
+#define GBR_ceil(a,b) impz_cdiv_q(a,GBR_numref(b),GBR_denref(b))
+#define GBR_set_num_neg(a, b) impz_neg(GBR_numref(*a), b)
+#define GBR_set_den(a, b) impz_set(GBR_denref(*a), b)
+#endif /* USE_SMALL_INT_OPT */
#endif /* USE_IMATH_FOR_MP */
static struct tab_lp *init_lp(struct isl_tab *tab);
@@ -222,8 +245,8 @@ static int cut_lp_to_hyperplane(struct tab_lp *lp, isl_int *row)
static void get_obj_val(struct tab_lp* lp, GBR_type *F)
{
- isl_int_neg(GBR_numref(*F), lp->opt);
- isl_int_set(GBR_denref(*F), lp->opt_denom);
+ GBR_set_num_neg(F, lp->opt);
+ GBR_set_den(F, lp->opt_denom);
}
static void delete_lp(struct tab_lp *lp)
@@ -259,8 +282,8 @@ static int add_lp_row(struct tab_lp *lp, isl_int *row, int dim)
static void get_alpha(struct tab_lp* lp, int row, GBR_type *alpha)
{
row += lp->con_offset;
- isl_int_neg(GBR_numref(*alpha), lp->tab->dual->el[1 + row]);
- isl_int_set(GBR_denref(*alpha), lp->tab->dual->el[0]);
+ GBR_set_num_neg(alpha, lp->tab->dual->el[1 + row]);
+ GBR_set_den(alpha, lp->tab->dual->el[0]);
}
static int del_lp_row(struct tab_lp *lp)
diff --git a/configure b/configure
index e05dae96..93f04606 100755
--- a/configure
+++ b/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.15.
+# Generated by GNU Autoconf 2.69 for isl 0.16.
#
# Report bugs to <isl-development@googlegroups.com>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='isl'
PACKAGE_TARNAME='isl'
-PACKAGE_VERSION='0.15'
-PACKAGE_STRING='isl 0.15'
+PACKAGE_VERSION='0.16'
+PACKAGE_STRING='isl 0.16'
PACKAGE_BUGREPORT='isl-development@googlegroups.com'
PACKAGE_URL=''
@@ -648,6 +648,8 @@ llvm_config_found
CLANG_LIBS
CLANG_LDFLAGS
CLANG_CXXFLAGS
+SMALL_INT_OPT_FALSE
+SMALL_INT_OPT_TRUE
GMP_FOR_MP_FALSE
GMP_FOR_MP_TRUE
IMATH_FOR_MP_FALSE
@@ -1359,7 +1361,7 @@ if test "$ac_init_help" = "long"; then
# 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.15 to adapt to many kinds of systems.
+\`configure' configures isl 0.16 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1429,7 +1431,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of isl 0.15:";;
+ short | recursive ) echo "Configuration of isl 0.16:";;
esac
cat <<\_ACEOF
@@ -1462,7 +1464,8 @@ Optional Packages:
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--with-sysroot[=DIR] Search for dependent libraries within DIR (or the
compiler's sysroot if not specified).
- --with-int=gmp|imath Which package to use to represent multi-precision
+ --with-int=gmp|imath|imath-32
+ Which package to use to represent multi-precision
integers [default=gmp]
--with-gmp=system|build Which gmp to use [default=system]
--with-gmp-prefix=DIR Prefix of gmp installation
@@ -1553,7 +1556,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-isl configure 0.15
+isl configure 0.16
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2417,7 +2420,7 @@ cat >config.log <<_ACEOF
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.15, which was
+It was created by isl $as_me 0.16, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3281,7 +3284,7 @@ fi
# Define the identity of the package.
PACKAGE='isl'
- VERSION='0.15'
+ VERSION='0.16'
cat >>confdefs.h <<_ACEOF
@@ -3413,7 +3416,7 @@ fi
AM_BACKSLASH='\'
-versioninfo=15:0:0
+versioninfo=16:0:1
if test "x$prefix" != "xNONE"; then
prefix_wd=`cd $prefix && pwd`
@@ -17260,10 +17263,10 @@ else
fi
case "$with_int" in
-gmp|imath)
+gmp|imath|imath-32)
;;
*)
- as_fn_error $? "bad value ${withval} for --with-int (use gmp or imath)" "$LINENO" 5
+ as_fn_error $? "bad value ${withval} for --with-int (use gmp, imath or imath-32)" "$LINENO" 5
esac
@@ -17496,7 +17499,7 @@ fi
;;
-imath)
+imath|imath-32)
$as_echo "#define USE_IMATH_FOR_MP /**/" >>confdefs.h
@@ -17537,8 +17540,11 @@ fi
;;
esac
+if test "x$with_int" = "ximath-32" -a "x$GCC" = "xyes"; then
+ MP_CPPFLAGS="-std=gnu99 $MP_CPPFLAGS"
+fi
- if test x$with_int = ximath; then
+ if test x$with_int = ximath -o x$with_int = ximath-32; then
IMATH_FOR_MP_TRUE=
IMATH_FOR_MP_FALSE='#'
else
@@ -17554,6 +17560,23 @@ else
GMP_FOR_MP_FALSE=
fi
+
+ if test "x$with_int" == "ximath-32"; then
+ SMALL_INT_OPT_TRUE=
+ SMALL_INT_OPT_FALSE='#'
+else
+ SMALL_INT_OPT_TRUE='#'
+ SMALL_INT_OPT_FALSE=
+fi
+
+if test "x$with_int" == "ximath-32"; then :
+
+
+$as_echo "#define USE_SMALL_INT_OPT /**/" >>confdefs.h
+
+
+fi
+
ac_fn_c_check_decl "$LINENO" "ffs" "ac_cv_have_decl_ffs" "#include <strings.h>
"
if test "x$ac_cv_have_decl_ffs" = xyes; then :
@@ -17577,6 +17600,104 @@ cat >>confdefs.h <<_ACEOF
#define HAVE_DECL___BUILTIN_FFS $ac_have_decl
_ACEOF
+ac_fn_c_check_decl "$LINENO" "_BitScanForward" "ac_cv_have_decl__BitScanForward" "#include <intrin.h>
+"
+if test "x$ac_cv_have_decl__BitScanForward" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL__BITSCANFORWARD $ac_have_decl
+_ACEOF
+
+if test "x$ac_cv_have_decl_ffs" = xno -a \
+ "x$ac_cv_have_decl___builtin_ffs" = xno -a \
+ "x$ac_cv_have_decl__BitScanForward" = xno; then
+ as_fn_error $? "No ffs implementation found" "$LINENO" 5
+fi
+ac_fn_c_check_decl "$LINENO" "strcasecmp" "ac_cv_have_decl_strcasecmp" "#include <strings.h>
+"
+if test "x$ac_cv_have_decl_strcasecmp" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STRCASECMP $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "strncasecmp" "ac_cv_have_decl_strncasecmp" "#include <strings.h>
+"
+if test "x$ac_cv_have_decl_strncasecmp" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STRNCASECMP $ac_have_decl
+_ACEOF
+
+ac_fn_c_check_decl "$LINENO" "_stricmp" "ac_cv_have_decl__stricmp" "#include <string.h>
+"
+if test "x$ac_cv_have_decl__stricmp" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL__STRICMP $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "_strnicmp" "ac_cv_have_decl__strnicmp" "#include <string.h>
+"
+if test "x$ac_cv_have_decl__strnicmp" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL__STRNICMP $ac_have_decl
+_ACEOF
+
+if test "x$ac_cv_have_decl_strcasecmp" = xno -a \
+ "x$ac_cv_have_decl__stricmp" = xno; then
+ as_fn_error $? "No strcasecmp implementation found" "$LINENO" 5
+fi
+if test "x$ac_cv_have_decl_strncasecmp" = xno -a \
+ "x$ac_cv_have_decl__strnicmp" = xno; then
+ as_fn_error $? "No strncasecmp implementation found" "$LINENO" 5
+fi
+ac_fn_c_check_decl "$LINENO" "snprintf" "ac_cv_have_decl_snprintf" "#include <stdio.h>
+"
+if test "x$ac_cv_have_decl_snprintf" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SNPRINTF $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "_snprintf" "ac_cv_have_decl__snprintf" "#include <stdio.h>
+"
+if test "x$ac_cv_have_decl__snprintf" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL__SNPRINTF $ac_have_decl
+_ACEOF
+
+if test "x$ac_cv_have_decl_snprintf" = xno -a \
+ "x$ac_cv_have_decl__snprintf" = xno; then
+ as_fn_error $? "No snprintf implementation found" "$LINENO" 5
+fi
@@ -17729,6 +17850,75 @@ $as_echo "$ac_cv_path_GREP" >&6; }
GREP="$ac_cv_path_GREP"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for ac_i in 1 2 3 4 5 6 7; do
+ ac_script="$ac_script$as_nl$ac_script"
+ done
+ echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+ { ac_script=; unset ac_script;}
+ if test -z "$SED"; then
+ ac_path_SED_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+ # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+ ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo '' >> "conftest.nl"
+ "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_SED_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_SED="$ac_path_SED"
+ ac_path_SED_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_SED_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_SED"; then
+ as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+ fi
+else
+ ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+ rm -f conftest.sed
+
llvm_config="llvm-config"
# Extract the first word of ""$llvm_config"", so it can be a program name with args.
set dummy "$llvm_config"; ac_word=$2
@@ -17776,7 +17966,8 @@ fi
if test "$llvm_config_found" != yes; then
as_fn_error $? "llvm-config not found" "$LINENO" 5
fi
- CLANG_CXXFLAGS=`$llvm_config --cxxflags`
+ CLANG_CXXFLAGS=`$llvm_config --cxxflags | \
+ $SED -e 's/-Wcovered-switch-default//'`
CLANG_LDFLAGS=`$llvm_config --ldflags`
targets=`$llvm_config --targets-built`
components="$targets asmparser bitreader support mc"
@@ -18111,6 +18302,21 @@ $as_echo "#define HAVE_ADT_OWNINGPTR_H /**/" >>confdefs.h
fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <clang/Basic/Builtins.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "initializeBuiltins" >/dev/null 2>&1; then :
+
+else
+
+$as_echo "#define initializeBuiltins InitializeBuiltins" >>confdefs.h
+
+fi
+rm -f conftest*
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -18433,7 +18639,6 @@ ac_config_commands="$ac_config_commands $ax_create_pkgconfig_generate"
GIT_HEAD_VERSION="\`GIT_DIR=$GIT_REPO git describe --always\`"
fi
-echo '#define GIT_HEAD_ID "'$GIT_HEAD_ID'"' > gitversion.h
ac_config_headers="$ac_config_headers isl_config.h"
@@ -18610,6 +18815,10 @@ if test -z "${GMP_FOR_MP_TRUE}" && test -z "${GMP_FOR_MP_FALSE}"; then
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 "${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
+fi
if test -z "${HAVE_CLANG_TRUE}" && test -z "${HAVE_CLANG_FALSE}"; then
as_fn_error $? "conditional \"HAVE_CLANG\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -19011,7 +19220,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# 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.15, which was
+This file was extended by isl $as_me 0.16, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -19077,7 +19286,7 @@ _ACEOF
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.15
+isl config.status 0.16
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 9c812562..ef27964b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,10 +1,10 @@
-AC_INIT([isl], [0.15], [isl-development@googlegroups.com])
+AC_INIT([isl], [0.16], [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=15:0:0
+versioninfo=16:0:1
if test "x$prefix" != "xNONE"; then
prefix_wd=`cd $prefix && pwd`
@@ -36,15 +36,16 @@ AM_CONDITIONAL(GENERATE_DOC, test -n "$PERL" -a -n "$PDFLATEX" -a -n "$POD2HTML"
AX_CREATE_STDINT_H(include/isl/stdint.h)
AC_ARG_WITH([int],
- [AS_HELP_STRING([--with-int=gmp|imath],
+ [AS_HELP_STRING([--with-int=gmp|imath|imath-32],
[Which package to use to represent
multi-precision integers [default=gmp]])],
[], [with_int=gmp])
case "$with_int" in
-gmp|imath)
+gmp|imath|imath-32)
;;
*)
- AC_MSG_ERROR([bad value ${withval} for --with-int (use gmp or imath)])
+ AC_MSG_ERROR(
+ [bad value ${withval} for --with-int (use gmp, imath or imath-32)])
esac
AC_SUBST(MP_CPPFLAGS)
@@ -54,15 +55,45 @@ case "$with_int" in
gmp)
AX_DETECT_GMP
;;
-imath)
+imath|imath-32)
AX_DETECT_IMATH
;;
esac
+if test "x$with_int" = "ximath-32" -a "x$GCC" = "xyes"; then
+ MP_CPPFLAGS="-std=gnu99 $MP_CPPFLAGS"
+fi
-AM_CONDITIONAL(IMATH_FOR_MP, test x$with_int = ximath)
+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(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])
+])
+
AC_CHECK_DECLS(ffs,[],[],[#include <strings.h>])
AC_CHECK_DECLS(__builtin_ffs,[],[],[])
+AC_CHECK_DECLS([_BitScanForward],[],[],[#include <intrin.h>])
+if test "x$ac_cv_have_decl_ffs" = xno -a \
+ "x$ac_cv_have_decl___builtin_ffs" = xno -a \
+ "x$ac_cv_have_decl__BitScanForward" = xno; then
+ AC_MSG_ERROR([No ffs implementation found])
+fi
+AC_CHECK_DECLS([strcasecmp,strncasecmp],[],[],[#include <strings.h>])
+AC_CHECK_DECLS([_stricmp,_strnicmp],[],[],[#include <string.h>])
+if test "x$ac_cv_have_decl_strcasecmp" = xno -a \
+ "x$ac_cv_have_decl__stricmp" = xno; then
+ AC_MSG_ERROR([No strcasecmp implementation found])
+fi
+if test "x$ac_cv_have_decl_strncasecmp" = xno -a \
+ "x$ac_cv_have_decl__strnicmp" = xno; then
+ AC_MSG_ERROR([No strncasecmp implementation found])
+fi
+AC_CHECK_DECLS([snprintf,_snprintf],[],[],[#include <stdio.h>])
+if test "x$ac_cv_have_decl_snprintf" = xno -a \
+ "x$ac_cv_have_decl__snprintf" = xno; then
+ AC_MSG_ERROR([No snprintf implementation found])
+fi
AC_SUBST(CLANG_CXXFLAGS)
AC_SUBST(CLANG_LDFLAGS)
@@ -71,6 +102,7 @@ AX_SUBMODULE(clang,system|no,no)
case "$with_clang" in
system)
AC_PROG_GREP
+ AC_PROG_SED
llvm_config="llvm-config"
AC_CHECK_PROG([llvm_config_found], ["$llvm_config"], [yes])
if test "x$with_clang_prefix" != "x"; then
@@ -82,7 +114,8 @@ system)
if test "$llvm_config_found" != yes; then
AC_MSG_ERROR([llvm-config not found])
fi
- CLANG_CXXFLAGS=`$llvm_config --cxxflags`
+ CLANG_CXXFLAGS=`$llvm_config --cxxflags | \
+ $SED -e 's/-Wcovered-switch-default//'`
CLANG_LDFLAGS=`$llvm_config --ldflags`
targets=`$llvm_config --targets-built`
components="$targets asmparser bitreader support mc"
@@ -194,6 +227,10 @@ system)
AC_CHECK_HEADER([llvm/ADT/OwningPtr.h],
[AC_DEFINE([HAVE_ADT_OWNINGPTR_H], [],
[Define if llvm/ADT/OwningPtr.h exists])])
+ AC_EGREP_HEADER([initializeBuiltins],
+ [clang/Basic/Builtins.h], [],
+ [AC_DEFINE([initializeBuiltins], [InitializeBuiltins],
+ [Define to InitializeBuiltins for older versions of clang])])
AC_LANG_POP
CPPFLAGS="$SAVE_CPPFLAGS"
@@ -216,7 +253,6 @@ PACKAGE_LIBS="-lisl $MP_LIBS"
AX_CREATE_PKGCONFIG_INFO
AX_DETECT_GIT_HEAD
-echo '#define GIT_HEAD_ID "'$GIT_HEAD_ID'"' > gitversion.h
AH_BOTTOM([#include <isl_config_post.h>])
AC_CONFIG_HEADERS(isl_config.h)
diff --git a/doc/Makefile.am b/doc/Makefile.am
index aa79a6c9..625af68b 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,3 +1,16 @@
+
+CLEANFILES = \
+ manual.toc \
+ manual.bbl \
+ version.tex \
+ user.tex \
+ manual.pdf \
+ manual.aux \
+ manual.out \
+ manual.blg \
+ manual.log \
+ manual.brf
+
if GENERATE_DOC
export TEXINPUTS := $(srcdir):$(TEXINPUTS)
export BIBINPUTS := $(srcdir):$(BIBINPUTS)
diff --git a/doc/Makefile.in b/doc/Makefile.in
index b5f56eb9..d58757b3 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -262,6 +262,18 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
versioninfo = @versioninfo@
+CLEANFILES = \
+ manual.toc \
+ manual.bbl \
+ version.tex \
+ user.tex \
+ manual.pdf \
+ manual.aux \
+ manual.out \
+ manual.blg \
+ manual.log \
+ manual.brf
+
all: all-am
.SUFFIXES:
@@ -364,6 +376,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -452,6 +465,7 @@ uninstall-am:
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags-am uninstall uninstall-am
+
@GENERATE_DOC_TRUE@export TEXINPUTS := $(srcdir):$(TEXINPUTS)
@GENERATE_DOC_TRUE@export BIBINPUTS := $(srcdir):$(BIBINPUTS)
@GENERATE_DOC_TRUE@export BSTINPUTS := $(srcdir):$(BSTINPUTS)
diff --git a/doc/manual.pdf b/doc/manual.pdf
index 55895a18..5c3b678e 100644
--- a/doc/manual.pdf
+++ b/doc/manual.pdf
Binary files differ
diff --git a/doc/user.pod b/doc/user.pod
index dd095526..a78ee9d7 100644
--- a/doc/user.pod
+++ b/doc/user.pod
@@ -196,7 +196,7 @@ an C<isl_val> instead of an C<isl_qpolynomial>.
=item * The function C<isl_band_member_is_zero_distance>
has been removed. Essentially the same functionality is available
-through C<isl_band_member_is_coincident>, except that is requires
+through C<isl_band_member_is_coincident>, except that it requires
setting up coincidence constraints.
The option C<schedule_outer_zero_distance> has accordingly been
replaced by the option C<schedule_outer_coincidence>.
@@ -212,9 +212,6 @@ a regular basic set, rather than a rational basic set.
=over
-=item * Objects of type C<isl_union_pw_multi_aff> can no longer contain
-two or more C<isl_pw_multi_aff> objects with the same domain space.
-
=item * The function C<isl_union_pw_multi_aff_add> now consistently
computes the sum on the shared definition domain.
The function C<isl_union_pw_multi_aff_union_add> has been added
@@ -286,8 +283,9 @@ Note that by default C<isl> requires C<GMP>, which is released
under the GNU Lesser General Public License (LGPL). This means
that code linked against C<isl> is also linked against LGPL code.
-When configuring with C<--with-int=imath>, C<isl> will link against C<imath>, a
-library for exact integer arithmetic released under the MIT license.
+When configuring with C<--with-int=imath> or C<--with-int=imath-32>, C<isl>
+will link against C<imath>, a library for exact integer arithmetic released
+under the MIT license.
=head1 Installation
@@ -364,10 +362,13 @@ Below we discuss some of the more common options.
Installation prefix for C<isl>
-=item C<--with-int=[gmp|imath]>
+=item C<--with-int=[gmp|imath|imath-32]>
Select the integer library to be used by C<isl>, the default is C<gmp>.
-Note that C<isl> may run significantly slower if you use C<imath>.
+With C<imath-32>, C<isl> will use 32 bit integers, but fall back to C<imath>
+for values out of the 32 bit range. In most applications, C<isl> will run
+fastest with the C<imath-32> option, followed by C<gmp> and C<imath>, the
+slowest.
=item C<--with-gmp-prefix>
@@ -637,6 +638,8 @@ They can be inspected using the following functions.
#include <isl/val.h>
long isl_val_get_num_si(__isl_keep isl_val *v);
long isl_val_get_den_si(__isl_keep isl_val *v);
+ __isl_give isl_val *isl_val_get_den_val(
+ __isl_keep isl_val *v);
double isl_val_get_d(__isl_keep isl_val *v);
size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v,
size_t size);
@@ -985,6 +988,9 @@ of the original object.
__isl_keep isl_qpolynomial *qp);
__isl_give isl_space *isl_qpolynomial_get_space(
__isl_keep isl_qpolynomial *qp);
+ __isl_give isl_space *
+ isl_qpolynomial_fold_get_domain_space(
+ __isl_keep isl_qpolynomial_fold *fold);
__isl_give isl_space *isl_qpolynomial_fold_get_space(
__isl_keep isl_qpolynomial_fold *fold);
__isl_give isl_space *isl_pw_qpolynomial_get_domain_space(
@@ -2125,6 +2131,11 @@ To iterate over all the sets or maps in a union set or map, use
isl_stat (*fn)(__isl_take isl_map *map, void *user),
void *user);
+These functions call the callback function once for each
+(pair of) space(s) for which there are elements in the input.
+The argument to the callback contains all elements in the input
+with that (pair of) space(s).
+
The number of sets or maps in a union set or map can be obtained
from
@@ -2175,6 +2186,14 @@ from
#include <isl/map.h>
int isl_map_n_basic_map(__isl_keep isl_map *map);
+It is also possible to obtain a list of basic sets from a set
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
+ __isl_keep isl_set *set);
+
+The returned list can be manipulated using the functions in L<"Lists">.
+
To iterate over the constraints of a basic set or map, use
#include <isl/constraint.h>
@@ -2318,6 +2337,8 @@ A singleton set can be created from a point using
__isl_take isl_point *pnt);
__isl_give isl_set *isl_set_from_point(
__isl_take isl_point *pnt);
+ __isl_give isl_union_set *isl_union_set_from_point(
+ __isl_take isl_point *pnt);
and a box can be created from two opposite extremal points using
@@ -2350,12 +2371,14 @@ enumerating and return C<-1> as well.
If the enumeration is performed successfully and to completion,
then C<isl_set_foreach_point> returns C<0>.
-To obtain a single point of a (basic) set, use
+To obtain a single point of a (basic or union) set, use
__isl_give isl_point *isl_basic_set_sample_point(
__isl_take isl_basic_set *bset);
__isl_give isl_point *isl_set_sample_point(
__isl_take isl_set *set);
+ __isl_give isl_point *isl_union_set_sample_point(
+ __isl_take isl_union_set *uset);
If C<set> does not contain any (integer) points, then the
resulting point will be ``void'', a property that can be
@@ -2717,6 +2740,10 @@ then this space also needs to be a set space.
__isl_give isl_multi_aff *isl_multi_aff_from_aff_list(
__isl_take isl_space *space,
__isl_take isl_aff_list *list);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_from_pw_aff_list(
+ __isl_take isl_space *space,
+ __isl_take isl_pw_aff_list *list);
__isl_give isl_multi_union_pw_aff *
isl_multi_union_pw_aff_from_union_pw_aff_list(
__isl_take isl_space *space,
@@ -3114,6 +3141,14 @@ is that of the shared parameter space.
The union expression types defined by C<isl>
are C<isl_union_pw_aff>, C<isl_union_pw_multi_aff>,
C<isl_union_pw_qpolynomial> and C<isl_union_pw_qpolynomial_fold>.
+In case of
+C<isl_union_pw_aff>,
+C<isl_union_pw_qpolynomial> and C<isl_union_pw_qpolynomial_fold>,
+there can be at most one base expression for a given domain space.
+In case of
+C<isl_union_pw_multi_aff>,
+there can be multiple such expressions for a given domain space,
+but the domains of these expressions need to be disjoint.
An empty union expression can be created using the following functions.
@@ -3387,6 +3422,9 @@ Objects can be read from input using the following functions.
isl_ctx *ctx, const char *str);
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str(
isl_ctx *ctx, const char *str);
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_read_from_str(
+ isl_ctx *ctx, const char *str);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_read_from_str(
isl_ctx *ctx, const char *str);
@@ -3870,18 +3908,39 @@ i.e., whether both domain and range are nested relations.
=item * Currying
+ #include <isl/space.h>
+ isl_bool isl_space_can_curry(
+ __isl_keep isl_space *space);
+
+ #include <isl/map.h>
isl_bool isl_basic_map_can_curry(
__isl_keep isl_basic_map *bmap);
isl_bool isl_map_can_curry(__isl_keep isl_map *map);
Check whether the domain of the (basic) relation is a wrapped relation.
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_uncurry(
+ __isl_take isl_space *space);
+
+ #include <isl/map.h>
isl_bool isl_basic_map_can_uncurry(
__isl_keep isl_basic_map *bmap);
isl_bool isl_map_can_uncurry(__isl_keep isl_map *map);
Check whether the range of the (basic) relation is a wrapped relation.
+ #include <isl/space.h>
+ isl_bool isl_space_can_range_curry(
+ __isl_keep isl_space *space);
+
+ #include <isl/map.h>
+ isl_bool isl_map_can_range_curry(
+ __isl_keep isl_map *map);
+
+Check whether the domain of the relation wrapped in the range of
+the input is itself a wrapped relation.
+
=item * Special Values
#include <isl/aff.h>
@@ -4313,10 +4372,11 @@ on a given parameter domain using the following functions.
__isl_give isl_set *isl_set_from_params(
__isl_take isl_set *set);
-=item * Constructing a relation from a set
+=item * Constructing a relation from one or two sets
-Create a relation with the given set as domain or range.
-The range or domain of the created relation is a zero-dimensional
+Create a relation with the given set(s) as domain and/or range.
+If only the domain or the range is specified, then
+the range or domain of the created relation is a zero-dimensional
flat anonymous space.
#include <isl/space.h>
@@ -4340,6 +4400,12 @@ flat anonymous space.
__isl_give isl_map *isl_map_from_range(
__isl_take isl_set *set);
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *
+ isl_union_map_from_domain_and_range(
+ __isl_take isl_union_set *domain,
+ __isl_take isl_union_set *range);
+
#include <isl/val.h>
__isl_give isl_multi_val *isl_multi_val_from_range(
__isl_take isl_multi_val *mv);
@@ -4617,6 +4683,9 @@ basic set or relation.
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_coalesce(
__isl_take isl_union_pw_multi_aff *upma);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_coalesce(
+ __isl_take isl_multi_union_pw_aff *aff);
#include <isl/polynomial.h>
__isl_give isl_pw_qpolynomial_fold *
@@ -4796,6 +4865,11 @@ per space.
__isl_take isl_basic_map *bmap,
enum isl_dim_type type,
unsigned first, unsigned n);
+ __isl_give isl_basic_map *
+ isl_basic_map_drop_constraints_not_involving_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
__isl_give isl_map *
isl_map_drop_constraints_involving_dims(
__isl_take isl_map *map,
@@ -5124,6 +5198,21 @@ and use it as the domain of a nested relation in the range,
with the original range as range of this nested relation.
The C<uncurry> functions perform the inverse operation.
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_range_curry(
+ __isl_take isl_space *space);
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_map_range_curry(
+ __isl_take isl_map *map);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_range_curry(
+ __isl_take isl_union_map *umap);
+
+These functions apply the currying to the relation that
+is nested inside the range of the input.
+
=item * Aligning parameters
Change the order of the parameters of the given set, relation
@@ -5189,7 +5278,21 @@ All parameters need to be named.
__isl_take isl_qpolynomial *qp,
__isl_take isl_space *model);
-=item * Unary Arithmethic Operations
+=item * Unary Arithmetic Operations
+
+ #include <isl/set.h>
+ __isl_give isl_set *isl_set_neg(
+ __isl_take isl_set *set);
+ #include <isl/map.h>
+ __isl_give isl_map *isl_map_neg(
+ __isl_take isl_map *map);
+
+C<isl_set_neg> constructs a set containing the opposites of
+the elements in its argument.
+The domain of the result of C<isl_map_neg> is the same
+as the domain of its argument. The corresponding range
+elements are the opposites of the corresponding range
+elements in the argument.
#include <isl/val.h>
__isl_give isl_multi_val *isl_multi_val_neg(
@@ -6257,7 +6360,7 @@ The functions C<isl_space_range_factor_domain> and
C<isl_space_range_factor_range> extract the two arguments from
the result of a call to C<isl_space_range_product>.
-The arguments of a call to C<isl_map_range_product> can be extracted
+The arguments of a call to a product can be extracted
from the result using the following functions.
#include <isl/map.h>
@@ -6286,10 +6389,15 @@ from the result using the following functions.
isl_union_map_domain_factor_range(
__isl_take isl_union_map *umap);
__isl_give isl_union_map *
+ isl_union_map_range_factor_domain(
+ __isl_take isl_union_map *umap);
+ __isl_give isl_union_map *
isl_union_map_range_factor_range(
__isl_take isl_union_map *umap);
#include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_factor_range(
+ __isl_take isl_multi_val *mv);
__isl_give isl_multi_val *
isl_multi_val_range_factor_domain(
__isl_take isl_multi_val *mv);
@@ -6298,6 +6406,8 @@ from the result using the following functions.
__isl_take isl_multi_val *mv);
#include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_factor_range(
+ __isl_take isl_multi_aff *ma);
__isl_give isl_multi_aff *
isl_multi_aff_range_factor_domain(
__isl_take isl_multi_aff *ma);
@@ -6305,12 +6415,18 @@ from the result using the following functions.
isl_multi_aff_range_factor_range(
__isl_take isl_multi_aff *ma);
__isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_factor_range(
+ __isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_multi_pw_aff *
isl_multi_pw_aff_range_factor_domain(
__isl_take isl_multi_pw_aff *mpa);
__isl_give isl_multi_pw_aff *
isl_multi_pw_aff_range_factor_range(
__isl_take isl_multi_pw_aff *mpa);
__isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_factor_range(
+ __isl_take isl_multi_union_pw_aff *mupa);
+ __isl_give isl_multi_union_pw_aff *
isl_multi_union_pw_aff_range_factor_domain(
__isl_take isl_multi_union_pw_aff *mupa);
__isl_give isl_multi_union_pw_aff *
@@ -6320,6 +6436,11 @@ from the result using the following functions.
The splice functions are a generalization of the flat product functions,
where the second argument may be inserted at any position inside
the first argument rather than being placed at the end.
+The functions C<isl_multi_val_factor_range>,
+C<isl_multi_aff_factor_range>,
+C<isl_multi_pw_aff_factor_range> and
+C<isl_multi_union_pw_aff_factor_range>
+take functions that live in a set space.
#include <isl/val.h>
__isl_give isl_multi_val *isl_multi_val_range_splice(
@@ -6513,9 +6634,29 @@ to simplify the expression associated to each cell.
__isl_take isl_union_pw_qpolynomial_fold *upwf,
__isl_take isl_set *context);
-=item * Binary Arithmethic Operations
+=item * Binary Arithmetic Operations
+
+ #include <isl/set.h>
+ __isl_give isl_set *isl_set_sum(
+ __isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+ #include <isl/map.h>
+ __isl_give isl_map *isl_map_sum(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+
+C<isl_set_sum> computes the Minkowski sum of its two arguments,
+i.e., the set containing the sums of pairs of elements from
+C<set1> and C<set2>.
+The domain of the result of C<isl_map_sum> is the intersection
+of the domains of its two arguments. The corresponding range
+elements are the sums of the corresponding range elements
+in the two arguments.
#include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_add(
+ __isl_take isl_multi_val *mv1,
+ __isl_take isl_multi_val *mv2);
__isl_give isl_multi_val *isl_multi_val_sub(
__isl_take isl_multi_val *mv1,
__isl_take isl_multi_val *mv2);
@@ -6530,6 +6671,9 @@ to simplify the expression associated to each cell.
__isl_give isl_pw_aff *isl_pw_aff_add(
__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_add(
+ __isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_add(
__isl_take isl_pw_multi_aff *pma1,
__isl_take isl_pw_multi_aff *pma2);
@@ -6539,6 +6683,10 @@ to simplify the expression associated to each cell.
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_add(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_add(
+ __isl_take isl_multi_union_pw_aff *mupa1,
+ __isl_take isl_multi_union_pw_aff *mupa2);
__isl_give isl_pw_aff *isl_pw_aff_min(
__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
@@ -7345,6 +7493,8 @@ assigns a different value to two domain elements, while all previous
schedule dimensions in the same band assign them the same value,
then the two domain elements are ordered according to these two
different values.
+Each expression is required to be total in the domain elements
+that reach the band node.
=item C<isl_schedule_node_expansion>
@@ -7535,6 +7685,15 @@ redundant.
__isl_take isl_schedule *schedule,
__isl_take isl_union_set *domain);
+The following function can be used to simplify the domain
+of a schedule with a domain node as root with respect to the given
+parameter domain.
+
+ #include <isl/schedule.h>
+ __isl_give isl_schedule *isl_schedule_gist_domain_params(
+ __isl_take isl_schedule *schedule,
+ __isl_take isl_set *context);
+
The following function resets the user pointers on all parameter
and tuple identifiers referenced by the nodes of the given schedule.
@@ -7588,6 +7747,10 @@ A representation of the schedule can be printed using
__isl_give isl_printer *isl_printer_print_schedule(
__isl_take isl_printer *p,
__isl_keep isl_schedule *schedule);
+ __isl_give char *isl_schedule_to_str(
+ __isl_keep isl_schedule *schedule);
+
+C<isl_schedule_to_str> prints the schedule in flow format.
The schedule tree can be traversed through the use of
C<isl_schedule_node> objects that point to a particular
@@ -8094,7 +8257,21 @@ introduced expansion node. Grouping instances of different statements
ensures that they will be treated as a single statement by the
AST generator up to the point of the expansion node.
-The partial schedule of a band node can be scaled (down) using
+The following function can be used to flatten a nested
+sequence.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *
+ isl_schedule_node_sequence_splice_child(
+ __isl_take isl_schedule_node *node, int pos);
+
+That is, given a sequence node C<node> that has another sequence node
+in its child at position C<pos> (in particular, the child of that filter
+node is a sequence node), attach the children of that other sequence
+node as children of C<node>, replacing the original child at position
+C<pos>.
+
+The partial schedule of a band node can be scaled (down) or reduced using
the following functions.
#include <isl/schedule_node.h>
@@ -8106,11 +8283,26 @@ the following functions.
isl_schedule_node_band_scale_down(
__isl_take isl_schedule_node *node,
__isl_take isl_multi_val *mv);
+ __isl_give isl_schedule_node *
+ isl_schedule_node_band_mod(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_val *mv);
The spaces of the two arguments need to match.
After scaling, the partial schedule is replaced by its greatest
integer part to ensure that the schedule remains integral.
+The partial schedule of a band node can be shifted by an
+C<isl_multi_union_pw_aff> with a domain that is a superset
+of the domain of the partial schedule using
+the following function.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *
+ isl_schedule_node_band_shift(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_union_pw_aff *shift);
+
A band node can be tiled using the following function.
#include <isl/schedule_node.h>
@@ -8161,14 +8353,20 @@ position as the node pointed to by C<node> in the original tree.
#include <isl/schedule_node.h>
__isl_give isl_schedule_node *
+ isl_schedule_node_order_before(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_union_set *filter);
+ __isl_give isl_schedule_node *
isl_schedule_node_order_after(
__isl_take isl_schedule_node *node,
__isl_take isl_union_set *filter);
-This function splits the domain elements that reach C<node>
+These functions split the domain elements that reach C<node>
into those that satisfy C<filter> and those that do not and
arranges for the elements that do satisfy the filter to be
-executed after those that do not. The order is imposed by
+executed before (in case of C<isl_schedule_node_order_before>)
+or after (in case of C<isl_schedule_node_order_after>)
+those that do not. The order is imposed by
a sequence node, possibly reusing the grandparent of C<node>
on two copies of the subtree attached to the original C<node>.
Both copies are simplified with respect to their filter.
@@ -8221,6 +8419,10 @@ A representation of the schedule node can be printed using
__isl_give isl_printer *isl_printer_print_schedule_node(
__isl_take isl_printer *p,
__isl_keep isl_schedule_node *node);
+ __isl_give char *isl_schedule_node_to_str(
+ __isl_keep isl_schedule_node *node);
+
+C<isl_schedule_node_to_str> prints the schedule node in block format.
=head2 Dependence Analysis
@@ -8233,7 +8435,8 @@ of which of the source access relations was the last
to access the same data element before the given iteration
of the sink access.
The resulting dependence relations map source iterations
-to the corresponding sink iterations.
+to either the corresponding sink iterations or
+pairs of corresponding sink iterations and accessed data elements.
To compute standard flow dependences, the sink should be
a read, while the sources should be writes.
If any of the source accesses are marked as being I<may>
@@ -8306,6 +8509,19 @@ the access relations. In particular, the domains of the access
relations are effectively intersected with the domain of the schedule
and only the resulting accesses are considered by the dependence analysis.
+A representation of the information contained in an object
+of type C<isl_union_access_info> can be obtained using
+
+ #include <isl/flow.h>
+ __isl_give isl_printer *
+ isl_printer_print_union_access_info(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_access_info *access);
+ __isl_give char *isl_union_access_info_to_str(
+ __isl_keep isl_union_access_info *access);
+
+C<isl_union_access_info_to_str> prints the information in flow format.
+
The output of C<isl_union_access_info_compute_flow> can be examined
and freed using the following functions.
@@ -8314,6 +8530,12 @@ and freed using the following functions.
__isl_keep isl_union_flow *flow);
__isl_give isl_union_map *isl_union_flow_get_may_dependence(
__isl_keep isl_union_flow *flow);
+ __isl_give isl_union_map *
+ isl_union_flow_get_full_must_dependence(
+ __isl_keep isl_union_flow *flow);
+ __isl_give isl_union_map *
+ isl_union_flow_get_full_may_dependence(
+ __isl_keep isl_union_flow *flow);
__isl_give isl_union_map *isl_union_flow_get_must_no_source(
__isl_keep isl_union_flow *flow);
__isl_give isl_union_map *isl_union_flow_get_may_no_source(
@@ -8326,6 +8548,13 @@ relates domain elements of must sources to domain elements of the sink.
The relation returned by C<isl_union_flow_get_may_dependence>
relates domain elements of must or may sources to domain elements of the sink
and includes the previous relation as a subset.
+The relation returned by C<isl_union_flow_get_full_must_dependence>
+relates domain elements of must sources to pairs of domain elements of the sink
+and accessed data elements.
+The relation returned by C<isl_union_flow_get_full_may_dependence>
+relates domain elements of must or may sources to pairs of
+domain elements of the sink and accessed data elements.
+This relation includes the previous relation as a subset.
The relation returned by C<isl_union_flow_get_must_no_source> is the subset
of the sink relation for which no dependences have been found.
The relation returned by C<isl_union_flow_get_may_no_source> is the subset
@@ -8334,6 +8563,18 @@ That is, it contains those sink access that do not contribute to any
of the elements in the relation returned
by C<isl_union_flow_get_must_dependence>.
+A representation of the information contained in an object
+of type C<isl_union_flow> can be obtained using
+
+ #include <isl/flow.h>
+ __isl_give isl_printer *isl_printer_print_union_flow(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_flow *flow);
+ __isl_give char *isl_union_flow_to_str(
+ __isl_keep isl_union_flow *flow);
+
+C<isl_union_flow_to_str> prints the information in flow format.
+
=head3 Low-level Interface
A lower-level interface is provided by the following functions.
@@ -8625,6 +8866,9 @@ An C<isl_schedule_constraints> object can be inspected
using the following functions.
#include <isl/schedule.h>
+ __isl_give isl_union_set *
+ isl_schedule_constraints_get_domain(
+ __isl_keep isl_schedule_constraints *sc);
__isl_give isl_union_map *
isl_schedule_constraints_get_validity(
__isl_keep isl_schedule_constraints *sc);
diff --git a/include/isl/aff.h b/include/isl/aff.h
index 5d023393..8c54c9cd 100644
--- a/include/isl/aff.h
+++ b/include/isl/aff.h
@@ -89,6 +89,7 @@ __isl_give isl_aff *isl_aff_mul(__isl_take isl_aff *aff1,
__isl_take isl_aff *aff2);
__isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1,
__isl_take isl_aff *aff2);
+__isl_export
__isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
__isl_take isl_aff *aff2);
__isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
@@ -121,6 +122,7 @@ __isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
__isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1,
__isl_take isl_aff *aff2);
+__isl_overload
__isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
__isl_take isl_multi_aff *ma);
@@ -132,6 +134,7 @@ __isl_give isl_basic_set *isl_aff_le_basic_set(__isl_take isl_aff *aff1,
__isl_give isl_basic_set *isl_aff_ge_basic_set(__isl_take isl_aff *aff1,
__isl_take isl_aff *aff2);
+__isl_constructor
__isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str);
__isl_give isl_printer *isl_printer_print_aff(__isl_take isl_printer *p,
__isl_keep isl_aff *aff);
@@ -141,6 +144,7 @@ isl_ctx *isl_pw_aff_get_ctx(__isl_keep isl_pw_aff *pwaff);
__isl_give isl_space *isl_pw_aff_get_domain_space(__isl_keep isl_pw_aff *pwaff);
__isl_give isl_space *isl_pw_aff_get_space(__isl_keep isl_pw_aff *pwaff);
+__isl_constructor
__isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff);
__isl_give isl_pw_aff *isl_pw_aff_empty(__isl_take isl_space *dim);
__isl_give isl_pw_aff *isl_pw_aff_alloc(__isl_take isl_set *set,
@@ -179,6 +183,7 @@ __isl_give isl_pw_aff *isl_pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
__isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
+__isl_export
__isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
@@ -216,6 +221,7 @@ __isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
__isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1,
__isl_take isl_pw_aff *pa2);
+__isl_export
__isl_give isl_pw_aff *isl_pw_aff_add(__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
__isl_give isl_pw_aff *isl_pw_aff_sub(__isl_take isl_pw_aff *pwaff1,
@@ -261,10 +267,13 @@ __isl_give isl_pw_aff *isl_pw_aff_gist(__isl_take isl_pw_aff *pwaff,
__isl_give isl_pw_aff *isl_pw_aff_gist_params(__isl_take isl_pw_aff *pwaff,
__isl_take isl_set *context);
+__isl_overload
__isl_give isl_pw_aff *isl_pw_aff_pullback_multi_aff(
__isl_take isl_pw_aff *pa, __isl_take isl_multi_aff *ma);
+__isl_overload
__isl_give isl_pw_aff *isl_pw_aff_pullback_pw_multi_aff(
__isl_take isl_pw_aff *pa, __isl_take isl_pw_multi_aff *pma);
+__isl_overload
__isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
__isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa);
@@ -301,6 +310,7 @@ __isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1,
__isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1,
__isl_take isl_pw_aff *pa2);
+__isl_constructor
__isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str);
__isl_give isl_printer *isl_printer_print_pw_aff(__isl_take isl_printer *p,
__isl_keep isl_pw_aff *pwaff);
@@ -327,6 +337,7 @@ ISL_DECLARE_MULTI_NEG(aff)
ISL_DECLARE_MULTI_DIMS(aff)
ISL_DECLARE_MULTI_WITH_DOMAIN(aff)
+__isl_constructor
__isl_give isl_multi_aff *isl_multi_aff_from_aff(__isl_take isl_aff *aff);
__isl_give isl_multi_aff *isl_multi_aff_identity(__isl_take isl_space *space);
__isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space);
@@ -340,12 +351,6 @@ __isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space(
__isl_give isl_multi_aff *isl_multi_aff_floor(__isl_take isl_multi_aff *ma);
-__isl_give isl_multi_aff *isl_multi_aff_add(__isl_take isl_multi_aff *maff1,
- __isl_take isl_multi_aff *maff2);
-
-__isl_give isl_multi_aff *isl_multi_aff_product(
- __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2);
-
__isl_give isl_multi_aff *isl_multi_aff_gist_params(
__isl_take isl_multi_aff *maff, __isl_take isl_set *context);
__isl_give isl_multi_aff *isl_multi_aff_gist(__isl_take isl_multi_aff *maff,
@@ -354,6 +359,7 @@ __isl_give isl_multi_aff *isl_multi_aff_gist(__isl_take isl_multi_aff *maff,
__isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
__isl_give isl_local_space **ls);
+__isl_overload
__isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
__isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2);
@@ -370,6 +376,7 @@ __isl_give char *isl_multi_aff_to_str(__isl_keep isl_multi_aff *aff);
__isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p,
__isl_keep isl_multi_aff *maff);
+__isl_constructor
__isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
const char *str);
void isl_multi_aff_dump(__isl_keep isl_multi_aff *maff);
@@ -387,8 +394,10 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map(
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out_map(
__isl_take isl_space *space, enum isl_dim_type type,
unsigned first, unsigned n);
+__isl_constructor
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_aff(
__isl_take isl_multi_aff *ma);
+__isl_constructor
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff(
__isl_take isl_pw_aff *pa);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_alloc(__isl_take isl_set *set,
@@ -459,12 +468,14 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_fix_si(
__isl_take isl_pw_multi_aff *pma, enum isl_dim_type type,
unsigned pos, int value);
+__isl_export
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add(
__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_neg(
__isl_take isl_pw_multi_aff *pma);
+__isl_export
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_add(
__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
@@ -487,10 +498,13 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax(
__isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
__isl_take isl_multi_aff *ma);
+__isl_export
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_product(
__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+__isl_export
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product(
__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+__isl_export
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_product(
__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
@@ -514,8 +528,10 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist_params(
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist(
__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+__isl_overload
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_pullback_multi_aff(
__isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_aff *ma);
+__isl_overload
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_pullback_pw_multi_aff(
__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
@@ -532,6 +548,7 @@ __isl_give isl_printer *isl_printer_print_pw_multi_aff(__isl_take isl_printer *p
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_set(__isl_take isl_set *set);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map);
+__isl_constructor
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
const char *str);
void isl_pw_multi_aff_dump(__isl_keep isl_pw_multi_aff *pma);
@@ -541,6 +558,7 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_empty(
__isl_take isl_space *space);
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_aff(
__isl_take isl_aff *aff);
+__isl_constructor
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_pw_multi_aff(
__isl_take isl_pw_multi_aff *pma);
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain(
@@ -591,6 +609,7 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_gist(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_union_set *context);
+__isl_overload
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_pullback_union_pw_multi_aff(
__isl_take isl_union_pw_multi_aff *upma1,
@@ -619,9 +638,11 @@ __isl_give isl_union_set *isl_union_pw_multi_aff_domain(
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_neg(
__isl_take isl_union_pw_multi_aff *upma);
+__isl_export
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_add(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2);
+__isl_export
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_union_add(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2);
@@ -636,6 +657,7 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_down_val(
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
__isl_take isl_union_pw_multi_aff *upma, __isl_take isl_multi_val *mv);
+__isl_export
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_flat_range_product(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2);
@@ -649,6 +671,7 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_subtract_domain(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_union_set *uset);
+__isl_overload
__isl_give isl_union_map *isl_union_map_from_union_pw_multi_aff(
__isl_take isl_union_pw_multi_aff *upma);
@@ -660,6 +683,7 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set(
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map(
__isl_take isl_union_map *umap);
+__isl_constructor
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_read_from_str(
isl_ctx *ctx, const char *str);
void isl_union_pw_multi_aff_dump(__isl_keep isl_union_pw_multi_aff *upma);
@@ -668,8 +692,10 @@ __isl_give char *isl_union_pw_multi_aff_to_str(
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_identity(
__isl_take isl_space *space);
+__isl_constructor
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
__isl_take isl_multi_aff *ma);
+__isl_constructor
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_aff(
__isl_take isl_pw_aff *pa);
__isl_give isl_set *isl_multi_pw_aff_domain(__isl_take isl_multi_pw_aff *mpa);
@@ -688,10 +714,13 @@ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_gist_params(
isl_bool isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1,
__isl_keep isl_multi_pw_aff *mpa2);
+__isl_overload
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff(
__isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma);
+__isl_overload
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_pw_multi_aff(
__isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma);
+__isl_overload
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_pw_aff(
__isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2);
@@ -704,6 +733,7 @@ __isl_give isl_set *isl_set_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa);
__isl_give isl_map *isl_map_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff(
__isl_take isl_multi_pw_aff *mpa);
+__isl_constructor
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
__isl_take isl_pw_multi_aff *pma);
@@ -714,6 +744,7 @@ __isl_give isl_map *isl_multi_pw_aff_lex_lt_map(
__isl_give isl_map *isl_multi_pw_aff_lex_gt_map(
__isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2);
+__isl_constructor
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str(isl_ctx *ctx,
const char *str);
__isl_give isl_printer *isl_printer_print_multi_pw_aff(
@@ -746,6 +777,7 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_user(
__isl_give isl_union_pw_aff *isl_union_pw_aff_empty(
__isl_take isl_space *space);
+__isl_constructor
__isl_give isl_union_pw_aff *isl_union_pw_aff_from_pw_aff(
__isl_take isl_pw_aff *pa);
__isl_give isl_union_pw_aff *isl_union_pw_aff_val_on_domain(
@@ -755,6 +787,7 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_aff_on_domain(
__isl_give isl_union_pw_aff *isl_union_pw_aff_add_pw_aff(
__isl_take isl_union_pw_aff *upa, __isl_take isl_pw_aff *pa);
+__isl_constructor
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_pw_aff(
__isl_take isl_union_pw_aff *upa);
@@ -774,8 +807,10 @@ __isl_give isl_union_set *isl_union_pw_aff_domain(
__isl_give isl_union_pw_aff *isl_union_pw_aff_neg(
__isl_take isl_union_pw_aff *upa);
+__isl_export
__isl_give isl_union_pw_aff *isl_union_pw_aff_add(
__isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2);
+__isl_export
__isl_give isl_union_pw_aff *isl_union_pw_aff_union_add(
__isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2);
__isl_give isl_union_pw_aff *isl_union_pw_aff_sub(
@@ -788,6 +823,7 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_gist(
__isl_give isl_union_pw_aff *isl_union_pw_aff_gist_params(
__isl_take isl_union_pw_aff *upa, __isl_take isl_set *context);
+__isl_overload
__isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
__isl_take isl_union_pw_aff *upa,
__isl_take isl_union_pw_multi_aff *upma);
@@ -822,6 +858,9 @@ __isl_give isl_union_set *isl_union_pw_aff_zero_union_set(
__isl_give isl_union_map *isl_union_map_from_union_pw_aff(
__isl_take isl_union_pw_aff *upa);
+__isl_constructor
+__isl_give isl_union_pw_aff *isl_union_pw_aff_read_from_str(isl_ctx *ctx,
+ const char *str);
__isl_give char *isl_union_pw_aff_to_str(__isl_keep isl_union_pw_aff *upa);
__isl_give isl_printer *isl_printer_print_union_pw_aff(
__isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa);
@@ -831,8 +870,10 @@ ISL_DECLARE_MULTI_NEG(union_pw_aff)
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_aff(
__isl_take isl_multi_aff *ma);
+__isl_constructor
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_union_pw_aff(
__isl_take isl_union_pw_aff *upa);
+__isl_constructor
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_pw_aff(
__isl_take isl_multi_pw_aff *mpa);
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_val_on_domain(
@@ -854,6 +895,8 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range(
__isl_give isl_union_set *isl_multi_union_pw_aff_domain(
__isl_take isl_multi_union_pw_aff *mupa);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_coalesce(
+ __isl_take isl_multi_union_pw_aff *aff);
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_gist(
__isl_take isl_multi_union_pw_aff *aff,
__isl_take isl_union_set *context);
@@ -870,6 +913,7 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
__isl_take isl_multi_union_pw_aff *mupa,
__isl_take isl_pw_multi_aff *pma);
+__isl_overload
__isl_give isl_multi_union_pw_aff *
isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
__isl_take isl_multi_union_pw_aff *mupa,
@@ -879,6 +923,7 @@ __isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_from_multi_union_pw_aff(
__isl_take isl_multi_union_pw_aff *mupa);
+__isl_export
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_union_add(
__isl_take isl_multi_union_pw_aff *mupa1,
__isl_take isl_multi_union_pw_aff *mupa2);
@@ -889,6 +934,7 @@ isl_multi_union_pw_aff_from_union_pw_multi_aff(
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_union_map(
__isl_take isl_union_map *umap);
+__isl_overload
__isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff(
__isl_take isl_multi_union_pw_aff *mupa);
@@ -898,6 +944,7 @@ __isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
__isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
__isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space);
+__isl_constructor
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_read_from_str(
isl_ctx *ctx, const char *str);
__isl_give char *isl_multi_union_pw_aff_to_str(
diff --git a/include/isl/aff_type.h b/include/isl/aff_type.h
index 12daf943..9a618d68 100644
--- a/include/isl/aff_type.h
+++ b/include/isl/aff_type.h
@@ -7,36 +7,40 @@
extern "C" {
#endif
-struct isl_aff;
+struct __isl_subclass(isl_multi_aff) __isl_subclass(isl_pw_aff) isl_aff;
typedef struct isl_aff isl_aff;
ISL_DECLARE_LIST(aff)
-struct isl_pw_aff;
+struct __isl_subclass(isl_pw_multi_aff) __isl_subclass(isl_multi_pw_aff)
+ __isl_subclass(isl_union_pw_aff) isl_pw_aff;
typedef struct isl_pw_aff isl_pw_aff;
ISL_DECLARE_LIST(pw_aff)
-struct isl_union_pw_aff;
+struct __isl_subclass(isl_multi_union_pw_aff)
+ __isl_subclass(isl_union_pw_multi_aff) isl_union_pw_aff;
typedef struct isl_union_pw_aff isl_union_pw_aff;
ISL_DECLARE_LIST_TYPE(union_pw_aff)
-struct isl_multi_aff;
+struct __isl_subclass(isl_pw_multi_aff) __isl_subclass(isl_multi_pw_aff)
+ isl_multi_aff;
typedef struct isl_multi_aff isl_multi_aff;
-struct isl_pw_multi_aff;
+struct __isl_subclass(isl_union_pw_multi_aff) __isl_subclass(isl_multi_pw_aff)
+ isl_pw_multi_aff;
typedef struct isl_pw_multi_aff isl_pw_multi_aff;
-struct isl_union_pw_multi_aff;
+struct __isl_export isl_union_pw_multi_aff;
typedef struct isl_union_pw_multi_aff isl_union_pw_multi_aff;
ISL_DECLARE_LIST_TYPE(union_pw_multi_aff)
-struct isl_multi_pw_aff;
+struct __isl_subclass(isl_multi_union_pw_aff) isl_multi_pw_aff;
typedef struct isl_multi_pw_aff isl_multi_pw_aff;
-struct isl_multi_union_pw_aff;
+struct __isl_export isl_multi_union_pw_aff;
typedef struct isl_multi_union_pw_aff isl_multi_union_pw_aff;
#if defined(__cplusplus)
diff --git a/include/isl/ctx.h b/include/isl/ctx.h
index 6cd26a1b..bd1f00fd 100644
--- a/include/isl/ctx.h
+++ b/include/isl/ctx.h
@@ -30,6 +30,9 @@
#ifndef __isl_export
#define __isl_export
#endif
+#ifndef __isl_overload
+#define __isl_overload
+#endif
#ifndef __isl_constructor
#define __isl_constructor
#endif
@@ -80,7 +83,7 @@ enum isl_error {
};
typedef enum {
isl_stat_error = -1,
- isl_stat_ok = 0,
+ isl_stat_ok = 0
} isl_stat;
typedef enum {
isl_bool_error = -1,
diff --git a/include/isl/flow.h b/include/isl/flow.h
index 0b985667..388d7919 100644
--- a/include/isl/flow.h
+++ b/include/isl/flow.h
@@ -6,6 +6,7 @@
#include <isl/union_set_type.h>
#include <isl/union_map_type.h>
#include <isl/schedule.h>
+#include <isl/printer.h>
#if defined(__cplusplus)
extern "C" {
@@ -64,22 +65,27 @@ void isl_flow_free(__isl_take isl_flow *deps);
isl_ctx *isl_flow_get_ctx(__isl_keep isl_flow *deps);
-struct isl_union_access_info;
+struct __isl_export isl_union_access_info;
typedef struct isl_union_access_info isl_union_access_info;
-struct isl_union_flow;
+struct __isl_export isl_union_flow;
typedef struct isl_union_flow isl_union_flow;
+__isl_constructor
__isl_give isl_union_access_info *isl_union_access_info_from_sink(
__isl_take isl_union_map *sink);
+__isl_export
__isl_give isl_union_access_info *isl_union_access_info_set_must_source(
__isl_take isl_union_access_info *access,
__isl_take isl_union_map *must_source);
+__isl_export
__isl_give isl_union_access_info *isl_union_access_info_set_may_source(
__isl_take isl_union_access_info *access,
__isl_take isl_union_map *may_source);
+__isl_export
__isl_give isl_union_access_info *isl_union_access_info_set_schedule(
__isl_take isl_union_access_info *access,
__isl_take isl_schedule *schedule);
+__isl_export
__isl_give isl_union_access_info *isl_union_access_info_set_schedule_map(
__isl_take isl_union_access_info *access,
__isl_take isl_union_map *schedule_map);
@@ -91,20 +97,40 @@ __isl_null isl_union_access_info *isl_union_access_info_free(
isl_ctx *isl_union_access_info_get_ctx(
__isl_keep isl_union_access_info *access);
+__isl_give isl_printer *isl_printer_print_union_access_info(
+ __isl_take isl_printer *p, __isl_keep isl_union_access_info *access);
+__isl_give char *isl_union_access_info_to_str(
+ __isl_keep isl_union_access_info *access);
+
+__isl_export
__isl_give isl_union_flow *isl_union_access_info_compute_flow(
__isl_take isl_union_access_info *access);
isl_ctx *isl_union_flow_get_ctx(__isl_keep isl_union_flow *flow);
+__isl_export
__isl_give isl_union_map *isl_union_flow_get_must_dependence(
__isl_keep isl_union_flow *flow);
+__isl_export
__isl_give isl_union_map *isl_union_flow_get_may_dependence(
__isl_keep isl_union_flow *flow);
+__isl_export
+__isl_give isl_union_map *isl_union_flow_get_full_must_dependence(
+ __isl_keep isl_union_flow *flow);
+__isl_export
+__isl_give isl_union_map *isl_union_flow_get_full_may_dependence(
+ __isl_keep isl_union_flow *flow);
+__isl_export
__isl_give isl_union_map *isl_union_flow_get_must_no_source(
__isl_keep isl_union_flow *flow);
+__isl_export
__isl_give isl_union_map *isl_union_flow_get_may_no_source(
__isl_keep isl_union_flow *flow);
__isl_null isl_union_flow *isl_union_flow_free(__isl_take isl_union_flow *flow);
+__isl_give isl_printer *isl_printer_print_union_flow(
+ __isl_take isl_printer *p, __isl_keep isl_union_flow *flow);
+__isl_give char *isl_union_flow_to_str(__isl_keep isl_union_flow *flow);
+
int isl_union_map_compute_flow(__isl_take isl_union_map *sink,
__isl_take isl_union_map *must_source,
__isl_take isl_union_map *may_source,
diff --git a/include/isl/map.h b/include/isl/map.h
index 0e7219c2..619a9ce1 100644
--- a/include/isl/map.h
+++ b/include/isl/map.h
@@ -222,8 +222,9 @@ struct isl_basic_map *isl_basic_map_sum(
struct isl_basic_map *bmap1, struct isl_basic_map *bmap2);
struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap);
-struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2);
-struct isl_map *isl_map_neg(struct isl_map *map);
+__isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_map *isl_map_neg(__isl_take isl_map *map);
__isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
__isl_take isl_val *d);
@@ -551,6 +552,9 @@ isl_bool isl_map_can_curry(__isl_keep isl_map *map);
__isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap);
__isl_give isl_map *isl_map_curry(__isl_take isl_map *map);
+isl_bool isl_map_can_range_curry(__isl_keep isl_map *map);
+__isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map);
+
isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap);
isl_bool isl_map_can_uncurry(__isl_keep isl_map *map);
__isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap);
@@ -564,6 +568,9 @@ __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map);
__isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
__isl_take isl_basic_map *bmap,
enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n);
__isl_give isl_map *isl_map_drop_constraints_involving_dims(
__isl_take isl_map *map,
enum isl_dim_type type, unsigned first, unsigned n);
diff --git a/include/isl/multi.h b/include/isl/multi.h
index 9842d6ca..612bafce 100644
--- a/include/isl/multi.h
+++ b/include/isl/multi.h
@@ -73,12 +73,16 @@ __isl_give isl_multi_##BASE *isl_multi_##BASE##_range_splice( \
__isl_take isl_multi_##BASE *multi2); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_flatten_range( \
__isl_take isl_multi_##BASE *multi); \
+__isl_export \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_flat_range_product( \
__isl_take isl_multi_##BASE *multi1, \
__isl_take isl_multi_##BASE *multi2); \
+__isl_export \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_range_product( \
__isl_take isl_multi_##BASE *multi1, \
__isl_take isl_multi_##BASE *multi2); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_factor_range( \
+ __isl_take isl_multi_##BASE *multi); \
isl_bool isl_multi_##BASE##_range_is_wrapping( \
__isl_keep isl_multi_##BASE *multi); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_range_factor_domain( \
@@ -98,6 +102,10 @@ __isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_down_multi_val( \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_mod_multi_val( \
__isl_take isl_multi_##BASE *multi, \
__isl_take isl_multi_val *mv); \
+__isl_export \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_add( \
+ __isl_take isl_multi_##BASE *multi1, \
+ __isl_take isl_multi_##BASE *multi2); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_sub( \
__isl_take isl_multi_##BASE *multi1, \
__isl_take isl_multi_##BASE *multi2); \
@@ -123,6 +131,7 @@ __isl_give isl_multi_##BASE *isl_multi_##BASE##_add_dims( \
unsigned n);
#define ISL_DECLARE_MULTI_WITH_DOMAIN(BASE) \
+__isl_export \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_product( \
__isl_take isl_multi_##BASE *multi1, \
__isl_take isl_multi_##BASE *multi2); \
diff --git a/include/isl/point.h b/include/isl/point.h
index ae295d3b..53970d3a 100644
--- a/include/isl/point.h
+++ b/include/isl/point.h
@@ -9,7 +9,7 @@
extern "C" {
#endif
-struct isl_point;
+struct __isl_subclass(isl_basic_set) isl_point;
typedef struct isl_point isl_point;
isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt);
diff --git a/include/isl/polynomial.h b/include/isl/polynomial.h
index 23fb2395..5a242950 100644
--- a/include/isl/polynomial.h
+++ b/include/isl/polynomial.h
@@ -284,6 +284,8 @@ isl_bool isl_qpolynomial_fold_is_nan(__isl_keep isl_qpolynomial_fold *fold);
int isl_qpolynomial_fold_plain_is_equal(__isl_keep isl_qpolynomial_fold *fold1,
__isl_keep isl_qpolynomial_fold *fold2);
+__isl_give isl_space *isl_qpolynomial_fold_get_domain_space(
+ __isl_keep isl_qpolynomial_fold *fold);
__isl_give isl_space *isl_qpolynomial_fold_get_space(
__isl_keep isl_qpolynomial_fold *fold);
diff --git a/include/isl/schedule.h b/include/isl/schedule.h
index 7a037895..793f253c 100644
--- a/include/isl/schedule.h
+++ b/include/isl/schedule.h
@@ -63,6 +63,8 @@ __isl_null isl_schedule_constraints *isl_schedule_constraints_free(
isl_ctx *isl_schedule_constraints_get_ctx(
__isl_keep isl_schedule_constraints *sc);
+__isl_give isl_union_set *isl_schedule_constraints_get_domain(
+ __isl_keep isl_schedule_constraints *sc);
__isl_give isl_union_map *isl_schedule_constraints_get_validity(
__isl_keep isl_schedule_constraints *sc);
__isl_give isl_union_map *isl_schedule_constraints_get_coincidence(
@@ -88,12 +90,14 @@ __isl_give isl_schedule *isl_schedule_from_domain(
__isl_take isl_union_set *domain);
__isl_give isl_schedule *isl_schedule_copy(__isl_keep isl_schedule *sched);
__isl_null isl_schedule *isl_schedule_free(__isl_take isl_schedule *sched);
+__isl_export
__isl_give isl_union_map *isl_schedule_get_map(__isl_keep isl_schedule *sched);
isl_ctx *isl_schedule_get_ctx(__isl_keep isl_schedule *sched);
isl_bool isl_schedule_plain_is_equal(__isl_keep isl_schedule *schedule1,
__isl_keep isl_schedule *schedule2);
+__isl_export
__isl_give isl_schedule_node *isl_schedule_get_root(
__isl_keep isl_schedule *schedule);
__isl_give isl_union_set *isl_schedule_get_domain(
@@ -121,11 +125,14 @@ __isl_give isl_schedule *isl_schedule_set(
__isl_take isl_schedule *schedule1, __isl_take isl_schedule *schedule2);
__isl_give isl_schedule *isl_schedule_intersect_domain(
__isl_take isl_schedule *schedule, __isl_take isl_union_set *domain);
+__isl_give isl_schedule *isl_schedule_gist_domain_params(
+ __isl_take isl_schedule *schedule, __isl_take isl_set *context);
__isl_give isl_schedule *isl_schedule_reset_user(
__isl_take isl_schedule *schedule);
__isl_give isl_schedule *isl_schedule_align_params(
__isl_take isl_schedule *schedule, __isl_take isl_space *space);
+__isl_overload
__isl_give isl_schedule *isl_schedule_pullback_union_pw_multi_aff(
__isl_take isl_schedule *schedule,
__isl_take isl_union_pw_multi_aff *upma);
@@ -134,11 +141,13 @@ __isl_give isl_band_list *isl_schedule_get_band_forest(
__isl_keep isl_schedule *schedule);
__isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input);
+__isl_constructor
__isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
const char *str);
__isl_give isl_printer *isl_printer_print_schedule(__isl_take isl_printer *p,
__isl_keep isl_schedule *schedule);
void isl_schedule_dump(__isl_keep isl_schedule *schedule);
+__isl_give char *isl_schedule_to_str(__isl_keep isl_schedule *schedule);
int isl_schedule_foreach_band(__isl_keep isl_schedule *sched,
int (*fn)(__isl_keep isl_band *band, void *user), void *user);
diff --git a/include/isl/schedule_node.h b/include/isl/schedule_node.h
index 9cb05e17..0ddc81f3 100644
--- a/include/isl/schedule_node.h
+++ b/include/isl/schedule_node.h
@@ -29,6 +29,7 @@ enum isl_schedule_node_type isl_schedule_node_get_type(
__isl_keep isl_schedule_node *node);
enum isl_schedule_node_type isl_schedule_node_get_parent_type(
__isl_keep isl_schedule_node *node);
+__isl_export
__isl_give isl_schedule *isl_schedule_node_get_schedule(
__isl_keep isl_schedule_node *node);
@@ -64,10 +65,12 @@ __isl_give isl_schedule_node *isl_schedule_node_get_shared_ancestor(
__isl_give isl_schedule_node *isl_schedule_node_root(
__isl_take isl_schedule_node *node);
+__isl_export
__isl_give isl_schedule_node *isl_schedule_node_parent(
__isl_take isl_schedule_node *node);
__isl_give isl_schedule_node *isl_schedule_node_ancestor(
__isl_take isl_schedule_node *node, int generation);
+__isl_export
__isl_give isl_schedule_node *isl_schedule_node_child(
__isl_take isl_schedule_node *node, int pos);
__isl_give isl_schedule_node *isl_schedule_node_first_child(
@@ -83,6 +86,9 @@ isl_bool isl_schedule_node_is_subtree_anchored(
__isl_give isl_schedule_node *isl_schedule_node_group(
__isl_take isl_schedule_node *node, __isl_take isl_id *group_id);
+__isl_give isl_schedule_node *isl_schedule_node_sequence_splice_child(
+ __isl_take isl_schedule_node *node, int pos);
+
__isl_give isl_space *isl_schedule_node_band_get_space(
__isl_keep isl_schedule_node *node);
__isl_give isl_multi_union_pw_aff *isl_schedule_node_band_get_partial_schedule(
@@ -105,8 +111,10 @@ __isl_give isl_union_set *isl_schedule_node_band_get_ast_build_options(
__isl_give isl_schedule_node *isl_schedule_node_band_set_ast_build_options(
__isl_take isl_schedule_node *node, __isl_take isl_union_set *options);
unsigned isl_schedule_node_band_n_member(__isl_keep isl_schedule_node *node);
+__isl_export
isl_bool isl_schedule_node_band_member_get_coincident(
__isl_keep isl_schedule_node *node, int pos);
+__isl_export
__isl_give isl_schedule_node *isl_schedule_node_band_member_set_coincident(
__isl_take isl_schedule_node *node, int pos, int coincident);
isl_bool isl_schedule_node_band_get_permutable(
@@ -123,6 +131,11 @@ __isl_give isl_schedule_node *isl_schedule_node_band_scale(
__isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv);
__isl_give isl_schedule_node *isl_schedule_node_band_scale_down(
__isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_node *isl_schedule_node_band_mod(
+ __isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_node *isl_schedule_node_band_shift(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_union_pw_aff *shift);
__isl_give isl_schedule_node *isl_schedule_node_band_tile(
__isl_take isl_schedule_node *node, __isl_take isl_multi_val *sizes);
__isl_give isl_schedule_node *isl_schedule_node_band_sink(
@@ -152,12 +165,15 @@ __isl_give isl_union_set *isl_schedule_node_get_domain(
__isl_keep isl_schedule_node *node);
__isl_give isl_union_set *isl_schedule_node_get_universe_domain(
__isl_keep isl_schedule_node *node);
+__isl_export
__isl_give isl_multi_union_pw_aff *
isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(
__isl_keep isl_schedule_node *node);
+__isl_export
__isl_give isl_union_pw_multi_aff *
isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(
__isl_keep isl_schedule_node *node);
+__isl_export
__isl_give isl_union_map *isl_schedule_node_get_prefix_schedule_union_map(
__isl_keep isl_schedule_node *node);
__isl_give isl_union_map *isl_schedule_node_get_prefix_schedule_relation(
@@ -192,6 +208,8 @@ __isl_give isl_schedule_node *isl_schedule_node_cut(
__isl_give isl_schedule_node *isl_schedule_node_delete(
__isl_take isl_schedule_node *node);
+__isl_give isl_schedule_node *isl_schedule_node_order_before(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *filter);
__isl_give isl_schedule_node *isl_schedule_node_order_after(
__isl_take isl_schedule_node *node, __isl_take isl_union_set *filter);
@@ -210,6 +228,7 @@ __isl_give isl_schedule_node *isl_schedule_node_align_params(
__isl_give isl_printer *isl_printer_print_schedule_node(
__isl_take isl_printer *p, __isl_keep isl_schedule_node *node);
void isl_schedule_node_dump(__isl_keep isl_schedule_node *node);
+__isl_give char *isl_schedule_node_to_str(__isl_keep isl_schedule_node *node);
#if defined(__cplusplus)
}
diff --git a/include/isl/schedule_type.h b/include/isl/schedule_type.h
index b1e63d61..f5a6d4ca 100644
--- a/include/isl/schedule_type.h
+++ b/include/isl/schedule_type.h
@@ -20,10 +20,10 @@ enum isl_schedule_node_type {
isl_schedule_node_set
};
-struct isl_schedule_node;
+struct __isl_export isl_schedule_node;
typedef struct isl_schedule_node isl_schedule_node;
-struct isl_schedule;
+struct __isl_export isl_schedule;
typedef struct isl_schedule isl_schedule;
#if defined(__cplusplus)
diff --git a/include/isl/set.h b/include/isl/set.h
index 72414b8c..e855de13 100644
--- a/include/isl/set.h
+++ b/include/isl/set.h
@@ -433,12 +433,16 @@ int isl_set_n_basic_set(__isl_keep isl_set *set);
__isl_export
isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user);
+__isl_give isl_basic_set_list *isl_set_get_basic_set_list(
+ __isl_keep isl_set *set);
isl_stat isl_set_foreach_point(__isl_keep isl_set *set,
isl_stat (*fn)(__isl_take isl_point *pnt, void *user), void *user);
__isl_give isl_val *isl_set_count_val(__isl_keep isl_set *set);
+__isl_constructor
__isl_give isl_basic_set *isl_basic_set_from_point(__isl_take isl_point *pnt);
+__isl_constructor
__isl_give isl_set *isl_set_from_point(__isl_take isl_point *pnt);
__isl_give isl_basic_set *isl_basic_set_box_from_points(
__isl_take isl_point *pnt1, __isl_take isl_point *pnt2);
diff --git a/include/isl/space.h b/include/isl/space.h
index fdcbff1d..c03a99e7 100644
--- a/include/isl/space.h
+++ b/include/isl/space.h
@@ -141,6 +141,9 @@ __isl_give isl_space *isl_space_zip(__isl_take isl_space *dim);
isl_bool isl_space_can_curry(__isl_keep isl_space *space);
__isl_give isl_space *isl_space_curry(__isl_take isl_space *space);
+isl_bool isl_space_can_range_curry(__isl_keep isl_space *space);
+__isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space);
+
isl_bool isl_space_can_uncurry(__isl_keep isl_space *space);
__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space);
diff --git a/include/isl/union_map.h b/include/isl/union_map.h
index 2dac338a..b81caef8 100644
--- a/include/isl/union_map.h
+++ b/include/isl/union_map.h
@@ -40,12 +40,17 @@ int isl_union_map_find_dim_by_name(__isl_keep isl_union_map *umap,
__isl_give isl_union_map *isl_union_map_universe(
__isl_take isl_union_map *umap);
__isl_give isl_set *isl_union_map_params(__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_map *isl_union_map_domain_map(
__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_pw_multi_aff *isl_union_map_domain_map_union_pw_multi_aff(
__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_map *isl_union_map_range_map(
__isl_take isl_union_map *umap);
__isl_give isl_union_map *isl_union_set_wrapped_domain_map(
@@ -68,6 +73,7 @@ __isl_give isl_union_map *isl_union_map_simple_hull(
__isl_export
__isl_give isl_union_map *isl_union_map_coalesce(
__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_map *isl_union_map_compute_divs(
__isl_take isl_union_map *umap);
__isl_export
@@ -89,24 +95,35 @@ __isl_give isl_union_map *isl_union_map_intersect(
__isl_export
__isl_give isl_union_map *isl_union_map_intersect_params(
__isl_take isl_union_map *umap, __isl_take isl_set *set);
+__isl_export
__isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1,
__isl_take isl_union_map *umap2);
+__isl_export
__isl_give isl_union_map *isl_union_map_domain_product(
__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
__isl_give isl_union_map *isl_union_map_flat_domain_product(
__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_export
__isl_give isl_union_map *isl_union_map_range_product(
__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
__isl_give isl_union_map *isl_union_map_flat_range_product(
__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_export
__isl_give isl_union_map *isl_union_map_domain_factor_domain(
__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_map *isl_union_map_domain_factor_range(
__isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_range_factor_domain(
+ __isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_map *isl_union_map_range_factor_range(
__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_map *isl_union_map_factor_domain(
__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_map *isl_union_map_factor_range(
__isl_take isl_union_map *umap);
__isl_export
@@ -160,6 +177,7 @@ __isl_give isl_union_map *isl_union_map_preimage_range_union_pw_multi_aff(
__isl_take isl_union_pw_multi_aff *upma);
__isl_export
__isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_map *isl_union_map_from_domain_and_range(
__isl_take isl_union_set *domain, __isl_take isl_union_set *range);
@@ -211,6 +229,7 @@ __isl_give isl_map *isl_map_from_union_map(__isl_take isl_union_map *umap);
__isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap);
+__isl_overload
__isl_give isl_union_map *isl_union_map_fixed_power_val(
__isl_take isl_union_map *umap, __isl_take isl_val *exp);
__isl_give isl_union_map *isl_union_map_power(__isl_take isl_union_map *umap,
@@ -247,11 +266,16 @@ __isl_give isl_printer *isl_printer_print_union_map(__isl_take isl_printer *p,
__isl_keep isl_union_map *umap);
void isl_union_map_dump(__isl_keep isl_union_map *umap);
+__isl_export
__isl_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap);
+__isl_export
__isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset);
+__isl_export
__isl_give isl_union_map *isl_union_map_zip(__isl_take isl_union_map *umap);
__isl_give isl_union_map *isl_union_map_curry(__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_range_curry(
+ __isl_take isl_union_map *umap);
__isl_give isl_union_map *isl_union_map_uncurry(__isl_take isl_union_map *umap);
__isl_give isl_union_map *isl_union_map_align_params(
diff --git a/include/isl/union_set.h b/include/isl/union_set.h
index 3d818fe9..65b3a092 100644
--- a/include/isl/union_set.h
+++ b/include/isl/union_set.h
@@ -46,6 +46,7 @@ __isl_give isl_union_set *isl_union_set_simple_hull(
__isl_export
__isl_give isl_union_set *isl_union_set_coalesce(
__isl_take isl_union_set *uset);
+__isl_export
__isl_give isl_union_set *isl_union_set_compute_divs(
__isl_take isl_union_set *uset);
__isl_export
@@ -55,6 +56,7 @@ __isl_give isl_union_set *isl_union_set_lexmax(__isl_take isl_union_set *uset);
__isl_give isl_union_set *isl_union_set_add_set(__isl_take isl_union_set *uset,
__isl_take isl_set *set);
+__isl_export
__isl_give isl_union_set *isl_union_set_union(__isl_take isl_union_set *uset1,
__isl_take isl_union_set *uset2);
__isl_export
@@ -115,10 +117,17 @@ __isl_give int isl_union_set_contains(__isl_keep isl_union_set *uset,
__isl_give isl_set *isl_union_set_extract_set(__isl_keep isl_union_set *uset,
__isl_take isl_space *dim);
__isl_give isl_set *isl_set_from_union_set(__isl_take isl_union_set *uset);
+__isl_export
isl_stat isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
isl_stat (*fn)(__isl_take isl_point *pnt, void *user), void *user);
__isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_point *isl_union_set_sample_point(
+ __isl_take isl_union_set *uset);
+
+__isl_constructor
+__isl_give isl_union_set *isl_union_set_from_point(__isl_take isl_point *pnt);
__isl_give isl_union_set *isl_union_set_lift(__isl_take isl_union_set *uset);
diff --git a/include/isl/val.h b/include/isl/val.h
index b5a56691..5595989a 100644
--- a/include/isl/val.h
+++ b/include/isl/val.h
@@ -10,12 +10,12 @@
extern "C" {
#endif
-struct isl_val;
+struct __isl_export isl_val;
typedef struct isl_val isl_val;
ISL_DECLARE_LIST(val)
-struct isl_multi_val;
+struct __isl_export isl_multi_val;
typedef struct isl_multi_val isl_multi_val;
ISL_DECLARE_MULTI(val)
@@ -23,12 +23,19 @@ ISL_DECLARE_MULTI_NEG(val)
ISL_DECLARE_MULTI_DIMS(val)
ISL_DECLARE_MULTI_WITH_DOMAIN(val)
+__isl_export
__isl_give isl_val *isl_val_zero(isl_ctx *ctx);
+__isl_export
__isl_give isl_val *isl_val_one(isl_ctx *ctx);
+__isl_export
__isl_give isl_val *isl_val_negone(isl_ctx *ctx);
+__isl_export
__isl_give isl_val *isl_val_nan(isl_ctx *ctx);
+__isl_export
__isl_give isl_val *isl_val_infty(isl_ctx *ctx);
+__isl_export
__isl_give isl_val *isl_val_neginfty(isl_ctx *ctx);
+__isl_constructor
__isl_give isl_val *isl_val_int_from_si(isl_ctx *ctx, long i);
__isl_give isl_val *isl_val_int_from_ui(isl_ctx *ctx, unsigned long u);
__isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n,
@@ -40,6 +47,7 @@ __isl_null isl_val *isl_val_free(__isl_take isl_val *v);
isl_ctx *isl_val_get_ctx(__isl_keep isl_val *val);
long isl_val_get_num_si(__isl_keep isl_val *v);
long isl_val_get_den_si(__isl_keep isl_val *v);
+__isl_give isl_val *isl_val_get_den_val(__isl_keep isl_val *v);
double isl_val_get_d(__isl_keep isl_val *v);
size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size);
int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
@@ -95,6 +103,7 @@ isl_bool isl_val_abs_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
isl_bool isl_val_is_divisible_by(__isl_keep isl_val *v1,
__isl_keep isl_val *v2);
+__isl_constructor
__isl_give isl_val *isl_val_read_from_str(isl_ctx *ctx, const char *str);
__isl_give isl_printer *isl_printer_print_val(__isl_take isl_printer *p,
__isl_keep isl_val *v);
diff --git a/interface/Makefile.am b/interface/Makefile.am
index 0269e911..242294e2 100644
--- a/interface/Makefile.am
+++ b/interface/Makefile.am
@@ -20,6 +20,8 @@ extract_interface_LDADD = \
-lclangAnalysis -lclangAST -lclangLex -lclangBasic -lclangDriver \
$(CLANG_LIBS) $(CLANG_LDFLAGS)
+CLEANFILES = isl.py
+
test: extract_interface
./extract_interface$(EXEEXT) $(includes) $(srcdir)/all.h
diff --git a/interface/Makefile.in b/interface/Makefile.in
index c8b089d4..855c51c9 100644
--- a/interface/Makefile.in
+++ b/interface/Makefile.in
@@ -353,6 +353,7 @@ extract_interface_LDADD = \
-lclangAnalysis -lclangAST -lclangLex -lclangBasic -lclangDriver \
$(CLANG_LIBS) $(CLANG_LDFLAGS)
+CLEANFILES = isl.py
all: all-am
.SUFFIXES:
@@ -576,6 +577,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
diff --git a/interface/all.h b/interface/all.h
index 46634e2b..1c7d1064 100644
--- a/interface/all.h
+++ b/interface/all.h
@@ -1,4 +1,9 @@
+#include <isl/val.h>
+#include <isl/aff.h>
#include <isl/set.h>
#include <isl/map.h>
#include <isl/union_set.h>
#include <isl/union_map.h>
+#include <isl/flow.h>
+#include <isl/schedule.h>
+#include <isl/schedule_node.h>
diff --git a/interface/extract_interface.cc b/interface/extract_interface.cc
index 3663ef76..83b81319 100644
--- a/interface/extract_interface.cc
+++ b/interface/extract_interface.cc
@@ -174,12 +174,15 @@ static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
}
#endif
-/* Clang changed its API from 3.5 to 3.6, we fix this with a simple overloaded
- * function here.
+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
@@ -366,13 +369,17 @@ int main(int argc, char *argv[])
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_subclass(super)=__attribute__((annotate(\"isl_subclass(\" #super \")\"))) __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);
+ PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), LO);
const FileEntry *file = Clang->getFileManager().getFile(InputFilename);
assert(file);
diff --git a/interface/isl.py b/interface/isl.py
index e3bdf5f1..744f1364 100644
--- a/interface/isl.py
+++ b/interface/isl.py
@@ -28,6 +28,807 @@ class Context:
isl.isl_ctx_alloc.restype = c_void_p
isl.isl_ctx_free.argtypes = [Context]
+class union_pw_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 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
+ 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])
+ return
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_union_pw_multi_aff_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_union_pw_multi_aff_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_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_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_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_free.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_to_str.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_to_str.restype = POINTER(c_char)
+
+class 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 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])
+ return
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_multi_union_pw_aff_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_multi_union_pw_aff_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_free.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_to_str.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_to_str.restype = POINTER(c_char)
+
+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])
+ return
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_union_pw_aff_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_union_pw_aff_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_free.argtypes = [c_void_p]
+isl.isl_union_pw_aff_to_str.argtypes = [c_void_p]
+isl.isl_union_pw_aff_to_str.restype = POINTER(c_char)
+
+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 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])
+ 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
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_multi_pw_aff_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_multi_pw_aff_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_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_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_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_free.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_to_str.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_to_str.restype = POINTER(c_char)
+
+class pw_multi_aff(multi_pw_aff, union_pw_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 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])
+ return
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_pw_multi_aff_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_pw_multi_aff_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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 multi_pw_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 multi_pw_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 multi_pw_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 multi_pw_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 multi_pw_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_free.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_to_str.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_to_str.restype = POINTER(c_char)
+
+class pw_aff(union_pw_aff, multi_pw_aff, pw_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 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])
+ return
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_pw_aff_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_pw_aff_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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 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 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_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_union_add.restype = c_void_p
+isl.isl_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_free.argtypes = [c_void_p]
+isl.isl_pw_aff_to_str.argtypes = [c_void_p]
+isl.isl_pw_aff_to_str.restype = POINTER(c_char)
+
+class multi_aff(multi_pw_aff, pw_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 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])
+ return
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_multi_aff_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_multi_aff_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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 multi_pw_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 multi_pw_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 multi_pw_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 multi_pw_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_free.argtypes = [c_void_p]
+isl.isl_multi_aff_to_str.argtypes = [c_void_p]
+isl.isl_multi_aff_to_str.restype = POINTER(c_char)
+
+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])
+ return
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_aff_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_aff_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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 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)
+
+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_pullback_multi_aff.restype = c_void_p
+isl.isl_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_free.argtypes = [c_void_p]
+isl.isl_aff_to_str.argtypes = [c_void_p]
+isl.isl_aff_to_str.restype = POINTER(c_char)
+
class union_map:
def __init__(self, *args, **keywords):
if "ptr" in keywords:
@@ -56,74 +857,130 @@ class union_map:
libc.free(ptr)
return res
def __repr__(self):
- return 'isl.union_map("%s")' % str(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=arg0.ctx, ptr=res)
- def polyhedral_hull(arg0):
+ 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
- res = isl.isl_union_map_polyhedral_hull(isl.isl_union_map_copy(arg0.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
+ 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=arg0.ctx, ptr=res)
- def lexmin(arg0):
+ 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
- res = isl.isl_union_map_lexmin(isl.isl_union_map_copy(arg0.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
- def lexmax(arg0):
+ 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
- res = isl.isl_union_map_lexmax(isl.isl_union_map_copy(arg0.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
- def union(arg0, arg1):
+ 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 arg1.__class__ is union_map:
- arg1 = union_map(arg1)
+ if not arg0.__class__ is union_map:
+ arg0 = union_map(arg0)
except:
raise
- res = isl.isl_union_map_union(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
- def subtract(arg0, arg1):
+ 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 arg1.__class__ is union_map:
- arg1 = union_map(arg1)
+ if not arg0.__class__ is union_map:
+ arg0 = union_map(arg0)
except:
raise
- res = isl.isl_union_map_subtract(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
- def intersect(arg0, arg1):
+ 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)
@@ -134,21 +991,77 @@ class union_map:
arg1 = union_map(arg1)
except:
raise
- res = isl.isl_union_map_intersect(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
- def intersect_params(arg0, arg1):
+ 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 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 arg1.__class__ is set:
- arg1 = set(arg1)
+ if not arg0.__class__ is union_map:
+ arg0 = union_map(arg0)
except:
raise
- res = isl.isl_union_map_intersect_params(isl.isl_union_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
+ 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_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)
def gist(arg0, arg1):
try:
if not arg0.__class__ is union_map:
@@ -160,8 +1073,23 @@ class 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=arg0.ctx, ptr=res)
+ 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:
@@ -173,9 +1101,10 @@ class union_map:
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=arg0.ctx, ptr=res)
- def gist_domain(arg0, arg1):
+ return union_map(ctx=ctx, ptr=res)
+ def gist_range(arg0, arg1):
try:
if not arg0.__class__ is union_map:
arg0 = union_map(arg0)
@@ -186,21 +1115,23 @@ class union_map:
arg1 = union_set(arg1)
except:
raise
- 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=arg0.ctx, ptr=res)
- def gist_range(arg0, arg1):
+ 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_set:
- arg1 = union_set(arg1)
+ if not arg1.__class__ is union_map:
+ arg1 = union_map(arg1)
except:
raise
- 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=arg0.ctx, ptr=res)
+ 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:
@@ -212,8 +1143,23 @@ class union_map:
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=arg0.ctx, ptr=res)
+ 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:
@@ -225,35 +1171,70 @@ class union_map:
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=arg0.ctx, ptr=res)
- def subtract_domain(arg0, arg1):
+ 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 arg1.__class__ is union_set:
- arg1 = union_set(arg1)
+ if not arg0.__class__ is union_map:
+ arg0 = union_map(arg0)
except:
raise
- 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=arg0.ctx, ptr=res)
- def subtract_range(arg0, arg1):
+ 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_set:
- arg1 = union_set(arg1)
+ if not arg1.__class__ is union_map:
+ arg1 = union_map(arg1)
except:
raise
- 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=arg0.ctx, ptr=res)
- def apply_domain(arg0, arg1):
+ 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)
@@ -264,9 +1245,12 @@ class union_map:
arg1 = union_map(arg1)
except:
raise
- 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=arg0.ctx, ptr=res)
- def apply_range(arg0, arg1):
+ 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)
@@ -277,65 +1261,89 @@ class union_map:
arg1 = union_map(arg1)
except:
raise
- 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=arg0.ctx, ptr=res)
- def reverse(arg0):
+ 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
- res = isl.isl_union_map_reverse(isl.isl_union_map_copy(arg0.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
- def detect_equalities(arg0):
+ 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
- res = isl.isl_union_map_detect_equalities(isl.isl_union_map_copy(arg0.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
- def deltas(arg0):
+ 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
- res = isl.isl_union_map_deltas(isl.isl_union_map_copy(arg0.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def is_empty(arg0):
+ 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
- res = isl.isl_union_map_is_empty(arg0.ptr)
- return res
- def is_single_valued(arg0):
+ 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 range(arg0):
try:
if not arg0.__class__ is union_map:
arg0 = union_map(arg0)
except:
raise
- res = isl.isl_union_map_is_single_valued(arg0.ptr)
- return res
- def is_injective(arg0):
+ 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
- res = isl.isl_union_map_is_injective(arg0.ptr)
- return res
- def is_bijective(arg0):
+ 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
- res = isl.isl_union_map_is_bijective(arg0.ptr)
- return res
- def is_subset(arg0, arg1):
+ 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)
@@ -346,9 +1354,19 @@ class union_map:
arg1 = union_map(arg1)
except:
raise
- res = isl.isl_union_map_is_subset(arg0.ptr, arg1.ptr)
- return res
- def is_equal(arg0, arg1):
+ 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)
@@ -359,9 +1377,38 @@ class union_map:
arg1 = union_map(arg1)
except:
raise
- res = isl.isl_union_map_is_equal(arg0.ptr, arg1.ptr)
- return res
- def is_strict_subset(arg0, arg1):
+ 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)
@@ -372,35 +1419,27 @@ class union_map:
arg1 = union_map(arg1)
except:
raise
- res = isl.isl_union_map_is_strict_subset(arg0.ptr, arg1.ptr)
- return res
- def foreach_map(arg0, arg1):
+ 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 arg1.__class__ is stat (isl_map *, void *):
- arg1 = stat (isl_map *, void *)(arg1)
+ 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)
- 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
+ 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]
@@ -409,27 +1448,106 @@ 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_polyhedral_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_lexmin.restype = c_void_p
-isl.isl_union_map_lexmax.restype = c_void_p
-isl.isl_union_map_union.restype = c_void_p
-isl.isl_union_map_subtract.restype = c_void_p
-isl.isl_union_map_intersect.restype = c_void_p
-isl.isl_union_map_intersect_params.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_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_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_gist.restype = c_void_p
-isl.isl_union_map_gist_params.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_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_apply_domain.restype = c_void_p
-isl.isl_union_map_apply_range.restype = c_void_p
-isl.isl_union_map_reverse.restype = c_void_p
-isl.isl_union_map_detect_equalities.restype = c_void_p
-isl.isl_union_map_deltas.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_free.argtypes = [c_void_p]
isl.isl_union_map_to_str.argtypes = [c_void_p]
isl.isl_union_map_to_str.restype = POINTER(c_char)
@@ -440,14 +1558,14 @@ class map(union_map):
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])
- 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
+ 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])
+ return
raise Error
def __del__(self):
if hasattr(self, 'ptr'):
@@ -458,32 +1576,35 @@ class map(union_map):
libc.free(ptr)
return res
def __repr__(self):
- return 'isl.map("%s")' % str(self)
- def lexmin(arg0):
+ 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
- res = isl.isl_map_lexmin(isl.isl_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def lexmax(arg0):
+ 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
- res = isl.isl_map_lexmax(isl.isl_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def reverse(arg0):
try:
- if not arg0.__class__ is map:
- arg0 = map(arg0)
+ if not arg1.__class__ is map:
+ arg1 = map(arg1)
except:
- raise
- res = isl.isl_map_reverse(isl.isl_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def union(arg0, arg1):
+ 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)
@@ -493,62 +1614,97 @@ class map(union_map):
if not arg1.__class__ is map:
arg1 = map(arg1)
except:
- return union_map(arg0).union(arg1)
- res = isl.isl_map_union(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def intersect_domain(arg0, arg1):
+ 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 arg1.__class__ is set:
- arg1 = set(arg1)
+ if not arg0.__class__ is map:
+ arg0 = map(arg0)
except:
- return union_map(arg0).intersect_domain(arg1)
- res = isl.isl_map_intersect_domain(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def intersect_range(arg0, arg1):
+ 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 arg1.__class__ is set:
- arg1 = set(arg1)
+ if not arg0.__class__ is map:
+ arg0 = map(arg0)
except:
- return union_map(arg0).intersect_range(arg1)
- res = isl.isl_map_intersect_range(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def apply_domain(arg0, arg1):
+ 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 arg1.__class__ is map:
- arg1 = map(arg1)
+ if not arg0.__class__ is map:
+ arg0 = map(arg0)
except:
- return union_map(arg0).apply_domain(arg1)
- res = isl.isl_map_apply_domain(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def apply_range(arg0, arg1):
+ 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 arg1.__class__ is map:
- arg1 = map(arg1)
+ if not arg0.__class__ is map:
+ arg0 = map(arg0)
except:
- return union_map(arg0).apply_range(arg1)
- res = isl.isl_map_apply_range(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def intersect(arg0, arg1):
+ 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)
@@ -558,10 +1714,11 @@ class map(union_map):
if not arg1.__class__ is map:
arg1 = map(arg1)
except:
- return union_map(arg0).intersect(arg1)
- res = isl.isl_map_intersect(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def intersect_params(arg0, arg1):
+ 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)
@@ -571,10 +1728,11 @@ class map(union_map):
if not arg1.__class__ is set:
arg1 = set(arg1)
except:
- return union_map(arg0).intersect_params(arg1)
- res = isl.isl_map_intersect_params(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def subtract(arg0, arg1):
+ 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)
@@ -584,90 +1742,91 @@ class map(union_map):
if not arg1.__class__ is map:
arg1 = map(arg1)
except:
- return union_map(arg0).subtract(arg1)
- res = isl.isl_map_subtract(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def complement(arg0):
+ 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
- res = isl.isl_map_complement(isl.isl_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def deltas(arg0):
try:
- if not arg0.__class__ is map:
- arg0 = map(arg0)
+ if not arg1.__class__ is set:
+ arg1 = set(arg1)
except:
- raise
- res = isl.isl_map_deltas(isl.isl_map_copy(arg0.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def detect_equalities(arg0):
+ 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
- res = isl.isl_map_detect_equalities(isl.isl_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def affine_hull(arg0):
try:
- if not arg0.__class__ is map:
- arg0 = map(arg0)
+ if not arg1.__class__ is set:
+ arg1 = set(arg1)
except:
- raise
- res = isl.isl_map_affine_hull(isl.isl_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def polyhedral_hull(arg0):
+ 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
- res = isl.isl_map_polyhedral_hull(isl.isl_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def flatten(arg0):
try:
- if not arg0.__class__ is map:
- arg0 = map(arg0)
+ if not arg1.__class__ is set:
+ arg1 = set(arg1)
except:
- raise
- res = isl.isl_map_flatten(isl.isl_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def flatten_domain(arg0):
+ 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
- res = isl.isl_map_flatten_domain(isl.isl_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def flatten_range(arg0):
+ 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
- res = isl.isl_map_flatten_range(isl.isl_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def sample(arg0):
try:
- if not arg0.__class__ is map:
- arg0 = map(arg0)
+ 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
- res = isl.isl_map_sample(isl.isl_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
+ 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)
- return res
- def is_subset(arg0, arg1):
+ if res < 0:
+ raise
+ return bool(res)
+ def is_equal(arg0, arg1):
try:
if not arg0.__class__ is map:
arg0 = map(arg0)
@@ -677,23 +1836,35 @@ class map(union_map):
if not arg1.__class__ is map:
arg1 = map(arg1)
except:
- return union_map(arg0).is_subset(arg1)
- res = isl.isl_map_is_subset(arg0.ptr, arg1.ptr)
- return res
- def is_strict_subset(arg0, arg1):
+ 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 arg1.__class__ is map:
- arg1 = map(arg1)
+ if not arg0.__class__ is map:
+ arg0 = map(arg0)
except:
- return union_map(arg0).is_strict_subset(arg1)
- res = isl.isl_map_is_strict_subset(arg0.ptr, arg1.ptr)
- return res
- def is_equal(arg0, arg1):
+ 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)
@@ -703,10 +1874,13 @@ class map(union_map):
if not arg1.__class__ is map:
arg1 = map(arg1)
except:
- return union_map(arg0).is_equal(arg1)
- res = isl.isl_map_is_equal(arg0.ptr, arg1.ptr)
- return res
- def is_disjoint(arg0, arg1):
+ 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)
@@ -716,122 +1890,153 @@ class map(union_map):
if not arg1.__class__ is map:
arg1 = map(arg1)
except:
- return union_map(arg0).is_disjoint(arg1)
- res = isl.isl_map_is_disjoint(arg0.ptr, arg1.ptr)
- return res
- def is_single_valued(arg0):
+ 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
- res = isl.isl_map_is_single_valued(arg0.ptr)
- return res
- def is_injective(arg0):
+ 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
- res = isl.isl_map_is_injective(arg0.ptr)
- return res
- def is_bijective(arg0):
+ 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
- res = isl.isl_map_is_bijective(arg0.ptr)
- return res
- def gist(arg0, arg1):
+ 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
- try:
- if not arg1.__class__ is map:
- arg1 = map(arg1)
- except:
- return union_map(arg0).gist(arg1)
- res = isl.isl_map_gist(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def gist_domain(arg0, arg1):
+ 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
- try:
- if not arg1.__class__ is set:
- arg1 = set(arg1)
- except:
- return union_map(arg0).gist_domain(arg1)
- res = isl.isl_map_gist_domain(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def coalesce(arg0):
+ 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
- res = isl.isl_map_coalesce(isl.isl_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def foreach_basic_map(arg0, arg1):
+ 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 stat (isl_basic_map *, void *):
- arg1 = stat (isl_basic_map *, void *)(arg1)
+ if not arg1.__class__ is map:
+ arg1 = map(arg1)
except:
- return union_map(arg0).foreach_basic_map(arg1)
- 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)
- 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
+ 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)
-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_lexmin.restype = c_void_p
-isl.isl_map_lexmax.restype = c_void_p
-isl.isl_map_reverse.restype = c_void_p
-isl.isl_map_union.restype = c_void_p
-isl.isl_map_intersect_domain.restype = c_void_p
-isl.isl_map_intersect_range.restype = c_void_p
+isl.isl_map_read_from_str.restype = c_void_p
+isl.isl_map_read_from_str.argtypes = [Context, c_char_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_intersect.restype = c_void_p
-isl.isl_map_intersect_params.restype = c_void_p
-isl.isl_map_subtract.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_affine_hull.restype = c_void_p
-isl.isl_map_polyhedral_hull.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_sample.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_coalesce.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_free.argtypes = [c_void_p]
isl.isl_map_to_str.argtypes = [c_void_p]
isl.isl_map_to_str.restype = POINTER(c_char)
@@ -856,34 +2061,21 @@ class basic_map(map):
libc.free(ptr)
return res
def __repr__(self):
- return 'isl.basic_map("%s")' % str(self)
- 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)
- 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=arg0.ctx, ptr=res)
- def intersect_range(arg0, arg1):
+ 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
- try:
- if not arg1.__class__ is basic_set:
- arg1 = basic_set(arg1)
- except:
- return map(arg0).intersect_range(arg1)
- 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=arg0.ctx, ptr=res)
- def intersect(arg0, arg1):
+ 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)
@@ -893,10 +2085,11 @@ class basic_map(map):
if not arg1.__class__ is basic_map:
arg1 = basic_map(arg1)
except:
- return map(arg0).intersect(arg1)
- res = isl.isl_basic_map_intersect(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def union(arg0, arg1):
+ 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)
@@ -906,68 +2099,70 @@ class basic_map(map):
if not arg1.__class__ is basic_map:
arg1 = basic_map(arg1)
except:
- return map(arg0).union(arg1)
- res = isl.isl_basic_map_union(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def apply_domain(arg0, arg1):
+ 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
- try:
- if not arg1.__class__ is basic_map:
- arg1 = basic_map(arg1)
- except:
- return map(arg0).apply_domain(arg1)
- 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=arg0.ctx, ptr=res)
- def apply_range(arg0, arg1):
+ 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
- try:
- if not arg1.__class__ is basic_map:
- arg1 = basic_map(arg1)
- except:
- return map(arg0).apply_range(arg1)
- 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=arg0.ctx, ptr=res)
- def affine_hull(arg0):
+ 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
- res = isl.isl_basic_map_affine_hull(isl.isl_basic_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def reverse(arg0):
+ 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
- res = isl.isl_basic_map_reverse(isl.isl_basic_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def sample(arg0):
+ 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
- res = isl.isl_basic_map_sample(isl.isl_basic_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def detect_equalities(arg0):
+ 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
- res = isl.isl_basic_map_detect_equalities(isl.isl_basic_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def is_equal(arg0, arg1):
+ 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)
@@ -977,33 +2172,65 @@ class basic_map(map):
if not arg1.__class__ is basic_map:
arg1 = basic_map(arg1)
except:
- return map(arg0).is_equal(arg1)
- res = isl.isl_basic_map_is_equal(arg0.ptr, arg1.ptr)
- return res
- def lexmin(arg0):
+ 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
- res = isl.isl_basic_map_lexmin(isl.isl_basic_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def lexmax(arg0):
+ 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
- res = isl.isl_basic_map_lexmax(isl.isl_basic_map_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
+ 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)
- return res
+ 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:
@@ -1015,41 +2242,48 @@ class basic_map(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)
- return res
- def deltas(arg0):
+ if res < 0:
+ raise
+ return bool(res)
+ def lexmax(arg0):
try:
if not arg0.__class__ is basic_map:
arg0 = basic_map(arg0)
except:
raise
- res = isl.isl_basic_map_deltas(isl.isl_basic_map_copy(arg0.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
- def flatten(arg0):
+ 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
- res = isl.isl_basic_map_flatten(isl.isl_basic_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def flatten_domain(arg0):
+ 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
- res = isl.isl_basic_map_flatten_domain(isl.isl_basic_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def flatten_range(arg0):
+ 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
- res = isl.isl_basic_map_flatten_range(isl.isl_basic_map_copy(arg0.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
- def gist(arg0, arg1):
+ 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)
@@ -1059,29 +2293,53 @@ class basic_map(map):
if not arg1.__class__ is basic_map:
arg1 = basic_map(arg1)
except:
- return map(arg0).gist(arg1)
- res = isl.isl_basic_map_gist(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
- return basic_map(ctx=arg0.ctx, ptr=res)
+ 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_intersect_domain.restype = c_void_p
-isl.isl_basic_map_intersect_range.restype = c_void_p
-isl.isl_basic_map_intersect.restype = c_void_p
-isl.isl_basic_map_union.restype = c_void_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_affine_hull.restype = c_void_p
-isl.isl_basic_map_reverse.restype = c_void_p
-isl.isl_basic_map_sample.restype = c_void_p
-isl.isl_basic_map_detect_equalities.restype = c_void_p
-isl.isl_basic_map_lexmin.restype = c_void_p
-isl.isl_basic_map_lexmax.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_free.argtypes = [c_void_p]
isl.isl_basic_map_to_str.argtypes = [c_void_p]
isl.isl_basic_map_to_str.restype = POINTER(c_char)
@@ -1100,6 +2358,10 @@ class union_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])
@@ -1114,64 +2376,108 @@ class union_set:
libc.free(ptr)
return res
def __repr__(self):
- return 'isl.union_set("%s")' % str(self)
- def identity(arg0):
+ 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
- res = isl.isl_union_set_identity(isl.isl_union_set_copy(arg0.ptr))
- return union_map(ctx=arg0.ctx, ptr=res)
- def detect_equalities(arg0):
+ 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
- res = isl.isl_union_set_detect_equalities(isl.isl_union_set_copy(arg0.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def affine_hull(arg0):
+ 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
- res = isl.isl_union_set_affine_hull(isl.isl_union_set_copy(arg0.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def polyhedral_hull(arg0):
+ 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
- res = isl.isl_union_set_polyhedral_hull(isl.isl_union_set_copy(arg0.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def coalesce(arg0):
+ 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
- res = isl.isl_union_set_coalesce(isl.isl_union_set_copy(arg0.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def lexmin(arg0):
+ 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
- res = isl.isl_union_set_lexmin(isl.isl_union_set_copy(arg0.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def lexmax(arg0):
+ 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
- res = isl.isl_union_set_lexmax(isl.isl_union_set_copy(arg0.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def subtract(arg0, arg1):
+ 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)
@@ -1182,8 +2488,32 @@ class union_set:
arg1 = union_set(arg1)
except:
raise
- res = isl.isl_union_set_subtract(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
+ 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:
@@ -1195,8 +2525,9 @@ class 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=arg0.ctx, ptr=res)
+ return union_set(ctx=ctx, ptr=res)
def intersect_params(arg0, arg1):
try:
if not arg0.__class__ is union_set:
@@ -1208,9 +2539,21 @@ class union_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=arg0.ctx, ptr=res)
- def gist(arg0, arg1):
+ 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)
@@ -1221,56 +2564,80 @@ class union_set:
arg1 = union_set(arg1)
except:
raise
- res = isl.isl_union_set_gist(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def gist_params(arg0, arg1):
+ 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 set:
- arg1 = set(arg1)
+ if not arg1.__class__ is union_set:
+ arg1 = union_set(arg1)
except:
raise
- res = isl.isl_union_set_gist_params(isl.isl_union_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def apply(arg0, arg1):
+ 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_map:
- arg1 = union_map(arg1)
+ if not arg1.__class__ is union_set:
+ arg1 = union_set(arg1)
except:
raise
- res = isl.isl_union_set_apply(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
- return union_set(ctx=arg0.ctx, ptr=res)
- def is_empty(arg0):
+ 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
- res = isl.isl_union_set_is_empty(arg0.ptr)
- return res
- def is_subset(arg0, arg1):
+ 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 arg1.__class__ is union_set:
- arg1 = union_set(arg1)
+ if not arg0.__class__ is union_set:
+ arg0 = union_set(arg0)
except:
raise
- res = isl.isl_union_set_is_subset(arg0.ptr, arg1.ptr)
- return res
- def is_equal(arg0, arg1):
+ 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 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)
@@ -1281,9 +2648,10 @@ class union_set:
arg1 = union_set(arg1)
except:
raise
- res = isl.isl_union_set_is_equal(arg0.ptr, arg1.ptr)
- return res
- def is_strict_subset(arg0, arg1):
+ 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)
@@ -1294,55 +2662,71 @@ class union_set:
arg1 = union_set(arg1)
except:
raise
- res = isl.isl_union_set_is_strict_subset(arg0.ptr, arg1.ptr)
- return res
- def foreach_set(arg0, arg1):
+ 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
- try:
- if not arg1.__class__ is stat (isl_set *, void *):
- arg1 = stat (isl_set *, void *)(arg1)
- 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)
- 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
+ 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_identity.restype = c_void_p
-isl.isl_union_set_detect_equalities.restype = c_void_p
isl.isl_union_set_affine_hull.restype = c_void_p
-isl.isl_union_set_polyhedral_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_lexmin.restype = c_void_p
-isl.isl_union_set_lexmax.restype = c_void_p
-isl.isl_union_set_subtract.restype = c_void_p
-isl.isl_union_set_intersect.restype = c_void_p
-isl.isl_union_set_intersect_params.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_apply.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_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_free.argtypes = [c_void_p]
isl.isl_union_set_to_str.argtypes = [c_void_p]
isl.isl_union_set_to_str.restype = POINTER(c_char)
@@ -1361,6 +2745,10 @@ class set(union_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'):
@@ -1371,56 +2759,94 @@ class set(union_set):
libc.free(ptr)
return res
def __repr__(self):
- return 'isl.set("%s")' % str(self)
- def lexmin(arg0):
+ 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
- res = isl.isl_set_lexmin(isl.isl_set_copy(arg0.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def lexmax(arg0):
+ 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
- res = isl.isl_set_lexmax(isl.isl_set_copy(arg0.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def sample(arg0):
+ 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
- res = isl.isl_set_sample(isl.isl_set_copy(arg0.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
+ 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=arg0.ctx, ptr=res)
- def affine_hull(arg0):
+ return set(ctx=ctx, ptr=res)
+ def flatten(arg0):
try:
if not arg0.__class__ is set:
arg0 = set(arg0)
except:
raise
- res = isl.isl_set_affine_hull(isl.isl_set_copy(arg0.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
- def polyhedral_hull(arg0):
+ 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
- res = isl.isl_set_polyhedral_hull(isl.isl_set_copy(arg0.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
- def union(arg0, arg1):
+ 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 gist(arg0, arg1):
try:
if not arg0.__class__ is set:
arg0 = set(arg0)
@@ -1430,9 +2856,19 @@ class set(union_set):
if not arg1.__class__ is set:
arg1 = set(arg1)
except:
- return union_set(arg0).union(arg1)
- res = isl.isl_set_union(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
- return set(ctx=arg0.ctx, ptr=res)
+ 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:
@@ -1444,8 +2880,9 @@ class set(union_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=arg0.ctx, ptr=res)
+ return set(ctx=ctx, ptr=res)
def intersect_params(arg0, arg1):
try:
if not arg0.__class__ is set:
@@ -1457,9 +2894,10 @@ class set(union_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=arg0.ctx, ptr=res)
- def subtract(arg0, arg1):
+ return set(ctx=ctx, ptr=res)
+ def is_disjoint(arg0, arg1):
try:
if not arg0.__class__ is set:
arg0 = set(arg0)
@@ -1469,39 +2907,24 @@ class set(union_set):
if not arg1.__class__ is set:
arg1 = set(arg1)
except:
- return union_set(arg0).subtract(arg1)
- res = isl.isl_set_subtract(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def complement(arg0):
- try:
- if not arg0.__class__ is set:
- arg0 = set(arg0)
- except:
- raise
- res = isl.isl_set_complement(isl.isl_set_copy(arg0.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def apply(arg0, arg1):
- try:
- if not arg0.__class__ is set:
- arg0 = set(arg0)
- 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
- try:
- if not arg1.__class__ is map:
- arg1 = map(arg1)
- except:
- return union_set(arg0).apply(arg1)
- res = isl.isl_set_apply(isl.isl_set_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
- return set(ctx=arg0.ctx, ptr=res)
+ 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)
- return res
- def is_subset(arg0, arg1):
+ if res < 0:
+ raise
+ return bool(res)
+ def is_equal(arg0, arg1):
try:
if not arg0.__class__ is set:
arg0 = set(arg0)
@@ -1511,9 +2934,12 @@ class set(union_set):
if not arg1.__class__ is set:
arg1 = set(arg1)
except:
- return union_set(arg0).is_subset(arg1)
- res = isl.isl_set_is_subset(arg0.ptr, arg1.ptr)
- return res
+ 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:
@@ -1525,9 +2951,12 @@ class set(union_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)
- return res
- def is_equal(arg0, arg1):
+ if res < 0:
+ raise
+ return bool(res)
+ def is_subset(arg0, arg1):
try:
if not arg0.__class__ is set:
arg0 = set(arg0)
@@ -1537,115 +2966,139 @@ class set(union_set):
if not arg1.__class__ is set:
arg1 = set(arg1)
except:
- return union_set(arg0).is_equal(arg1)
- res = isl.isl_set_is_equal(arg0.ptr, arg1.ptr)
- return res
- def is_disjoint(arg0, arg1):
+ 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
- try:
- if not arg1.__class__ is set:
- arg1 = set(arg1)
- except:
- return union_set(arg0).is_disjoint(arg1)
- res = isl.isl_set_is_disjoint(arg0.ptr, arg1.ptr)
- return res
- def gist(arg0, arg1):
+ 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
- try:
- if not arg1.__class__ is set:
- arg1 = set(arg1)
- except:
- return union_set(arg0).gist(arg1)
- res = isl.isl_set_gist(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def coalesce(arg0):
+ 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
- res = isl.isl_set_coalesce(isl.isl_set_copy(arg0.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def foreach_basic_set(arg0, arg1):
+ ctx = arg0.ctx
+ res = isl.isl_set_lexmin(isl.isl_set_copy(arg0.ptr))
+ return set(ctx=ctx, ptr=res)
+ def polyhedral_hull(arg0):
try:
if not arg0.__class__ is set:
arg0 = set(arg0)
except:
raise
- try:
- if not arg1.__class__ is stat (isl_basic_set *, void *):
- arg1 = stat (isl_basic_set *, void *)(arg1)
- except:
- return union_set(arg0).foreach_basic_set(arg1)
- 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)
- 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 identity(arg0):
+ 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
- res = isl.isl_set_identity(isl.isl_set_copy(arg0.ptr))
- return map(ctx=arg0.ctx, ptr=res)
- def is_wrapping(arg0):
+ ctx = arg0.ctx
+ res = isl.isl_set_sample(isl.isl_set_copy(arg0.ptr))
+ return basic_set(ctx=ctx, ptr=res)
+ def subtract(arg0, arg1):
try:
if not arg0.__class__ is set:
arg0 = set(arg0)
except:
raise
- res = isl.isl_set_is_wrapping(arg0.ptr)
- return res
- def flatten(arg0):
+ 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
- res = isl.isl_set_flatten(isl.isl_set_copy(arg0.ptr))
- return set(ctx=arg0.ctx, ptr=res)
+ 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)
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_lexmin.restype = c_void_p
-isl.isl_set_lexmax.restype = c_void_p
-isl.isl_set_sample.restype = c_void_p
-isl.isl_set_detect_equalities.restype = 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_polyhedral_hull.restype = c_void_p
-isl.isl_set_union.restype = c_void_p
-isl.isl_set_intersect.restype = c_void_p
-isl.isl_set_intersect_params.restype = c_void_p
-isl.isl_set_subtract.restype = c_void_p
-isl.isl_set_complement.restype = c_void_p
+isl.isl_set_affine_hull.argtypes = [c_void_p]
isl.isl_set_apply.restype = c_void_p
-isl.isl_set_gist.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_identity.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_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_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_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_free.argtypes = [c_void_p]
isl.isl_set_to_str.argtypes = [c_void_p]
isl.isl_set_to_str.restype = POINTER(c_char)
@@ -1660,6 +3113,10 @@ class basic_set(set):
self.ctx = Context.getDefaultInstance()
self.ptr = isl.isl_basic_set_read_from_str(self.ctx, args[0])
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'):
@@ -1670,33 +3127,20 @@ class basic_set(set):
libc.free(ptr)
return res
def __repr__(self):
- return 'isl.basic_set("%s")' % str(self)
- 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)
- res = isl.isl_basic_set_intersect(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
- def intersect_params(arg0, arg1):
+ 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
- try:
- if not arg1.__class__ is basic_set:
- arg1 = basic_set(arg1)
- except:
- return set(arg0).intersect_params(arg1)
- 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=arg0.ctx, ptr=res)
+ 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:
@@ -1708,33 +3152,42 @@ class basic_set(set):
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=arg0.ctx, ptr=res)
- def affine_hull(arg0):
+ 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
- res = isl.isl_basic_set_affine_hull(isl.isl_basic_set_copy(arg0.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
- def sample(arg0):
+ 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 flatten(arg0):
try:
if not arg0.__class__ is basic_set:
arg0 = basic_set(arg0)
except:
raise
- res = isl.isl_basic_set_sample(isl.isl_basic_set_copy(arg0.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
- def detect_equalities(arg0):
+ 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
- res = isl.isl_basic_set_detect_equalities(isl.isl_basic_set_copy(arg0.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
- def is_equal(arg0, arg1):
+ 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)
@@ -1744,26 +3197,36 @@ class basic_set(set):
if not arg1.__class__ is basic_set:
arg1 = basic_set(arg1)
except:
- return set(arg0).is_equal(arg1)
- res = isl.isl_basic_set_is_equal(arg0.ptr, arg1.ptr)
- return res
- def lexmin(arg0):
+ 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
- res = isl.isl_basic_set_lexmin(isl.isl_basic_set_copy(arg0.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def lexmax(arg0):
+ 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
- res = isl.isl_basic_set_lexmax(isl.isl_basic_set_copy(arg0.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def union(arg0, arg1):
+ 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)
@@ -1773,17 +3236,12 @@ class basic_set(set):
if not arg1.__class__ is basic_set:
arg1 = basic_set(arg1)
except:
- return set(arg0).union(arg1)
- res = isl.isl_basic_set_union(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
- return set(ctx=arg0.ctx, ptr=res)
- def is_empty(arg0):
- try:
- if not arg0.__class__ is basic_set:
- arg0 = basic_set(arg0)
- 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
- res = isl.isl_basic_set_is_empty(arg0.ptr)
- return res
+ return bool(res)
def is_subset(arg0, arg1):
try:
if not arg0.__class__ is basic_set:
@@ -1795,51 +3253,669 @@ class basic_set(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)
- return res
- def gist(arg0, arg1):
+ 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 arg1.__class__ is basic_set:
- arg1 = basic_set(arg1)
+ if not arg0.__class__ is basic_set:
+ arg0 = basic_set(arg0)
except:
- return set(arg0).gist(arg1)
- res = isl.isl_basic_set_gist(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
- def is_wrapping(arg0):
+ 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
- res = isl.isl_basic_set_is_wrapping(arg0.ptr)
- return res
- def flatten(arg0):
+ 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
- res = isl.isl_basic_set_flatten(isl.isl_basic_set_copy(arg0.ptr))
- return basic_set(ctx=arg0.ctx, ptr=res)
+ ctx = arg0.ctx
+ res = isl.isl_basic_set_sample(isl.isl_basic_set_copy(arg0.ptr))
+ return basic_set(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_intersect.restype = c_void_p
-isl.isl_basic_set_intersect_params.restype = c_void_p
-isl.isl_basic_set_apply.restype = c_void_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_sample.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_lexmin.restype = c_void_p
+isl.isl_basic_set_detect_equalities.argtypes = [c_void_p]
+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_union.restype = c_void_p
-isl.isl_basic_set_gist.restype = c_void_p
-isl.isl_basic_set_flatten.restype = c_void_p
+isl.isl_basic_set_union.argtypes = [c_void_p, c_void_p]
isl.isl_basic_set_free.argtypes = [c_void_p]
isl.isl_basic_set_to_str.argtypes = [c_void_p]
isl.isl_basic_set_to_str.restype = POINTER(c_char)
+
+class multi_val:
+ 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__(self):
+ ptr = isl.isl_multi_val_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_free.argtypes = [c_void_p]
+isl.isl_multi_val_to_str.argtypes = [c_void_p]
+isl.isl_multi_val_to_str.restype = POINTER(c_char)
+
+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__(self):
+ ptr = isl.isl_point_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_free.argtypes = [c_void_p]
+isl.isl_point_to_str.argtypes = [c_void_p]
+isl.isl_point_to_str.restype = POINTER(c_char)
+
+class schedule:
+ 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])
+ return
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_schedule_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_schedule_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_free.argtypes = [c_void_p]
+isl.isl_schedule_to_str.argtypes = [c_void_p]
+isl.isl_schedule_to_str.restype = POINTER(c_char)
+
+class schedule_node:
+ 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__(self):
+ ptr = isl.isl_schedule_node_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+
+class union_access_info:
+ 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__(self):
+ ptr = isl.isl_union_access_info_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_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_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_free.argtypes = [c_void_p]
+isl.isl_union_access_info_to_str.argtypes = [c_void_p]
+isl.isl_union_access_info_to_str.restype = POINTER(c_char)
+
+class union_flow:
+ 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__(self):
+ ptr = isl.isl_union_flow_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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_free.argtypes = [c_void_p]
+isl.isl_union_flow_to_str.argtypes = [c_void_p]
+isl.isl_union_flow_to_str.restype = POINTER(c_char)
+
+class val:
+ 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]) == int:
+ self.ctx = Context.getDefaultInstance()
+ self.ptr = isl.isl_val_int_from_si(self.ctx, args[0])
+ 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])
+ return
+ raise Error
+ def __del__(self):
+ if hasattr(self, 'ptr'):
+ isl.isl_val_free(self.ptr)
+ def __str__(self):
+ ptr = isl.isl_val_to_str(self.ptr)
+ res = str(cast(ptr, c_char_p).value)
+ 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
+ @staticmethod
+ def infty():
+ ctx = Context.getDefaultInstance()
+ res = isl.isl_val_infty(ctx)
+ return val(ctx=ctx, ptr=res)
+ @staticmethod
+ def nan():
+ ctx = Context.getDefaultInstance()
+ res = isl.isl_val_nan(ctx)
+ 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)
+ @staticmethod
+ def zero():
+ ctx = Context.getDefaultInstance()
+ res = isl.isl_val_zero(ctx)
+ return val(ctx=ctx, ptr=res)
+
+isl.isl_val_int_from_si.restype = c_void_p
+isl.isl_val_int_from_si.argtypes = [Context, c_int]
+isl.isl_val_read_from_str.restype = c_void_p
+isl.isl_val_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_val_infty.restype = c_void_p
+isl.isl_val_infty.argtypes = [Context]
+isl.isl_val_nan.restype = c_void_p
+isl.isl_val_nan.argtypes = [Context]
+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_zero.restype = c_void_p
+isl.isl_val_zero.argtypes = [Context]
+isl.isl_val_free.argtypes = [c_void_p]
+isl.isl_val_to_str.argtypes = [c_void_p]
+isl.isl_val_to_str.restype = POINTER(c_char)
diff --git a/interface/python.cc b/interface/python.cc
index 0b4c0e28..a3b48286 100644
--- a/interface/python.cc
+++ b/interface/python.cc
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Sven Verdoolaege. All rights reserved.
+ * 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
@@ -36,17 +36,20 @@
#include <stdio.h>
#include <iostream>
#include <map>
+#include <vector>
#include <clang/AST/Attr.h>
#include "extract_interface.h"
#include "python.h"
-/* Is the given type declaration marked as being a subtype of some other
- * type? If so, return that other type in "super".
+/* Return a sequence of the types of which the given type declaration is
+ * marked as being a subtype.
*/
-static bool is_subclass(RecordDecl *decl, string &super)
+static vector<string> find_superclasses(RecordDecl *decl)
{
+ vector<string> super;
+
if (!decl->hasAttrs())
- return false;
+ return super;
string sub = "isl_subclass";
size_t len = sub.length();
@@ -57,12 +60,19 @@ static bool is_subclass(RecordDecl *decl, string &super)
continue;
string s = ann->getAnnotation().str();
if (s.substr(0, len) == sub) {
- super = s.substr(len + 1, s.length() - len - 2);
- return true;
+ s = s.substr(len + 1, s.length() - len - 2);
+ super.push_back(s);
}
}
- return false;
+ return super;
+}
+
+/* Is decl marked as being part of an overloaded method?
+ */
+static bool is_overload(Decl *decl)
+{
+ return has_annotation(decl, "isl_overload");
}
/* Is decl marked as a constructor?
@@ -82,22 +92,28 @@ static bool takes(Decl *decl)
/* 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.
*/
struct isl_class {
string name;
RecordDecl *type;
set<FunctionDecl *> constructors;
- set<FunctionDecl *> methods;
+ map<string, set<FunctionDecl *> > methods;
+
+ bool is_static(FunctionDecl *method);
void print(map<string, isl_class> &classes, set<string> &done);
void print_constructor(FunctionDecl *method);
- void print_method(FunctionDecl *method, bool subclass, string super);
+ void print_method(FunctionDecl *method, vector<string> super);
+ void print_method_overload(FunctionDecl *method, vector<string> super);
+ void print_method(const string &fullname,
+ const set<FunctionDecl *> &methods, vector<string> super);
};
/* Return the class that has a name that matches the initial part
- * of the namd of function "fd".
+ * of the name of function "fd" or NULL if no such class could be found.
*/
-static isl_class &method2class(map<string, isl_class> &classes,
+static isl_class *method2class(map<string, isl_class> &classes,
FunctionDecl *fd)
{
string best;
@@ -109,7 +125,12 @@ static isl_class &method2class(map<string, isl_class> &classes,
best = ci->first;
}
- return classes[best];
+ 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 *"?
@@ -143,13 +164,31 @@ static bool first_arg_is_isl_ctx(FunctionDecl *fd)
static bool is_isl_type(QualType type)
{
if (type->isPointerType()) {
- string s = type->getPointeeType().getAsString();
+ 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?
+ */
+static bool is_isl_bool(QualType type)
+{
+ string s;
+
+ if (type->isPointerType())
+ return false;
+
+ s = type.getAsString();
+ return s == "isl_bool";
+}
+
/* Is "type" that of a pointer to a function?
*/
static bool is_callback(QualType type)
@@ -189,6 +228,74 @@ static string type2python(string name)
return name.substr(4);
}
+/* 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).
+ */
+static string 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;
+}
+
+/* Should "method" be considered to be a static method?
+ * That is, is the first argument something other than
+ * an instance of the class?
+ */
+bool isl_class::is_static(FunctionDecl *method)
+{
+ ParmVarDecl *param = method->getParamDecl(0);
+ QualType type = param->getOriginalType();
+
+ if (!is_isl_type(type))
+ return true;
+ return extract_type(type) != name;
+}
+
+/* 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.
+ */
+static void 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");
+}
+
/* 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.
@@ -239,9 +346,41 @@ static void print_callback(QualType type, int arg)
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 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.
+ */
+static void 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 a python method corresponding to the C function "method".
- * "subclass" is set if the method belongs to a class that is a subclass
- * of some other class ("super").
+ * "super" contains the superclasses of the class to which the method belongs.
+ *
+ * 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
@@ -253,17 +392,22 @@ static void print_callback(QualType type, int arg)
* we check if the corresponding actual argument is of the right type.
* If not, we try to convert it to the right type.
* It that doesn't work and if subclass is set, we try to convert self
- * to the type of the superclass and call the corresponding method.
+ * 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.
+ *
+ * If the return type is isl_bool, then convert the result to
+ * a Python boolean, raising an error on isl_bool_error.
*/
-void isl_class::print_method(FunctionDecl *method, bool subclass, string super)
+void isl_class::print_method(FunctionDecl *method, vector<string> super)
{
string fullname = method->getName();
string cname = fullname.substr(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);
@@ -272,12 +416,10 @@ void isl_class::print_method(FunctionDecl *method, bool subclass, string super)
drop_user = 1;
}
- printf(" def %s(arg0", cname.c_str());
- for (int i = 1; i < num_params - drop_user; ++i)
- printf(", arg%d", i);
- printf("):\n");
+ print_method_header(is_static(method), cname,
+ num_params - drop_ctx - drop_user);
- for (int i = 0; i < num_params; ++i) {
+ for (int i = drop_ctx; i < num_params; ++i) {
ParmVarDecl *param = method->getParamDecl(i);
string type;
if (!is_isl_type(param->getOriginalType()))
@@ -285,13 +427,13 @@ void isl_class::print_method(FunctionDecl *method, bool subclass, string super)
type = type2python(extract_type(param->getOriginalType()));
printf(" try:\n");
printf(" if not arg%d.__class__ is %s:\n",
- i, type.c_str());
+ i - drop_ctx, type.c_str());
printf(" arg%d = %s(arg%d)\n",
- i, type.c_str(), i);
+ i - drop_ctx, type.c_str(), i - drop_ctx);
printf(" except:\n");
- if (i > 0 && subclass) {
+ if (!drop_ctx && i > 0 && super.size() > 0) {
printf(" return %s(arg0).%s(",
- type2python(super).c_str(), cname.c_str());
+ type2python(super[0]).c_str(), cname.c_str());
for (int i = 1; i < num_params - drop_user; ++i) {
if (i != 1)
printf(", ");
@@ -306,23 +448,20 @@ void isl_class::print_method(FunctionDecl *method, bool subclass, string super)
QualType type = param->getOriginalType();
if (!is_callback(type))
continue;
- print_callback(type->getPointeeType(), i);
+ 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 (takes(method->getParamDecl(0)))
- printf("isl.%s_copy(arg0.ptr)", name.c_str());
+ if (drop_ctx)
+ printf("ctx");
else
- printf("arg0.ptr");
+ print_arg_in_call(method, 0, 0);
for (int i = 1; i < num_params - drop_user; ++i) {
- ParmVarDecl *param = method->getParamDecl(i);
- 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(), i);
- } else
- printf(", arg%d.ptr", i);
+ printf(", ");
+ print_arg_in_call(method, i, drop_ctx);
}
if (drop_user)
printf(", None");
@@ -331,7 +470,7 @@ void isl_class::print_method(FunctionDecl *method, bool subclass, string super)
if (is_isl_type(method->getReturnType())) {
string type;
type = type2python(extract_type(method->getReturnType()));
- printf(" return %s(ctx=arg0.ctx, ptr=res)\n",
+ printf(" return %s(ctx=ctx, ptr=res)\n",
type.c_str());
} else {
if (drop_user) {
@@ -339,10 +478,91 @@ void isl_class::print_method(FunctionDecl *method, bool subclass, string super)
printf(" raise exc_info[0][0], "
"exc_info[0][1], exc_info[0][2]\n");
}
- printf(" return res\n");
+ if (is_isl_bool(method->getReturnType())) {
+ printf(" if res < 0:\n");
+ printf(" raise\n");
+ printf(" return bool(res)\n");
+ } else {
+ printf(" return res\n");
+ }
}
}
+/* Print part of an overloaded python method corresponding to the C function
+ * "method".
+ * "super" contains the superclasses of the class to which the method belongs.
+ *
+ * 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 isl_class::print_method_overload(FunctionDecl *method,
+ vector<string> super)
+{
+ string fullname = method->getName();
+ int num_params = method->getNumParams();
+ int first;
+ string type;
+
+ first = is_static(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 isl_class::print_method(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(any_method, super);
+ return;
+ }
+
+ cname = fullname.substr(name.length() + 1);
+ num_params = any_method->getNumParams();
+
+ print_method_header(is_static(any_method), cname, num_params);
+
+ for (it = methods.begin(); it != methods.end(); ++it)
+ print_method_overload(*it, super);
+}
+
/* Print part of the constructor for this isl_class.
*
* In particular, check if the actual arguments correspond to the
@@ -362,14 +582,17 @@ void isl_class::print_constructor(FunctionDecl *cons)
printf(" if len(args) == %d", num_params - drop_ctx);
for (int i = drop_ctx; i < num_params; ++i) {
ParmVarDecl *param = cons->getParamDecl(i);
- if (is_isl_type(param->getOriginalType())) {
- string type;
- type = extract_type(param->getOriginalType());
- type = type2python(type);
+ 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, type.c_str());
- } else
+ 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");
@@ -395,10 +618,73 @@ void isl_class::print_constructor(FunctionDecl *cons)
printf(" return\n");
}
+/* Print the header of the class "name" with superclasses "super".
+ */
+static void print_class_header(const string &name, const vector<string> &super)
+{
+ printf("class %s", name.c_str());
+ if (super.size() > 0) {
+ printf("(");
+ for (int i = 0; i < super.size(); ++i) {
+ if (i > 0)
+ printf(", ");
+ printf("%s", type2python(super[i]).c_str());
+ }
+ printf(")");
+ }
+ 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".
+ */
+static void 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());
+}
+
+/* Tell ctypes about the types of the arguments of the function "fd".
+ */
+static void 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
+ printf("c_int");
+ }
+ if (drop_user)
+ printf(", c_void_p");
+ printf("]\n");
+}
+
/* Print out the definition of this isl_class.
*
- * We first check if this isl_class is a subclass of some other class.
- * If it is, we make sure the superclass is printed out first.
+ * 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
@@ -413,20 +699,18 @@ void isl_class::print_constructor(FunctionDecl *cons)
*/
void isl_class::print(map<string, isl_class> &classes, set<string> &done)
{
- string super;
string p_name = type2python(name);
set<FunctionDecl *>::iterator in;
- bool subclass = is_subclass(type, super);
+ map<string, set<FunctionDecl *> >::iterator it;
+ vector<string> super = find_superclasses(type);
- if (subclass && done.find(super) == done.end())
- classes[super].print(classes, done);
+ for (int i = 0; i < super.size(); ++i)
+ if (done.find(super[i]) == done.end())
+ classes[super[i]].print(classes, done);
done.insert(name);
printf("\n");
- printf("class %s", p_name.c_str());
- if (subclass)
- printf("(%s)", type2python(super).c_str());
- printf(":\n");
+ print_class_header(p_name, super);
printf(" def __init__(self, *args, **keywords):\n");
printf(" if \"ptr\" in keywords:\n");
@@ -446,38 +730,27 @@ void isl_class::print(map<string, isl_class> &classes, set<string> &done)
printf(" libc.free(ptr)\n");
printf(" return res\n");
printf(" def __repr__(self):\n");
- printf(" return 'isl.%s(\"%%s\")' %% str(self)\n",
+ printf(" s = str(self)\n");
+ printf(" if '\"' in s:\n");
+ printf(" return 'isl.%s(\"\"\"%%s\"\"\")' %% s\n",
+ p_name.c_str());
+ printf(" else:\n");
+ printf(" return 'isl.%s(\"%%s\")' %% s\n",
p_name.c_str());
- for (in = methods.begin(); in != methods.end(); ++in)
- print_method(*in, subclass, super);
+ for (it = methods.begin(); it != methods.end(); ++it)
+ print_method(it->first, it->second, super);
printf("\n");
for (in = constructors.begin(); in != constructors.end(); ++in) {
- string fullname = (*in)->getName();
- printf("isl.%s.restype = c_void_p\n", fullname.c_str());
- printf("isl.%s.argtypes = [", fullname.c_str());
- for (int i = 0; i < (*in)->getNumParams(); ++i) {
- ParmVarDecl *param = (*in)->getParamDecl(i);
- QualType type = param->getOriginalType();
- if (i)
- printf(", ");
- if (is_isl_ctx(type))
- printf("Context");
- else if (is_isl_type(type))
- printf("c_void_p");
- else if (is_string(type))
- printf("c_char_p");
- else
- printf("c_int");
- }
- printf("]\n");
- }
- for (in = methods.begin(); in != methods.end(); ++in) {
- string fullname = (*in)->getName();
- if (is_isl_type((*in)->getReturnType()))
- printf("isl.%s.restype = c_void_p\n", fullname.c_str());
+ print_restype(*in);
+ print_argtypes(*in);
}
+ for (it = methods.begin(); it != methods.end(); ++it)
+ for (in = it->second.begin(); in != it->second.end(); ++in) {
+ print_restype(*in);
+ print_argtypes(*in);
+ }
printf("isl.%s_free.argtypes = [c_void_p]\n", name.c_str());
printf("isl.%s_to_str.argtypes = [c_void_p]\n", name.c_str());
printf("isl.%s_to_str.restype = POINTER(c_char)\n", name.c_str());
@@ -485,7 +758,9 @@ void isl_class::print(map<string, isl_class> &classes, set<string> &done)
/* Generate a python interface based on the extracted types and functions.
* We first collect all functions that belong to a certain type,
- * separating constructors from regular methods.
+ * separating constructors from regular methods. If there are any
+ * overloaded functions, then they are grouped based on their name
+ * after removing the argument type suffix.
*
* Then we print out each class in turn. If one of these is a subclass
* of some other class, it will make sure the superclass is printed out first.
@@ -506,11 +781,17 @@ void generate_python(set<RecordDecl *> &types, set<FunctionDecl *> functions)
set<FunctionDecl *>::iterator in;
for (in = functions.begin(); in != functions.end(); ++in) {
- isl_class &c = method2class(classes, *in);
- if (is_constructor(*in))
- c.constructors.insert(*in);
- else
- c.methods.insert(*in);
+ isl_class *c = method2class(classes, *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);
+ }
}
for (ci = classes.begin(); ci != classes.end(); ++ci) {
diff --git a/isl_aff.c b/isl_aff.c
index 41d04c24..b072b956 100644
--- a/isl_aff.c
+++ b/isl_aff.c
@@ -1242,7 +1242,7 @@ __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
* expression, but we would also need to check that no other divs are
* defined in terms of them.
*/
-__isl_give isl_aff *isl_aff_remove_unused_divs( __isl_take isl_aff *aff)
+__isl_give isl_aff *isl_aff_remove_unused_divs(__isl_take isl_aff *aff)
{
int pos;
int off;
@@ -2578,9 +2578,8 @@ __isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
#undef PARTS
#define PARTS pw_aff
-#define NO_EVAL
-
-#include <isl_union_templ.c>
+#include <isl_union_single.c>
+#include <isl_union_neg.c>
static __isl_give isl_set *align_params_pw_pw_set_and(
__isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2,
@@ -3950,25 +3949,6 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_identity(space));
}
-/* Add "ma2" to "ma1" and return the result.
- *
- * The parameters of "ma1" and "ma2" are assumed to have been aligned.
- */
-static __isl_give isl_multi_aff *isl_multi_aff_add_aligned(
- __isl_take isl_multi_aff *maff1, __isl_take isl_multi_aff *maff2)
-{
- return isl_multi_aff_bin_op(maff1, maff2, &isl_aff_add);
-}
-
-/* Add "ma2" to "ma1" and return the result.
- */
-__isl_give isl_multi_aff *isl_multi_aff_add(__isl_take isl_multi_aff *ma1,
- __isl_take isl_multi_aff *ma2)
-{
- return isl_multi_aff_align_params_multi_multi_and(ma1, ma2,
- &isl_multi_aff_add_aligned);
-}
-
/* Exploit the equalities in "eq" to simplify the affine expressions.
*/
static __isl_give isl_multi_aff *isl_multi_aff_substitute_equalities(
@@ -4093,9 +4073,8 @@ __isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
#undef PARTS
#define PARTS pw_multi_aff
-#define NO_EVAL
-
-#include <isl_union_templ.c>
+#include <isl_union_multi.c>
+#include <isl_union_neg.c>
/* Given a function "cmp" that returns the set of elements where
* "ma1" is "better" than "ma2", return the intersection of this
@@ -4401,58 +4380,198 @@ error:
return NULL;
}
-/* Given a basic map with a single output dimension that is defined
- * in terms of the parameters and input dimensions using an equality,
- * extract an isl_aff that expresses the output dimension in terms
+/* Subtract the initial "n" elements in "ma" with coefficients in "c" and
+ * denominator "denom".
+ * "denom" is allowed to be negative, in which case the actual denominator
+ * is -denom and the expressions are added instead.
+ */
+static __isl_give isl_aff *subtract_initial(__isl_take isl_aff *aff,
+ __isl_keep isl_multi_aff *ma, int n, isl_int *c, isl_int denom)
+{
+ int i, first;
+ int sign;
+ isl_int d;
+
+ first = isl_seq_first_non_zero(c, n);
+ if (first == -1)
+ return aff;
+
+ sign = isl_int_sgn(denom);
+ isl_int_init(d);
+ isl_int_abs(d, denom);
+ for (i = first; i < n; ++i) {
+ isl_aff *aff_i;
+
+ if (isl_int_is_zero(c[i]))
+ continue;
+ aff_i = isl_multi_aff_get_aff(ma, i);
+ aff_i = isl_aff_scale(aff_i, c[i]);
+ aff_i = isl_aff_scale_down(aff_i, d);
+ if (sign >= 0)
+ aff = isl_aff_sub(aff, aff_i);
+ else
+ aff = isl_aff_add(aff, aff_i);
+ }
+ isl_int_clear(d);
+
+ return aff;
+}
+
+/* Extract an affine expression that expresses the output dimension "pos"
+ * of "bmap" in terms of the parameters and input dimensions from
+ * equality "eq".
+ * Note that this expression may involve integer divisions defined
+ * in terms of parameters and input dimensions.
+ * The equality may also involve references to earlier (but not later)
+ * output dimensions. These are replaced by the corresponding elements
+ * in "ma".
+ *
+ * If the equality is of the form
+ *
+ * f(i) + h(j) + a x + g(i) = 0,
+ *
+ * with f(i) a linear combinations of the parameters and input dimensions,
+ * g(i) a linear combination of integer divisions defined in terms of the same
+ * and h(j) a linear combinations of earlier output dimensions,
+ * then the affine expression is
+ *
+ * (-f(i) - g(i))/a - h(j)/a
+ *
+ * If the equality is of the form
+ *
+ * f(i) + h(j) - a x + g(i) = 0,
+ *
+ * then the affine expression is
+ *
+ * (f(i) + g(i))/a - h(j)/(-a)
+ *
+ *
+ * If "div" refers to an integer division (i.e., it is smaller than
+ * the number of integer divisions), then the equality constraint
+ * does involve an integer division (the one at position "div") that
+ * is defined in terms of output dimensions. However, this integer
+ * division can be eliminated by exploiting a pair of constraints
+ * x >= l and x <= l + n, with n smaller than the coefficient of "div"
+ * in the equality constraint. "ineq" refers to inequality x >= l, i.e.,
+ * -l + x >= 0.
+ * In particular, let
+ *
+ * x = e(i) + m floor(...)
+ *
+ * with e(i) the expression derived above and floor(...) the integer
+ * division involving output dimensions.
+ * From
+ *
+ * l <= x <= l + n,
+ *
+ * we have
+ *
+ * 0 <= x - l <= n
+ *
+ * This means
+ *
+ * e(i) + m floor(...) - l = (e(i) + m floor(...) - l) mod m
+ * = (e(i) - l) mod m
+ *
+ * Therefore,
+ *
+ * x - l = (e(i) - l) mod m
+ *
+ * or
+ *
+ * x = ((e(i) - l) mod m) + l
+ *
+ * The variable "shift" below contains the expression -l, which may
+ * also involve a linear combination of earlier output dimensions.
+ */
+static __isl_give isl_aff *extract_aff_from_equality(
+ __isl_keep isl_basic_map *bmap, int pos, int eq, int div, int ineq,
+ __isl_keep isl_multi_aff *ma)
+{
+ unsigned o_out;
+ unsigned n_div, n_out;
+ isl_ctx *ctx;
+ isl_local_space *ls;
+ isl_aff *aff, *shift;
+ isl_val *mod;
+
+ ctx = isl_basic_map_get_ctx(bmap);
+ ls = isl_basic_map_get_local_space(bmap);
+ ls = isl_local_space_domain(ls);
+ aff = isl_aff_alloc(isl_local_space_copy(ls));
+ if (!aff)
+ goto error;
+ o_out = isl_basic_map_offset(bmap, isl_dim_out);
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ if (isl_int_is_neg(bmap->eq[eq][o_out + pos])) {
+ isl_seq_cpy(aff->v->el + 1, bmap->eq[eq], o_out);
+ isl_seq_cpy(aff->v->el + 1 + o_out,
+ bmap->eq[eq] + o_out + n_out, n_div);
+ } else {
+ isl_seq_neg(aff->v->el + 1, bmap->eq[eq], o_out);
+ isl_seq_neg(aff->v->el + 1 + o_out,
+ bmap->eq[eq] + o_out + n_out, n_div);
+ }
+ if (div < n_div)
+ isl_int_set_si(aff->v->el[1 + o_out + div], 0);
+ isl_int_abs(aff->v->el[0], bmap->eq[eq][o_out + pos]);
+ aff = subtract_initial(aff, ma, pos, bmap->eq[eq] + o_out,
+ bmap->eq[eq][o_out + pos]);
+ if (div < n_div) {
+ shift = isl_aff_alloc(isl_local_space_copy(ls));
+ if (!shift)
+ goto error;
+ isl_seq_cpy(shift->v->el + 1, bmap->ineq[ineq], o_out);
+ isl_seq_cpy(shift->v->el + 1 + o_out,
+ bmap->ineq[ineq] + o_out + n_out, n_div);
+ isl_int_set_si(shift->v->el[0], 1);
+ shift = subtract_initial(shift, ma, pos,
+ bmap->ineq[ineq] + o_out, ctx->negone);
+ aff = isl_aff_add(aff, isl_aff_copy(shift));
+ mod = isl_val_int_from_isl_int(ctx,
+ bmap->eq[eq][o_out + n_out + div]);
+ mod = isl_val_abs(mod);
+ aff = isl_aff_mod_val(aff, mod);
+ aff = isl_aff_sub(aff, shift);
+ }
+
+ isl_local_space_free(ls);
+ return aff;
+error:
+ isl_local_space_free(ls);
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Given a basic map with output dimensions defined
+ * in terms of the parameters input dimensions and earlier
+ * output dimensions using an equality (and possibly a pair on inequalities),
+ * extract an isl_aff that expresses output dimension "pos" in terms
* of the parameters and input dimensions.
* Note that this expression may involve integer divisions defined
* in terms of parameters and input dimensions.
+ * "ma" contains the expressions corresponding to earlier output dimensions.
*
* This function shares some similarities with
* isl_basic_map_has_defining_equality and isl_constraint_get_bound.
*/
static __isl_give isl_aff *extract_isl_aff_from_basic_map(
- __isl_take isl_basic_map *bmap)
+ __isl_keep isl_basic_map *bmap, int pos, __isl_keep isl_multi_aff *ma)
{
- int eq;
- unsigned offset;
- unsigned n_div;
- isl_local_space *ls;
+ int eq, div, ineq;
isl_aff *aff;
if (!bmap)
return NULL;
- if (isl_basic_map_dim(bmap, isl_dim_out) != 1)
- isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
- "basic map should have a single output dimension",
- goto error);
- eq = isl_basic_map_output_defining_equality(bmap, 0);
+ eq = isl_basic_map_output_defining_equality(bmap, pos, &div, &ineq);
if (eq >= bmap->n_eq)
isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
- "unable to find suitable equality", goto error);
- ls = isl_basic_map_get_local_space(bmap);
- aff = isl_aff_alloc(isl_local_space_domain(ls));
- if (!aff)
- goto error;
- offset = isl_basic_map_offset(bmap, isl_dim_out);
- n_div = isl_basic_map_dim(bmap, isl_dim_div);
- if (isl_int_is_neg(bmap->eq[eq][offset])) {
- isl_seq_cpy(aff->v->el + 1, bmap->eq[eq], offset);
- isl_seq_cpy(aff->v->el + 1 + offset, bmap->eq[eq] + offset + 1,
- n_div);
- } else {
- isl_seq_neg(aff->v->el + 1, bmap->eq[eq], offset);
- isl_seq_neg(aff->v->el + 1 + offset, bmap->eq[eq] + offset + 1,
- n_div);
- }
- isl_int_abs(aff->v->el[0], bmap->eq[eq][offset]);
- isl_basic_map_free(bmap);
+ "unable to find suitable equality", return NULL);
+ aff = extract_aff_from_equality(bmap, pos, eq, div, ineq, ma);
aff = isl_aff_remove_unused_divs(aff);
return aff;
-error:
- isl_basic_map_free(bmap);
- return NULL;
}
/* Given a basic map where each output dimension is defined
@@ -4474,14 +4593,9 @@ static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map(
n_out = isl_basic_map_dim(bmap, isl_dim_out);
for (i = 0; i < n_out; ++i) {
- isl_basic_map *bmap_i;
isl_aff *aff;
- bmap_i = isl_basic_map_copy(bmap);
- bmap_i = isl_basic_map_project_out(bmap_i, isl_dim_out,
- i + 1, n_out - (1 + i));
- bmap_i = isl_basic_map_project_out(bmap_i, isl_dim_out, 0, i);
- aff = extract_isl_aff_from_basic_map(bmap_i);
+ aff = extract_isl_aff_from_basic_map(bmap, i, ma);
ma = isl_multi_aff_set_aff(ma, i, aff);
}
@@ -4509,12 +4623,22 @@ __isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities(
* Since some applications expect the result of isl_pw_multi_aff_from_map
* to only contain integer affine expressions, we compute the floor
* of the expression before returning.
+ *
+ * Remove all constraints involving local variables without
+ * an explicit representation (resulting in the removal of those
+ * local variables) prior to the actual extraction to ensure
+ * that the local spaces in which the resulting affine expressions
+ * are created do not contain any unknown local variables.
+ * Removing such constraints is safe because constraints involving
+ * unknown local variables are not used to determine whether
+ * a basic map is obviously single-valued.
*/
static __isl_give isl_pw_multi_aff *plain_pw_multi_aff_from_map(
__isl_take isl_set *domain, __isl_take isl_basic_map *bmap)
{
isl_multi_aff *ma;
+ bmap = isl_basic_map_drop_constraint_involving_unknown_divs(bmap);
ma = extract_isl_multi_aff_from_basic_map(bmap);
ma = isl_multi_aff_floor(ma);
return isl_pw_multi_aff_alloc(domain, ma);
@@ -4821,7 +4945,7 @@ static __isl_give isl_multi_aff *range_map(__isl_take isl_aff *aff, int d,
*
* We basically plug (1) into "map", resulting in a map with "a"
* in the range instead of "x". The corresponding isl_pw_multi_aff
- * defining "a" is then plugged back into (1) to obtain a definition fro "x".
+ * defining "a" is then plugged back into (1) to obtain a definition for "x".
*
* Specifically, given the input map
*
@@ -4935,8 +5059,8 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride(
*
* x = m a + f(..)
*
- * with m greater than 1, a some combination of existentiall quantified
- * variables and f and expression in the parameters and input dimensions.
+ * with m greater than 1, a some combination of existentially quantified
+ * variables and f an expression in the parameters and input dimensions.
* If so, we remove the stride in pw_multi_aff_from_map_stride.
*
* Otherwise, we continue with pw_multi_aff_from_map_check_div for a further
@@ -4945,7 +5069,7 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride(
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map)
{
int i, j;
- int sv;
+ isl_bool sv;
isl_basic_map *hull;
unsigned n_out;
unsigned o_out;
@@ -4956,7 +5080,8 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map)
if (!map)
return NULL;
- hull = isl_map_affine_hull(isl_map_copy(map));
+ map = isl_map_detect_equalities(map);
+ hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
sv = isl_basic_map_plain_is_single_valued(hull);
if (sv >= 0 && sv)
return plain_pw_multi_aff_from_map(isl_map_domain(map), hull);
@@ -5743,23 +5868,23 @@ struct isl_union_pw_multi_aff_bin_data {
isl_union_pw_multi_aff *upma2;
isl_union_pw_multi_aff *res;
isl_pw_multi_aff *pma;
- isl_stat (*fn)(void **entry, void *user);
+ isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user);
};
/* Given an isl_pw_multi_aff from upma1, store it in data->pma
* and call data->fn for each isl_pw_multi_aff in data->upma2.
*/
-static isl_stat bin_entry(void **entry, void *user)
+static isl_stat bin_entry(__isl_take isl_pw_multi_aff *pma, void *user)
{
struct isl_union_pw_multi_aff_bin_data *data = user;
- isl_pw_multi_aff *pma = *entry;
+ isl_stat r;
data->pma = pma;
- if (isl_hash_table_foreach(data->upma2->space->ctx, &data->upma2->table,
- data->fn, data) < 0)
- return isl_stat_error;
+ r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma2,
+ data->fn, data);
+ isl_pw_multi_aff_free(pma);
- return isl_stat_ok;
+ return r;
}
/* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2".
@@ -5770,7 +5895,7 @@ static isl_stat bin_entry(void **entry, void *user)
static __isl_give isl_union_pw_multi_aff *bin_op(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2,
- isl_stat (*fn)(void **entry, void *user))
+ isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user))
{
isl_space *space;
struct isl_union_pw_multi_aff_bin_data data = { NULL, NULL, NULL, fn };
@@ -5784,9 +5909,8 @@ static __isl_give isl_union_pw_multi_aff *bin_op(
goto error;
data.upma2 = upma2;
- data.res = isl_union_pw_multi_aff_alloc(isl_space_copy(upma1->space),
- upma1->table.n);
- if (isl_hash_table_foreach(upma1->space->ctx, &upma1->table,
+ data.res = isl_union_pw_multi_aff_alloc_same_size(upma1);
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma1,
&bin_entry, &data) < 0)
goto error;
@@ -5849,21 +5973,22 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product(
&pw_multi_aff_flat_range_product);
}
-/* If data->pma and *entry have the same domain space, then compute
+/* If data->pma and "pma2" have the same domain space, then compute
* their flat range product and the result to data->res.
*/
-static isl_stat flat_range_product_entry(void **entry, void *user)
+static isl_stat flat_range_product_entry(__isl_take isl_pw_multi_aff *pma2,
+ void *user)
{
struct isl_union_pw_multi_aff_bin_data *data = user;
- isl_pw_multi_aff *pma2 = *entry;
if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
- pma2->dim, isl_dim_in))
+ pma2->dim, isl_dim_in)) {
+ isl_pw_multi_aff_free(pma2);
return isl_stat_ok;
+ }
pma2 = isl_pw_multi_aff_flat_range_product(
- isl_pw_multi_aff_copy(data->pma),
- isl_pw_multi_aff_copy(pma2));
+ isl_pw_multi_aff_copy(data->pma), pma2);
data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
@@ -6026,6 +6151,7 @@ error:
#include <isl_multi_templ.c>
#include <isl_multi_apply_set.c>
+#include <isl_multi_coalesce.c>
#include <isl_multi_gist.c>
#include <isl_multi_intersect.c>
@@ -6068,40 +6194,26 @@ error:
return NULL;
}
-/* Internal data structure for isl_union_pw_multi_aff_scale_multi_val.
- * mv contains the mv argument.
- * res collects the results.
- */
-struct isl_union_pw_multi_aff_scale_multi_val_data {
- isl_multi_val *mv;
- isl_union_pw_multi_aff *res;
-};
-
/* This function is called for each entry of an isl_union_pw_multi_aff.
* If the space of the entry matches that of data->mv,
- * then apply isl_pw_multi_aff_scale_multi_val and add the result
- * to data->res.
+ * then apply isl_pw_multi_aff_scale_multi_val and return the result.
+ * Otherwise, return an empty isl_pw_multi_aff.
*/
-static isl_stat union_pw_multi_aff_scale_multi_val_entry(void **entry,
- void *user)
+static __isl_give isl_pw_multi_aff *union_pw_multi_aff_scale_multi_val_entry(
+ __isl_take isl_pw_multi_aff *pma, void *user)
{
- struct isl_union_pw_multi_aff_scale_multi_val_data *data = user;
- isl_pw_multi_aff *pma = *entry;
+ isl_multi_val *mv = user;
if (!pma)
- return isl_stat_error;
+ return NULL;
if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
- data->mv->space, isl_dim_set))
- return isl_stat_ok;
-
- pma = isl_pw_multi_aff_copy(pma);
- pma = isl_pw_multi_aff_scale_multi_val(pma,
- isl_multi_val_copy(data->mv));
- data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
- if (!data->res)
- return isl_stat_error;
+ mv->space, isl_dim_set)) {
+ isl_space *space = isl_pw_multi_aff_get_space(pma);
+ isl_pw_multi_aff_free(pma);
+ return isl_pw_multi_aff_empty(space);
+ }
- return isl_stat_ok;
+ return isl_pw_multi_aff_scale_multi_val(pma, isl_multi_val_copy(mv));
}
/* Scale the elements of "upma" by the corresponding elements of "mv",
@@ -6110,8 +6222,6 @@ static isl_stat union_pw_multi_aff_scale_multi_val_entry(void **entry,
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
__isl_take isl_union_pw_multi_aff *upma, __isl_take isl_multi_val *mv)
{
- struct isl_union_pw_multi_aff_scale_multi_val_data data;
-
upma = isl_union_pw_multi_aff_align_params(upma,
isl_multi_val_get_space(mv));
mv = isl_multi_val_align_params(mv,
@@ -6119,16 +6229,11 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
if (!upma || !mv)
goto error;
- data.mv = mv;
- data.res = isl_union_pw_multi_aff_alloc(isl_space_copy(upma->space),
- upma->table.n);
- if (isl_hash_table_foreach(upma->space->ctx, &upma->table,
- &union_pw_multi_aff_scale_multi_val_entry, &data) < 0)
- goto error;
+ return isl_union_pw_multi_aff_transform(upma,
+ &union_pw_multi_aff_scale_multi_val_entry, mv);
isl_multi_val_free(mv);
- isl_union_pw_multi_aff_free(upma);
- return data.res;
+ return upma;
error:
isl_multi_val_free(mv);
isl_union_pw_multi_aff_free(upma);
@@ -6417,32 +6522,6 @@ isl_bool isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1,
return isl_bool_true;
}
-/* Coalesce the elements of "mpa".
- *
- * Note that such coalescing does not change the meaning of "mpa"
- * so there is no need to cow. We do need to be careful not to
- * destroy any other copies of "mpa" in case of failure.
- */
-__isl_give isl_multi_pw_aff *isl_multi_pw_aff_coalesce(
- __isl_take isl_multi_pw_aff *mpa)
-{
- int i;
-
- if (!mpa)
- return NULL;
-
- for (i = 0; i < mpa->n; ++i) {
- isl_pw_aff *pa = isl_pw_aff_copy(mpa->p[i]);
- pa = isl_pw_aff_coalesce(pa);
- if (!pa)
- return isl_multi_pw_aff_free(mpa);
- isl_pw_aff_free(mpa->p[i]);
- mpa->p[i] = pa;
- }
-
- return mpa;
-}
-
/* Compute the pullback of "mpa" by the function represented by "ma".
* In other words, plug in "ma" in "mpa".
*
@@ -7161,18 +7240,18 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_multi_val_on_domain(
/* Compute the pullback of data->pma by the function represented by "pma2",
* provided the spaces match, and add the results to data->res.
*/
-static isl_stat pullback_entry(void **entry, void *user)
+static isl_stat pullback_entry(__isl_take isl_pw_multi_aff *pma2, void *user)
{
struct isl_union_pw_multi_aff_bin_data *data = user;
- isl_pw_multi_aff *pma2 = *entry;
if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
- pma2->dim, isl_dim_out))
+ pma2->dim, isl_dim_out)) {
+ isl_pw_multi_aff_free(pma2);
return isl_stat_ok;
+ }
pma2 = isl_pw_multi_aff_pullback_pw_multi_aff(
- isl_pw_multi_aff_copy(data->pma),
- isl_pw_multi_aff_copy(pma2));
+ isl_pw_multi_aff_copy(data->pma), pma2);
data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
if (!data->res)
@@ -7308,18 +7387,11 @@ static __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_domain_space(
return data.res;
}
-/* Replace the entry of isl_union_pw_aff to which "entry" points
- * by its floor.
+/* Return the floor of "pa".
*/
-static isl_stat floor_entry(void **entry, void *user)
+static __isl_give isl_pw_aff *floor_entry(__isl_take isl_pw_aff *pa, void *user)
{
- isl_pw_aff **pa = (isl_pw_aff **) entry;
-
- *pa = isl_pw_aff_floor(*pa);
- if (!*pa)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return isl_pw_aff_floor(pa);
}
/* Given f, return floor(f).
@@ -7327,17 +7399,7 @@ static isl_stat floor_entry(void **entry, void *user)
__isl_give isl_union_pw_aff *isl_union_pw_aff_floor(
__isl_take isl_union_pw_aff *upa)
{
- isl_ctx *ctx;
-
- upa = isl_union_pw_aff_cow(upa);
- if (!upa)
- return NULL;
-
- ctx = isl_union_pw_aff_get_ctx(upa);
- if (isl_hash_table_foreach(ctx, &upa->table, &floor_entry, NULL) < 0)
- upa = isl_union_pw_aff_free(upa);
-
- return upa;
+ return isl_union_pw_aff_transform_inplace(upa, &floor_entry, NULL);
}
/* Compute
@@ -7661,17 +7723,17 @@ struct isl_union_pw_aff_pullback_upma_data {
/* Check if "pma" can be plugged into data->pa.
* If so, perform the pullback and add the result to data->res.
*/
-static isl_stat pa_pb_pma(void **entry, void *user)
+static isl_stat pa_pb_pma(__isl_take isl_pw_multi_aff *pma, void *user)
{
struct isl_union_pw_aff_pullback_upma_data *data = user;
- isl_pw_multi_aff *pma = *entry;
isl_pw_aff *pa;
if (!isl_space_tuple_is_equal(data->pa->dim, isl_dim_in,
- pma->dim, isl_dim_out))
+ pma->dim, isl_dim_out)) {
+ isl_pw_multi_aff_free(pma);
return isl_stat_ok;
+ }
- pma = isl_pw_multi_aff_copy(pma);
pa = isl_pw_aff_copy(data->pa);
pa = isl_pw_aff_pullback_pw_multi_aff(pa, pma);
@@ -7683,19 +7745,17 @@ static isl_stat pa_pb_pma(void **entry, void *user)
/* Check if any of the elements of data->upma can be plugged into pa,
* add if so add the result to data->res.
*/
-static isl_stat upa_pb_upma(void **entry, void *user)
+static isl_stat upa_pb_upma(__isl_take isl_pw_aff *pa, void *user)
{
struct isl_union_pw_aff_pullback_upma_data *data = user;
- isl_ctx *ctx;
- isl_pw_aff *pa = *entry;
+ isl_stat r;
data->pa = pa;
- ctx = isl_union_pw_multi_aff_get_ctx(data->upma);
- if (isl_hash_table_foreach(ctx, &data->upma->table,
- &pa_pb_pma, data) < 0)
- return isl_stat_error;
+ r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma,
+ &pa_pb_pma, data);
+ isl_pw_aff_free(pa);
- return isl_stat_ok;
+ return r;
}
/* Compute the pullback of "upa" by the function represented by "upma".
@@ -7713,7 +7773,6 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
__isl_take isl_union_pw_multi_aff *upma)
{
struct isl_union_pw_aff_pullback_upma_data data = { NULL, NULL };
- isl_ctx *ctx;
isl_space *space;
space = isl_union_pw_multi_aff_get_space(upma);
@@ -7724,11 +7783,9 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
if (!upa || !upma)
goto error;
- ctx = isl_union_pw_aff_get_ctx(upa);
data.upma = upma;
- space = isl_union_pw_aff_get_space(upa);
- data.res = isl_union_pw_aff_alloc(space, upa->table.n);
- if (isl_hash_table_foreach(ctx, &upa->table, &upa_pb_upma, &data) < 0)
+ data.res = isl_union_pw_aff_alloc_same_size(upa);
+ if (isl_union_pw_aff_foreach_pw_aff(upa, &upa_pb_upma, &data) < 0)
data.res = isl_union_pw_aff_free(data.res);
isl_union_pw_aff_free(upa);
@@ -7757,6 +7814,7 @@ error:
#include <isl_multi_templ.c>
#include <isl_multi_apply_set.c>
#include <isl_multi_apply_union_set.c>
+#include <isl_multi_coalesce.c>
#include <isl_multi_floor.c>
#include <isl_multi_gist.c>
#include <isl_multi_intersect.c>
diff --git a/isl_affine_hull.c b/isl_affine_hull.c
index e7bde3f6..3f219016 100644
--- a/isl_affine_hull.c
+++ b/isl_affine_hull.c
@@ -652,6 +652,9 @@ __isl_give isl_map *isl_map_drop_constraints_involving_dims(
return isl_map_free(map);
}
+ if (map->n > 1)
+ ISL_F_CLR(map, ISL_MAP_DISJOINT);
+
return map;
}
@@ -1160,6 +1163,15 @@ __isl_give isl_basic_map *isl_basic_map_plain_affine_hull(
return bmap;
}
+/* Return the superset of "bset" described by the equalities
+ * satisfied by "bset" that are already known.
+ */
+__isl_give isl_basic_set *isl_basic_set_plain_affine_hull(
+ __isl_take isl_basic_set *bset)
+{
+ return isl_basic_map_plain_affine_hull(bset);
+}
+
/* After computing the rational affine hull (by detecting the implicit
* equalities), we compute the additional equalities satisfied by
* the integer points (if any) and add the original equalities back in.
diff --git a/isl_arg.c b/isl_arg.c
index 70d1b345..4798a421 100644
--- a/isl_arg.c
+++ b/isl_arg.c
@@ -13,6 +13,7 @@
#include <isl/arg.h>
#include <isl/ctx.h>
+#include <isl_config.h>
static struct isl_arg help_arg[] = {
ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit")
@@ -811,7 +812,8 @@ static int parse_choice_option(struct isl_arg *decl, char **arg,
if (!has_argument && (!arg[1] || arg[1][0] == '-')) {
unsigned u = decl->u.choice.default_selected;
- *(unsigned *)(((char *)opt) + decl->offset) = u;
+ if (decl->offset != (size_t) -1)
+ *(unsigned *)(((char *)opt) + decl->offset) = u;
if (decl->u.choice.set)
decl->u.choice.set(opt, u);
@@ -828,7 +830,8 @@ static int parse_choice_option(struct isl_arg *decl, char **arg,
continue;
u = decl->u.choice.choice[i].value;
- *(unsigned *)(((char *)opt) + decl->offset) = u;
+ if (decl->offset != (size_t) -1)
+ *(unsigned *)(((char *)opt) + decl->offset) = u;
if (decl->u.choice.set)
decl->u.choice.set(opt, u);
diff --git a/isl_ast.c b/isl_ast.c
index 0ac01f92..4aff82e7 100644
--- a/isl_ast.c
+++ b/isl_ast.c
@@ -1658,6 +1658,7 @@ static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
case isl_ast_node_mark:
p = isl_printer_print_str(p, "mark: ");
p = isl_printer_print_id(p, node->u.m.mark);
+ p = isl_printer_print_str(p, ", ");
p = isl_printer_print_str(p, "node: ");
p = isl_printer_print_ast_node(p, node->u.m.node);
case isl_ast_node_user:
diff --git a/isl_ast_build.c b/isl_ast_build.c
index 018d1154..ce7272c4 100644
--- a/isl_ast_build.c
+++ b/isl_ast_build.c
@@ -18,6 +18,7 @@
#include <isl/union_map.h>
#include <isl_ast_build_private.h>
#include <isl_ast_private.h>
+#include <isl_config.h>
/* Construct a map that isolates the current dimension.
*
@@ -824,6 +825,10 @@ static __isl_give isl_ast_build *update_values(
* Otherwise, we would indirectly intersect the build domain with itself,
* which can lead to inefficiencies, in particular if the build domain
* contains any unknown divs.
+ *
+ * The pending and generated sets are not updated by this function to
+ * match the updated domain.
+ * The caller still needs to call isl_ast_build_set_pending_generated.
*/
__isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
__isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
@@ -834,12 +839,10 @@ __isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
if (!build)
goto error;
- bounds = isl_basic_set_preimage_multi_aff(bounds,
- isl_multi_aff_copy(build->values));
build = update_values(build, isl_basic_set_copy(bounds));
if (!build)
goto error;
- set = isl_set_from_basic_set(isl_basic_set_copy(bounds));
+ set = isl_set_from_basic_set(bounds);
if (isl_ast_build_has_affine_value(build, build->depth)) {
set = isl_set_eliminate(set, isl_dim_set, build->depth, 1);
set = isl_set_compute_divs(set);
@@ -847,24 +850,11 @@ __isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
isl_set_copy(set));
build->domain = isl_set_intersect(build->domain, set);
} else {
- isl_basic_set *generated, *pending;
-
- pending = isl_basic_set_copy(bounds);
- pending = isl_basic_set_drop_constraints_involving_dims(pending,
- isl_dim_set, build->depth, 1);
- build->pending = isl_set_intersect(build->pending,
- isl_set_from_basic_set(pending));
- generated = isl_basic_set_copy(bounds);
- generated = isl_basic_set_drop_constraints_not_involving_dims(
- generated, isl_dim_set, build->depth, 1);
- build->generated = isl_set_intersect(build->generated,
- isl_set_from_basic_set(generated));
build->domain = isl_set_intersect(build->domain, set);
build = isl_ast_build_include_stride(build);
if (!build)
goto error;
}
- isl_basic_set_free(bounds);
if (!build->domain || !build->pending || !build->generated)
return isl_ast_build_free(build);
@@ -876,6 +866,49 @@ error:
return NULL;
}
+/* Update the pending and generated sets of "build" according to "bounds".
+ * If the build has an affine value at the current depth,
+ * then isl_ast_build_set_loop_bounds has already set the pending set.
+ * Otherwise, do it here.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_pending_generated(
+ __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
+{
+ isl_basic_set *generated, *pending;
+
+ if (!build)
+ goto error;
+
+ if (isl_ast_build_has_affine_value(build, build->depth)) {
+ isl_basic_set_free(bounds);
+ return build;
+ }
+
+ build = isl_ast_build_cow(build);
+ if (!build)
+ goto error;
+
+ pending = isl_basic_set_copy(bounds);
+ pending = isl_basic_set_drop_constraints_involving_dims(pending,
+ isl_dim_set, build->depth, 1);
+ build->pending = isl_set_intersect(build->pending,
+ isl_set_from_basic_set(pending));
+ generated = bounds;
+ generated = isl_basic_set_drop_constraints_not_involving_dims(
+ generated, isl_dim_set, build->depth, 1);
+ build->generated = isl_set_intersect(build->generated,
+ isl_set_from_basic_set(generated));
+
+ if (!build->pending || !build->generated)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_ast_build_free(build);
+ isl_basic_set_free(bounds);
+ return NULL;
+}
+
/* Intersect build->domain with "set", where "set" is specified
* in terms of the internal schedule domain.
*/
@@ -949,31 +982,6 @@ __isl_give isl_ast_build *isl_ast_build_replace_pending_by_guard(
return build;
}
-/* Intersect build->pending and build->domain with "set",
- * where "set" is specified in terms of the internal schedule domain.
- */
-__isl_give isl_ast_build *isl_ast_build_restrict_pending(
- __isl_take isl_ast_build *build, __isl_take isl_set *set)
-{
- set = isl_set_compute_divs(set);
- build = isl_ast_build_restrict_internal(build, isl_set_copy(set));
- build = isl_ast_build_cow(build);
- if (!build)
- goto error;
-
- build->pending = isl_set_intersect(build->pending, set);
- build->pending = isl_set_coalesce(build->pending);
-
- if (!build->pending)
- return isl_ast_build_free(build);
-
- return build;
-error:
- isl_ast_build_free(build);
- isl_set_free(set);
- return NULL;
-}
-
/* Intersect build->domain with "set", where "set" is specified
* in terms of the external schedule domain.
*/
@@ -2192,6 +2200,18 @@ __isl_give isl_set *isl_ast_build_specialize(__isl_keep isl_ast_build *build,
isl_multi_aff_copy(build->values));
}
+/* Plug in the known affine values of outer loop iterators in "bset".
+ */
+__isl_give isl_basic_set *isl_ast_build_specialize_basic_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
+{
+ if (!build)
+ return isl_basic_set_free(bset);
+
+ return isl_basic_set_preimage_multi_aff(bset,
+ isl_multi_aff_copy(build->values));
+}
+
/* Simplify the map "map" based on what we know about
* the iterators of already generated loops.
*
diff --git a/isl_ast_build_expr.c b/isl_ast_build_expr.c
index bdd70e79..f0dd22df 100644
--- a/isl_ast_build_expr.c
+++ b/isl_ast_build_expr.c
@@ -661,6 +661,12 @@ static int mod_constraint_is_simpler(struct isl_extract_mod_data *data,
* not to involve any coefficients that are multiples of d, "c" may
* very well involve such coefficients. This means that we may actually
* miss some cases.
+ *
+ * If the constant term is "too large", then the constraint is rejected,
+ * where "too large" is fairly arbitrarily set to 1 << 15.
+ * We do this to avoid picking up constraints that bound a variable
+ * by a very large number, say the largest or smallest possible
+ * variable in the representation of some integer type.
*/
static isl_stat check_parallel_or_opposite(__isl_take isl_constraint *c,
void *user)
@@ -684,6 +690,15 @@ static isl_stat check_parallel_or_opposite(__isl_take isl_constraint *c,
}
}
+ if (parallel || opposite) {
+ isl_val *v;
+
+ v = isl_val_abs(isl_constraint_get_constant_val(c));
+ if (isl_val_cmp_si(v, 1 << 15) > 0)
+ parallel = opposite = 0;
+ isl_val_free(v);
+ }
+
for (t = 0; t < 2; ++t) {
for (i = 0; i < n[t]; ++i) {
isl_val *v1, *v2;
@@ -1438,7 +1453,7 @@ __isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
return NULL;
n = isl_constraint_list_n_constraint(list);
if (n == 0) {
- isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+ isl_ctx *ctx = isl_constraint_list_get_ctx(list);
isl_constraint_list_free(list);
return isl_ast_expr_alloc_int_si(ctx, 1);
}
@@ -1467,55 +1482,73 @@ __isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
return res;
}
-struct isl_expr_from_set_data {
- isl_ast_build *build;
- int first;
- isl_ast_expr *res;
-};
-
-/* Construct an isl_ast_expr that evaluates the conditions defining "bset"
- * and add it to data->res.
- * The result is simplified in terms of data->build->domain.
- */
-static isl_stat expr_from_set(__isl_take isl_basic_set *bset, void *user)
-{
- struct isl_expr_from_set_data *data = user;
- isl_ast_expr *expr;
-
- expr = isl_ast_build_expr_from_basic_set(data->build, bset);
- if (data->first)
- data->res = expr;
- else
- data->res = isl_ast_expr_or(data->res, expr);
-
- data->first = 0;
-
- if (!data->res)
- return isl_stat_error;
- return isl_stat_ok;
-}
-
/* Construct an isl_ast_expr that evaluates the conditions defining "set".
* The result is simplified in terms of build->domain.
*
* If "set" is an (obviously) empty set, then return the expression "0".
*
+ * If there are multiple disjuncts in the description of the set,
+ * then subsequent disjuncts are simplified in a context where
+ * the previous disjuncts have been removed from build->domain.
+ * In particular, constraints that ensure that there is no overlap
+ * with these previous disjuncts, can be removed.
+ * This is mostly useful for disjuncts that are only defined by
+ * a single constraint (relative to the build domain) as the opposite
+ * of that single constraint can then be removed from the other disjuncts.
+ * In order not to increase the number of disjuncts in the build domain
+ * after subtracting the previous disjuncts of "set", the simple hull
+ * is computed after taking the difference with each of these disjuncts.
+ * This means that constraints that prevent overlap with a union
+ * of multiple previous disjuncts are not removed.
+ *
* "set" lives in the internal schedule space.
*/
__isl_give isl_ast_expr *isl_ast_build_expr_from_set_internal(
__isl_keep isl_ast_build *build, __isl_take isl_set *set)
{
- struct isl_expr_from_set_data data = { build, 1, NULL };
+ int i, n;
+ isl_basic_set *bset;
+ isl_basic_set_list *list;
+ isl_set *domain;
+ isl_ast_expr *res;
+
+ list = isl_set_get_basic_set_list(set);
+ isl_set_free(set);
- if (isl_set_foreach_basic_set(set, &expr_from_set, &data) < 0)
- data.res = isl_ast_expr_free(data.res);
- else if (data.first) {
+ if (!list)
+ return NULL;
+ n = isl_basic_set_list_n_basic_set(list);
+ if (n == 0) {
isl_ctx *ctx = isl_ast_build_get_ctx(build);
- data.res = isl_ast_expr_from_val(isl_val_zero(ctx));
+ isl_basic_set_list_free(list);
+ return isl_ast_expr_from_val(isl_val_zero(ctx));
}
+ domain = isl_ast_build_get_domain(build);
+
+ bset = isl_basic_set_list_get_basic_set(list, 0);
+ set = isl_set_from_basic_set(isl_basic_set_copy(bset));
+ res = isl_ast_build_expr_from_basic_set(build, bset);
+
+ for (i = 1; i < n; ++i) {
+ isl_ast_expr *expr;
+ isl_set *rest;
+
+ rest = isl_set_subtract(isl_set_copy(domain), set);
+ rest = isl_set_from_basic_set(isl_set_simple_hull(rest));
+ domain = isl_set_intersect(domain, rest);
+ bset = isl_basic_set_list_get_basic_set(list, i);
+ set = isl_set_from_basic_set(isl_basic_set_copy(bset));
+ bset = isl_basic_set_gist(bset,
+ isl_set_simple_hull(isl_set_copy(domain)));
+ expr = isl_ast_build_expr_from_basic_set(build, bset);
+ res = isl_ast_expr_or(res, expr);
+ }
+
+ isl_set_free(domain);
isl_set_free(set);
- return data.res;
+ isl_basic_set_list_free(list);
+ return res;
}
/* Construct an isl_ast_expr that evaluates the conditions defining "set".
diff --git a/isl_ast_build_private.h b/isl_ast_build_private.h
index 59eec25f..9cd010be 100644
--- a/isl_ast_build_private.h
+++ b/isl_ast_build_private.h
@@ -221,6 +221,8 @@ __isl_give isl_ast_build *isl_ast_build_product(
__isl_take isl_ast_build *build, __isl_take isl_space *embedding);
__isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
__isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds);
+__isl_give isl_ast_build *isl_ast_build_set_pending_generated(
+ __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds);
__isl_give isl_ast_build *isl_ast_build_detect_strides(
__isl_take isl_ast_build *build, __isl_take isl_set *set);
__isl_give isl_ast_build *isl_ast_build_include_stride(
@@ -242,8 +244,6 @@ __isl_give isl_ast_build *isl_ast_build_restrict_generated(
__isl_take isl_ast_build *build, __isl_take isl_set *set);
__isl_give isl_ast_build *isl_ast_build_replace_pending_by_guard(
__isl_take isl_ast_build *build, __isl_take isl_set *guard);
-__isl_give isl_ast_build *isl_ast_build_restrict_pending(
- __isl_take isl_ast_build *build, __isl_take isl_set *set);
__isl_give int isl_ast_build_need_schedule_map(
__isl_keep isl_ast_build *build);
__isl_give isl_multi_aff *isl_ast_build_get_schedule_map_multi_aff(
@@ -270,6 +270,8 @@ int isl_ast_build_has_isolated(__isl_keep isl_ast_build *build);
__isl_give isl_set *isl_ast_build_get_isolated(
__isl_keep isl_ast_build *build);
+__isl_give isl_basic_set *isl_ast_build_specialize_basic_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
__isl_give isl_basic_set *isl_ast_build_compute_gist_basic_set(
__isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
__isl_give isl_set *isl_ast_build_specialize(__isl_keep isl_ast_build *build,
diff --git a/isl_ast_codegen.c b/isl_ast_codegen.c
index fc8e2d7b..350a8402 100644
--- a/isl_ast_codegen.c
+++ b/isl_ast_codegen.c
@@ -109,6 +109,54 @@ static __isl_give isl_ast_graft *at_each_domain(__isl_take isl_ast_graft *graft,
return graft;
}
+/* Generate a call expression for the single executed
+ * domain element "map" and put a guard around it based its (simplified)
+ * domain. "executed" is the original inverse schedule from which "map"
+ * has been derived. In particular, "map" is either identical to "executed"
+ * or it is the result of gisting "executed" with respect to the build domain.
+ * "executed" is only used if there is an at_each_domain callback.
+ *
+ * At this stage, any pending constraints in the build can no longer
+ * be simplified with respect to any enforced constraints since
+ * the call node does not have any enforced constraints.
+ * Since all pending constraints not covered by any enforced constraints
+ * will be added as a guard to the graft in create_node_scaled,
+ * even in the eliminated case, the pending constraints
+ * can be considered to have been generated by outer constructs.
+ *
+ * If the user has set an at_each_domain callback, it is called
+ * on the constructed call expression node.
+ */
+static isl_stat add_domain(__isl_take isl_map *executed,
+ __isl_take isl_map *map, struct isl_generate_domain_data *data)
+{
+ isl_ast_build *build;
+ isl_ast_graft *graft;
+ isl_ast_graft_list *list;
+ isl_set *guard, *pending;
+
+ build = isl_ast_build_copy(data->build);
+ pending = isl_ast_build_get_pending(build);
+ build = isl_ast_build_replace_pending_by_guard(build, pending);
+
+ guard = isl_map_domain(isl_map_copy(map));
+ guard = isl_set_compute_divs(guard);
+ guard = isl_set_coalesce(guard);
+ guard = isl_set_gist(guard, isl_ast_build_get_generated(build));
+ guard = isl_ast_build_specialize(build, guard);
+
+ graft = isl_ast_graft_alloc_domain(map, build);
+ graft = at_each_domain(graft, executed, build);
+ isl_ast_build_free(build);
+ isl_map_free(executed);
+ graft = isl_ast_graft_add_guard(graft, guard, data->build);
+
+ list = isl_ast_graft_list_from_ast_graft(graft);
+ data->list = isl_ast_graft_list_concat(data->list, list);
+
+ return isl_stat_ok;
+}
+
/* Generate an AST for a single domain based on
* the inverse schedule "executed" and add it to data->list.
*
@@ -127,7 +175,11 @@ static __isl_give isl_ast_graft *at_each_domain(__isl_take isl_ast_graft *graft,
* On the other hand, we only perform the test after having taken the gist
* of the domain as the resulting map is the one from which the call
* expression is constructed. Using this map to construct the call
- * expression usually yields simpler results.
+ * expression usually yields simpler results in cases where the original
+ * map is not obviously single-valued.
+ * If the original map is obviously single-valued, then the gist
+ * operation is skipped.
+ *
* Because we perform the single-valuedness test on the gisted map,
* we may in rare cases fail to recognize that the inverse schedule
* is single-valued. This becomes problematic if this happens
@@ -137,29 +189,13 @@ static __isl_give isl_ast_graft *at_each_domain(__isl_take isl_ast_graft *graft,
* and revert to the ungisted map if the gisted map turns out not to be
* single-valued.
*
- * Otherwise, we generate a call expression for the single executed
- * domain element and put a guard around it based on the (simplified)
- * domain of "executed".
- *
- * At this stage, any pending constraints in the build can no longer
- * be simplified with respect to any enforced constraints since
- * the call node does not have any enforced constraints.
- * We therefore turn all pending constraints into guards
- * (after simplifying them with respect to the already generated
- * constraints) and add them to both the generated constraints
- * and the guard of the constructed graft. This guard will ensure
- * that the constraints are effectively generated.
- *
- * If the user has set an at_each_domain callback, it is called
- * on the constructed call expression node.
+ * Otherwise, call add_domain to generate a call expression (with guard) and
+ * to call the at_each_domain callback, if any.
*/
static isl_stat generate_domain(__isl_take isl_map *executed, void *user)
{
struct isl_generate_domain_data *data = user;
- isl_ast_build *build;
- isl_ast_graft *graft;
- isl_ast_graft_list *list;
- isl_set *guard, *domain;
+ isl_set *domain;
isl_map *map = NULL;
int empty, sv;
@@ -174,6 +210,12 @@ static isl_stat generate_domain(__isl_take isl_map *executed, void *user)
return isl_stat_ok;
}
+ sv = isl_map_plain_is_single_valued(executed);
+ if (sv < 0)
+ goto error;
+ if (sv)
+ return add_domain(executed, isl_map_copy(executed), data);
+
executed = isl_map_coalesce(executed);
map = isl_map_copy(executed);
map = isl_ast_build_compute_gist_map_domain(data->build, map);
@@ -187,27 +229,8 @@ static isl_stat generate_domain(__isl_take isl_map *executed, void *user)
else
return generate_non_single_valued(executed, data);
}
- guard = isl_map_domain(isl_map_copy(map));
- guard = isl_set_compute_divs(guard);
- guard = isl_set_intersect(guard,
- isl_ast_build_get_pending(data->build));
- guard = isl_set_coalesce(guard);
- guard = isl_ast_build_specialize(data->build, guard);
- guard = isl_set_gist(guard, isl_ast_build_get_generated(data->build));
- build = isl_ast_build_copy(data->build);
- build = isl_ast_build_replace_pending_by_guard(build,
- isl_set_copy(guard));
- graft = isl_ast_graft_alloc_domain(map, build);
- graft = at_each_domain(graft, executed, build);
- isl_ast_build_free(build);
- isl_map_free(executed);
- graft = isl_ast_graft_add_guard(graft, guard, data->build);
-
- list = isl_ast_graft_list_from_ast_graft(graft);
- data->list = isl_ast_graft_list_concat(data->list, list);
-
- return isl_stat_ok;
+ return add_domain(executed, map, data);
error:
isl_map_free(map);
isl_map_free(executed);
@@ -1449,12 +1472,18 @@ static __isl_give isl_ast_graft *create_node_scaled(
depth = isl_ast_build_get_depth(build);
sub_build = isl_ast_build_copy(build);
+ bounds = isl_basic_set_remove_redundancies(bounds);
+ bounds = isl_ast_build_specialize_basic_set(sub_build, bounds);
sub_build = isl_ast_build_set_loop_bounds(sub_build,
isl_basic_set_copy(bounds));
degenerate = isl_ast_build_has_value(sub_build);
eliminated = isl_ast_build_has_affine_value(sub_build, depth);
if (degenerate < 0 || eliminated < 0)
executed = isl_union_map_free(executed);
+ if (!degenerate)
+ bounds = isl_ast_build_compute_gist_basic_set(build, bounds);
+ sub_build = isl_ast_build_set_pending_generated(sub_build,
+ isl_basic_set_copy(bounds));
if (eliminated)
executed = plug_in_values(executed, sub_build);
else
@@ -1480,8 +1509,6 @@ static __isl_give isl_ast_graft *create_node_scaled(
graft = isl_ast_graft_alloc_from_children(children,
isl_set_copy(guard), enforced, build, sub_build);
- if (!degenerate)
- bounds = isl_ast_build_compute_gist_basic_set(build, bounds);
if (!eliminated) {
isl_ast_build *for_build;
@@ -2555,10 +2582,11 @@ static int foreach_iteration(__isl_take isl_set *domain,
int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
{
int i, n;
+ int empty;
int depth;
isl_multi_aff *expansion;
isl_basic_map *bmap;
- isl_aff *lower;
+ isl_aff *lower = NULL;
isl_ast_build *stride_build;
depth = isl_ast_build_get_depth(build);
@@ -2577,10 +2605,17 @@ static int foreach_iteration(__isl_take isl_set *domain,
bmap = isl_basic_map_from_multi_aff(expansion);
- lower = find_unroll_lower_bound(build, domain, depth, bmap, &n);
- if (!lower)
+ empty = isl_set_is_empty(domain);
+ if (empty < 0) {
n = -1;
- else if (init && init(n, user) < 0)
+ } else if (empty) {
+ n = 0;
+ } else {
+ lower = find_unroll_lower_bound(build, domain, depth, bmap, &n);
+ if (!lower)
+ n = -1;
+ }
+ if (n >= 0 && init && init(n, user) < 0)
n = -1;
for (i = 0; i < n; ++i) {
isl_set *set;
@@ -3263,18 +3298,76 @@ error:
return NULL;
}
+/* Extract out the disjunction imposed by "domain" on the outer
+ * schedule dimensions.
+ *
+ * In particular, remove all inner dimensions from "domain" (including
+ * the current dimension) and then remove the constraints that are shared
+ * by all disjuncts in the result.
+ */
+static __isl_give isl_set *extract_disjunction(__isl_take isl_set *domain,
+ __isl_keep isl_ast_build *build)
+{
+ isl_set *hull;
+ int depth, dim;
+
+ domain = isl_ast_build_specialize(build, domain);
+ depth = isl_ast_build_get_depth(build);
+ dim = isl_set_dim(domain, isl_dim_set);
+ domain = isl_set_eliminate(domain, isl_dim_set, depth, dim - depth);
+ domain = isl_set_remove_unknown_divs(domain);
+ hull = isl_set_copy(domain);
+ hull = isl_set_from_basic_set(isl_set_unshifted_simple_hull(hull));
+ domain = isl_set_gist(domain, hull);
+
+ return domain;
+}
+
+/* Add "guard" to the grafts in "list".
+ * "build" is the outer AST build, while "sub_build" includes "guard"
+ * in its generated domain.
+ *
+ * First combine the grafts into a single graft and then add the guard.
+ * If the list is empty, or if some error occurred, then simply return
+ * the list.
+ */
+static __isl_give isl_ast_graft_list *list_add_guard(
+ __isl_take isl_ast_graft_list *list, __isl_keep isl_set *guard,
+ __isl_keep isl_ast_build *build, __isl_keep isl_ast_build *sub_build)
+{
+ isl_ast_graft *graft;
+
+ list = isl_ast_graft_list_fuse(list, sub_build);
+
+ if (isl_ast_graft_list_n_ast_graft(list) != 1)
+ return list;
+
+ graft = isl_ast_graft_list_get_ast_graft(list, 0);
+ graft = isl_ast_graft_add_guard(graft, isl_set_copy(guard), build);
+ list = isl_ast_graft_list_set_ast_graft(list, 0, graft);
+
+ return list;
+}
+
/* Generate code for a single component, after shifting (if any)
* has been applied, in case the schedule was specified as a schedule tree.
* In particular, do so for the specified subset of the schedule domain.
+ *
+ * If we are outside of the isolated part, then "domain" may include
+ * a disjunction. Explicitly generate this disjunction at this point
+ * instead of relying on the disjunction getting hoisted back up
+ * to this level.
*/
static __isl_give isl_ast_graft_list *generate_shifted_component_tree_part(
__isl_keep isl_union_map *executed, __isl_take isl_set *domain,
__isl_keep isl_ast_build *build, int isolated)
{
isl_union_set *uset;
+ isl_ast_graft_list *list;
+ isl_ast_build *sub_build;
int empty;
- uset = isl_union_set_from_set(domain);
+ uset = isl_union_set_from_set(isl_set_copy(domain));
executed = isl_union_map_copy(executed);
executed = isl_union_map_intersect_domain(executed, uset);
empty = isl_union_map_is_empty(executed);
@@ -3283,19 +3376,99 @@ static __isl_give isl_ast_graft_list *generate_shifted_component_tree_part(
if (empty) {
isl_ctx *ctx;
isl_union_map_free(executed);
+ isl_set_free(domain);
ctx = isl_ast_build_get_ctx(build);
return isl_ast_graft_list_alloc(ctx, 0);
}
- build = isl_ast_build_copy(build);
- return generate_shifted_component_tree_base(executed, build, isolated);
+ sub_build = isl_ast_build_copy(build);
+ if (!isolated) {
+ domain = extract_disjunction(domain, build);
+ sub_build = isl_ast_build_restrict_generated(sub_build,
+ isl_set_copy(domain));
+ }
+ list = generate_shifted_component_tree_base(executed,
+ isl_ast_build_copy(sub_build), isolated);
+ if (!isolated)
+ list = list_add_guard(list, domain, build, sub_build);
+ isl_ast_build_free(sub_build);
+ isl_set_free(domain);
+ return list;
error:
isl_union_map_free(executed);
+ isl_set_free(domain);
return NULL;
}
/* Generate code for a single component, after shifting (if any)
* has been applied, in case the schedule was specified as a schedule tree.
+ * In particular, do so for the specified sequence of subsets
+ * of the schedule domain, "before", "isolated", "after" and "other",
+ * where only the "isolated" part is considered to be isolated.
+ */
+static __isl_give isl_ast_graft_list *generate_shifted_component_parts(
+ __isl_take isl_union_map *executed, __isl_take isl_set *before,
+ __isl_take isl_set *isolated, __isl_take isl_set *after,
+ __isl_take isl_set *other, __isl_take isl_ast_build *build)
+{
+ isl_ast_graft_list *list, *res;
+
+ res = generate_shifted_component_tree_part(executed, before, build, 0);
+ list = generate_shifted_component_tree_part(executed, isolated,
+ build, 1);
+ res = isl_ast_graft_list_concat(res, list);
+ list = generate_shifted_component_tree_part(executed, after, build, 0);
+ res = isl_ast_graft_list_concat(res, list);
+ list = generate_shifted_component_tree_part(executed, other, build, 0);
+ res = isl_ast_graft_list_concat(res, list);
+
+ isl_union_map_free(executed);
+ isl_ast_build_free(build);
+
+ return res;
+}
+
+/* Does "set" intersect "first", but not "second"?
+ */
+static isl_bool only_intersects_first(__isl_keep isl_set *set,
+ __isl_keep isl_set *first, __isl_keep isl_set *second)
+{
+ isl_bool disjoint;
+
+ disjoint = isl_set_is_disjoint(set, first);
+ if (disjoint < 0)
+ return isl_bool_error;
+ if (disjoint)
+ return isl_bool_false;
+
+ return isl_set_is_disjoint(set, second);
+}
+
+/* Generate code for a single component, after shifting (if any)
+ * has been applied, in case the schedule was specified as a schedule tree.
+ * In particular, do so in case of isolation where there is
+ * only an "isolated" part and an "after" part.
+ * "dead1" and "dead2" are freed by this function in order to simplify
+ * the caller.
+ *
+ * The "before" and "other" parts are set to empty sets.
+ */
+static __isl_give isl_ast_graft_list *generate_shifted_component_only_after(
+ __isl_take isl_union_map *executed, __isl_take isl_set *isolated,
+ __isl_take isl_set *after, __isl_take isl_ast_build *build,
+ __isl_take isl_set *dead1, __isl_take isl_set *dead2)
+{
+ isl_set *empty;
+
+ empty = isl_set_empty(isl_set_get_space(after));
+ isl_set_free(dead1);
+ isl_set_free(dead2);
+ return generate_shifted_component_parts(executed, isl_set_copy(empty),
+ isolated, after, empty, build);
+}
+
+/* Generate code for a single component, after shifting (if any)
+ * has been applied, in case the schedule was specified as a schedule tree.
*
* We first check if the user has specified an isolated schedule domain
* and that we are not already outside of this isolated schedule domain.
@@ -3305,6 +3478,14 @@ error:
* the remaining iterations (those that are incomparable
* to the isolated domain).
* We generate an AST for each piece and concatenate the results.
+ *
+ * In the special case where at least one element of the schedule
+ * domain that does not belong to the isolated domain needs
+ * to be scheduled after this isolated domain, but none of those
+ * elements need to be scheduled before, break up the schedule domain
+ * in only two parts, the isolated domain, and a part that will be
+ * scheduled after the isolated domain.
+ *
* If no isolated set has been specified, then we generate an
* AST for the entire inverse schedule.
*/
@@ -3319,7 +3500,7 @@ static __isl_give isl_ast_graft_list *generate_shifted_component_tree(
isl_basic_set *hull;
isl_set *isolated, *before, *after, *test;
isl_map *gt, *lt;
- isl_ast_graft_list *list, *res;
+ isl_bool pure;
build = isl_ast_build_extract_isolated(build);
has_isolate = isl_ast_build_has_isolated(build);
@@ -3358,25 +3539,20 @@ static __isl_give isl_ast_graft_list *generate_shifted_component_tree(
after = isl_set_apply(isl_set_copy(isolated), lt);
domain = isl_set_subtract(domain, isl_set_copy(isolated));
+ pure = only_intersects_first(domain, after, before);
+ if (pure < 0)
+ executed = isl_union_map_free(executed);
+ else if (pure)
+ return generate_shifted_component_only_after(executed, isolated,
+ domain, build, before, after);
domain = isl_set_subtract(domain, isl_set_copy(before));
domain = isl_set_subtract(domain, isl_set_copy(after));
after = isl_set_subtract(after, isl_set_copy(isolated));
after = isl_set_subtract(after, isl_set_copy(before));
before = isl_set_subtract(before, isl_set_copy(isolated));
- res = generate_shifted_component_tree_part(executed, before, build, 0);
- list = generate_shifted_component_tree_part(executed, isolated,
- build, 1);
- res = isl_ast_graft_list_concat(res, list);
- list = generate_shifted_component_tree_part(executed, after, build, 0);
- res = isl_ast_graft_list_concat(res, list);
- list = generate_shifted_component_tree_part(executed, domain, build, 0);
- res = isl_ast_graft_list_concat(res, list);
-
- isl_union_map_free(executed);
- isl_ast_build_free(build);
-
- return res;
+ return generate_shifted_component_parts(executed, before, isolated,
+ after, domain, build);
error:
isl_set_free(domain);
isl_set_free(isolated);
@@ -5080,6 +5256,7 @@ static __isl_give isl_ast_graft_list *build_ast_from_extension(
isl_set *set;
set = isl_ast_build_get_generated(build);
+ set = isl_set_from_basic_set(isl_set_simple_hull(set));
schedule_domain = isl_union_set_from_set(set);
extension = isl_schedule_node_extension_get_extension(node);
@@ -5105,6 +5282,11 @@ static __isl_give isl_ast_graft_list *build_ast_from_extension(
* with the filter and continue with the descendants of the node,
* unless the resulting inverse schedule is empty, in which
* case we return an empty list.
+ *
+ * If the result of the intersection is equal to the original "executed"
+ * relation, then keep the original representation since the intersection
+ * may have unnecessarily broken up the relation into a greater number
+ * of disjuncts.
*/
static __isl_give isl_ast_graft_list *build_ast_from_filter(
__isl_take isl_ast_build *build, __isl_take isl_schedule_node *node,
@@ -5112,10 +5294,13 @@ static __isl_give isl_ast_graft_list *build_ast_from_filter(
{
isl_ctx *ctx;
isl_union_set *filter;
+ isl_union_map *orig;
isl_ast_graft_list *list;
int empty;
+ isl_bool unchanged;
unsigned n1, n2;
+ orig = isl_union_map_copy(executed);
if (!build || !node || !executed)
goto error;
@@ -5130,9 +5315,15 @@ static __isl_give isl_ast_graft_list *build_ast_from_filter(
"filter node is not allowed to introduce "
"new parameters", goto error);
+ unchanged = isl_union_map_is_subset(orig, executed);
empty = isl_union_map_is_empty(executed);
- if (empty < 0)
+ if (unchanged < 0 || empty < 0)
goto error;
+ if (unchanged) {
+ isl_union_map_free(executed);
+ return build_ast_from_child(build, node, orig);
+ }
+ isl_union_map_free(orig);
if (!empty)
return build_ast_from_child(build, node, executed);
@@ -5146,6 +5337,7 @@ error:
isl_ast_build_free(build);
isl_schedule_node_free(node);
isl_union_map_free(executed);
+ isl_union_map_free(orig);
return NULL;
}
diff --git a/isl_ast_graft.c b/isl_ast_graft.c
index cfcfbd38..6d90dd2b 100644
--- a/isl_ast_graft.c
+++ b/isl_ast_graft.c
@@ -719,7 +719,7 @@ static __isl_give isl_ast_node_list *extract_node_list(
/* Look for shared enforced constraints by all the elements in "list"
* on outer loops (with respect to the current depth) and return the result.
*
- * We assume that the number of children is at least one.
+ * If there are no elements in "list", then return the empty set.
*/
__isl_give isl_basic_set *isl_ast_graft_list_extract_shared_enforced(
__isl_keep isl_ast_graft_list *list,
@@ -733,16 +733,11 @@ __isl_give isl_basic_set *isl_ast_graft_list_extract_shared_enforced(
if (!list)
return NULL;
- n = isl_ast_graft_list_n_ast_graft(list);
- if (n == 0)
- isl_die(isl_ast_graft_list_get_ctx(list), isl_error_invalid,
- "for node should have at least one child",
- return NULL);
-
space = isl_ast_build_get_space(build, 1);
enforced = isl_basic_set_empty(space);
depth = isl_ast_build_get_depth(build);
+ n = isl_ast_graft_list_n_ast_graft(list);
for (i = 0; i < n; ++i) {
isl_ast_graft *graft;
diff --git a/isl_coalesce.c b/isl_coalesce.c
index 5e7f9a8d..e7a1863f 100644
--- a/isl_coalesce.c
+++ b/isl_coalesce.c
@@ -1689,7 +1689,7 @@ static int shift_div(struct isl_coalesce_info *info, int div, isl_int shift)
{
unsigned total;
- info->bmap = isl_basic_map_shift_div(info->bmap, div, shift);
+ info->bmap = isl_basic_map_shift_div(info->bmap, div, 0, shift);
if (!info->bmap)
return -1;
@@ -2142,18 +2142,26 @@ error:
return NULL;
}
-/* Add variables to "tab" corresponding to the elements in "list"
- * that are not set to NaN.
+/* Add variables to info->bmap and info->tab corresponding to the elements
+ * in "list" that are not set to NaN.
+ * "extra_var" is the number of these elements.
* "dim" is the offset in the variables of "tab" where we should
* start considering the elements in "list".
* When this function returns, the total number of variables in "tab"
* is equal to "dim" plus the number of elements in "list".
*/
-static int add_sub_vars(struct isl_tab *tab, __isl_keep isl_aff_list *list,
- int dim)
+static int add_sub_vars(struct isl_coalesce_info *info,
+ __isl_keep isl_aff_list *list, int dim, int extra_var)
{
- int i, n;
+ int i, j, n;
+ isl_space *space;
+ space = isl_basic_map_get_space(info->bmap);
+ info->bmap = isl_basic_map_cow(info->bmap);
+ info->bmap = isl_basic_map_extend_space(info->bmap, space,
+ extra_var, 0, 0);
+ if (!info->bmap)
+ return -1;
n = isl_aff_list_n_aff(list);
for (i = 0; i < n; ++i) {
int is_nan;
@@ -2164,9 +2172,15 @@ static int add_sub_vars(struct isl_tab *tab, __isl_keep isl_aff_list *list,
isl_aff_free(aff);
if (is_nan < 0)
return -1;
+ if (is_nan)
+ continue;
- if (!is_nan && isl_tab_insert_var(tab, dim + i) < 0)
+ if (isl_tab_insert_var(info->tab, dim + i) < 0)
+ return -1;
+ if (isl_basic_map_alloc_div(info->bmap) < 0)
return -1;
+ for (j = n - 1; j > i; --j)
+ isl_basic_map_swap_div(info->bmap, j - 1, j);
}
return 0;
@@ -2217,53 +2231,33 @@ error:
return -1;
}
-/* Add variables to info->tab corresponding to the elements in "list"
- * that are not set to NaN. The value of the added variable
- * is fixed to the purely affine expression defined by the element.
+/* Add variables to info->tab and info->bmap corresponding to the elements
+ * in "list" that are not set to NaN. The value of the added variable
+ * in info->tab is fixed to the purely affine expression defined by the element.
* "dim" is the offset in the variables of info->tab where we should
* start considering the elements in "list".
* When this function returns, the total number of variables in info->tab
* is equal to "dim" plus the number of elements in "list".
- * Additionally, add the div constraints that have been added info->bmap
- * after the tableau was constructed to info->tab. These constraints
- * start at position "n_ineq" in info->bmap.
- * The constraints need to be added to the tableau before
- * the equalities assigning the purely affine expression
- * because the position needs to match that in info->bmap.
- * They are frozen because the corresponding added equality is a consequence
- * of the two div constraints and the other equalities, meaning that
- * the div constraints would otherwise get marked as redundant,
- * while they are only redundant with respect to the extra equalities
- * added to the tableau, which do not appear explicitly in the basic map.
*/
static int add_subs(struct isl_coalesce_info *info,
- __isl_keep isl_aff_list *list, int dim, int n_ineq)
+ __isl_keep isl_aff_list *list, int dim)
{
- int i, extra_var, extra_con;
+ int extra_var;
int n;
- unsigned n_eq = info->bmap->n_eq;
if (!list)
return -1;
n = isl_aff_list_n_aff(list);
extra_var = n - (info->tab->n_var - dim);
- extra_con = info->bmap->n_ineq - n_ineq;
if (isl_tab_extend_vars(info->tab, extra_var) < 0)
return -1;
- if (isl_tab_extend_cons(info->tab, extra_con + 2 * extra_var) < 0)
+ if (isl_tab_extend_cons(info->tab, 2 * extra_var) < 0)
return -1;
- if (add_sub_vars(info->tab, list, dim) < 0)
+ if (add_sub_vars(info, list, dim, extra_var) < 0)
return -1;
- for (i = n_ineq; i < info->bmap->n_ineq; ++i) {
- if (isl_tab_add_ineq(info->tab, info->bmap->ineq[i]) < 0)
- return -1;
- if (isl_tab_freeze_constraint(info->tab, n_eq + i) < 0)
- return -1;
- }
-
return add_sub_equalities(info->tab, list, dim);
}
@@ -2273,9 +2267,6 @@ static int add_subs(struct isl_coalesce_info *info,
* is equal to the number of integer divisions in "i", while the number
* of NaN elements in the list is equal to the number of integer divisions
* in "j".
- * Adding extra integer divisions to "j" through isl_basic_map_align_divs
- * also adds the corresponding div constraints. These need to be added
- * to the corresponding tableau as well in add_subs to maintain consistency.
*
* If no coalescing can be performed, then we need to revert basic map "j"
* to its original state. We do the same if basic map "i" gets dropped
@@ -2290,19 +2281,13 @@ static enum isl_change coalesce_with_subs(int i, int j,
struct isl_tab_undo *snap;
unsigned dim;
enum isl_change change;
- int n_ineq;
bmap_j = isl_basic_map_copy(info[j].bmap);
- n_ineq = info[j].bmap->n_ineq;
- info[j].bmap = isl_basic_map_align_divs(info[j].bmap, info[i].bmap);
- if (!info[j].bmap)
- goto error;
-
snap = isl_tab_snap(info[j].tab);
dim = isl_basic_map_dim(bmap_j, isl_dim_all);
dim -= isl_basic_map_dim(bmap_j, isl_dim_div);
- if (add_subs(&info[j], list, dim, n_ineq) < 0)
+ if (add_subs(&info[j], list, dim) < 0)
goto error;
change = coalesce_local_pair(i, j, info);
@@ -2464,7 +2449,7 @@ static enum isl_change coalesce_pair(int i, int j,
/* Return the maximum of "a" and "b".
*/
-static inline int max(int a, int b)
+static int isl_max(int a, int b)
{
return a > b ? a : b;
}
@@ -2491,7 +2476,7 @@ static int coalesce_range(isl_ctx *ctx, struct isl_coalesce_info *info,
for (i = end1 - 1; i >= start1; --i) {
if (info[i].removed)
continue;
- for (j = max(i + 1, start2); j < end2; ++j) {
+ for (j = isl_max(i + 1, start2); j < end2; ++j) {
enum isl_change changed;
if (info[j].removed)
diff --git a/isl_config.h.in b/isl_config.h.in
index c523bdaa..395da3c9 100644
--- a/isl_config.h.in
+++ b/isl_config.h.in
@@ -44,6 +44,34 @@
to 0 if you don't. */
#undef HAVE_DECL_MP_GET_MEMORY_FUNCTIONS
+/* Define to 1 if you have the declaration of `snprintf', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SNPRINTF
+
+/* Define to 1 if you have the declaration of `strcasecmp', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRCASECMP
+
+/* Define to 1 if you have the declaration of `strncasecmp', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRNCASECMP
+
+/* Define to 1 if you have the declaration of `_BitScanForward', and to 0 if
+ you don't. */
+#undef HAVE_DECL__BITSCANFORWARD
+
+/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you
+ don't. */
+#undef HAVE_DECL__SNPRINTF
+
+/* Define to 1 if you have the declaration of `_stricmp', and to 0 if you
+ don't. */
+#undef HAVE_DECL__STRICMP
+
+/* Define to 1 if you have the declaration of `_strnicmp', and to 0 if you
+ don't. */
+#undef HAVE_DECL__STRNICMP
+
/* Define to 1 if you have the declaration of `__builtin_ffs', and to 0 if you
don't. */
#undef HAVE_DECL___BUILTIN_FFS
@@ -147,6 +175,9 @@
/* use imath to implement isl_int */
#undef USE_IMATH_FOR_MP
+/* Use small integer optimization */
+#undef USE_SMALL_INT_OPT
+
/* Version number of package */
#undef VERSION
@@ -165,4 +196,7 @@
/* Define to getResultType for older versions of clang */
#undef getReturnType
+/* Define to InitializeBuiltins for older versions of clang */
+#undef initializeBuiltins
+
#include <isl_config_post.h>
diff --git a/isl_config_post.h b/isl_config_post.h
index 5d67aae4..39373af3 100644
--- a/isl_config_post.h
+++ b/isl_config_post.h
@@ -2,10 +2,35 @@
#define __attribute__(x)
#endif
+#if HAVE_DECL_FFS
+#include <strings.h>
+#endif
+
#if (HAVE_DECL_FFS==0) && (HAVE_DECL___BUILTIN_FFS==1)
#define ffs __builtin_ffs
#endif
+#if !HAVE_DECL_FFS && !HAVE_DECL___BUILTIN_FFS && HAVE_DECL__BITSCANFORWARD
+int isl_ffs(int i);
+#define ffs isl_ffs
+#endif
+
+#if HAVE_DECL_STRCASECMP || HAVE_DECL_STRNCASECMP
+#include <strings.h>
+#endif
+
+#if !HAVE_DECL_STRCASECMP && HAVE_DECL__STRICMP
+#define strcasecmp _stricmp
+#endif
+
+#if !HAVE_DECL_STRNCASECMP && HAVE_DECL__STRNICMP
+#define strncasecmp _strnicmp
+#endif
+
+#if !HAVE_DECL_SNPRINTF && HAVE_DECL__SNPRINTF
+#define snprintf _snprintf
+#endif
+
#ifdef GCC_WARN_UNUSED_RESULT
#define WARN_UNUSED GCC_WARN_UNUSED_RESULT
#else
diff --git a/isl_convex_hull.c b/isl_convex_hull.c
index b5ca0d9d..fbd40dc2 100644
--- a/isl_convex_hull.c
+++ b/isl_convex_hull.c
@@ -2326,6 +2326,25 @@ error:
/* Compute a superset of the convex hull of map that is described
* by only (translates of) the constraints in the constituents of map.
+ * Handle trivial cases where map is NULL or contains at most one disjunct.
+ */
+static __isl_give isl_basic_map *map_simple_hull_trivial(
+ __isl_take isl_map *map)
+{
+ isl_basic_map *hull;
+
+ if (!map)
+ return NULL;
+ if (map->n == 0)
+ return replace_map_by_empty_basic_map(map);
+
+ hull = isl_basic_map_copy(map->p[0]);
+ isl_map_free(map);
+ return hull;
+}
+
+/* Compute a superset of the convex hull of map that is described
+ * by only (translates of) the constraints in the constituents of map.
* Translation is only allowed if "shift" is set.
*/
static __isl_give isl_basic_map *map_simple_hull(__isl_take isl_map *map,
@@ -2337,17 +2356,12 @@ static __isl_give isl_basic_map *map_simple_hull(__isl_take isl_map *map,
struct isl_basic_map *affine_hull;
struct isl_basic_set *bset = NULL;
- if (!map)
- return NULL;
- if (map->n == 0)
- return replace_map_by_empty_basic_map(map);
- if (map->n == 1) {
- hull = isl_basic_map_copy(map->p[0]);
- isl_map_free(map);
- return hull;
- }
+ if (!map || map->n <= 1)
+ return map_simple_hull_trivial(map);
map = isl_map_detect_equalities(map);
+ if (!map || map->n <= 1)
+ return map_simple_hull_trivial(map);
affine_hull = isl_map_affine_hull(isl_map_copy(map));
map = isl_map_align_divs(map);
model = map ? isl_basic_map_copy(map->p[0]) : NULL;
@@ -2400,6 +2414,176 @@ __isl_give isl_basic_set *isl_set_unshifted_simple_hull(
return isl_map_unshifted_simple_hull(set);
}
+/* Drop all inequalities from "bmap1" that do not also appear in "bmap2".
+ * A constraint that appears with different constant terms
+ * in "bmap1" and "bmap2" is also kept, with the least restrictive
+ * (i.e., greatest) constant term.
+ * "bmap1" and "bmap2" are assumed to have the same (known)
+ * integer divisions.
+ * The constraints of both "bmap1" and "bmap2" are assumed
+ * to have been sorted using isl_basic_map_sort_constraints.
+ *
+ * Run through the inequality constraints of "bmap1" and "bmap2"
+ * in sorted order.
+ * Each constraint of "bmap1" without a matching constraint in "bmap2"
+ * is removed.
+ * If a match is found, the constraint is kept. If needed, the constant
+ * term of the constraint is adjusted.
+ */
+static __isl_give isl_basic_map *select_shared_inequalities(
+ __isl_take isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
+{
+ int i1, i2;
+
+ bmap1 = isl_basic_map_cow(bmap1);
+ if (!bmap1 || !bmap2)
+ return isl_basic_map_free(bmap1);
+
+ i1 = bmap1->n_ineq - 1;
+ i2 = bmap2->n_ineq - 1;
+ while (bmap1 && i1 >= 0 && i2 >= 0) {
+ int cmp;
+
+ cmp = isl_basic_map_constraint_cmp(bmap1, bmap1->ineq[i1],
+ bmap2->ineq[i2]);
+ if (cmp < 0) {
+ --i2;
+ continue;
+ }
+ if (cmp > 0) {
+ if (isl_basic_map_drop_inequality(bmap1, i1) < 0)
+ bmap1 = isl_basic_map_free(bmap1);
+ --i1;
+ continue;
+ }
+ if (isl_int_lt(bmap1->ineq[i1][0], bmap2->ineq[i2][0]))
+ isl_int_set(bmap1->ineq[i1][0], bmap2->ineq[i2][0]);
+ --i1;
+ --i2;
+ }
+ for (; i1 >= 0; --i1)
+ if (isl_basic_map_drop_inequality(bmap1, i1) < 0)
+ bmap1 = isl_basic_map_free(bmap1);
+
+ return bmap1;
+}
+
+/* Drop all equalities from "bmap1" that do not also appear in "bmap2".
+ * "bmap1" and "bmap2" are assumed to have the same (known)
+ * integer divisions.
+ *
+ * Run through the equality constraints of "bmap1" and "bmap2".
+ * Each constraint of "bmap1" without a matching constraint in "bmap2"
+ * is removed.
+ */
+static __isl_give isl_basic_map *select_shared_equalities(
+ __isl_take isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
+{
+ int i1, i2;
+ unsigned total;
+
+ bmap1 = isl_basic_map_cow(bmap1);
+ if (!bmap1 || !bmap2)
+ return isl_basic_map_free(bmap1);
+
+ total = isl_basic_map_total_dim(bmap1);
+
+ i1 = bmap1->n_eq - 1;
+ i2 = bmap2->n_eq - 1;
+ while (bmap1 && i1 >= 0 && i2 >= 0) {
+ int last1, last2;
+
+ last1 = isl_seq_last_non_zero(bmap1->eq[i1] + 1, total);
+ last2 = isl_seq_last_non_zero(bmap2->eq[i2] + 1, total);
+ if (last1 > last2) {
+ --i2;
+ continue;
+ }
+ if (last1 < last2) {
+ if (isl_basic_map_drop_equality(bmap1, i1) < 0)
+ bmap1 = isl_basic_map_free(bmap1);
+ --i1;
+ continue;
+ }
+ if (!isl_seq_eq(bmap1->eq[i1], bmap2->eq[i2], 1 + total)) {
+ if (isl_basic_map_drop_equality(bmap1, i1) < 0)
+ bmap1 = isl_basic_map_free(bmap1);
+ }
+ --i1;
+ --i2;
+ }
+ for (; i1 >= 0; --i1)
+ if (isl_basic_map_drop_equality(bmap1, i1) < 0)
+ bmap1 = isl_basic_map_free(bmap1);
+
+ return bmap1;
+}
+
+/* Compute a superset of "bmap1" and "bmap2" that is described
+ * by only the constraints that appear in both "bmap1" and "bmap2".
+ *
+ * First drop constraints that involve unknown integer divisions
+ * since it is not trivial to check whether two such integer divisions
+ * in different basic maps are the same.
+ * Then align the remaining (known) divs and sort the constraints.
+ * Finally drop all inequalities and equalities from "bmap1" that
+ * do not also appear in "bmap2".
+ */
+__isl_give isl_basic_map *isl_basic_map_plain_unshifted_simple_hull(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
+{
+ bmap1 = isl_basic_map_drop_constraint_involving_unknown_divs(bmap1);
+ bmap2 = isl_basic_map_drop_constraint_involving_unknown_divs(bmap2);
+ bmap2 = isl_basic_map_align_divs(bmap2, bmap1);
+ bmap1 = isl_basic_map_align_divs(bmap1, bmap2);
+ bmap1 = isl_basic_map_gauss(bmap1, NULL);
+ bmap2 = isl_basic_map_gauss(bmap2, NULL);
+ bmap1 = isl_basic_map_sort_constraints(bmap1);
+ bmap2 = isl_basic_map_sort_constraints(bmap2);
+
+ bmap1 = select_shared_inequalities(bmap1, bmap2);
+ bmap1 = select_shared_equalities(bmap1, bmap2);
+
+ isl_basic_map_free(bmap2);
+ bmap1 = isl_basic_map_finalize(bmap1);
+ return bmap1;
+}
+
+/* Compute a superset of the convex hull of "map" that is described
+ * by only the constraints in the constituents of "map".
+ * In particular, the result is composed of constraints that appear
+ * in each of the basic maps of "map"
+ *
+ * Constraints that involve unknown integer divisions are dropped
+ * since it is not trivial to check whether two such integer divisions
+ * in different basic maps are the same.
+ *
+ * The hull is initialized from the first basic map and then
+ * updated with respect to the other basic maps in turn.
+ */
+__isl_give isl_basic_map *isl_map_plain_unshifted_simple_hull(
+ __isl_take isl_map *map)
+{
+ int i;
+ isl_basic_map *hull;
+
+ if (!map)
+ return NULL;
+ if (map->n <= 1)
+ return map_simple_hull_trivial(map);
+ map = isl_map_drop_constraint_involving_unknown_divs(map);
+ hull = isl_basic_map_copy(map->p[0]);
+ for (i = 1; i < map->n; ++i) {
+ isl_basic_map *bmap_i;
+
+ bmap_i = isl_basic_map_copy(map->p[i]);
+ hull = isl_basic_map_plain_unshifted_simple_hull(hull, bmap_i);
+ }
+
+ isl_map_free(map);
+ return hull;
+}
+
/* Check if "ineq" is a bound on "set" and, if so, add it to "hull".
*
* For each basic set in "set", we first check if the basic set
diff --git a/isl_equalities.c b/isl_equalities.c
index 44cf8f06..83572a07 100644
--- a/isl_equalities.c
+++ b/isl_equalities.c
@@ -514,7 +514,7 @@ __isl_give isl_mat *isl_mat_variable_compression(__isl_take isl_mat *B,
isl_mat_free(U);
if (T2) {
isl_mat_free(*T2);
- *T2 = NULL;
+ *T2 = isl_mat_alloc(ctx, 0, 1 + dim);
}
return isl_mat_alloc(ctx, 1 + dim, 0);
}
@@ -544,6 +544,32 @@ error:
return NULL;
}
+/* Return "bset" and set *T and *T2 to the identity transformation
+ * on "bset" (provided T and T2 are not NULL).
+ */
+static __isl_give isl_basic_set *return_with_identity(
+ __isl_take isl_basic_set *bset, __isl_give isl_mat **T,
+ __isl_give isl_mat **T2)
+{
+ unsigned dim;
+ isl_mat *id;
+
+ if (!bset)
+ return NULL;
+ if (!T && !T2)
+ return bset;
+
+ dim = isl_basic_set_dim(bset, isl_dim_set);
+ id = isl_mat_identity(isl_basic_map_get_ctx(bset), 1 + dim);
+ if (T)
+ *T = isl_mat_copy(id);
+ if (T2)
+ *T2 = isl_mat_copy(id);
+ isl_mat_free(id);
+
+ return bset;
+}
+
/* Use the n equalities of bset to unimodularly transform the
* variables x such that n transformed variables x1' have a constant value
* and rewrite the constraints of bset in terms of the remaining
@@ -568,7 +594,7 @@ static struct isl_basic_set *compress_variables(
dim = isl_basic_set_n_dim(bset);
isl_assert(bset->ctx, bset->n_eq <= dim, goto error);
if (bset->n_eq == 0)
- return bset;
+ return return_with_identity(bset, T, T2);
B = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq, 0, 1 + dim);
TC = isl_mat_variable_compression(B, T2);
@@ -604,7 +630,7 @@ struct isl_basic_set *isl_basic_set_remove_equalities(
isl_assert(bset->ctx, isl_basic_set_n_param(bset) == 0, goto error);
bset = isl_basic_set_gauss(bset, NULL);
if (ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY))
- return bset;
+ return return_with_identity(bset, T, T2);
bset = compress_variables(bset, T, T2);
return bset;
error:
diff --git a/isl_ffs.c b/isl_ffs.c
new file mode 100644
index 00000000..c1ee928f
--- /dev/null
+++ b/isl_ffs.c
@@ -0,0 +1,24 @@
+#include <isl_config.h>
+
+#if !HAVE_DECL_FFS && !HAVE_DECL___BUILTIN_FFS && HAVE_DECL__BITSCANFORWARD
+#include <intrin.h>
+
+/* Implementation of ffs in terms of _BitScanForward.
+ *
+ * ffs returns the position of the least significant bit set in i,
+ * with the least significant bit is position 1, or 0 if not bits are set.
+ *
+ * _BitScanForward returns 1 if mask is non-zero and sets index
+ * to the position of the least significant bit set in i,
+ * with the least significant bit is position 0.
+ */
+int isl_ffs(int i)
+{
+ unsigned char non_zero;
+ unsigned long index, mask = i;
+
+ non_zero = _BitScanForward(&index, mask);
+
+ return non_zero ? 1 + index : 0;
+}
+#endif
diff --git a/isl_flow.c b/isl_flow.c
index 5034c285..b5ae691d 100644
--- a/isl_flow.c
+++ b/isl_flow.c
@@ -167,6 +167,8 @@ struct isl_labeled_map {
*
* domain_map is an auxiliary map that maps the sink access relation
* to the domain of this access relation.
+ * This field is only needed when restrict_fn is set and
+ * the field itself is set by isl_access_info_compute_flow.
*
* restrict_fn is a callback that (if not NULL) will be called
* right before any lexicographical maximization.
@@ -1062,18 +1064,17 @@ error:
*
* To deal with multi-valued sink access relations, the sink iteration
* domain is first extended with dimensions that correspond to the data
- * space. After the computation is finished, these extra dimensions are
- * projected out again.
+ * space. However, these extra dimensions are not projected out again.
+ * It is up to the caller to decide whether these dimensions should be kept.
*/
-__isl_give isl_flow *isl_access_info_compute_flow(__isl_take isl_access_info *acc)
+static __isl_give isl_flow *access_info_compute_flow_core(
+ __isl_take isl_access_info *acc)
{
- int j;
struct isl_flow *res = NULL;
if (!acc)
return NULL;
- acc->domain_map = isl_map_domain_map(isl_map_copy(acc->sink.map));
acc->sink.map = isl_map_range_map(acc->sink.map);
if (!acc->sink.map)
goto error;
@@ -1084,22 +1085,56 @@ __isl_give isl_flow *isl_access_info_compute_flow(__isl_take isl_access_info *ac
acc = isl_access_info_sort_sources(acc);
res = compute_val_based_dependences(acc);
}
+ acc = isl_access_info_free(acc);
if (!res)
+ return NULL;
+ if (!res->must_no_source || !res->may_no_source)
goto error;
+ return res;
+error:
+ isl_access_info_free(acc);
+ isl_flow_free(res);
+ return NULL;
+}
+
+/* Given a "sink" access, a list of n "source" accesses,
+ * compute for each iteration of the sink access
+ * and for each element accessed by that iteration,
+ * the source access in the list that last accessed the
+ * element accessed by the sink access before this sink access.
+ * Each access is given as a map from the loop iterators
+ * to the array indices.
+ * The result is a list of n relations between source and sink
+ * iterations and a subset of the domain of the sink access,
+ * corresponding to those iterations that access an element
+ * not previously accessed.
+ *
+ * To deal with multi-valued sink access relations,
+ * access_info_compute_flow_core extends the sink iteration domain
+ * with dimensions that correspond to the data space. These extra dimensions
+ * are projected out from the result of access_info_compute_flow_core.
+ */
+__isl_give isl_flow *isl_access_info_compute_flow(__isl_take isl_access_info *acc)
+{
+ int j;
+ struct isl_flow *res;
+
+ if (!acc)
+ return NULL;
+
+ acc->domain_map = isl_map_domain_map(isl_map_copy(acc->sink.map));
+ res = access_info_compute_flow_core(acc);
+ if (!res)
+ return NULL;
for (j = 0; j < res->n_source; ++j) {
- res->dep[j].map = isl_map_apply_range(res->dep[j].map,
- isl_map_copy(acc->domain_map));
+ res->dep[j].map = isl_map_range_factor_domain(res->dep[j].map);
if (!res->dep[j].map)
goto error;
}
- if (!res->must_no_source || !res->may_no_source)
- goto error;
- isl_access_info_free(acc);
return res;
error:
- isl_access_info_free(acc);
isl_flow_free(res);
return NULL;
}
@@ -1368,6 +1403,70 @@ __isl_give isl_union_access_info *isl_union_access_info_copy(
return copy;
}
+/* Print a key-value pair of a YAML mapping to "p",
+ * with key "name" and value "umap".
+ */
+static __isl_give isl_printer *print_union_map_field(__isl_take isl_printer *p,
+ const char *name, __isl_keep isl_union_map *umap)
+{
+ p = isl_printer_print_str(p, name);
+ p = isl_printer_yaml_next(p);
+ p = isl_printer_print_str(p, "\"");
+ p = isl_printer_print_union_map(p, umap);
+ p = isl_printer_print_str(p, "\"");
+ p = isl_printer_yaml_next(p);
+
+ return p;
+}
+
+/* Print the information contained in "access" to "p".
+ * The information is printed as a YAML document.
+ */
+__isl_give isl_printer *isl_printer_print_union_access_info(
+ __isl_take isl_printer *p, __isl_keep isl_union_access_info *access)
+{
+ if (!access)
+ return isl_printer_free(p);
+
+ p = isl_printer_yaml_start_mapping(p);
+ p = print_union_map_field(p, "sink", access->sink);
+ p = print_union_map_field(p, "must_source", access->must_source);
+ p = print_union_map_field(p, "may_source", access->may_source);
+ if (access->schedule) {
+ p = isl_printer_print_str(p, "schedule");
+ p = isl_printer_yaml_next(p);
+ p = isl_printer_print_schedule(p, access->schedule);
+ p = isl_printer_yaml_next(p);
+ } else {
+ p = print_union_map_field(p, "schedule_map",
+ access->schedule_map);
+ }
+ p = isl_printer_yaml_end_mapping(p);
+
+ return p;
+}
+
+/* Return a string representation of the information in "access".
+ * The information is printed in flow format.
+ */
+__isl_give char *isl_union_access_info_to_str(
+ __isl_keep isl_union_access_info *access)
+{
+ isl_printer *p;
+ char *s;
+
+ if (!access)
+ return NULL;
+
+ p = isl_printer_to_str(isl_union_access_info_get_ctx(access));
+ p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
+ p = isl_printer_print_union_access_info(p, access);
+ s = isl_printer_get_str(p);
+ isl_printer_free(p);
+
+ return s;
+}
+
/* Update the fields of "access" such that they all have the same parameters,
* keeping in mind that the schedule_map field may be NULL and ignoring
* the schedule field.
@@ -1457,10 +1556,15 @@ isl_union_access_info_introduce_schedule(
return access;
}
-/* This structure epresents the result of a dependence analysis computation.
+/* This structure represents the result of a dependence analysis computation.
*
- * "must_dep" represents the definite dependences.
- * "may_dep" represents the non-definite dependences.
+ * "must_dep" represents the full definite dependences
+ * "may_dep" represents the full non-definite dependences.
+ * Both are of the form
+ *
+ * [Source] -> [[Sink -> Data]]
+ *
+ * (after the schedule dimensions have been projected out).
* "must_no_source" represents the subset of the sink accesses for which
* definitely no source was found.
* "may_no_source" represents the subset of the sink accesses for which
@@ -1509,9 +1613,9 @@ void isl_union_flow_dump(__isl_keep isl_union_flow *flow)
isl_union_map_dump(flow->may_no_source);
}
-/* Return the definite dependences in "flow".
+/* Return the full definite dependences in "flow", with accessed elements.
*/
-__isl_give isl_union_map *isl_union_flow_get_must_dependence(
+__isl_give isl_union_map *isl_union_flow_get_full_must_dependence(
__isl_keep isl_union_flow *flow)
{
if (!flow)
@@ -1519,16 +1623,44 @@ __isl_give isl_union_map *isl_union_flow_get_must_dependence(
return isl_union_map_copy(flow->must_dep);
}
+/* Return the full possible dependences in "flow", including the definite
+ * dependences, with accessed elements.
+ */
+__isl_give isl_union_map *isl_union_flow_get_full_may_dependence(
+ __isl_keep isl_union_flow *flow)
+{
+ if (!flow)
+ return NULL;
+ return isl_union_map_union(isl_union_map_copy(flow->must_dep),
+ isl_union_map_copy(flow->may_dep));
+}
+
+/* Return the definite dependences in "flow", without the accessed elements.
+ */
+__isl_give isl_union_map *isl_union_flow_get_must_dependence(
+ __isl_keep isl_union_flow *flow)
+{
+ isl_union_map *dep;
+
+ if (!flow)
+ return NULL;
+ dep = isl_union_map_copy(flow->must_dep);
+ return isl_union_map_range_factor_domain(dep);
+}
+
/* Return the possible dependences in "flow", including the definite
- * dependences.
+ * dependences, without the accessed elements.
*/
__isl_give isl_union_map *isl_union_flow_get_may_dependence(
__isl_keep isl_union_flow *flow)
{
+ isl_union_map *dep;
+
if (!flow)
return NULL;
- return isl_union_map_union(isl_union_map_copy(flow->must_dep),
+ dep = isl_union_map_union(isl_union_map_copy(flow->must_dep),
isl_union_map_copy(flow->may_dep));
+ return isl_union_map_range_factor_domain(dep);
}
/* Return the non-definite dependences in "flow".
@@ -1614,6 +1746,20 @@ error:
* to the iteration domains prior to the dependence analysis by
* replacing the iteration domain D, by the wrapped map [S -> D].
* Replace these wrapped maps by the original D.
+ *
+ * In particular, the dependences computed by access_info_compute_flow_core
+ * are of the form
+ *
+ * [S -> D] -> [[S' -> D'] -> A]
+ *
+ * The schedule dimensions are projected out by first currying the range,
+ * resulting in
+ *
+ * [S -> D] -> [S' -> [D' -> A]]
+ *
+ * and then computing the factor range
+ *
+ * D -> [D' -> A]
*/
static __isl_give isl_union_flow *isl_union_flow_drop_schedule(
__isl_take isl_union_flow *flow)
@@ -1621,7 +1767,9 @@ static __isl_give isl_union_flow *isl_union_flow_drop_schedule(
if (!flow)
return NULL;
+ flow->must_dep = isl_union_map_range_curry(flow->must_dep);
flow->must_dep = isl_union_map_factor_range(flow->must_dep);
+ flow->may_dep = isl_union_map_range_curry(flow->may_dep);
flow->may_dep = isl_union_map_factor_range(flow->may_dep);
flow->must_no_source =
isl_union_map_domain_factor_range(flow->must_no_source);
@@ -1754,7 +1902,7 @@ static int before(void *first, void *second)
/* Given a sink access, look for all the source accesses that access
* the same array and perform dataflow analysis on them using
- * isl_access_info_compute_flow.
+ * isl_access_info_compute_flow_core.
*/
static isl_stat compute_flow(__isl_take isl_map *map, void *user)
{
@@ -1801,7 +1949,7 @@ static isl_stat compute_flow(__isl_take isl_map *map, void *user)
&collect_matching_array, data) < 0)
goto error;
- flow = isl_access_info_compute_flow(data->accesses);
+ flow = access_info_compute_flow_core(data->accesses);
data->accesses = NULL;
if (!flow)
@@ -2079,7 +2227,8 @@ static isl_stat extract_sink_source(__isl_take isl_map *map, void *user)
}
/* isl_schedule_foreach_schedule_node_top_down callback for collecting
- * individual scheduled source and sink accesses.
+ * individual scheduled source and sink accesses (taking into account
+ * the domain of the schedule).
*
* We only collect accesses at the leaves of the schedule tree.
* We prepend the schedule dimensions at the leaf to the iteration
@@ -2114,7 +2263,7 @@ static isl_bool collect_sink_source(__isl_keep isl_schedule_node *node,
data->node = node;
- prefix = isl_schedule_node_get_prefix_schedule_union_map(node);
+ prefix = isl_schedule_node_get_prefix_schedule_relation(node);
prefix = isl_union_map_reverse(prefix);
prefix = isl_union_map_range_map(prefix);
@@ -2232,6 +2381,19 @@ error:
/* Given a scheduled sink access relation "sink", compute the corresponding
* dependences on the sources in "data" and add the computed dependences
* to "uf".
+ *
+ * The dependences computed by access_info_compute_flow_core are of the form
+ *
+ * [S -> I] -> [[S' -> I'] -> A]
+ *
+ * The schedule dimensions are projected out by first currying the range,
+ * resulting in
+ *
+ * [S -> I] -> [S' -> [I' -> A]]
+ *
+ * and then computing the factor range
+ *
+ * I -> [I' -> A]
*/
static __isl_give isl_union_flow *compute_single_flow(
__isl_take isl_union_flow *uf, struct isl_scheduled_access *sink,
@@ -2249,7 +2411,7 @@ static __isl_give isl_union_flow *compute_single_flow(
&before_node, data->n_source);
access = add_matching_sources(access, sink, data);
- flow = isl_access_info_compute_flow(access);
+ flow = access_info_compute_flow_core(access);
if (!flow)
return isl_union_flow_free(uf);
@@ -2263,7 +2425,8 @@ static __isl_give isl_union_flow *compute_single_flow(
for (i = 0; i < flow->n_source; ++i) {
isl_union_map *dep;
- map = isl_map_factor_range(isl_map_copy(flow->dep[i].map));
+ map = isl_map_range_curry(isl_map_copy(flow->dep[i].map));
+ map = isl_map_factor_range(map);
dep = isl_union_map_from_map(map);
if (flow->dep[i].must)
uf->must_dep = isl_union_map_union(uf->must_dep, dep);
@@ -2282,6 +2445,8 @@ static __isl_give isl_union_flow *compute_single_flow(
* the possible or definite source accesses that last accessed the
* element accessed by the sink access before this sink access
* in the sense that there is no intermediate definite source access.
+ * Only consider dependences between statement instances that belong
+ * to the domain of the schedule.
*
* The must_no_source and may_no_source elements of the result
* are subsets of access->sink. The elements must_dep and may_dep
@@ -2291,7 +2456,8 @@ static __isl_give isl_union_flow *compute_single_flow(
* This function is used when a schedule tree representation
* is available.
*
- * We extract the individual scheduled source and sink access relations and
+ * We extract the individual scheduled source and sink access relations
+ * (taking into account the domain of the schedule) and
* then compute dependences for each scheduled sink individually.
*/
static __isl_give isl_union_flow *compute_flow_schedule(
@@ -2367,6 +2533,51 @@ __isl_give isl_union_flow *isl_union_access_info_compute_flow(
return compute_flow_union_map(access);
}
+/* Print the information contained in "flow" to "p".
+ * The information is printed as a YAML document.
+ */
+__isl_give isl_printer *isl_printer_print_union_flow(
+ __isl_take isl_printer *p, __isl_keep isl_union_flow *flow)
+{
+ isl_union_map *umap;
+
+ if (!flow)
+ return isl_printer_free(p);
+
+ p = isl_printer_yaml_start_mapping(p);
+ p = print_union_map_field(p, "must_dependence", flow->must_dep);
+ umap = isl_union_flow_get_may_dependence(flow);
+ p = print_union_map_field(p, "may_dependence", umap);
+ isl_union_map_free(umap);
+ p = print_union_map_field(p, "must_no_source", flow->must_no_source);
+ umap = isl_union_flow_get_may_no_source(flow);
+ p = print_union_map_field(p, "may_no_source", umap);
+ isl_union_map_free(umap);
+ p = isl_printer_yaml_end_mapping(p);
+
+ return p;
+}
+
+/* Return a string representation of the information in "flow".
+ * The information is printed in flow format.
+ */
+__isl_give char *isl_union_flow_to_str(__isl_keep isl_union_flow *flow)
+{
+ isl_printer *p;
+ char *s;
+
+ if (!flow)
+ return NULL;
+
+ p = isl_printer_to_str(isl_union_flow_get_ctx(flow));
+ p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
+ p = isl_printer_print_union_flow(p, flow);
+ s = isl_printer_get_str(p);
+ isl_printer_free(p);
+
+ return s;
+}
+
/* Given a collection of "sink" and "source" accesses,
* compute for each iteration of a sink access
* and for each element accessed by that iteration,
diff --git a/isl_fold.c b/isl_fold.c
index a7f088ad..c2162cfb 100644
--- a/isl_fold.c
+++ b/isl_fold.c
@@ -684,7 +684,8 @@ __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist_params(
#define NO_SUB
-#include <isl_union_templ.c>
+#include <isl_union_single.c>
+#include <isl_union_eval.c>
__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
__isl_take isl_space *dim)
@@ -927,7 +928,6 @@ __isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold_pw_
__isl_take isl_union_pw_qpolynomial_fold *u,
__isl_take isl_pw_qpolynomial_fold *part)
{
- uint32_t hash;
struct isl_hash_table_entry *entry;
u = isl_union_pw_qpolynomial_fold_cow(u);
@@ -939,10 +939,7 @@ __isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold_pw_
isl_space_match(part->dim, isl_dim_param, u->space, isl_dim_param),
goto error);
- hash = isl_space_get_hash(part->dim);
- entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
- &isl_union_pw_qpolynomial_fold_has_same_domain_space,
- part->dim, 1);
+ entry = isl_union_pw_qpolynomial_fold_find_part_entry(u, part->dim, 1);
if (!entry)
goto error;
@@ -1399,15 +1396,12 @@ static isl_stat add_pwqp(__isl_take isl_pw_qpolynomial *pwqp, void *user)
isl_ctx *ctx;
isl_pw_qpolynomial_fold *pwf;
isl_union_pw_qpolynomial_fold **upwf;
- uint32_t hash;
struct isl_hash_table_entry *entry;
upwf = (isl_union_pw_qpolynomial_fold **)user;
ctx = pwqp->dim->ctx;
- hash = isl_space_get_hash(pwqp->dim);
- entry = isl_hash_table_find(ctx, &(*upwf)->table, hash,
- &isl_union_pw_qpolynomial_fold_has_same_domain_space,
+ entry = isl_union_pw_qpolynomial_fold_find_part_entry(*upwf,
pwqp->dim, 1);
if (!entry)
goto error;
@@ -1419,10 +1413,9 @@ static isl_stat add_pwqp(__isl_take isl_pw_qpolynomial *pwqp, void *user)
entry->data = isl_pw_qpolynomial_fold_add(entry->data, pwf);
if (!entry->data)
return isl_stat_error;
- if (isl_pw_qpolynomial_fold_is_zero(entry->data)) {
- isl_pw_qpolynomial_fold_free(entry->data);
- isl_hash_table_remove(ctx, &(*upwf)->table, entry);
- }
+ if (isl_pw_qpolynomial_fold_is_zero(entry->data))
+ *upwf = isl_union_pw_qpolynomial_fold_remove_part_entry(
+ *upwf, entry);
}
return isl_stat_ok;
diff --git a/isl_hash.c b/isl_hash.c
index 290807bc..ca25d0d5 100644
--- a/isl_hash.c
+++ b/isl_hash.c
@@ -8,8 +8,7 @@
*/
#include <stdlib.h>
-#include <strings.h>
-#include <isl/hash.h>
+#include <isl_hash_private.h>
#include <isl/ctx.h>
#include "isl_config.h"
@@ -149,6 +148,13 @@ void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table)
free(table);
}
+/* A dummy entry that can be used to make a distinction between
+ * a missing entry and an error condition.
+ * It is used by isl_union_*_find_part_entry.
+ */
+static struct isl_hash_table_entry none = { 0, NULL };
+struct isl_hash_table_entry *isl_hash_table_entry_none = &none;
+
struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx,
struct isl_hash_table *table,
uint32_t key_hash,
diff --git a/isl_hash_private.h b/isl_hash_private.h
new file mode 100644
index 00000000..c6b272ae
--- /dev/null
+++ b/isl_hash_private.h
@@ -0,0 +1,8 @@
+#ifndef ISL_HASH_PRIVATE
+#define ISL_HASH_PRIVATE
+
+#include <isl/hash.h>
+
+extern struct isl_hash_table_entry *isl_hash_table_entry_none;
+
+#endif
diff --git a/isl_imath.c b/isl_imath.c
index fc8e70a6..cffd79a1 100644
--- a/isl_imath.c
+++ b/isl_imath.c
@@ -32,22 +32,24 @@ int isl_imath_fits_ulong_p(mp_int op)
void isl_imath_addmul_ui(mp_int rop, mp_int op1, unsigned long op2)
{
- isl_int temp;
- isl_int_init(temp);
+ mpz_t temp;
+ mp_int_init(&temp);
- isl_int_set_ui(temp, op2);
- isl_int_addmul(rop, op1, temp);
+ mp_int_set_uvalue(&temp, op2);
+ mp_int_mul(op1, &temp, &temp);
+ mp_int_add(rop, &temp, rop);
- isl_int_clear(temp);
+ mp_int_clear(&temp);
}
void isl_imath_submul_ui(mp_int rop, mp_int op1, unsigned long op2)
{
- isl_int temp;
- isl_int_init(temp);
+ mpz_t temp;
+ mp_int_init(&temp);
- isl_int_set_ui(temp, op2);
- isl_int_submul(rop, op1, temp);
+ mp_int_set_uvalue(&temp, op2);
+ mp_int_mul(op1, &temp, &temp);
+ mp_int_sub(rop, &temp, rop);
- isl_int_clear(temp);
+ mp_int_clear(&temp);
}
diff --git a/isl_input.c b/isl_input.c
index 99cf7e41..72381270 100644
--- a/isl_input.c
+++ b/isl_input.c
@@ -658,10 +658,28 @@ error:
return NULL;
}
+/* Is "type" the type of a comparison operator between lists
+ * of affine expressions?
+ */
+static int is_list_comparator_type(int type)
+{
+ switch (type) {
+ case ISL_TOKEN_LEX_LT:
+ case ISL_TOKEN_LEX_GT:
+ case ISL_TOKEN_LEX_LE:
+ case ISL_TOKEN_LEX_GE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static int is_comparator(struct isl_token *tok)
{
if (!tok)
return 0;
+ if (is_list_comparator_type(tok->type))
+ return 1;
switch (tok->type) {
case ISL_TOKEN_LT:
@@ -1426,6 +1444,81 @@ static __isl_give isl_map *read_map_tuple(__isl_keep isl_stream *s,
return map_from_tuple(tuple, map, type, v, rational);
}
+/* Given two equal-length lists of piecewise affine expression with the space
+ * of "set" as domain, construct a set in the same space that expresses
+ * that "left" and "right" satisfy the comparison "type".
+ *
+ * A space is constructed of the same dimension as the number of elements
+ * in the two lists. The comparison is then expressed in a map from
+ * this space to itself and wrapped into a set. Finally the two lists
+ * of piecewise affine expressions are plugged into this set.
+ *
+ * Let S be the space of "set" and T the constructed space.
+ * The lists are first changed into two isl_multi_pw_affs in S -> T and
+ * then combined into an isl_multi_pw_aff in S -> [T -> T],
+ * while the comparison is first expressed in T -> T, then [T -> T]
+ * and finally in S.
+ */
+static __isl_give isl_set *list_cmp(__isl_keep isl_set *set, int type,
+ __isl_take isl_pw_aff_list *left, __isl_take isl_pw_aff_list *right)
+{
+ isl_space *space;
+ int n;
+ isl_multi_pw_aff *mpa1, *mpa2;
+
+ if (!set || !left || !right)
+ goto error;
+
+ space = isl_set_get_space(set);
+ n = isl_pw_aff_list_n_pw_aff(left);
+ space = isl_space_from_domain(space);
+ space = isl_space_add_dims(space, isl_dim_out, n);
+ mpa1 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), left);
+ mpa2 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), right);
+ mpa1 = isl_multi_pw_aff_range_product(mpa1, mpa2);
+
+ space = isl_space_range(space);
+ switch (type) {
+ case ISL_TOKEN_LEX_LT:
+ set = isl_map_wrap(isl_map_lex_lt(space));
+ break;
+ case ISL_TOKEN_LEX_GT:
+ set = isl_map_wrap(isl_map_lex_gt(space));
+ break;
+ case ISL_TOKEN_LEX_LE:
+ set = isl_map_wrap(isl_map_lex_le(space));
+ break;
+ case ISL_TOKEN_LEX_GE:
+ set = isl_map_wrap(isl_map_lex_ge(space));
+ break;
+ default:
+ isl_multi_pw_aff_free(mpa1);
+ isl_space_free(space);
+ isl_die(isl_set_get_ctx(set), isl_error_internal,
+ "unhandled list comparison type", return NULL);
+ }
+ set = isl_set_preimage_multi_pw_aff(set, mpa1);
+ return set;
+error:
+ isl_pw_aff_list_free(left);
+ isl_pw_aff_list_free(right);
+ return NULL;
+}
+
+/* Construct constraints of the form
+ *
+ * a op b
+ *
+ * where a is an element in "left", op is an operator of type "type" and
+ * b is an element in "right", add the constraints to "set" and return
+ * the result.
+ * "rational" is set if the constraints should be treated as
+ * a rational constraints.
+ *
+ * If "type" is the type of a comparison operator between lists
+ * of affine expressions, then a single (compound) constraint
+ * is constructed by list_cmp instead.
+ */
static __isl_give isl_set *construct_constraints(
__isl_take isl_set *set, int type,
__isl_keep isl_pw_aff_list *left, __isl_keep isl_pw_aff_list *right,
@@ -1439,7 +1532,9 @@ static __isl_give isl_set *construct_constraints(
left = isl_pw_aff_list_set_rational(left);
right = isl_pw_aff_list_set_rational(right);
}
- if (type == ISL_TOKEN_LE)
+ if (is_list_comparator_type(type))
+ cond = list_cmp(set, type, left, right);
+ else if (type == ISL_TOKEN_LE)
cond = isl_pw_aff_list_le_set(left, right);
else if (type == ISL_TOKEN_GE)
cond = isl_pw_aff_list_ge_set(left, right);
@@ -1455,11 +1550,32 @@ static __isl_give isl_set *construct_constraints(
return isl_set_intersect(set, cond);
}
+/* Read a constraint from "s", add it to "map" and return the result.
+ * "v" contains a description of the identifiers parsed so far.
+ * "rational" is set if the constraint should be treated as
+ * a rational constraint.
+ * The constraint read from "s" may be applied to multiple pairs
+ * of affine expressions and may be chained.
+ * In particular, a list of affine expressions is read, followed
+ * by a comparison operator and another list of affine expressions.
+ * The comparison operator is then applied to each pair of elements
+ * in the two lists and the results are added to "map".
+ * However, if the operator expects two lists of affine expressions,
+ * then it is applied directly to those lists and the two lists
+ * are required to have the same length.
+ * If the next token is another comparison operator, then another
+ * list of affine expressions is read and the process repeats.
+ *
+ * The processing is performed on a wrapped copy of "map" because
+ * an affine expression cannot have a binary relation as domain.
+ */
static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational)
{
- struct isl_token *tok = NULL;
+ struct isl_token *tok;
+ int type;
isl_pw_aff_list *list1 = NULL, *list2 = NULL;
+ int n1, n2;
isl_set *set;
set = isl_map_wrap(map);
@@ -1471,17 +1587,23 @@ static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
isl_stream_error(s, tok, "missing operator");
if (tok)
isl_stream_push_token(s, tok);
- tok = NULL;
goto error;
}
+ type = tok->type;
+ isl_token_free(tok);
for (;;) {
list2 = accept_affine_list(s, isl_set_get_space(set), v);
if (!list2)
goto error;
+ n1 = isl_pw_aff_list_n_pw_aff(list1);
+ n2 = isl_pw_aff_list_n_pw_aff(list2);
+ if (is_list_comparator_type(type) && n1 != n2) {
+ isl_stream_error(s, NULL,
+ "list arguments not of same size");
+ goto error;
+ }
- set = construct_constraints(set, tok->type, list1, list2,
- rational);
- isl_token_free(tok);
+ set = construct_constraints(set, type, list1, list2, rational);
isl_pw_aff_list_free(list1);
list1 = list2;
@@ -1491,13 +1613,13 @@ static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
isl_stream_push_token(s, tok);
break;
}
+ type = tok->type;
+ isl_token_free(tok);
}
isl_pw_aff_list_free(list1);
return isl_set_unwrap(set);
error:
- if (tok)
- isl_token_free(tok);
isl_pw_aff_list_free(list1);
isl_pw_aff_list_free(list2);
isl_set_free(set);
@@ -3588,6 +3710,61 @@ static __isl_give isl_union_pw_aff *read_union_pw_aff_with_dom(
return upa;
}
+/* Read an isl_union_pw_aff from "s".
+ *
+ * First check if there are any paramters, then read in the opening brace
+ * and use read_union_pw_aff_with_dom to read in the body of
+ * the isl_union_pw_aff. Finally, read the closing brace.
+ */
+__isl_give isl_union_pw_aff *isl_stream_read_union_pw_aff(
+ __isl_keep isl_stream *s)
+{
+ struct vars *v;
+ isl_set *dom;
+ isl_union_pw_aff *upa = NULL;
+
+ v = vars_new(s->ctx);
+ if (!v)
+ return NULL;
+
+ dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
+ if (next_is_tuple(s)) {
+ dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
+ if (isl_stream_eat(s, ISL_TOKEN_TO))
+ goto error;
+ }
+ if (isl_stream_eat(s, '{'))
+ goto error;
+
+ upa = read_union_pw_aff_with_dom(s, isl_set_copy(dom), v);
+
+ if (isl_stream_eat(s, '}'))
+ goto error;
+
+ vars_free(v);
+ isl_set_free(dom);
+ return upa;
+error:
+ vars_free(v);
+ isl_set_free(dom);
+ isl_union_pw_aff_free(upa);
+ return NULL;
+}
+
+/* Read an isl_union_pw_aff from "str".
+ */
+__isl_give isl_union_pw_aff *isl_union_pw_aff_read_from_str(isl_ctx *ctx,
+ const char *str)
+{
+ isl_union_pw_aff *upa;
+ isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ upa = isl_stream_read_union_pw_aff(s);
+ isl_stream_free(s);
+ return upa;
+}
+
/* This function is called for each element in a tuple inside
* isl_stream_read_multi_union_pw_aff.
*
diff --git a/isl_int.h b/isl_int.h
index 3be0661e..07be2bae 100644
--- a/isl_int.h
+++ b/isl_int.h
@@ -21,8 +21,12 @@
#endif
#ifdef USE_IMATH_FOR_MP
+#ifdef USE_SMALL_INT_OPT
+#include <isl_int_sioimath.h>
+#else /* USE_SMALL_INT_OPT */
#include <isl_int_imath.h>
-#endif
+#endif /* USE_SMALL_INT_OPT */
+#endif /* USE_IMATH_FOR_MP */
#define isl_int_is_zero(i) (isl_int_sgn(i) == 0)
#define isl_int_is_one(i) (isl_int_cmp_si(i,1) == 0)
@@ -32,6 +36,7 @@
#define isl_int_is_nonpos(i) (isl_int_sgn(i) <= 0)
#define isl_int_is_nonneg(i) (isl_int_sgn(i) >= 0)
+#ifndef USE_SMALL_INT_OPT
#define isl_int_print(out,i,width) \
do { \
char *s; \
@@ -39,6 +44,7 @@
fprintf(out, "%*s", width, s); \
isl_int_free_str(s); \
} while (0)
+#endif /* USE_SMALL_INT_OPT */
__isl_give isl_printer *isl_printer_print_isl_int(__isl_take isl_printer *p,
isl_int i);
diff --git a/isl_int_sioimath.c b/isl_int_sioimath.c
new file mode 100644
index 00000000..50c159f3
--- /dev/null
+++ b/isl_int_sioimath.c
@@ -0,0 +1,221 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <isl_int.h>
+
+extern int isl_sioimath_decode(isl_sioimath val, int32_t *small, mp_int *big);
+extern int isl_sioimath_decode_big(isl_sioimath val, mp_int *big);
+extern int isl_sioimath_decode_small(isl_sioimath val, int32_t *small);
+
+extern isl_sioimath isl_sioimath_encode_small(int32_t val);
+extern isl_sioimath isl_sioimath_encode_big(mp_int val);
+extern int isl_sioimath_is_small(isl_sioimath val);
+extern int isl_sioimath_is_big(isl_sioimath val);
+extern int32_t isl_sioimath_get_small(isl_sioimath val);
+extern mp_int isl_sioimath_get_big(isl_sioimath val);
+
+extern void isl_siomath_uint32_to_digits(uint32_t num, mp_digit *digits,
+ mp_size *used);
+extern void isl_siomath_ulong_to_digits(unsigned long num, mp_digit *digits,
+ mp_size *used);
+extern void isl_siomath_uint64_to_digits(uint64_t num, mp_digit *digits,
+ mp_size *used);
+
+extern mp_int isl_sioimath_bigarg_src(isl_sioimath arg,
+ isl_sioimath_scratchspace_t *scratch);
+extern mp_int isl_sioimath_siarg_src(signed long arg,
+ isl_sioimath_scratchspace_t *scratch);
+extern mp_int isl_sioimath_si64arg_src(int64_t arg,
+ isl_sioimath_scratchspace_t *scratch);
+extern mp_int isl_sioimath_uiarg_src(unsigned long arg,
+ isl_sioimath_scratchspace_t *scratch);
+extern mp_int isl_sioimath_reinit_big(isl_sioimath_ptr ptr);
+extern void isl_sioimath_set_small(isl_sioimath_ptr ptr, int32_t val);
+extern void isl_sioimath_set_int32(isl_sioimath_ptr ptr, int32_t val);
+extern void isl_sioimath_set_int64(isl_sioimath_ptr ptr, int64_t val);
+extern void isl_sioimath_promote(isl_sioimath_ptr dst);
+extern void isl_sioimath_try_demote(isl_sioimath_ptr dst);
+
+extern void isl_sioimath_init(isl_sioimath_ptr dst);
+extern void isl_sioimath_clear(isl_sioimath_ptr dst);
+extern void isl_sioimath_set(isl_sioimath_ptr dst, isl_sioimath_src val);
+extern void isl_sioimath_set_si(isl_sioimath_ptr dst, long val);
+extern void isl_sioimath_set_ui(isl_sioimath_ptr dst, unsigned long val);
+extern int isl_sioimath_fits_slong(isl_sioimath_src val);
+extern long isl_sioimath_get_si(isl_sioimath_src val);
+extern int isl_sioimath_fits_ulong(isl_sioimath_src val);
+extern unsigned long isl_sioimath_get_ui(isl_sioimath_src val);
+extern double isl_sioimath_get_d(isl_sioimath_src val);
+extern char *isl_sioimath_get_str(isl_sioimath_src val);
+extern void isl_sioimath_abs(isl_sioimath_ptr dst, isl_sioimath_src arg);
+extern void isl_sioimath_neg(isl_sioimath_ptr dst, isl_sioimath_src arg);
+extern void isl_sioimath_swap(isl_sioimath_ptr lhs, isl_sioimath_ptr rhs);
+extern void isl_sioimath_add_ui(isl_sioimath_ptr dst, isl_sioimath lhs,
+ unsigned long rhs);
+extern void isl_sioimath_sub_ui(isl_sioimath_ptr dst, isl_sioimath lhs,
+ unsigned long rhs);
+
+extern void isl_sioimath_add(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+extern void isl_sioimath_sub(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+extern void isl_sioimath_mul(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+extern void isl_sioimath_mul_2exp(isl_sioimath_ptr dst, isl_sioimath lhs,
+ unsigned long rhs);
+extern void isl_sioimath_mul_si(isl_sioimath_ptr dst, isl_sioimath lhs,
+ signed long rhs);
+extern void isl_sioimath_mul_ui(isl_sioimath_ptr dst, isl_sioimath lhs,
+ unsigned long rhs);
+extern void isl_sioimath_pow_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs);
+extern void isl_sioimath_addmul(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+extern void isl_sioimath_addmul_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs);
+extern void isl_sioimath_submul(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+extern void isl_sioimath_submul_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs);
+
+/* Implements the Euclidean algorithm to compute the greatest common divisor of
+ * two values in small representation.
+ */
+static uint32_t isl_sioimath_smallgcd(int32_t lhs, int32_t rhs)
+{
+ uint32_t dividend, divisor, remainder;
+
+ dividend = labs(lhs);
+ divisor = labs(rhs);
+ while (divisor) {
+ remainder = dividend % divisor;
+ dividend = divisor;
+ divisor = remainder;
+ }
+
+ return dividend;
+}
+
+/* Compute the greatest common divisor.
+ *
+ * Per GMP convention, gcd(0,0)==0 and otherwise always positive.
+ */
+void isl_sioimath_gcd(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ int32_t lhssmall, rhssmall;
+ uint32_t smallgcd;
+ isl_sioimath_scratchspace_t scratchlhs, scratchrhs;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall) &&
+ isl_sioimath_decode_small(rhs, &rhssmall)) {
+ smallgcd = isl_sioimath_smallgcd(lhssmall, rhssmall);
+ isl_sioimath_set_small(dst, smallgcd);
+ return;
+ }
+
+ impz_gcd(isl_sioimath_reinit_big(dst),
+ isl_sioimath_bigarg_src(lhs, &scratchlhs),
+ isl_sioimath_bigarg_src(rhs, &scratchrhs));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Compute the lowest common multiple of two numbers.
+ */
+void isl_sioimath_lcm(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ int32_t lhssmall, rhssmall;
+ uint32_t smallgcd;
+ uint64_t multiple;
+ isl_sioimath_scratchspace_t scratchlhs, scratchrhs;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall) &&
+ isl_sioimath_decode_small(rhs, &rhssmall)) {
+ if (lhssmall == 0 || rhssmall == 0) {
+ isl_sioimath_set_small(dst, 0);
+ return;
+ }
+ smallgcd = isl_sioimath_smallgcd(lhssmall, rhssmall);
+ multiple = (uint64_t) abs(lhssmall) * (uint64_t) abs(rhssmall);
+ isl_sioimath_set_int64(dst, multiple / smallgcd);
+ return;
+ }
+
+ impz_lcm(isl_sioimath_reinit_big(dst),
+ isl_sioimath_bigarg_src(lhs, &scratchlhs),
+ isl_sioimath_bigarg_src(rhs, &scratchrhs));
+ isl_sioimath_try_demote(dst);
+}
+
+extern void isl_sioimath_tdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+extern void isl_sioimath_tdiv_q_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs);
+extern void isl_sioimath_cdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+extern void isl_sioimath_fdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+extern void isl_sioimath_fdiv_q_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs);
+extern void isl_sioimath_fdiv_r(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+
+/* Parse a number from a string.
+ * If it has less than 10 characters then it will fit into the small
+ * representation (i.e. strlen("2147483647")). Otherwise, let IMath parse it.
+ */
+void isl_sioimath_read(isl_sioimath_ptr dst, const char *str)
+{
+ int32_t small;
+
+ if (strlen(str) < 10) {
+ small = strtol(str, NULL, 10);
+ isl_sioimath_set_small(dst, small);
+ return;
+ }
+
+ mp_int_read_string(isl_sioimath_reinit_big(dst), 10, str);
+ isl_sioimath_try_demote(dst);
+}
+
+extern int isl_sioimath_sgn(isl_sioimath_src arg);
+extern int isl_sioimath_cmp(isl_sioimath_src lhs, isl_sioimath_src rhs);
+extern int isl_sioimath_cmp_si(isl_sioimath_src lhs, signed long rhs);
+extern int isl_sioimath_abs_cmp(isl_sioimath_src lhs, isl_sioimath_src rhs);
+extern int isl_sioimath_is_divisible_by(isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+
+extern uint32_t isl_sioimath_hash(isl_sioimath_src arg, uint32_t hash);
+extern size_t isl_sioimath_sizeinbase(isl_sioimath_src arg, int base);
+extern void isl_sioimath_print(FILE *out, isl_sioimath_src i, int width);
+
+/* Print an isl_int to FILE*. Adds space padding to the left until at least
+ * width characters are printed.
+ */
+void isl_sioimath_print(FILE *out, isl_sioimath_src i, int width)
+{
+ size_t len;
+ int32_t small;
+ mp_int big;
+ char *buf;
+
+ if (isl_sioimath_decode_small(i, &small)) {
+ fprintf(out, "%*" PRIi32, width, small);
+ return;
+ }
+
+ big = isl_sioimath_get_big(i);
+ len = mp_int_string_len(big, 10);
+ buf = malloc(len);
+ mp_int_to_string(big, 10, buf, len);
+ fprintf(out, "%*s", width, buf);
+ free(buf);
+}
+
+/* Print a number to stdout. Meant for debugging.
+ */
+void isl_sioimath_dump(isl_sioimath_src arg)
+{
+ isl_sioimath_print(stdout, arg, 0);
+}
diff --git a/isl_int_sioimath.h b/isl_int_sioimath.h
new file mode 100644
index 00000000..0b6eb0ed
--- /dev/null
+++ b/isl_int_sioimath.h
@@ -0,0 +1,1223 @@
+/*
+ * Copyright 2015 INRIA Paris-Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Michael Kruse, INRIA Paris-Rocquencourt,
+ * Domaine de Voluceau, Rocquenqourt, B.P. 105,
+ * 78153 Le Chesnay Cedex France
+ */
+#ifndef ISL_INT_SIOIMATH_H
+#define ISL_INT_SIOIMATH_H
+
+#include <inttypes.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <isl_imath.h>
+#include <isl/hash.h>
+
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
+
+/* Visual Studio before VS2015 does not support the inline keyword when
+ * compiling in C mode because it was introduced in C99 which it does not
+ * officially support. Instead, it has a proprietary extension using __inline.
+ */
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+#define inline __inline
+#endif
+
+/* The type to represent integers optimized for small values. It is either a
+ * pointer to an mp_int ( = mpz_t*; big representation) or an int32_t (small
+ * represenation) with a discriminator at the least significant bit. In big
+ * representation it will be always zero because of heap alignment. It is set
+ * to 1 for small representation and use the 32 most significant bits for the
+ * int32_t.
+ *
+ * Structure on 64 bit machines, with 8-byte aligment (3 bits):
+ *
+ * Big representation:
+ * MSB LSB
+ * |------------------------------------------------------------000
+ * | mpz_t* |
+ * | != NULL |
+ *
+ * Small representation:
+ * MSB 32 LSB
+ * |------------------------------|00000000000000000000000000000001
+ * | int32_t |
+ * | 2147483647 ... -2147483647 |
+ * ^
+ * |
+ * discriminator bit
+ *
+ * On 32 bit machines isl_sioimath type is blown up to 8 bytes, i.e.
+ * isl_sioimath is guaranteed to be at least 8 bytes. This is to ensure the
+ * int32_t can be hidden in that type without data loss. In the future we might
+ * optimize this to use 31 hidden bits in a 32 bit pointer. We may also use 63
+ * bits on 64 bit machines, but this comes with the cost of additional overflow
+ * checks because there is no standardized 128 bit integer we could expand to.
+ *
+ * We use native integer types and avoid union structures to avoid assumptions
+ * on the machine's endianness.
+ *
+ * This implementation makes the following assumptions:
+ * - long can represent any int32_t
+ * - mp_small is signed long
+ * - mp_usmall is unsigned long
+ * - adresses returned by malloc are aligned to 2-byte boundaries (leastmost
+ * bit is zero)
+ */
+#if UINT64_MAX > UINTPTR_MAX
+typedef uint64_t isl_sioimath;
+#else
+typedef uintptr_t isl_sioimath;
+#endif
+
+/* The negation of the smallest possible number in int32_t, INT32_MIN
+ * (0x80000000u, -2147483648), cannot be represented in an int32_t, therefore
+ * every operation that may produce this value needs to special-case it.
+ * The operations are:
+ * abs(INT32_MIN)
+ * -INT32_MIN (negation)
+ * -1 * INT32_MIN (multiplication)
+ * INT32_MIN/-1 (any division: divexact, fdiv, cdiv, tdiv)
+ * To avoid checking these cases, we exclude INT32_MIN from small
+ * representation.
+ */
+#define ISL_SIOIMATH_SMALL_MIN (-INT32_MAX)
+
+/* Largest possible number in small representation */
+#define ISL_SIOIMATH_SMALL_MAX INT32_MAX
+
+/* Used for function parameters the function modifies. */
+typedef isl_sioimath *isl_sioimath_ptr;
+
+/* Used for function parameters that are read-only. */
+typedef isl_sioimath isl_sioimath_src;
+
+/* Return whether the argument is stored in small representation.
+ */
+inline int isl_sioimath_is_small(isl_sioimath val)
+{
+ return val & 0x00000001;
+}
+
+/* Return whether the argument is stored in big representation.
+ */
+inline int isl_sioimath_is_big(isl_sioimath val)
+{
+ return !isl_sioimath_is_small(val);
+}
+
+/* Get the number of an isl_int in small representation. Result is undefined if
+ * val is not stored in that format.
+ */
+inline int32_t isl_sioimath_get_small(isl_sioimath val)
+{
+ return val >> 32;
+}
+
+/* Get the number of an in isl_int in big representation. Result is undefined if
+ * val is not stored in that format.
+ */
+inline mp_int isl_sioimath_get_big(isl_sioimath val)
+{
+ return (mp_int)(uintptr_t) val;
+}
+
+/* Return 1 if val is stored in small representation and store its value to
+ * small. We rely on the compiler to optimize the isl_sioimath_get_small such
+ * that the shift is moved into the branch that executes in case of small
+ * representation. If there is no such branch, then a single shift is still
+ * cheaper than introducing branching code.
+ */
+inline int isl_sioimath_decode_small(isl_sioimath val, int32_t *small)
+{
+ *small = isl_sioimath_get_small(val);
+ return isl_sioimath_is_small(val);
+}
+
+/* Return 1 if val is stored in big representation and store its value to big.
+ */
+inline int isl_sioimath_decode_big(isl_sioimath val, mp_int *big)
+{
+ *big = isl_sioimath_get_big(val);
+ return isl_sioimath_is_big(val);
+}
+
+/* Encode a small representation into an isl_int.
+ */
+inline isl_sioimath isl_sioimath_encode_small(int32_t val)
+{
+ return ((isl_sioimath) val) << 32 | 0x00000001;
+}
+
+/* Encode a big representation.
+ */
+inline isl_sioimath isl_sioimath_encode_big(mp_int val)
+{
+ return (isl_sioimath)(uintptr_t) val;
+}
+
+/* A common situation is to call an IMath function with at least one argument
+ * that is currently in small representation or an integer parameter, i.e. a big
+ * representation of the same number is required. Promoting the original
+ * argument comes with multiple problems, such as modifying a read-only
+ * argument, the responsibility of deallocation and the execution cost. Instead,
+ * we make a copy by 'faking' the IMath internal structure.
+ *
+ * We reserve the maximum number of required digits on the stack to avoid heap
+ * allocations.
+ *
+ * mp_digit can be uint32_t or uint16_t. This code must work for little and big
+ * endian digits. The structure for an uint64_t argument and 32-bit mp_digits is
+ * sketched below.
+ *
+ * |----------------------------|
+ * uint64_t
+ *
+ * |-------------||-------------|
+ * mp_digit mp_digit
+ * digits[1] digits[0]
+ * Most sig digit Least sig digit
+ */
+typedef struct {
+ mpz_t big;
+ mp_digit digits[(sizeof(uintmax_t) + sizeof(mp_digit) - 1) /
+ sizeof(mp_digit)];
+} isl_sioimath_scratchspace_t;
+
+/* Convert a native integer to IMath's digit representation. A native integer
+ * might be big- or little endian, but IMath always stores the least significant
+ * digit in the lowest array indices. memcpy therefore is not possible.
+ *
+ * We also have to consider that long and mp_digit can be of different sizes,
+ * depending on the compiler (LP64, LLP64) and IMath's USE_64BIT_WORDS. This
+ * macro should work for all of them.
+ *
+ * "used" is set to the number of written digits. It must be minimal (IMath
+ * checks zeroness using the used field), but always at least one. Also note
+ * that the result of num>>(sizeof(num)*CHAR_BIT) is undefined.
+ */
+#define ISL_SIOIMATH_TO_DIGITS(num, digits, used) \
+ do { \
+ int i = 0; \
+ do { \
+ (digits)[i] = \
+ ((num) >> (sizeof(mp_digit) * CHAR_BIT * i)); \
+ i += 1; \
+ if (i >= (sizeof(num) + sizeof(mp_digit) - 1) / \
+ sizeof(mp_digit)) \
+ break; \
+ if (((num) >> (sizeof(mp_digit) * CHAR_BIT * i)) == 0) \
+ break; \
+ } while (1); \
+ (used) = i; \
+ } while (0)
+
+inline void isl_siomath_uint32_to_digits(uint32_t num, mp_digit *digits,
+ mp_size *used)
+{
+ ISL_SIOIMATH_TO_DIGITS(num, digits, *used);
+}
+
+inline void isl_siomath_ulong_to_digits(unsigned long num, mp_digit *digits,
+ mp_size *used)
+{
+ ISL_SIOIMATH_TO_DIGITS(num, digits, *used);
+}
+
+inline void isl_siomath_uint64_to_digits(uint64_t num, mp_digit *digits,
+ mp_size *used)
+{
+ ISL_SIOIMATH_TO_DIGITS(num, digits, *used);
+}
+
+/* Get the IMath representation of an isl_int without modifying it.
+ * For the case it is not in big representation yet, pass some scratch space we
+ * can use to store the big representation in.
+ * In order to avoid requiring init and free on the scratch space, we directly
+ * modify the internal representation.
+ *
+ * The name derives from its indented use: getting the big representation of an
+ * input (src) argument.
+ */
+inline mp_int isl_sioimath_bigarg_src(isl_sioimath arg,
+ isl_sioimath_scratchspace_t *scratch)
+{
+ mp_int big;
+ int32_t small;
+ uint32_t num;
+
+ if (isl_sioimath_decode_big(arg, &big))
+ return big;
+
+ small = isl_sioimath_get_small(arg);
+ scratch->big.digits = scratch->digits;
+ scratch->big.alloc = ARRAY_SIZE(scratch->digits);
+ if (small >= 0) {
+ scratch->big.sign = MP_ZPOS;
+ num = small;
+ } else {
+ scratch->big.sign = MP_NEG;
+ num = -small;
+ }
+
+ isl_siomath_uint32_to_digits(num, scratch->digits, &scratch->big.used);
+ return &scratch->big;
+}
+
+/* Create a temporary IMath mp_int for a signed long.
+ */
+inline mp_int isl_sioimath_siarg_src(signed long arg,
+ isl_sioimath_scratchspace_t *scratch)
+{
+ unsigned long num;
+
+ scratch->big.digits = scratch->digits;
+ scratch->big.alloc = ARRAY_SIZE(scratch->digits);
+ if (arg >= 0) {
+ scratch->big.sign = MP_ZPOS;
+ num = arg;
+ } else {
+ scratch->big.sign = MP_NEG;
+ num = (arg == LONG_MIN) ? ((unsigned long) LONG_MAX) + 1 : -arg;
+ }
+
+ isl_siomath_ulong_to_digits(num, scratch->digits, &scratch->big.used);
+ return &scratch->big;
+}
+
+/* Create a temporary IMath mp_int for an int64_t.
+ */
+inline mp_int isl_sioimath_si64arg_src(int64_t arg,
+ isl_sioimath_scratchspace_t *scratch)
+{
+ uint64_t num;
+
+ scratch->big.digits = scratch->digits;
+ scratch->big.alloc = ARRAY_SIZE(scratch->digits);
+ if (arg >= 0) {
+ scratch->big.sign = MP_ZPOS;
+ num = arg;
+ } else {
+ scratch->big.sign = MP_NEG;
+ num = (arg == INT64_MIN) ? ((uint64_t) INT64_MAX) + 1 : -arg;
+ }
+
+ isl_siomath_uint64_to_digits(num, scratch->digits, &scratch->big.used);
+ return &scratch->big;
+}
+
+/* Create a temporary IMath mp_int for an unsigned long.
+ */
+inline mp_int isl_sioimath_uiarg_src(unsigned long arg,
+ isl_sioimath_scratchspace_t *scratch)
+{
+ scratch->big.digits = scratch->digits;
+ scratch->big.alloc = ARRAY_SIZE(scratch->digits);
+ scratch->big.sign = MP_ZPOS;
+
+ isl_siomath_ulong_to_digits(arg, scratch->digits, &scratch->big.used);
+ return &scratch->big;
+}
+
+/* Ensure big representation. Does not preserve the current number.
+ * Callers may use the fact that the value _is_ preserved if the presentation
+ * was big before.
+ */
+inline mp_int isl_sioimath_reinit_big(isl_sioimath_ptr ptr)
+{
+ if (isl_sioimath_is_small(*ptr))
+ *ptr = isl_sioimath_encode_big(mp_int_alloc());
+ return isl_sioimath_get_big(*ptr);
+}
+
+/* Set ptr to a number in small representation.
+ */
+inline void isl_sioimath_set_small(isl_sioimath_ptr ptr, int32_t val)
+{
+ if (isl_sioimath_is_big(*ptr))
+ mp_int_free(isl_sioimath_get_big(*ptr));
+ *ptr = isl_sioimath_encode_small(val);
+}
+
+/* Set ptr to val, choosing small representation if possible.
+ */
+inline void isl_sioimath_set_int32(isl_sioimath_ptr ptr, int32_t val)
+{
+ if (ISL_SIOIMATH_SMALL_MIN <= val && val <= ISL_SIOIMATH_SMALL_MAX) {
+ isl_sioimath_set_small(ptr, val);
+ return;
+ }
+
+ mp_int_init_value(isl_sioimath_reinit_big(ptr), val);
+}
+
+/* Assign an int64_t number using small representation if possible.
+ */
+inline void isl_sioimath_set_int64(isl_sioimath_ptr ptr, int64_t val)
+{
+ if (ISL_SIOIMATH_SMALL_MIN <= val && val <= ISL_SIOIMATH_SMALL_MAX) {
+ isl_sioimath_set_small(ptr, val);
+ return;
+ }
+
+ isl_sioimath_scratchspace_t scratch;
+ mp_int_copy(isl_sioimath_si64arg_src(val, &scratch),
+ isl_sioimath_reinit_big(ptr));
+}
+
+/* Convert to big representation while preserving the current number.
+ */
+inline void isl_sioimath_promote(isl_sioimath_ptr dst)
+{
+ int32_t small;
+
+ if (isl_sioimath_is_big(*dst))
+ return;
+
+ small = isl_sioimath_get_small(*dst);
+ mp_int_set_value(isl_sioimath_reinit_big(dst), small);
+}
+
+/* Convert to small representation while preserving the current number. Does
+ * nothing if dst doesn't fit small representation.
+ */
+inline void isl_sioimath_try_demote(isl_sioimath_ptr dst)
+{
+ mp_small small;
+
+ if (isl_sioimath_is_small(*dst))
+ return;
+
+ if (mp_int_to_int(isl_sioimath_get_big(*dst), &small) != MP_OK)
+ return;
+
+ if (ISL_SIOIMATH_SMALL_MIN <= small && small <= ISL_SIOIMATH_SMALL_MAX)
+ isl_sioimath_set_small(dst, small);
+}
+
+/* Initialize an isl_int. The implicit value is 0 in small representation.
+ */
+inline void isl_sioimath_init(isl_sioimath_ptr dst)
+{
+ *dst = isl_sioimath_encode_small(0);
+}
+
+/* Free the resources taken by an isl_int.
+ */
+inline void isl_sioimath_clear(isl_sioimath_ptr dst)
+{
+ if (isl_sioimath_is_small(*dst))
+ return;
+
+ mp_int_free(isl_sioimath_get_big(*dst));
+}
+
+/* Copy the value of one isl_int to another.
+ */
+inline void isl_sioimath_set(isl_sioimath_ptr dst, isl_sioimath_src val)
+{
+ if (isl_sioimath_is_small(val)) {
+ isl_sioimath_set_small(dst, isl_sioimath_get_small(val));
+ return;
+ }
+
+ mp_int_copy(isl_sioimath_get_big(val), isl_sioimath_reinit_big(dst));
+}
+
+/* Store a signed long into an isl_int.
+ */
+inline void isl_sioimath_set_si(isl_sioimath_ptr dst, long val)
+{
+ if (ISL_SIOIMATH_SMALL_MIN <= val && val <= ISL_SIOIMATH_SMALL_MAX) {
+ isl_sioimath_set_small(dst, val);
+ return;
+ }
+
+ mp_int_set_value(isl_sioimath_reinit_big(dst), val);
+}
+
+/* Store an unsigned long into an isl_int.
+ */
+inline void isl_sioimath_set_ui(isl_sioimath_ptr dst, unsigned long val)
+{
+ if (val <= ISL_SIOIMATH_SMALL_MAX) {
+ isl_sioimath_set_small(dst, val);
+ return;
+ }
+
+ mp_int_set_uvalue(isl_sioimath_reinit_big(dst), val);
+}
+
+/* Return whether a number can be represented by a signed long.
+ */
+inline int isl_sioimath_fits_slong(isl_sioimath_src val)
+{
+ mp_small dummy;
+
+ if (isl_sioimath_is_small(val))
+ return 1;
+
+ return mp_int_to_int(isl_sioimath_get_big(val), &dummy) == MP_OK;
+}
+
+/* Return a number as signed long. Result is undefined if the number cannot be
+ * represented as long.
+ */
+inline long isl_sioimath_get_si(isl_sioimath_src val)
+{
+ mp_small result;
+
+ if (isl_sioimath_is_small(val))
+ return isl_sioimath_get_small(val);
+
+ mp_int_to_int(isl_sioimath_get_big(val), &result);
+ return result;
+}
+
+/* Return whether a number can be represented as unsigned long.
+ */
+inline int isl_sioimath_fits_ulong(isl_sioimath_src val)
+{
+ mp_usmall dummy;
+
+ if (isl_sioimath_is_small(val))
+ return isl_sioimath_get_small(val) >= 0;
+
+ return mp_int_to_uint(isl_sioimath_get_big(val), &dummy) == MP_OK;
+}
+
+/* Return a number as unsigned long. Result is undefined if the number cannot be
+ * represented as unsigned long.
+ */
+inline unsigned long isl_sioimath_get_ui(isl_sioimath_src val)
+{
+ mp_usmall result;
+
+ if (isl_sioimath_is_small(val))
+ return isl_sioimath_get_small(val);
+
+ mp_int_to_uint(isl_sioimath_get_big(val), &result);
+ return result;
+}
+
+/* Return a number as floating point value.
+ */
+inline double isl_sioimath_get_d(isl_sioimath_src val)
+{
+ mp_int big;
+ double result = 0;
+ int i;
+
+ if (isl_sioimath_is_small(val))
+ return isl_sioimath_get_small(val);
+
+ big = isl_sioimath_get_big(val);
+ for (i = 0; i < big->used; ++i)
+ result = result * (double) ((uintmax_t) MP_DIGIT_MAX + 1) +
+ (double) big->digits[i];
+
+ if (big->sign == MP_NEG)
+ result = -result;
+
+ return result;
+}
+
+/* Format a number as decimal string.
+ *
+ * The largest possible string from small representation is 12 characters
+ * ("-2147483647").
+ */
+inline char *isl_sioimath_get_str(isl_sioimath_src val)
+{
+ char *result;
+
+ if (isl_sioimath_is_small(val)) {
+ result = malloc(12);
+ snprintf(result, 12, "%" PRIi32, isl_sioimath_get_small(val));
+ return result;
+ }
+
+ return impz_get_str(NULL, 10, isl_sioimath_get_big(val));
+}
+
+/* Return the absolute value.
+ */
+inline void isl_sioimath_abs(isl_sioimath_ptr dst, isl_sioimath_src arg)
+{
+ if (isl_sioimath_is_small(arg)) {
+ isl_sioimath_set_small(dst, labs(isl_sioimath_get_small(arg)));
+ return;
+ }
+
+ mp_int_abs(isl_sioimath_get_big(arg), isl_sioimath_reinit_big(dst));
+}
+
+/* Return the negation of a number.
+ */
+inline void isl_sioimath_neg(isl_sioimath_ptr dst, isl_sioimath_src arg)
+{
+ if (isl_sioimath_is_small(arg)) {
+ isl_sioimath_set_small(dst, -isl_sioimath_get_small(arg));
+ return;
+ }
+
+ mp_int_neg(isl_sioimath_get_big(arg), isl_sioimath_reinit_big(dst));
+}
+
+/* Swap two isl_ints.
+ *
+ * isl_sioimath can be copied bytewise; nothing depends on its address. It can
+ * also be stored in a CPU register.
+ */
+inline void isl_sioimath_swap(isl_sioimath_ptr lhs, isl_sioimath_ptr rhs)
+{
+ isl_sioimath tmp = *lhs;
+ *lhs = *rhs;
+ *rhs = tmp;
+}
+
+/* Add an unsigned long to the number.
+ *
+ * On LP64 unsigned long exceeds the range of an int64_t, therefore we check in
+ * advance whether small representation possibly overflows.
+ */
+inline void isl_sioimath_add_ui(isl_sioimath_ptr dst, isl_sioimath lhs,
+ unsigned long rhs)
+{
+ int32_t smalllhs;
+ isl_sioimath_scratchspace_t lhsscratch;
+
+ if (isl_sioimath_decode_small(lhs, &smalllhs) &&
+ (rhs <= (uint64_t) INT64_MAX - (uint64_t) ISL_SIOIMATH_SMALL_MAX)) {
+ isl_sioimath_set_int64(dst, (int64_t) smalllhs + rhs);
+ return;
+ }
+
+ impz_add_ui(isl_sioimath_reinit_big(dst),
+ isl_sioimath_bigarg_src(lhs, &lhsscratch), rhs);
+ isl_sioimath_try_demote(dst);
+}
+
+/* Subtract an unsigned long.
+ *
+ * On LP64 unsigned long exceeds the range of an int64_t. If
+ * ISL_SIOIMATH_SMALL_MIN-rhs>=INT64_MIN we can do the calculation using int64_t
+ * without risking an overflow.
+ */
+inline void isl_sioimath_sub_ui(isl_sioimath_ptr dst, isl_sioimath lhs,
+ unsigned long rhs)
+{
+ int32_t smalllhs;
+ isl_sioimath_scratchspace_t lhsscratch;
+
+ if (isl_sioimath_decode_small(lhs, &smalllhs) &&
+ (rhs < (uint64_t) INT64_MIN - (uint64_t) ISL_SIOIMATH_SMALL_MIN)) {
+ isl_sioimath_set_int64(dst, (int64_t) smalllhs - rhs);
+ return;
+ }
+
+ impz_sub_ui(isl_sioimath_reinit_big(dst),
+ isl_sioimath_bigarg_src(lhs, &lhsscratch), rhs);
+ isl_sioimath_try_demote(dst);
+}
+
+/* Sum of two isl_ints.
+ */
+inline void isl_sioimath_add(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ isl_sioimath_scratchspace_t scratchlhs, scratchrhs;
+ int32_t smalllhs, smallrhs;
+
+ if (isl_sioimath_decode_small(lhs, &smalllhs) &&
+ isl_sioimath_decode_small(rhs, &smallrhs)) {
+ isl_sioimath_set_int64(
+ dst, (int64_t) smalllhs + (int64_t) smallrhs);
+ return;
+ }
+
+ mp_int_add(isl_sioimath_bigarg_src(lhs, &scratchlhs),
+ isl_sioimath_bigarg_src(rhs, &scratchrhs),
+ isl_sioimath_reinit_big(dst));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Subtract two isl_ints.
+ */
+inline void isl_sioimath_sub(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ isl_sioimath_scratchspace_t scratchlhs, scratchrhs;
+ int32_t smalllhs, smallrhs;
+
+ if (isl_sioimath_decode_small(lhs, &smalllhs) &&
+ isl_sioimath_decode_small(rhs, &smallrhs)) {
+ isl_sioimath_set_int64(
+ dst, (int64_t) smalllhs - (int64_t) smallrhs);
+ return;
+ }
+
+ mp_int_sub(isl_sioimath_bigarg_src(lhs, &scratchlhs),
+ isl_sioimath_bigarg_src(rhs, &scratchrhs),
+ isl_sioimath_reinit_big(dst));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Multiply two isl_ints.
+ */
+inline void isl_sioimath_mul(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ isl_sioimath_scratchspace_t scratchlhs, scratchrhs;
+ int32_t smalllhs, smallrhs;
+
+ if (isl_sioimath_decode_small(lhs, &smalllhs) &&
+ isl_sioimath_decode_small(rhs, &smallrhs)) {
+ isl_sioimath_set_int64(
+ dst, (int64_t) smalllhs * (int64_t) smallrhs);
+ return;
+ }
+
+ mp_int_mul(isl_sioimath_bigarg_src(lhs, &scratchlhs),
+ isl_sioimath_bigarg_src(rhs, &scratchrhs),
+ isl_sioimath_reinit_big(dst));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Shift lhs by rhs bits to the left and store the result in dst. Effectively,
+ * this operation computes 'lhs * 2^rhs'.
+ */
+inline void isl_sioimath_mul_2exp(isl_sioimath_ptr dst, isl_sioimath lhs,
+ unsigned long rhs)
+{
+ isl_sioimath_scratchspace_t scratchlhs;
+ int32_t smalllhs;
+
+ if (isl_sioimath_decode_small(lhs, &smalllhs) && (rhs <= 32ul)) {
+ isl_sioimath_set_int64(dst, ((int64_t) smalllhs) << rhs);
+ return;
+ }
+
+ mp_int_mul_pow2(isl_sioimath_bigarg_src(lhs, &scratchlhs), rhs,
+ isl_sioimath_reinit_big(dst));
+}
+
+/* Multiply an isl_int and a signed long.
+ */
+inline void isl_sioimath_mul_si(isl_sioimath_ptr dst, isl_sioimath lhs,
+ signed long rhs)
+{
+ isl_sioimath_scratchspace_t scratchlhs, scratchrhs;
+ int32_t smalllhs;
+
+ if (isl_sioimath_decode_small(lhs, &smalllhs) && (rhs > LONG_MIN) &&
+ (labs(rhs) <= UINT32_MAX)) {
+ isl_sioimath_set_int64(dst, (int64_t) smalllhs * (int64_t) rhs);
+ return;
+ }
+
+ mp_int_mul(isl_sioimath_bigarg_src(lhs, &scratchlhs),
+ isl_sioimath_siarg_src(rhs, &scratchrhs),
+ isl_sioimath_reinit_big(dst));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Multiply an isl_int and an unsigned long.
+ */
+inline void isl_sioimath_mul_ui(isl_sioimath_ptr dst, isl_sioimath lhs,
+ unsigned long rhs)
+{
+ isl_sioimath_scratchspace_t scratchlhs, scratchrhs;
+ int32_t smalllhs;
+
+ if (isl_sioimath_decode_small(lhs, &smalllhs) && (rhs <= UINT32_MAX)) {
+ isl_sioimath_set_int64(dst, (int64_t) smalllhs * (int64_t) rhs);
+ return;
+ }
+
+ mp_int_mul(isl_sioimath_bigarg_src(lhs, &scratchlhs),
+ isl_sioimath_uiarg_src(rhs, &scratchrhs),
+ isl_sioimath_reinit_big(dst));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Compute the power of an isl_int to an unsigned long.
+ * Always let IMath do it; the result is unlikely to be small except in some
+ * special cases.
+ * Note: 0^0 == 1
+ */
+inline void isl_sioimath_pow_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs)
+{
+ isl_sioimath_scratchspace_t scratchlhs, scratchrhs;
+ int32_t smalllhs;
+
+ switch (rhs) {
+ case 0:
+ isl_sioimath_set_small(dst, 1);
+ return;
+ case 1:
+ isl_sioimath_set(dst, lhs);
+ return;
+ case 2:
+ isl_sioimath_mul(dst, lhs, lhs);
+ return;
+ }
+
+ if (isl_sioimath_decode_small(lhs, &smalllhs)) {
+ switch (smalllhs) {
+ case 0:
+ isl_sioimath_set_small(dst, 0);
+ return;
+ case 1:
+ isl_sioimath_set_small(dst, 1);
+ return;
+ case 2:
+ isl_sioimath_set_small(dst, 1);
+ isl_sioimath_mul_2exp(dst, *dst, rhs);
+ return;
+ default:
+ if ((MP_SMALL_MIN <= rhs) && (rhs <= MP_SMALL_MAX)) {
+ mp_int_expt_value(smalllhs, rhs,
+ isl_sioimath_reinit_big(dst));
+ isl_sioimath_try_demote(dst);
+ return;
+ }
+ }
+ }
+
+ mp_int_expt_full(isl_sioimath_bigarg_src(lhs, &scratchlhs),
+ isl_sioimath_uiarg_src(rhs, &scratchrhs),
+ isl_sioimath_reinit_big(dst));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Fused multiply-add.
+ */
+inline void isl_sioimath_addmul(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ isl_sioimath tmp;
+ isl_sioimath_init(&tmp);
+ isl_sioimath_mul(&tmp, lhs, rhs);
+ isl_sioimath_add(dst, *dst, tmp);
+ isl_sioimath_clear(&tmp);
+}
+
+/* Fused multiply-add with an unsigned long.
+ */
+inline void isl_sioimath_addmul_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs)
+{
+ isl_sioimath tmp;
+ isl_sioimath_init(&tmp);
+ isl_sioimath_mul_ui(&tmp, lhs, rhs);
+ isl_sioimath_add(dst, *dst, tmp);
+ isl_sioimath_clear(&tmp);
+}
+
+/* Fused multiply-subtract.
+ */
+inline void isl_sioimath_submul(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ isl_sioimath tmp;
+ isl_sioimath_init(&tmp);
+ isl_sioimath_mul(&tmp, lhs, rhs);
+ isl_sioimath_sub(dst, *dst, tmp);
+ isl_sioimath_clear(&tmp);
+}
+
+/* Fused multiply-add with an unsigned long.
+ */
+inline void isl_sioimath_submul_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs)
+{
+ isl_sioimath tmp;
+ isl_sioimath_init(&tmp);
+ isl_sioimath_mul_ui(&tmp, lhs, rhs);
+ isl_sioimath_sub(dst, *dst, tmp);
+ isl_sioimath_clear(&tmp);
+}
+
+void isl_sioimath_gcd(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+void isl_sioimath_lcm(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs);
+
+/* Divide lhs by rhs, rounding to zero (Truncate).
+ */
+inline void isl_sioimath_tdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ isl_sioimath_scratchspace_t lhsscratch, rhsscratch;
+ int32_t lhssmall, rhssmall;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall) &&
+ isl_sioimath_decode_small(rhs, &rhssmall)) {
+ isl_sioimath_set_small(dst, lhssmall / rhssmall);
+ return;
+ }
+
+ mp_int_div(isl_sioimath_bigarg_src(lhs, &lhsscratch),
+ isl_sioimath_bigarg_src(rhs, &rhsscratch),
+ isl_sioimath_reinit_big(dst), NULL);
+ isl_sioimath_try_demote(dst);
+ return;
+}
+
+/* Divide lhs by an unsigned long rhs, rounding to zero (Truncate).
+ */
+inline void isl_sioimath_tdiv_q_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs)
+{
+ isl_sioimath_scratchspace_t lhsscratch, rhsscratch;
+ int32_t lhssmall;
+
+ if (isl_sioimath_is_small(lhs) && (rhs <= (unsigned long) INT32_MAX)) {
+ lhssmall = isl_sioimath_get_small(lhs);
+ isl_sioimath_set_small(dst, lhssmall / (int32_t) rhs);
+ return;
+ }
+
+ if (rhs <= MP_SMALL_MAX) {
+ mp_int_div_value(isl_sioimath_bigarg_src(lhs, &lhsscratch), rhs,
+ isl_sioimath_reinit_big(dst), NULL);
+ isl_sioimath_try_demote(dst);
+ return;
+ }
+
+ mp_int_div(isl_sioimath_bigarg_src(lhs, &lhsscratch),
+ isl_sioimath_uiarg_src(rhs, &rhsscratch),
+ isl_sioimath_reinit_big(dst), NULL);
+ isl_sioimath_try_demote(dst);
+}
+
+/* Divide lhs by rhs, rounding to positive infinity (Ceil).
+ */
+inline void isl_sioimath_cdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ int32_t lhssmall, rhssmall;
+ isl_sioimath_scratchspace_t lhsscratch, rhsscratch;
+ int32_t q;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall) &&
+ isl_sioimath_decode_small(rhs, &rhssmall)) {
+ if ((lhssmall >= 0) && (rhssmall >= 0))
+ q = ((int64_t) lhssmall + (int64_t) rhssmall - 1) /
+ rhssmall;
+ else if ((lhssmall < 0) && (rhssmall < 0))
+ q = ((int64_t) lhssmall + (int64_t) rhssmall + 1) /
+ rhssmall;
+ else
+ q = lhssmall / rhssmall;
+ isl_sioimath_set_small(dst, q);
+ return;
+ }
+
+ impz_cdiv_q(isl_sioimath_reinit_big(dst),
+ isl_sioimath_bigarg_src(lhs, &lhsscratch),
+ isl_sioimath_bigarg_src(rhs, &rhsscratch));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Divide lhs by rhs, rounding to negative infinity (Floor).
+ */
+inline void isl_sioimath_fdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ isl_sioimath_scratchspace_t lhsscratch, rhsscratch;
+ int32_t lhssmall, rhssmall;
+ int32_t q;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall) &&
+ isl_sioimath_decode_small(rhs, &rhssmall)) {
+ if ((lhssmall < 0) && (rhssmall >= 0))
+ q = ((int64_t) lhssmall - ((int64_t) rhssmall - 1)) /
+ rhssmall;
+ else if ((lhssmall >= 0) && (rhssmall < 0))
+ q = ((int64_t) lhssmall - ((int64_t) rhssmall + 1)) /
+ rhssmall;
+ else
+ q = lhssmall / rhssmall;
+ isl_sioimath_set_small(dst, q);
+ return;
+ }
+
+ impz_fdiv_q(isl_sioimath_reinit_big(dst),
+ isl_sioimath_bigarg_src(lhs, &lhsscratch),
+ isl_sioimath_bigarg_src(rhs, &rhsscratch));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Compute the division of lhs by a rhs of type unsigned long, rounding towards
+ * negative infinity (Floor).
+ */
+inline void isl_sioimath_fdiv_q_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ unsigned long rhs)
+{
+ isl_sioimath_scratchspace_t lhsscratch, rhsscratch;
+ int32_t lhssmall, q;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall) && (rhs <= INT32_MAX)) {
+ if (lhssmall >= 0)
+ q = (uint32_t) lhssmall / rhs;
+ else
+ q = ((int64_t) lhssmall - ((int64_t) rhs - 1)) /
+ (int64_t) rhs;
+ isl_sioimath_set_small(dst, q);
+ return;
+ }
+
+ impz_fdiv_q(isl_sioimath_reinit_big(dst),
+ isl_sioimath_bigarg_src(lhs, &lhsscratch),
+ isl_sioimath_uiarg_src(rhs, &rhsscratch));
+ isl_sioimath_try_demote(dst);
+}
+
+/* Get the remainder of: lhs divided by rhs rounded towards negative infinite
+ * (Floor).
+ */
+inline void isl_sioimath_fdiv_r(isl_sioimath_ptr dst, isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ isl_sioimath_scratchspace_t lhsscratch, rhsscratch;
+ int64_t lhssmall, rhssmall;
+ int32_t r;
+
+ if (isl_sioimath_is_small(lhs) && isl_sioimath_is_small(rhs)) {
+ lhssmall = isl_sioimath_get_small(lhs);
+ rhssmall = isl_sioimath_get_small(rhs);
+ r = (rhssmall + lhssmall % rhssmall) % rhssmall;
+ isl_sioimath_set_small(dst, r);
+ return;
+ }
+
+ impz_fdiv_r(isl_sioimath_reinit_big(dst),
+ isl_sioimath_bigarg_src(lhs, &lhsscratch),
+ isl_sioimath_bigarg_src(rhs, &rhsscratch));
+ isl_sioimath_try_demote(dst);
+}
+
+void isl_sioimath_read(isl_sioimath_ptr dst, const char *str);
+
+/* Return:
+ * +1 for a positive number
+ * -1 for a negative number
+ * 0 if the number is zero
+ */
+inline int isl_sioimath_sgn(isl_sioimath_src arg)
+{
+ int32_t small;
+
+ if (isl_sioimath_decode_small(arg, &small))
+ return (small > 0) - (small < 0);
+
+ return mp_int_compare_zero(isl_sioimath_get_big(arg));
+}
+
+/* Return:
+ * +1 if lhs > rhs
+ * -1 if lhs < rhs
+ * 0 if lhs = rhs
+ */
+inline int isl_sioimath_cmp(isl_sioimath_src lhs, isl_sioimath_src rhs)
+{
+ isl_sioimath_scratchspace_t lhsscratch, rhsscratch;
+ int32_t lhssmall, rhssmall;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall) &&
+ isl_sioimath_decode_small(rhs, &rhssmall))
+ return (lhssmall > rhssmall) - (lhssmall < rhssmall);
+
+ if (isl_sioimath_decode_small(rhs, &rhssmall))
+ return mp_int_compare_value(
+ isl_sioimath_bigarg_src(lhs, &lhsscratch), rhssmall);
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall))
+ return -mp_int_compare_value(
+ isl_sioimath_bigarg_src(rhs, &rhsscratch), lhssmall);
+
+ return mp_int_compare(
+ isl_sioimath_get_big(lhs), isl_sioimath_get_big(rhs));
+}
+
+/* As isl_sioimath_cmp, but with signed long rhs.
+ */
+inline int isl_sioimath_cmp_si(isl_sioimath_src lhs, signed long rhs)
+{
+ int32_t lhssmall;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall))
+ return (lhssmall > rhs) - (lhssmall < rhs);
+
+ return mp_int_compare_value(isl_sioimath_get_big(lhs), rhs);
+}
+
+/* Return:
+ * +1 if |lhs| > |rhs|
+ * -1 if |lhs| < |rhs|
+ * 0 if |lhs| = |rhs|
+ */
+inline int isl_sioimath_abs_cmp(isl_sioimath_src lhs, isl_sioimath_src rhs)
+{
+ isl_sioimath_scratchspace_t lhsscratch, rhsscratch;
+ int32_t lhssmall, rhssmall;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall) &&
+ isl_sioimath_decode_small(rhs, &rhssmall)) {
+ lhssmall = labs(lhssmall);
+ rhssmall = labs(rhssmall);
+ return (lhssmall > rhssmall) - (lhssmall < rhssmall);
+ }
+
+ return mp_int_compare_unsigned(
+ isl_sioimath_bigarg_src(lhs, &lhsscratch),
+ isl_sioimath_bigarg_src(rhs, &rhsscratch));
+}
+
+/* Return whether lhs is divisible by rhs.
+ */
+inline int isl_sioimath_is_divisible_by(isl_sioimath_src lhs,
+ isl_sioimath_src rhs)
+{
+ isl_sioimath_scratchspace_t lhsscratch, rhsscratch;
+ int32_t lhssmall, rhssmall;
+ mpz_t rem;
+ int cmp;
+
+ if (isl_sioimath_decode_small(lhs, &lhssmall) &&
+ isl_sioimath_decode_small(rhs, &rhssmall))
+ return lhssmall % rhssmall == 0;
+
+ if (isl_sioimath_decode_small(rhs, &rhssmall))
+ return mp_int_divisible_value(
+ isl_sioimath_bigarg_src(lhs, &lhsscratch), rhssmall);
+
+ mp_int_init(&rem);
+ mp_int_div(isl_sioimath_bigarg_src(lhs, &lhsscratch),
+ isl_sioimath_bigarg_src(rhs, &rhsscratch), NULL, &rem);
+ cmp = mp_int_compare_zero(&rem);
+ mp_int_clear(&rem);
+ return cmp == 0;
+}
+
+/* Return a hash code of an isl_sioimath.
+ * The hash code for a number in small and big representation must be identical
+ * on the same machine because small representation if not obligatory if fits.
+ */
+inline uint32_t isl_sioimath_hash(isl_sioimath_src arg, uint32_t hash)
+{
+ int32_t small;
+ int i;
+ uint32_t num;
+ mp_digit digits[(sizeof(uint32_t) + sizeof(mp_digit) - 1) /
+ sizeof(mp_digit)];
+ mp_size used;
+ const unsigned char *digitdata = (const unsigned char *) &digits;
+
+ if (isl_sioimath_decode_small(arg, &small)) {
+ if (small < 0)
+ isl_hash_byte(hash, 0xFF);
+ num = labs(small);
+
+ isl_siomath_uint32_to_digits(num, digits, &used);
+ for (i = 0; i < used * sizeof(mp_digit); i += 1)
+ isl_hash_byte(hash, digitdata[i]);
+ return hash;
+ }
+
+ return isl_imath_hash(isl_sioimath_get_big(arg), hash);
+}
+
+/* Return the number of digits in a number of the given base or more, i.e. the
+ * string length without sign and null terminator.
+ *
+ * Current implementation for small representation returns the maximal number
+ * of binary digits in that representation, which can be much larger than the
+ * smallest possible solution.
+ */
+inline size_t isl_sioimath_sizeinbase(isl_sioimath_src arg, int base)
+{
+ int32_t small;
+
+ if (isl_sioimath_decode_small(arg, &small))
+ return sizeof(int32_t) * CHAR_BIT - 1;
+
+ return impz_sizeinbase(isl_sioimath_get_big(arg), base);
+}
+
+void isl_sioimath_print(FILE *out, isl_sioimath_src i, int width);
+void isl_sioimath_dump(isl_sioimath_src arg);
+
+typedef isl_sioimath isl_int[1];
+#define isl_int_init(i) isl_sioimath_init((i))
+#define isl_int_clear(i) isl_sioimath_clear((i))
+
+#define isl_int_set(r, i) isl_sioimath_set((r), *(i))
+#define isl_int_set_si(r, i) isl_sioimath_set_si((r), i)
+#define isl_int_set_ui(r, i) isl_sioimath_set_ui((r), i)
+#define isl_int_fits_slong(r) isl_sioimath_fits_slong(*(r))
+#define isl_int_get_si(r) isl_sioimath_get_si(*(r))
+#define isl_int_fits_ulong(r) isl_sioimath_fits_ulong(*(r))
+#define isl_int_get_ui(r) isl_sioimath_get_ui(*(r))
+#define isl_int_get_d(r) isl_sioimath_get_d(*(r))
+#define isl_int_get_str(r) isl_sioimath_get_str(*(r))
+#define isl_int_abs(r, i) isl_sioimath_abs((r), *(i))
+#define isl_int_neg(r, i) isl_sioimath_neg((r), *(i))
+#define isl_int_swap(i, j) isl_sioimath_swap((i), (j))
+#define isl_int_swap_or_set(i, j) isl_sioimath_swap((i), (j))
+#define isl_int_add_ui(r, i, j) isl_sioimath_add_ui((r), *(i), j)
+#define isl_int_sub_ui(r, i, j) isl_sioimath_sub_ui((r), *(i), j)
+
+#define isl_int_add(r, i, j) isl_sioimath_add((r), *(i), *(j))
+#define isl_int_sub(r, i, j) isl_sioimath_sub((r), *(i), *(j))
+#define isl_int_mul(r, i, j) isl_sioimath_mul((r), *(i), *(j))
+#define isl_int_mul_2exp(r, i, j) isl_sioimath_mul_2exp((r), *(i), j)
+#define isl_int_mul_si(r, i, j) isl_sioimath_mul_si((r), *(i), j)
+#define isl_int_mul_ui(r, i, j) isl_sioimath_mul_ui((r), *(i), j)
+#define isl_int_pow_ui(r, i, j) isl_sioimath_pow_ui((r), *(i), j)
+#define isl_int_addmul(r, i, j) isl_sioimath_addmul((r), *(i), *(j))
+#define isl_int_addmul_ui(r, i, j) isl_sioimath_addmul_ui((r), *(i), j)
+#define isl_int_submul(r, i, j) isl_sioimath_submul((r), *(i), *(j))
+#define isl_int_submul_ui(r, i, j) isl_sioimath_submul_ui((r), *(i), j)
+
+#define isl_int_gcd(r, i, j) isl_sioimath_gcd((r), *(i), *(j))
+#define isl_int_lcm(r, i, j) isl_sioimath_lcm((r), *(i), *(j))
+#define isl_int_divexact(r, i, j) isl_sioimath_tdiv_q((r), *(i), *(j))
+#define isl_int_divexact_ui(r, i, j) isl_sioimath_tdiv_q_ui((r), *(i), j)
+#define isl_int_tdiv_q(r, i, j) isl_sioimath_tdiv_q((r), *(i), *(j))
+#define isl_int_cdiv_q(r, i, j) isl_sioimath_cdiv_q((r), *(i), *(j))
+#define isl_int_fdiv_q(r, i, j) isl_sioimath_fdiv_q((r), *(i), *(j))
+#define isl_int_fdiv_r(r, i, j) isl_sioimath_fdiv_r((r), *(i), *(j))
+#define isl_int_fdiv_q_ui(r, i, j) isl_sioimath_fdiv_q_ui((r), *(i), j)
+
+#define isl_int_read(r, s) isl_sioimath_read((r), s)
+#define isl_int_sgn(i) isl_sioimath_sgn(*(i))
+#define isl_int_cmp(i, j) isl_sioimath_cmp(*(i), *(j))
+#define isl_int_cmp_si(i, si) isl_sioimath_cmp_si(*(i), si)
+#define isl_int_eq(i, j) (isl_sioimath_cmp(*(i), *(j)) == 0)
+#define isl_int_ne(i, j) (isl_sioimath_cmp(*(i), *(j)) != 0)
+#define isl_int_lt(i, j) (isl_sioimath_cmp(*(i), *(j)) < 0)
+#define isl_int_le(i, j) (isl_sioimath_cmp(*(i), *(j)) <= 0)
+#define isl_int_gt(i, j) (isl_sioimath_cmp(*(i), *(j)) > 0)
+#define isl_int_ge(i, j) (isl_sioimath_cmp(*(i), *(j)) >= 0)
+#define isl_int_abs_cmp(i, j) isl_sioimath_abs_cmp(*(i), *(j))
+#define isl_int_abs_eq(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) == 0)
+#define isl_int_abs_ne(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) != 0)
+#define isl_int_abs_lt(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) < 0)
+#define isl_int_abs_gt(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) > 0)
+#define isl_int_abs_ge(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) >= 0)
+#define isl_int_is_divisible_by(i, j) isl_sioimath_is_divisible_by(*(i), *(j))
+
+#define isl_int_hash(v, h) isl_sioimath_hash(*(v), h)
+#define isl_int_free_str(s) free(s)
+#define isl_int_print(out, i, width) isl_sioimath_print(out, *(i), width)
+
+#endif /* ISL_INT_SIOIMATH_H */
diff --git a/isl_local_space.c b/isl_local_space.c
index 7b3347cf..7c06b59d 100644
--- a/isl_local_space.c
+++ b/isl_local_space.c
@@ -740,18 +740,20 @@ int isl_local_space_div_is_known(__isl_keep isl_local_space *ls, int div)
return !isl_int_is_zero(ls->div->row[div][0]);
}
-int isl_local_space_divs_known(__isl_keep isl_local_space *ls)
+/* Does "ls" have an explicit representation for all local variables?
+ */
+isl_bool isl_local_space_divs_known(__isl_keep isl_local_space *ls)
{
int i;
if (!ls)
- return -1;
+ return isl_bool_error;
for (i = 0; i < ls->div->n_row; ++i)
if (isl_int_is_zero(ls->div->row[i][0]))
- return 0;
+ return isl_bool_false;
- return 1;
+ return isl_bool_true;
}
__isl_give isl_local_space *isl_local_space_domain(
diff --git a/isl_local_space_private.h b/isl_local_space_private.h
index 4d7e69ff..5d533050 100644
--- a/isl_local_space_private.h
+++ b/isl_local_space_private.h
@@ -32,7 +32,7 @@ unsigned isl_local_space_offset(__isl_keep isl_local_space *ls,
__isl_give isl_local_space *isl_local_space_replace_divs(
__isl_take isl_local_space *ls, __isl_take isl_mat *div);
int isl_local_space_div_is_known(__isl_keep isl_local_space *ls, int div);
-int isl_local_space_divs_known(__isl_keep isl_local_space *ls);
+isl_bool isl_local_space_divs_known(__isl_keep isl_local_space *ls);
__isl_give isl_local_space *isl_local_space_substitute_equalities(
__isl_take isl_local_space *ls, __isl_take isl_basic_set *eq);
diff --git a/isl_map.c b/isl_map.c
index 6dbb5759..f92dd616 100644
--- a/isl_map.c
+++ b/isl_map.c
@@ -322,6 +322,38 @@ __isl_give isl_local_space *isl_basic_set_get_local_space(
return isl_basic_map_get_local_space(bset);
}
+/* For each known div d = floor(f/m), add the constraints
+ *
+ * f - m d >= 0
+ * -(f-(n-1)) + m d >= 0
+ *
+ * Do not finalize the result.
+ */
+static __isl_give isl_basic_map *add_known_div_constraints(
+ __isl_take isl_basic_map *bmap)
+{
+ int i;
+ unsigned n_div;
+
+ if (!bmap)
+ return NULL;
+ n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ if (n_div == 0)
+ return bmap;
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
+ if (!bmap)
+ return NULL;
+ for (i = 0; i < n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ if (isl_basic_map_add_div_constraints(bmap, i) < 0)
+ return isl_basic_map_free(bmap);
+ }
+
+ return bmap;
+}
+
__isl_give isl_basic_map *isl_basic_map_from_local_space(
__isl_take isl_local_space *ls)
{
@@ -340,11 +372,9 @@ __isl_give isl_basic_map *isl_basic_map_from_local_space(
if (isl_basic_map_alloc_div(bmap) < 0)
goto error;
- for (i = 0; i < n_div; ++i) {
+ for (i = 0; i < n_div; ++i)
isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
- if (isl_basic_map_add_div_constraints(bmap, i) < 0)
- goto error;
- }
+ bmap = add_known_div_constraints(bmap);
isl_local_space_free(ls);
return bmap;
@@ -2857,6 +2887,15 @@ struct isl_basic_map *isl_basic_map_intersect(
isl_assert(bmap1->ctx,
isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
+ if (isl_basic_map_plain_is_empty(bmap1)) {
+ isl_basic_map_free(bmap2);
+ return bmap1;
+ }
+ if (isl_basic_map_plain_is_empty(bmap2)) {
+ isl_basic_map_free(bmap1);
+ return bmap2;
+ }
+
if (bmap1->sample &&
isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
isl_basic_map_contains(bmap2, bmap1->sample) > 0)
@@ -4432,11 +4471,13 @@ int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
*
* f - m d >= 0
* -(f-(n-1)) + m d >= 0
+ *
+ * Remove duplicate constraints in case of some these div constraints
+ * already appear in "bmap".
*/
__isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
__isl_take isl_basic_map *bmap)
{
- int i;
unsigned n_div;
if (!bmap)
@@ -4444,17 +4485,8 @@ __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
n_div = isl_basic_map_dim(bmap, isl_dim_div);
if (n_div == 0)
return bmap;
- bmap = isl_basic_map_cow(bmap);
- bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
- if (!bmap)
- return NULL;
- for (i = 0; i < n_div; ++i) {
- if (isl_int_is_zero(bmap->div[i][0]))
- continue;
- if (isl_basic_map_add_div_constraints(bmap, i) < 0)
- return isl_basic_map_free(bmap);
- }
+ bmap = add_known_div_constraints(bmap);
bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
bmap = isl_basic_map_finalize(bmap);
return bmap;
@@ -4566,9 +4598,10 @@ struct isl_basic_map *isl_basic_map_overlying_set(
isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
goto error);
- if (isl_space_is_equal(bset->dim, like->dim) && like->n_div == 0) {
+ if (like->n_div == 0) {
+ isl_space *space = isl_basic_map_get_space(like);
isl_basic_map_free(like);
- return (struct isl_basic_map *)bset;
+ return isl_basic_map_reset_space(bset, space);
}
bset = isl_basic_set_cow(bset);
if (!bset)
@@ -4693,22 +4726,44 @@ struct isl_set *isl_set_to_underlying_set(struct isl_set *set)
return (struct isl_set *)isl_map_underlying_set((struct isl_map *)set);
}
+/* Replace the space of "bmap" by "space".
+ *
+ * If the space of "bmap" is identical to "space" (including the identifiers
+ * of the input and output dimensions), then simply return the original input.
+ */
__isl_give isl_basic_map *isl_basic_map_reset_space(
- __isl_take isl_basic_map *bmap, __isl_take isl_space *dim)
+ __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
{
+ isl_bool equal;
+
+ if (!bmap)
+ goto error;
+ equal = isl_space_is_equal(bmap->dim, space);
+ if (equal >= 0 && equal)
+ equal = isl_space_match(bmap->dim, isl_dim_in,
+ space, isl_dim_in);
+ if (equal >= 0 && equal)
+ equal = isl_space_match(bmap->dim, isl_dim_out,
+ space, isl_dim_out);
+ if (equal < 0)
+ goto error;
+ if (equal) {
+ isl_space_free(space);
+ return bmap;
+ }
bmap = isl_basic_map_cow(bmap);
- if (!bmap || !dim)
+ if (!bmap || !space)
goto error;
isl_space_free(bmap->dim);
- bmap->dim = dim;
+ bmap->dim = space;
bmap = isl_basic_map_finalize(bmap);
return bmap;
error:
isl_basic_map_free(bmap);
- isl_space_free(dim);
+ isl_space_free(space);
return NULL;
}
@@ -6865,30 +6920,47 @@ error:
return NULL;
}
-int isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
+/* Does local variable "div" of "bmap" have an explicit representation?
+ */
+isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
+{
+ if (!bmap)
+ return isl_bool_error;
+ if (div < 0 || div >= isl_basic_map_dim(bmap, isl_dim_div))
+ isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+ "position out of bounds", return isl_bool_error);
+ return !isl_int_is_zero(bmap->div[div][0]);
+}
+
+/* Does "bmap" have an explicit representation for all local variables?
+ */
+isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
{
int i;
unsigned off;
if (!bmap)
- return -1;
+ return isl_bool_error;
off = isl_space_dim(bmap->dim, isl_dim_all);
for (i = 0; i < bmap->n_div; ++i) {
- if (isl_int_is_zero(bmap->div[i][0]))
- return 0;
+ if (!isl_basic_map_div_is_known(bmap, i))
+ return isl_bool_false;
isl_assert(bmap->ctx, isl_int_is_zero(bmap->div[i][1+1+off+i]),
- return -1);
+ return isl_bool_error);
}
- return 1;
+ return isl_bool_true;
}
-static int map_divs_known(__isl_keep isl_map *map)
+/* Do all basic maps in "map" have an explicit representation
+ * for all local variables?
+ */
+isl_bool isl_map_divs_known(__isl_keep isl_map *map)
{
int i;
if (!map)
- return -1;
+ return isl_bool_error;
for (i = 0; i < map->n; ++i) {
int known = isl_basic_map_divs_known(map->p[i]);
@@ -6896,7 +6968,7 @@ static int map_divs_known(__isl_keep isl_map *map)
return known;
}
- return 1;
+ return isl_bool_true;
}
/* If bmap contains any unknown divs, then compute explicit
@@ -6941,7 +7013,7 @@ struct isl_map *isl_map_compute_divs(struct isl_map *map)
if (map->n == 0)
return map;
- known = map_divs_known(map);
+ known = isl_map_divs_known(map);
if (known < 0) {
isl_map_free(map);
return NULL;
@@ -8768,8 +8840,23 @@ int isl_set_plain_dim_has_fixed_lower_bound(__isl_keep isl_set *set,
return fixed;
}
-/* uset_gist depends on constraints without existentially quantified
+/* Return -1 if the constraint "c1" should be sorted before "c2"
+ * and 1 if it should be sorted after "c2".
+ * Return 0 if the two constraints are the same (up to the constant term).
+ *
+ * In particular, if a constraint involves later variables than another
+ * then it is sorted after this other constraint.
+ * uset_gist depends on constraints without existentially quantified
* variables sorting first.
+ *
+ * For constraints that have the same latest variable, those
+ * with the same coefficient for this latest variable (first in absolute value
+ * and then in actual value) are grouped together.
+ * This is useful for detecting pairs of constraints that can
+ * be chained in their printed representation.
+ *
+ * Finally, within a group, constraints are sorted according to
+ * their coefficients (excluding the constant term).
*/
static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
{
@@ -8777,6 +8864,7 @@ static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
isl_int **c2 = (isl_int **) p2;
int l1, l2;
unsigned size = *(unsigned *) arg;
+ int cmp;
l1 = isl_seq_last_non_zero(*c1 + 1, size);
l2 = isl_seq_last_non_zero(*c2 + 1, size);
@@ -8784,11 +8872,33 @@ static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
if (l1 != l2)
return l1 - l2;
+ cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
+ if (cmp != 0)
+ return cmp;
+ cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
+ if (cmp != 0)
+ return -cmp;
+
return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
}
-static struct isl_basic_map *isl_basic_map_sort_constraints(
- struct isl_basic_map *bmap)
+/* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
+ * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
+ * and 0 if the two constraints are the same (up to the constant term).
+ */
+int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
+ isl_int *c1, isl_int *c2)
+{
+ unsigned total;
+
+ if (!bmap)
+ return -2;
+ total = isl_basic_map_total_dim(bmap);
+ return sort_constraint_cmp(&c1, &c2, &total);
+}
+
+__isl_give isl_basic_map *isl_basic_map_sort_constraints(
+ __isl_take isl_basic_map *bmap)
{
unsigned total;
@@ -9832,6 +9942,28 @@ isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
return isl_stat_ok;
}
+/* Return a list of basic sets, the union of which is equal to "set".
+ */
+__isl_give isl_basic_set_list *isl_set_get_basic_set_list(
+ __isl_keep isl_set *set)
+{
+ int i;
+ isl_basic_set_list *list;
+
+ if (!set)
+ return NULL;
+
+ list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
+ for (i = 0; i < set->n; ++i) {
+ isl_basic_set *bset;
+
+ bset = isl_basic_set_copy(set->p[i]);
+ list = isl_basic_set_list_add(list, bset);
+ }
+
+ return list;
+}
+
__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
{
isl_space *dim;
@@ -10259,18 +10391,126 @@ static int div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
return 0;
}
+/* Return the first integer division of "bmap" in the range
+ * [first, first + n[ that may depend on any output dimensions and
+ * that has a non-zero coefficient in "c" (where the first coefficient
+ * in "c" corresponds to integer division "first").
+ */
+static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
+ isl_int *c, int first, int n)
+{
+ int k;
+
+ if (!bmap)
+ return -1;
+
+ for (k = first; k < first + n; ++k) {
+ if (isl_int_is_zero(c[k]))
+ continue;
+ if (div_may_involve_output(bmap, k))
+ return k;
+ }
+
+ return first + n;
+}
+
+/* Look for a pair of inequality constraints in "bmap" of the form
+ *
+ * -l + i >= 0 or i >= l
+ * and
+ * n + l - i >= 0 or i <= l + n
+ *
+ * with n < "m" and i the output dimension at position "pos".
+ * (Note that n >= 0 as otherwise the two constraints would conflict.)
+ * Furthermore, "l" is only allowed to involve parameters, input dimensions
+ * and earlier output dimensions, as well as integer divisions that do
+ * not involve any of the output dimensions.
+ *
+ * Return the index of the first inequality constraint or bmap->n_ineq
+ * if no such pair can be found.
+ */
+static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
+ int pos, isl_int m)
+{
+ int i, j;
+ isl_ctx *ctx;
+ unsigned total;
+ unsigned n_div, o_div;
+ unsigned n_out, o_out;
+ int less;
+
+ if (!bmap)
+ return -1;
+
+ ctx = isl_basic_map_get_ctx(bmap);
+ total = isl_basic_map_total_dim(bmap);
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ o_out = isl_basic_map_offset(bmap, isl_dim_out);
+ n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ o_div = isl_basic_map_offset(bmap, isl_dim_div);
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
+ continue;
+ if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
+ n_out - (pos + 1)) != -1)
+ continue;
+ if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
+ 0, n_div) < n_div)
+ continue;
+ for (j = i + 1; j < bmap->n_ineq; ++j) {
+ if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
+ ctx->one))
+ continue;
+ if (!isl_seq_is_neg(bmap->ineq[i] + 1,
+ bmap->ineq[j] + 1, total))
+ continue;
+ break;
+ }
+ if (j >= bmap->n_ineq)
+ continue;
+ isl_int_add(bmap->ineq[i][0],
+ bmap->ineq[i][0], bmap->ineq[j][0]);
+ less = isl_int_abs_lt(bmap->ineq[i][0], m);
+ isl_int_sub(bmap->ineq[i][0],
+ bmap->ineq[i][0], bmap->ineq[j][0]);
+ if (!less)
+ continue;
+ if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
+ return i;
+ else
+ return j;
+ }
+
+ return bmap->n_ineq;
+}
+
/* Return the index of the equality of "bmap" that defines
* the output dimension "pos" in terms of earlier dimensions.
* The equality may also involve integer divisions, as long
* as those integer divisions are defined in terms of
* parameters or input dimensions.
+ * In this case, *div is set to the number of integer divisions and
+ * *ineq is set to the number of inequality constraints (provided
+ * div and ineq are not NULL).
+ *
+ * The equality may also involve a single integer division involving
+ * the output dimensions (typically only output dimension "pos") as
+ * long as the coefficient of output dimension "pos" is 1 or -1 and
+ * there is a pair of constraints i >= l and i <= l + n, with i referring
+ * to output dimension "pos", l an expression involving only earlier
+ * dimensions and n smaller than the coefficient of the integer division
+ * in the equality. In this case, the output dimension can be defined
+ * in terms of a modulo expression that does not involve the integer division.
+ * *div is then set to this single integer division and
+ * *ineq is set to the index of constraint i >= l.
+ *
* Return bmap->n_eq if there is no such equality.
* Return -1 on error.
*/
int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
- int pos)
+ int pos, int *div, int *ineq)
{
- int j, k;
+ int j, k, l;
unsigned n_out, o_out;
unsigned n_div, o_div;
@@ -10282,20 +10522,37 @@ int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
n_div = isl_basic_map_dim(bmap, isl_dim_div);
o_div = isl_basic_map_offset(bmap, isl_dim_div);
+ if (ineq)
+ *ineq = bmap->n_ineq;
+ if (div)
+ *div = n_div;
for (j = 0; j < bmap->n_eq; ++j) {
if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
continue;
if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
n_out - (pos + 1)) != -1)
continue;
- for (k = 0; k < n_div; ++k) {
- if (isl_int_is_zero(bmap->eq[j][o_div + k]))
- continue;
- if (div_may_involve_output(bmap, k))
- break;
- }
+ k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
+ 0, n_div);
if (k >= n_div)
return j;
+ if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
+ !isl_int_is_negone(bmap->eq[j][o_out + pos]))
+ continue;
+ if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
+ k + 1, n_div - (k+1)) < n_div)
+ continue;
+ l = find_modulo_constraint_pair(bmap, pos,
+ bmap->eq[j][o_div + k]);
+ if (l < 0)
+ return -1;
+ if (l >= bmap->n_ineq)
+ continue;
+ if (div)
+ *div = k;
+ if (ineq)
+ *ineq = l;
+ return j;
}
return bmap->n_eq;
@@ -10319,7 +10576,8 @@ isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
for (i = 0; i < n_out; ++i) {
int eq;
- eq = isl_basic_map_output_defining_equality(bmap, i);
+ eq = isl_basic_map_output_defining_equality(bmap, i,
+ NULL, NULL);
if (eq < 0)
return isl_bool_error;
if (eq >= bmap->n_eq)
@@ -10539,6 +10797,35 @@ isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
return isl_space_is_wrapping(set->dim);
}
+/* Modify the space of "map" through a call to "change".
+ * If "can_change" is set (not NULL), then first call it to check
+ * if the modification is allowed, printing the error message "cannot_change"
+ * if it is not.
+ */
+static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
+ isl_bool (*can_change)(__isl_keep isl_map *map),
+ const char *cannot_change,
+ __isl_give isl_space *(*change)(__isl_take isl_space *space))
+{
+ isl_bool ok;
+ isl_space *space;
+
+ if (!map)
+ return NULL;
+
+ ok = can_change ? can_change(map) : isl_bool_true;
+ if (ok < 0)
+ return isl_map_free(map);
+ if (!ok)
+ isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
+ return isl_map_free(map));
+
+ space = change(isl_map_get_space(map));
+ map = isl_map_reset_space(map, space);
+
+ return map;
+}
+
/* Is the domain of "map" a wrapped relation?
*/
isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
@@ -10577,27 +10864,11 @@ error:
return NULL;
}
+/* Given a map A -> B, return the set (A -> B).
+ */
__isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
{
- int i;
-
- map = isl_map_cow(map);
- if (!map)
- return NULL;
-
- for (i = 0; i < map->n; ++i) {
- map->p[i] = (isl_basic_map *)isl_basic_map_wrap(map->p[i]);
- if (!map->p[i])
- goto error;
- }
- map->dim = isl_space_wrap(map->dim);
- if (!map->dim)
- goto error;
-
- return (isl_set *)map;
-error:
- isl_map_free(map);
- return NULL;
+ return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
}
__isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
@@ -10618,35 +10889,13 @@ error:
return NULL;
}
+/* Given a set (A -> B), return the map A -> B.
+ * Error out if "set" is not of the form (A -> B).
+ */
__isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
{
- int i;
-
- if (!set)
- return NULL;
-
- if (!isl_set_is_wrapping(set))
- isl_die(set->ctx, isl_error_invalid, "not a wrapping set",
- goto error);
-
- set = isl_set_cow(set);
- if (!set)
- return NULL;
-
- for (i = 0; i < set->n; ++i) {
- set->p[i] = (isl_basic_set *)isl_basic_set_unwrap(set->p[i]);
- if (!set->p[i])
- goto error;
- }
-
- set->dim = isl_space_unwrap(set->dim);
- if (!set->dim)
- goto error;
-
- return (isl_map *)set;
-error:
- isl_set_free(set);
- return NULL;
+ return isl_map_change_space(set, &isl_set_is_wrapping,
+ "not a wrapping set", &isl_space_unwrap);
}
__isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
@@ -10783,33 +11032,17 @@ error:
return NULL;
}
+/* Remove any internal structure from the spaces of domain and range of "map".
+ */
__isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
{
- int i;
-
if (!map)
return NULL;
if (!map->dim->nested[0] && !map->dim->nested[1])
return map;
- map = isl_map_cow(map);
- if (!map)
- return NULL;
-
- for (i = 0; i < map->n; ++i) {
- map->p[i] = isl_basic_map_flatten(map->p[i]);
- if (!map->p[i])
- goto error;
- }
- map->dim = isl_space_flatten(map->dim);
- if (!map->dim)
- goto error;
-
- return map;
-error:
- isl_map_free(map);
- return NULL;
+ return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
}
__isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
@@ -10830,62 +11063,30 @@ __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
return map;
}
+/* Remove any internal structure from the space of the domain of "map".
+ */
__isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
{
- int i;
-
if (!map)
return NULL;
if (!map->dim->nested[0])
return map;
- map = isl_map_cow(map);
- if (!map)
- return NULL;
-
- for (i = 0; i < map->n; ++i) {
- map->p[i] = isl_basic_map_flatten_domain(map->p[i]);
- if (!map->p[i])
- goto error;
- }
- map->dim = isl_space_flatten_domain(map->dim);
- if (!map->dim)
- goto error;
-
- return map;
-error:
- isl_map_free(map);
- return NULL;
+ return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
}
+/* Remove any internal structure from the space of the range of "map".
+ */
__isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
{
- int i;
-
if (!map)
return NULL;
if (!map->dim->nested[1])
return map;
- map = isl_map_cow(map);
- if (!map)
- return NULL;
-
- for (i = 0; i < map->n; ++i) {
- map->p[i] = isl_basic_map_flatten_range(map->p[i]);
- if (!map->p[i])
- goto error;
- }
- map->dim = isl_space_flatten_range(map->dim);
- if (!map->dim)
- goto error;
-
- return map;
-error:
- isl_map_free(map);
- return NULL;
+ return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
}
/* Reorder the dimensions of "bmap" according to the given dim_map
@@ -11262,6 +11463,7 @@ __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
bmap->dim = isl_space_zip(bmap->dim);
if (!bmap->dim)
goto error;
+ bmap = isl_basic_map_mark_final(bmap);
return bmap;
error:
isl_basic_map_free(bmap);
@@ -11342,6 +11544,7 @@ __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
bmap->dim = isl_space_curry(bmap->dim);
if (!bmap->dim)
goto error;
+ bmap = isl_basic_map_mark_final(bmap);
return bmap;
error:
isl_basic_map_free(bmap);
@@ -11353,33 +11556,30 @@ error:
*/
__isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
{
- int i;
-
- if (!map)
- return NULL;
-
- if (!isl_map_can_curry(map))
- isl_die(map->ctx, isl_error_invalid, "map cannot be curried",
- goto error);
+ return isl_map_change_space(map, &isl_map_can_curry,
+ "map cannot be curried", &isl_space_curry);
+}
- map = isl_map_cow(map);
+/* Can isl_map_range_curry be applied to "map"?
+ * That is, does it have a nested relation in its range,
+ * the domain of which is itself a nested relation?
+ */
+isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
+{
if (!map)
- return NULL;
-
- for (i = 0; i < map->n; ++i) {
- map->p[i] = isl_basic_map_curry(map->p[i]);
- if (!map->p[i])
- goto error;
- }
+ return isl_bool_error;
- map->dim = isl_space_curry(map->dim);
- if (!map->dim)
- goto error;
+ return isl_space_can_range_curry(map->dim);
+}
- return map;
-error:
- isl_map_free(map);
- return NULL;
+/* Given a map A -> ((B -> C) -> D), return the corresponding map
+ * A -> (B -> (C -> D)).
+ */
+__isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
+{
+ return isl_map_change_space(map, &isl_map_can_range_curry,
+ "map range cannot be curried",
+ &isl_space_range_curry);
}
/* Can we apply isl_basic_map_uncurry to "bmap"?
@@ -11423,6 +11623,7 @@ __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
bmap->dim = isl_space_uncurry(bmap->dim);
if (!bmap->dim)
return isl_basic_map_free(bmap);
+ bmap = isl_basic_map_mark_final(bmap);
return bmap;
}
@@ -11431,30 +11632,8 @@ __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
*/
__isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
{
- int i;
-
- if (!map)
- return NULL;
-
- if (!isl_map_can_uncurry(map))
- isl_die(map->ctx, isl_error_invalid, "map cannot be uncurried",
- return isl_map_free(map));
-
- map = isl_map_cow(map);
- if (!map)
- return NULL;
-
- for (i = 0; i < map->n; ++i) {
- map->p[i] = isl_basic_map_uncurry(map->p[i]);
- if (!map->p[i])
- return isl_map_free(map);
- }
-
- map->dim = isl_space_uncurry(map->dim);
- if (!map->dim)
- return isl_map_free(map);
-
- return map;
+ return isl_map_change_space(map, &isl_map_can_uncurry,
+ "map cannot be uncurried", &isl_space_uncurry);
}
/* Construct a basic map mapping the domain of the affine expression
diff --git a/isl_map_private.h b/isl_map_private.h
index 1a1c5ee2..df44fb02 100644
--- a/isl_map_private.h
+++ b/isl_map_private.h
@@ -128,6 +128,8 @@ __isl_give isl_basic_set *isl_basic_set_simplify(
__isl_give isl_basic_map *isl_basic_map_alloc(isl_ctx *ctx,
unsigned nparam, unsigned in, unsigned out, unsigned extra,
unsigned n_eq, unsigned n_ineq);
+__isl_give isl_basic_map *isl_basic_map_mark_final(
+ __isl_take isl_basic_map *bmap);
__isl_give isl_basic_map *isl_basic_map_finalize(
__isl_take isl_basic_map *bmap);
__isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,
@@ -271,6 +273,10 @@ struct isl_basic_map *isl_basic_map_gauss(
struct isl_basic_map *bmap, int *progress);
struct isl_basic_set *isl_basic_set_gauss(
struct isl_basic_set *bset, int *progress);
+int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
+ isl_int *c1, isl_int *c2);
+__isl_give isl_basic_map *isl_basic_map_sort_constraints(
+ __isl_take isl_basic_map *bmap);
__isl_give isl_basic_set *isl_basic_set_sort_constraints(
__isl_take isl_basic_set *bset);
int isl_basic_map_plain_cmp(const __isl_keep isl_basic_map *bmap1,
@@ -291,6 +297,10 @@ __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
struct isl_set *isl_map_underlying_set(struct isl_map *map);
struct isl_basic_map *isl_basic_map_overlying_set(struct isl_basic_set *bset,
struct isl_basic_map *like);
+__isl_give isl_basic_map *isl_basic_map_drop_constraint_involving_unknown_divs(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_drop_constraint_involving_unknown_divs(
+ __isl_take isl_map *map);
__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
__isl_take isl_basic_set *bset, unsigned first, unsigned n);
__isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
@@ -397,7 +407,9 @@ __isl_give isl_basic_map *isl_basic_map_from_local_space(
__isl_give isl_basic_set *isl_basic_set_expand_divs(
__isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp);
-int isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap);
+isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div);
+isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap);
+isl_bool isl_map_divs_known(__isl_keep isl_map *map);
__isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset);
__isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap);
@@ -436,6 +448,13 @@ int isl_map_is_set(__isl_keep isl_map *map);
int isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
unsigned dim, isl_int *val);
+__isl_give isl_map *isl_map_plain_gist_basic_map(__isl_take isl_map *map,
+ __isl_take isl_basic_map *context);
+
+__isl_give isl_basic_map *isl_map_plain_unshifted_simple_hull(
+ __isl_take isl_map *map);
+__isl_give isl_basic_set *isl_basic_set_plain_affine_hull(
+ __isl_take isl_basic_set *bset);
__isl_give isl_basic_map *isl_basic_map_plain_affine_hull(
__isl_take isl_basic_map *bmap);
@@ -452,13 +471,13 @@ int isl_map_plain_is_fixed(__isl_keep isl_map *map,
enum isl_dim_type type, unsigned pos, isl_int *val);
int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
- int pos);
+ int pos, int *div, int *ineq);
__isl_give isl_basic_map *isl_basic_map_reduce_coefficients(
__isl_take isl_basic_map *bmap);
__isl_give isl_basic_map *isl_basic_map_shift_div(
- __isl_take isl_basic_map *bmap, int div, isl_int shift);
+ __isl_take isl_basic_map *bmap, int div, int pos, isl_int shift);
__isl_give isl_basic_map_list *isl_map_get_basic_map_list(
__isl_keep isl_map *map);
diff --git a/isl_map_simplify.c b/isl_map_simplify.c
index 0f3da78c..e4557109 100644
--- a/isl_map_simplify.c
+++ b/isl_map_simplify.c
@@ -1,7 +1,7 @@
/*
* Copyright 2008-2009 Katholieke Universiteit Leuven
* Copyright 2012-2013 Ecole Normale Superieure
- * Copyright 2014 INRIA Rocquencourt
+ * Copyright 2014-2015 INRIA Rocquencourt
*
* Use of this software is governed by the MIT license
*
@@ -12,7 +12,6 @@
* B.P. 105 - 78153 Le Chesnay, France
*/
-#include <strings.h>
#include <isl_ctx_private.h>
#include <isl_map_private.h>
#include "isl_equalities.h"
@@ -376,6 +375,80 @@ struct isl_basic_set *isl_basic_set_normalize_constraints(
(struct isl_basic_map *)bset);
}
+/* Assuming the variable at position "pos" has an integer coefficient
+ * in integer division "div", extract it from this integer division.
+ * "pos" is as determined by isl_basic_map_offset, i.e., pos == 0
+ * corresponds to the constant term.
+ *
+ * That is, the integer division is of the form
+ *
+ * floor((... + c * d * x_pos + ...)/d)
+ *
+ * Replace it by
+ *
+ * floor((... + 0 * x_pos + ...)/d) + c * x_pos
+ */
+static __isl_give isl_basic_map *remove_var_from_div(
+ __isl_take isl_basic_map *bmap, int div, int pos)
+{
+ isl_int shift;
+
+ isl_int_init(shift);
+ isl_int_divexact(shift, bmap->div[div][1 + pos], bmap->div[div][0]);
+ isl_int_neg(shift, shift);
+ bmap = isl_basic_map_shift_div(bmap, div, pos, shift);
+ isl_int_clear(shift);
+
+ return bmap;
+}
+
+/* Check if integer division "div" has any integral coefficient
+ * (or constant term). If so, extract them from the integer division.
+ */
+static __isl_give isl_basic_map *remove_independent_vars_from_div(
+ __isl_take isl_basic_map *bmap, int div)
+{
+ int i;
+ unsigned total = 1 + isl_basic_map_total_dim(bmap);
+
+ for (i = 0; i < total; ++i) {
+ if (isl_int_is_zero(bmap->div[div][1 + i]))
+ continue;
+ if (!isl_int_is_divisible_by(bmap->div[div][1 + i],
+ bmap->div[div][0]))
+ continue;
+ bmap = remove_var_from_div(bmap, div, i);
+ if (!bmap)
+ break;
+ }
+
+ return bmap;
+}
+
+/* Check if any known integer division has any integral coefficient
+ * (or constant term). If so, extract them from the integer division.
+ */
+static __isl_give isl_basic_map *remove_independent_vars_from_divs(
+ __isl_take isl_basic_map *bmap)
+{
+ int i;
+
+ if (!bmap)
+ return NULL;
+ if (bmap->n_div == 0)
+ return bmap;
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ bmap = remove_independent_vars_from_div(bmap, i);
+ if (!bmap)
+ break;
+ }
+
+ return bmap;
+}
+
/* Remove any common factor in numerator and denominator of the div expression,
* not taking into account the constant term.
* That is, if the div is of the form
@@ -687,23 +760,127 @@ static unsigned int round_up(unsigned int v)
return old_v << 1;
}
-static int hash_index(isl_int ***index, unsigned int size, int bits,
- struct isl_basic_map *bmap, int k)
+/* Hash table of inequalities in a basic map.
+ * "index" is an array of addresses of inequalities in the basic map, some
+ * of which are NULL. The inequalities are hashed on the coefficients
+ * except the constant term.
+ * "size" is the number of elements in the array and is always a power of two
+ * "bits" is the number of bits need to represent an index into the array.
+ * "total" is the total dimension of the basic map.
+ */
+struct isl_constraint_index {
+ unsigned int size;
+ int bits;
+ isl_int ***index;
+ unsigned total;
+};
+
+/* Fill in the "ci" data structure for holding the inequalities of "bmap".
+ */
+static isl_stat create_constraint_index(struct isl_constraint_index *ci,
+ __isl_keep isl_basic_map *bmap)
+{
+ isl_ctx *ctx;
+
+ ci->index = NULL;
+ if (!bmap)
+ return isl_stat_error;
+ ci->total = isl_basic_set_total_dim(bmap);
+ if (bmap->n_ineq == 0)
+ return isl_stat_ok;
+ ci->size = round_up(4 * (bmap->n_ineq + 1) / 3 - 1);
+ ci->bits = ffs(ci->size) - 1;
+ ctx = isl_basic_map_get_ctx(bmap);
+ ci->index = isl_calloc_array(ctx, isl_int **, ci->size);
+ if (!ci->index)
+ return isl_stat_error;
+
+ return isl_stat_ok;
+}
+
+/* Free the memory allocated by create_constraint_index.
+ */
+static void constraint_index_free(struct isl_constraint_index *ci)
+{
+ free(ci->index);
+}
+
+/* Return the position in ci->index that contains the address of
+ * an inequality that is equal to *ineq up to the constant term,
+ * provided this address is not identical to "ineq".
+ * If there is no such inequality, then return the position where
+ * such an inequality should be inserted.
+ */
+static int hash_index_ineq(struct isl_constraint_index *ci, isl_int **ineq)
{
int h;
- unsigned total = isl_basic_map_total_dim(bmap);
- uint32_t hash = isl_seq_get_hash_bits(bmap->ineq[k]+1, total, bits);
- for (h = hash; index[h]; h = (h+1) % size)
- if (&bmap->ineq[k] != index[h] &&
- isl_seq_eq(bmap->ineq[k]+1, index[h][0]+1, total))
+ uint32_t hash = isl_seq_get_hash_bits((*ineq) + 1, ci->total, ci->bits);
+ for (h = hash; ci->index[h]; h = (h+1) % ci->size)
+ if (ineq != ci->index[h] &&
+ isl_seq_eq((*ineq) + 1, ci->index[h][0]+1, ci->total))
break;
return h;
}
-static int set_hash_index(isl_int ***index, unsigned int size, int bits,
+/* Return the position in ci->index that contains the address of
+ * an inequality that is equal to the k'th inequality of "bmap"
+ * up to the constant term, provided it does not point to the very
+ * same inequality.
+ * If there is no such inequality, then return the position where
+ * such an inequality should be inserted.
+ */
+static int hash_index(struct isl_constraint_index *ci,
+ __isl_keep isl_basic_map *bmap, int k)
+{
+ return hash_index_ineq(ci, &bmap->ineq[k]);
+}
+
+static int set_hash_index(struct isl_constraint_index *ci,
struct isl_basic_set *bset, int k)
{
- return hash_index(index, size, bits, (struct isl_basic_map *)bset, k);
+ return hash_index(ci, bset, k);
+}
+
+/* Fill in the "ci" data structure with the inequalities of "bset".
+ */
+static isl_stat setup_constraint_index(struct isl_constraint_index *ci,
+ __isl_keep isl_basic_set *bset)
+{
+ int k, h;
+
+ if (create_constraint_index(ci, bset) < 0)
+ return isl_stat_error;
+
+ for (k = 0; k < bset->n_ineq; ++k) {
+ h = set_hash_index(ci, bset, k);
+ ci->index[h] = &bset->ineq[k];
+ }
+
+ return isl_stat_ok;
+}
+
+/* Is the inequality ineq (obviously) redundant with respect
+ * to the constraints in "ci"?
+ *
+ * Look for an inequality in "ci" with the same coefficients and then
+ * check if the contant term of "ineq" is greater than or equal
+ * to the constant term of that inequality. If so, "ineq" is clearly
+ * redundant.
+ *
+ * Note that hash_index_ineq ignores a stored constraint if it has
+ * the same address as the passed inequality. It is ok to pass
+ * the address of a local variable here since it will never be
+ * the same as the address of a constraint in "ci".
+ */
+static isl_bool constraint_index_is_redundant(struct isl_constraint_index *ci,
+ isl_int *ineq)
+{
+ int h;
+
+ h = hash_index_ineq(ci, &ineq);
+ if (!ci->index[h])
+ return isl_bool_false;
+ return isl_int_ge(ineq[0], (*ci->index[h])[0]);
}
/* If we can eliminate more than one div, then we need to make
@@ -1123,36 +1300,28 @@ static struct isl_basic_map *check_for_div_constraints(
__isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints(
__isl_take isl_basic_map *bmap, int *progress, int detect_divs)
{
- unsigned int size;
- isl_int ***index;
+ struct isl_constraint_index ci;
int k, l, h;
- int bits;
unsigned total = isl_basic_map_total_dim(bmap);
isl_int sum;
- isl_ctx *ctx;
if (!bmap || bmap->n_ineq <= 1)
return bmap;
- size = round_up(4 * (bmap->n_ineq+1) / 3 - 1);
- if (size == 0)
- return bmap;
- bits = ffs(size) - 1;
- ctx = isl_basic_map_get_ctx(bmap);
- index = isl_calloc_array(ctx, isl_int **, size);
- if (!index)
+ if (create_constraint_index(&ci, bmap) < 0)
return bmap;
- index[isl_seq_get_hash_bits(bmap->ineq[0]+1, total, bits)] = &bmap->ineq[0];
+ h = isl_seq_get_hash_bits(bmap->ineq[0] + 1, total, ci.bits);
+ ci.index[h] = &bmap->ineq[0];
for (k = 1; k < bmap->n_ineq; ++k) {
- h = hash_index(index, size, bits, bmap, k);
- if (!index[h]) {
- index[h] = &bmap->ineq[k];
+ h = hash_index(&ci, bmap, k);
+ if (!ci.index[h]) {
+ ci.index[h] = &bmap->ineq[k];
continue;
}
if (progress)
*progress = 1;
- l = index[h] - &bmap->ineq[0];
+ l = ci.index[h] - &bmap->ineq[0];
if (isl_int_lt(bmap->ineq[k][0], bmap->ineq[l][0]))
swap_inequality(bmap, k, l);
isl_basic_map_drop_inequality(bmap, k);
@@ -1161,11 +1330,11 @@ __isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints(
isl_int_init(sum);
for (k = 0; k < bmap->n_ineq-1; ++k) {
isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
- h = hash_index(index, size, bits, bmap, k);
+ h = hash_index(&ci, bmap, k);
isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
- if (!index[h])
+ if (!ci.index[h])
continue;
- l = index[h] - &bmap->ineq[0];
+ l = ci.index[h] - &bmap->ineq[0];
isl_int_add(sum, bmap->ineq[k][0], bmap->ineq[l][0]);
if (isl_int_is_pos(sum)) {
if (detect_divs)
@@ -1189,7 +1358,7 @@ __isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints(
}
isl_int_clear(sum);
- free(index);
+ constraint_index_free(&ci);
return bmap;
}
@@ -1319,6 +1488,7 @@ struct isl_basic_map *isl_basic_map_simplify(struct isl_basic_map *bmap)
if (isl_basic_map_plain_is_empty(bmap))
break;
bmap = isl_basic_map_normalize_constraints(bmap);
+ bmap = remove_independent_vars_from_divs(bmap);
bmap = normalize_div_expressions(bmap);
bmap = remove_duplicate_divs(bmap, &progress);
bmap = eliminate_unit_divs(bmap, &progress);
@@ -1440,15 +1610,28 @@ static struct isl_basic_map *remove_redundant_divs(struct isl_basic_map *bmap)
return bmap;
}
-struct isl_basic_map *isl_basic_map_finalize(struct isl_basic_map *bmap)
+/* Mark "bmap" as final, without checking for obviously redundant
+ * integer divisions. This function should be used when "bmap"
+ * is known not to involve any such integer divisions.
+ */
+__isl_give isl_basic_map *isl_basic_map_mark_final(
+ __isl_take isl_basic_map *bmap)
{
- bmap = remove_redundant_divs(bmap);
if (!bmap)
return NULL;
ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
return bmap;
}
+/* Mark "bmap" as final, after removing obviously redundant integer divisions.
+ */
+struct isl_basic_map *isl_basic_map_finalize(struct isl_basic_map *bmap)
+{
+ bmap = remove_redundant_divs(bmap);
+ bmap = isl_basic_map_mark_final(bmap);
+ return bmap;
+}
+
struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset)
{
return (struct isl_basic_set *)
@@ -1660,6 +1843,86 @@ __isl_give isl_basic_set *isl_basic_set_eliminate(
return isl_basic_map_eliminate(bset, type, first, n);
}
+/* Remove all constraints from "bmap" that reference any unknown local
+ * variables (directly or indirectly).
+ *
+ * Dropping all constraints on a local variable will make it redundant,
+ * so it will get removed implicitly by
+ * isl_basic_map_drop_constraints_involving_dims. Some other local
+ * variables may also end up becoming redundant if they only appear
+ * in constraints together with the unknown local variable.
+ * Therefore, start over after calling
+ * isl_basic_map_drop_constraints_involving_dims.
+ */
+__isl_give isl_basic_map *isl_basic_map_drop_constraint_involving_unknown_divs(
+ __isl_take isl_basic_map *bmap)
+{
+ isl_bool known;
+ int i, n_div, o_div;
+
+ known = isl_basic_map_divs_known(bmap);
+ if (known < 0)
+ return isl_basic_map_free(bmap);
+ if (known)
+ return bmap;
+
+ n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ o_div = isl_basic_map_offset(bmap, isl_dim_div) - 1;
+
+ for (i = 0; i < n_div; ++i) {
+ known = isl_basic_map_div_is_known(bmap, i);
+ if (known < 0)
+ return isl_basic_map_free(bmap);
+ if (known)
+ continue;
+ bmap = remove_dependent_vars(bmap, o_div + i);
+ bmap = isl_basic_map_drop_constraints_involving_dims(bmap,
+ isl_dim_div, i, 1);
+ if (!bmap)
+ return NULL;
+ n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ i = -1;
+ }
+
+ return bmap;
+}
+
+/* Remove all constraints from "map" that reference any unknown local
+ * variables (directly or indirectly).
+ *
+ * Since constraints may get dropped from the basic maps,
+ * they may no longer be disjoint from each other.
+ */
+__isl_give isl_map *isl_map_drop_constraint_involving_unknown_divs(
+ __isl_take isl_map *map)
+{
+ int i;
+ isl_bool known;
+
+ known = isl_map_divs_known(map);
+ if (known < 0)
+ return isl_map_free(map);
+ if (known)
+ return map;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] =
+ isl_basic_map_drop_constraint_involving_unknown_divs(
+ map->p[i]);
+ if (!map->p[i])
+ return isl_map_free(map);
+ }
+
+ if (map->n > 1)
+ ISL_F_CLR(map, ISL_MAP_DISJOINT);
+
+ return map;
+}
+
/* Don't assume equalities are in order, because align_divs
* may have changed the order of the divs.
*/
@@ -1754,37 +2017,73 @@ error:
return NULL;
}
+/* For each inequality in "ineq" that is a shifted (more relaxed)
+ * copy of an inequality in "context", mark the corresponding entry
+ * in "row" with -1.
+ * If an inequality only has a non-negative constant term, then
+ * mark it as well.
+ */
+static isl_stat mark_shifted_constraints(__isl_keep isl_mat *ineq,
+ __isl_keep isl_basic_set *context, int *row)
+{
+ struct isl_constraint_index ci;
+ int n_ineq;
+ unsigned total;
+ int k;
+
+ if (!ineq || !context)
+ return isl_stat_error;
+ if (context->n_ineq == 0)
+ return isl_stat_ok;
+ if (setup_constraint_index(&ci, context) < 0)
+ return isl_stat_error;
+
+ n_ineq = isl_mat_rows(ineq);
+ total = isl_mat_cols(ineq) - 1;
+ for (k = 0; k < n_ineq; ++k) {
+ int l;
+ isl_bool redundant;
+
+ l = isl_seq_first_non_zero(ineq->row[k] + 1, total);
+ if (l < 0 && isl_int_is_nonneg(ineq->row[k][0])) {
+ row[k] = -1;
+ continue;
+ }
+ redundant = constraint_index_is_redundant(&ci, ineq->row[k]);
+ if (redundant < 0)
+ goto error;
+ if (!redundant)
+ continue;
+ row[k] = -1;
+ }
+ constraint_index_free(&ci);
+ return isl_stat_ok;
+error:
+ constraint_index_free(&ci);
+ return isl_stat_error;
+}
+
static struct isl_basic_set *remove_shifted_constraints(
struct isl_basic_set *bset, struct isl_basic_set *context)
{
- unsigned int size;
- isl_int ***index;
- int bits;
- int k, h, l;
- isl_ctx *ctx;
+ struct isl_constraint_index ci;
+ int k;
if (!bset || !context)
return bset;
- size = round_up(4 * (context->n_ineq+1) / 3 - 1);
- if (size == 0)
+ if (context->n_ineq == 0)
return bset;
- bits = ffs(size) - 1;
- ctx = isl_basic_set_get_ctx(bset);
- index = isl_calloc_array(ctx, isl_int **, size);
- if (!index)
+ if (setup_constraint_index(&ci, context) < 0)
return bset;
- for (k = 0; k < context->n_ineq; ++k) {
- h = set_hash_index(index, size, bits, context, k);
- index[h] = &context->ineq[k];
- }
for (k = 0; k < bset->n_ineq; ++k) {
- h = set_hash_index(index, size, bits, bset, k);
- if (!index[h])
- continue;
- l = index[h] - &context->ineq[0];
- if (isl_int_lt(bset->ineq[k][0], context->ineq[l][0]))
+ isl_bool redundant;
+
+ redundant = constraint_index_is_redundant(&ci, bset->ineq[k]);
+ if (redundant < 0)
+ goto error;
+ if (!redundant)
continue;
bset = isl_basic_set_cow(bset);
if (!bset)
@@ -1792,10 +2091,10 @@ static struct isl_basic_set *remove_shifted_constraints(
isl_basic_set_drop_inequality(bset, k);
--k;
}
- free(index);
+ constraint_index_free(&ci);
return bset;
error:
- free(index);
+ constraint_index_free(&ci);
return bset;
}
@@ -1911,23 +2210,31 @@ static void update_groups(int dim, int *group, isl_int *c)
}
}
-/* Drop constraints from "context" that are irrelevant for computing
- * the gist of "bset".
- *
- * In particular, drop constraints in variables that are not related
- * to any of the variables involved in the constraints of "bset"
- * in the sense that there is no sequence of constraints that connects them.
+/* Allocate an array of groups of variables, one for each variable
+ * in "context", initialized to zero.
+ */
+static int *alloc_groups(__isl_keep isl_basic_set *context)
+{
+ isl_ctx *ctx;
+ int dim;
+
+ dim = isl_basic_set_dim(context, isl_dim_set);
+ ctx = isl_basic_set_get_ctx(context);
+ return isl_calloc_array(ctx, int, dim);
+}
+
+/* Drop constraints from "context" that only involve variables that are
+ * not related to any of the variables marked with a "-1" in "group".
*
* We construct groups of variables that collect variables that
* (indirectly) appear in some common constraint of "context".
* Each group is identified by the first variable in the group,
- * except for the special group of variables that appear in "bset"
- * (or are related to those variables), which is identified by -1.
+ * except for the special group of variables that was already identified
+ * in the input as -1 (or are related to those variables).
* If group[i] is equal to i (or -1), then the group of i is i (or -1),
* otherwise the group of i is the group of group[i].
*
- * We first initialize the -1 group with the variables that appear in "bset".
- * Then we initialize groups for the remaining variables.
+ * We first initialize groups for the remaining variables.
* Then we iterate over the constraints of "context" and update the
* group of the variables in the constraint by the smallest group.
* Finally, we resolve indirect references to groups by running over
@@ -1936,25 +2243,68 @@ static void update_groups(int dim, int *group, isl_int *c)
* After computing the groups, we drop constraints that do not involve
* any variables in the -1 group.
*/
+static __isl_give isl_basic_set *group_and_drop_irrelevant_constraints(
+ __isl_take isl_basic_set *context, __isl_take int *group)
+{
+ int dim;
+ int i;
+ int last;
+
+ dim = isl_basic_set_dim(context, isl_dim_set);
+
+ last = -1;
+ for (i = 0; i < dim; ++i)
+ if (group[i] >= 0)
+ last = group[i] = i;
+ if (last < 0) {
+ free(group);
+ return context;
+ }
+
+ for (i = 0; i < context->n_eq; ++i)
+ update_groups(dim, group, context->eq[i] + 1);
+ for (i = 0; i < context->n_ineq; ++i)
+ update_groups(dim, group, context->ineq[i] + 1);
+
+ for (i = 0; i < dim; ++i)
+ if (group[i] >= 0)
+ group[i] = group[group[i]];
+
+ for (i = 0; i < dim; ++i)
+ group[i] = group[i] == -1;
+
+ context = drop_unrelated_constraints(context, group);
+
+ free(group);
+ return context;
+}
+
+/* Drop constraints from "context" that are irrelevant for computing
+ * the gist of "bset".
+ *
+ * In particular, drop constraints in variables that are not related
+ * to any of the variables involved in the constraints of "bset"
+ * in the sense that there is no sequence of constraints that connects them.
+ *
+ * We first mark all variables that appear in "bset" as belonging
+ * to a "-1" group and then continue with group_and_drop_irrelevant_constraints.
+ */
static __isl_give isl_basic_set *drop_irrelevant_constraints(
__isl_take isl_basic_set *context, __isl_keep isl_basic_set *bset)
{
- isl_ctx *ctx;
int *group;
int dim;
int i, j;
- int last;
if (!context || !bset)
return isl_basic_set_free(context);
- dim = isl_basic_set_dim(bset, isl_dim_set);
- ctx = isl_basic_set_get_ctx(bset);
- group = isl_calloc_array(ctx, int, dim);
+ group = alloc_groups(context);
if (!group)
- goto error;
+ return isl_basic_set_free(context);
+ dim = isl_basic_set_dim(bset, isl_dim_set);
for (i = 0; i < dim; ++i) {
for (j = 0; j < bset->n_eq; ++j)
if (!isl_int_is_zero(bset->eq[j][1 + i]))
@@ -1970,40 +2320,148 @@ static __isl_give isl_basic_set *drop_irrelevant_constraints(
group[i] = -1;
}
- last = -1;
- for (i = 0; i < dim; ++i)
- if (group[i] >= 0)
- last = group[i] = i;
- if (last < 0) {
- free(group);
- return context;
+ return group_and_drop_irrelevant_constraints(context, group);
+}
+
+/* Drop constraints from "context" that are irrelevant for computing
+ * the gist of the inequalities "ineq".
+ * Inequalities in "ineq" for which the corresponding element of row
+ * is set to -1 have already been marked for removal and should be ignored.
+ *
+ * In particular, drop constraints in variables that are not related
+ * to any of the variables involved in "ineq"
+ * in the sense that there is no sequence of constraints that connects them.
+ *
+ * We first mark all variables that appear in "bset" as belonging
+ * to a "-1" group and then continue with group_and_drop_irrelevant_constraints.
+ */
+static __isl_give isl_basic_set *drop_irrelevant_constraints_marked(
+ __isl_take isl_basic_set *context, __isl_keep isl_mat *ineq, int *row)
+{
+ int *group;
+ int dim;
+ int i, j, n;
+
+ if (!context || !ineq)
+ return isl_basic_set_free(context);
+
+ group = alloc_groups(context);
+
+ if (!group)
+ return isl_basic_set_free(context);
+
+ dim = isl_basic_set_dim(context, isl_dim_set);
+ n = isl_mat_rows(ineq);
+ for (i = 0; i < dim; ++i) {
+ for (j = 0; j < n; ++j) {
+ if (row[j] < 0)
+ continue;
+ if (!isl_int_is_zero(ineq->row[j][1 + i]))
+ break;
+ }
+ if (j < n)
+ group[i] = -1;
}
- for (i = 0; i < context->n_eq; ++i)
- update_groups(dim, group, context->eq[i] + 1);
- for (i = 0; i < context->n_ineq; ++i)
- update_groups(dim, group, context->ineq[i] + 1);
+ return group_and_drop_irrelevant_constraints(context, group);
+}
- for (i = 0; i < dim; ++i)
- if (group[i] >= 0)
- group[i] = group[group[i]];
+/* Do all "n" entries of "row" contain a negative value?
+ */
+static int all_neg(int *row, int n)
+{
+ int i;
- for (i = 0; i < dim; ++i)
- group[i] = group[i] == -1;
+ for (i = 0; i < n; ++i)
+ if (row[i] >= 0)
+ return 0;
- context = drop_unrelated_constraints(context, group);
+ return 1;
+}
- free(group);
- return context;
-error:
- free(group);
- return isl_basic_set_free(context);
+/* Update the inequalities in "bset" based on the information in "row"
+ * and "tab".
+ *
+ * In particular, the array "row" contains either -1, meaning that
+ * the corresponding inequality of "bset" is redundant, or the index
+ * of an inequality in "tab".
+ *
+ * If the row entry is -1, then drop the inequality.
+ * Otherwise, if the constraint is marked redundant in the tableau,
+ * then drop the inequality. Similarly, if it is marked as an equality
+ * in the tableau, then turn the inequality into an equality and
+ * perform Gaussian elimination.
+ */
+static __isl_give isl_basic_set *update_ineq(__isl_take isl_basic_set *bset,
+ __isl_keep int *row, struct isl_tab *tab)
+{
+ int i;
+ unsigned n_ineq;
+ unsigned n_eq;
+ int found_equality = 0;
+
+ if (!bset)
+ return NULL;
+ if (tab && tab->empty)
+ return isl_basic_set_set_to_empty(bset);
+
+ n_ineq = bset->n_ineq;
+ for (i = n_ineq - 1; i >= 0; --i) {
+ if (row[i] < 0) {
+ if (isl_basic_set_drop_inequality(bset, i) < 0)
+ return isl_basic_set_free(bset);
+ continue;
+ }
+ if (!tab)
+ continue;
+ n_eq = tab->n_eq;
+ if (isl_tab_is_equality(tab, n_eq + row[i])) {
+ isl_basic_map_inequality_to_equality(bset, i);
+ found_equality = 1;
+ } else if (isl_tab_is_redundant(tab, n_eq + row[i])) {
+ if (isl_basic_set_drop_inequality(bset, i) < 0)
+ return isl_basic_set_free(bset);
+ }
+ }
+
+ if (found_equality)
+ bset = isl_basic_set_gauss(bset, NULL);
+ bset = isl_basic_set_finalize(bset);
+ return bset;
+}
+
+/* Update the inequalities in "bset" based on the information in "row"
+ * and "tab" and free all arguments (other than "bset").
+ */
+static __isl_give isl_basic_set *update_ineq_free(
+ __isl_take isl_basic_set *bset, __isl_take isl_mat *ineq,
+ __isl_take isl_basic_set *context, __isl_take int *row,
+ struct isl_tab *tab)
+{
+ isl_mat_free(ineq);
+ isl_basic_set_free(context);
+
+ bset = update_ineq(bset, row, tab);
+
+ free(row);
+ isl_tab_free(tab);
+ return bset;
}
/* Remove all information from bset that is redundant in the context
- * of context. Both bset and context are assumed to be full-dimensional.
+ * of context.
+ * "ineq" contains the (possibly transformed) inequalities of "bset",
+ * in the same order.
+ * The (explicit) equalities of "bset" are assumed to have been taken
+ * into account by the transformation such that only the inequalities
+ * are relevant.
+ * "context" is assumed not to be empty.
*
- * We first remove the inequalities from "bset"
+ * "row" keeps track of the constraint index of a "bset" inequality in "tab".
+ * A value of -1 means that the inequality is obviously redundant and may
+ * not even appear in "tab".
+ *
+ * We first mark the inequalities of "bset"
* that are obviously redundant with respect to some inequality in "context".
* Then we remove those constraints from "context" that have become
* irrelevant for computing the gist of "bset".
@@ -2023,96 +2481,96 @@ error:
* Finally, we update bset according to the results.
*/
static __isl_give isl_basic_set *uset_gist_full(__isl_take isl_basic_set *bset,
- __isl_take isl_basic_set *context)
+ __isl_take isl_mat *ineq, __isl_take isl_basic_set *context)
{
- int i, k;
+ int i, r;
+ int *row = NULL;
+ isl_ctx *ctx;
isl_basic_set *combined = NULL;
struct isl_tab *tab = NULL;
- unsigned context_ineq;
+ unsigned n_eq, context_ineq;
unsigned total;
- if (!bset || !context)
+ if (!bset || !ineq || !context)
goto error;
- if (isl_basic_set_is_universe(bset)) {
+ if (bset->n_ineq == 0 || isl_basic_set_is_universe(context)) {
isl_basic_set_free(context);
+ isl_mat_free(ineq);
return bset;
}
- if (isl_basic_set_is_universe(context)) {
- isl_basic_set_free(context);
- return bset;
- }
+ ctx = isl_basic_set_get_ctx(context);
+ row = isl_calloc_array(ctx, int, bset->n_ineq);
+ if (!row)
+ goto error;
- bset = remove_shifted_constraints(bset, context);
- if (!bset)
+ if (mark_shifted_constraints(ineq, context, row) < 0)
goto error;
- if (bset->n_ineq == 0)
- goto done;
+ if (all_neg(row, bset->n_ineq))
+ return update_ineq_free(bset, ineq, context, row, NULL);
- context = drop_irrelevant_constraints(context, bset);
+ context = drop_irrelevant_constraints_marked(context, ineq, row);
if (!context)
goto error;
- if (isl_basic_set_is_universe(context)) {
- isl_basic_set_free(context);
- return bset;
- }
+ if (isl_basic_set_is_universe(context))
+ return update_ineq_free(bset, ineq, context, row, NULL);
+ n_eq = context->n_eq;
context_ineq = context->n_ineq;
combined = isl_basic_set_cow(isl_basic_set_copy(context));
combined = isl_basic_set_extend_constraints(combined, 0, bset->n_ineq);
tab = isl_tab_from_basic_set(combined, 0);
for (i = 0; i < context_ineq; ++i)
- if (isl_tab_freeze_constraint(tab, i) < 0)
+ if (isl_tab_freeze_constraint(tab, n_eq + i) < 0)
goto error;
if (isl_tab_extend_cons(tab, bset->n_ineq) < 0)
goto error;
- for (i = 0; i < bset->n_ineq; ++i)
- if (isl_tab_add_ineq(tab, bset->ineq[i]) < 0)
+ r = context_ineq;
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (row[i] < 0)
+ continue;
+ combined = isl_basic_set_add_ineq(combined, ineq->row[i]);
+ if (isl_tab_add_ineq(tab, ineq->row[i]) < 0)
goto error;
- bset = isl_basic_set_add_constraints(combined, bset, 0);
- combined = NULL;
- if (!bset)
+ row[i] = r++;
+ }
+ if (isl_tab_detect_implicit_equalities(tab) < 0)
goto error;
if (isl_tab_detect_redundant(tab) < 0)
goto error;
total = isl_basic_set_total_dim(bset);
- for (i = context_ineq; i < bset->n_ineq; ++i) {
+ for (i = bset->n_ineq - 1; i >= 0; --i) {
+ isl_basic_set *test;
int is_empty;
- if (tab->con[i].is_redundant)
+
+ if (row[i] < 0)
continue;
- tab->con[i].is_redundant = 1;
- combined = isl_basic_set_dup(bset);
- combined = isl_basic_set_update_from_tab(combined, tab);
- combined = isl_basic_set_extend_constraints(combined, 0, 1);
- k = isl_basic_set_alloc_inequality(combined);
- if (k < 0)
- goto error;
- isl_seq_neg(combined->ineq[k], bset->ineq[i], 1 + total);
- isl_int_sub_ui(combined->ineq[k][0], combined->ineq[k][0], 1);
- is_empty = isl_basic_set_is_empty(combined);
+ r = row[i];
+ if (tab->con[n_eq + r].is_redundant)
+ continue;
+ test = isl_basic_set_dup(combined);
+ if (isl_inequality_negate(test, r) < 0)
+ test = isl_basic_set_free(test);
+ test = isl_basic_set_update_from_tab(test, tab);
+ is_empty = isl_basic_set_is_empty(test);
+ isl_basic_set_free(test);
if (is_empty < 0)
goto error;
- isl_basic_set_free(combined);
- combined = NULL;
- if (!is_empty)
- tab->con[i].is_redundant = 0;
+ if (is_empty)
+ tab->con[n_eq + r].is_redundant = 1;
}
- for (i = 0; i < context_ineq; ++i)
- tab->con[i].is_redundant = 1;
- bset = isl_basic_set_update_from_tab(bset, tab);
+ bset = update_ineq_free(bset, ineq, context, row, tab);
if (bset) {
ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT);
ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT);
}
- isl_tab_free(tab);
-done:
- bset = isl_basic_set_simplify(bset);
- bset = isl_basic_set_finalize(bset);
- isl_basic_set_free(context);
+ isl_basic_set_free(combined);
return bset;
error:
+ free(row);
+ isl_mat_free(ineq);
isl_tab_free(tab);
isl_basic_set_free(combined);
isl_basic_set_free(context);
@@ -2120,6 +2578,146 @@ error:
return NULL;
}
+/* Extract the inequalities of "bset" as an isl_mat.
+ */
+static __isl_give isl_mat *extract_ineq(__isl_keep isl_basic_set *bset)
+{
+ unsigned total;
+ isl_ctx *ctx;
+ isl_mat *ineq;
+
+ if (!bset)
+ return NULL;
+
+ ctx = isl_basic_set_get_ctx(bset);
+ total = isl_basic_set_total_dim(bset);
+ ineq = isl_mat_sub_alloc6(ctx, bset->ineq, 0, bset->n_ineq,
+ 0, 1 + total);
+
+ return ineq;
+}
+
+/* Remove all information from "bset" that is redundant in the context
+ * of "context", for the case where both "bset" and "context" are
+ * full-dimensional.
+ */
+static __isl_give isl_basic_set *uset_gist_uncompressed(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *context)
+{
+ isl_mat *ineq;
+
+ ineq = extract_ineq(bset);
+ return uset_gist_full(bset, ineq, context);
+}
+
+/* Remove all information from "bset" that is redundant in the context
+ * of "context", for the case where the combined equalities of
+ * "bset" and "context" allow for a compression that can be obtained
+ * by preapplication of "T".
+ *
+ * "bset" itself is not transformed by "T". Instead, the inequalities
+ * are extracted from "bset" and those are transformed by "T".
+ * uset_gist_full then determines which of the transformed inequalities
+ * are redundant with respect to the transformed "context" and removes
+ * the corresponding inequalities from "bset".
+ *
+ * After preapplying "T" to the inequalities, any common factor is
+ * removed from the coefficients. If this results in a tightening
+ * of the constant term, then the same tightening is applied to
+ * the corresponding untransformed inequality in "bset".
+ * That is, if after plugging in T, a constraint f(x) >= 0 is of the form
+ *
+ * g f'(x) + r >= 0
+ *
+ * with 0 <= r < g, then it is equivalent to
+ *
+ * f'(x) >= 0
+ *
+ * This means that f(x) >= 0 is equivalent to f(x) - r >= 0 in the affine
+ * subspace compressed by T since the latter would be transformed to
+ *
+ * g f'(x) >= 0
+ */
+static __isl_give isl_basic_set *uset_gist_compressed(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *context,
+ __isl_take isl_mat *T)
+{
+ isl_ctx *ctx;
+ isl_mat *ineq;
+ int i, n_row, n_col;
+ isl_int rem;
+
+ ineq = extract_ineq(bset);
+ ineq = isl_mat_product(ineq, isl_mat_copy(T));
+ context = isl_basic_set_preimage(context, T);
+
+ if (!ineq || !context)
+ goto error;
+ if (isl_basic_set_plain_is_empty(context)) {
+ isl_mat_free(ineq);
+ isl_basic_set_free(context);
+ return isl_basic_set_set_to_empty(bset);
+ }
+
+ ctx = isl_mat_get_ctx(ineq);
+ n_row = isl_mat_rows(ineq);
+ n_col = isl_mat_cols(ineq);
+ isl_int_init(rem);
+ for (i = 0; i < n_row; ++i) {
+ isl_seq_gcd(ineq->row[i] + 1, n_col - 1, &ctx->normalize_gcd);
+ if (isl_int_is_zero(ctx->normalize_gcd))
+ continue;
+ if (isl_int_is_one(ctx->normalize_gcd))
+ continue;
+ isl_seq_scale_down(ineq->row[i] + 1, ineq->row[i] + 1,
+ ctx->normalize_gcd, n_col - 1);
+ isl_int_fdiv_r(rem, ineq->row[i][0], ctx->normalize_gcd);
+ isl_int_fdiv_q(ineq->row[i][0],
+ ineq->row[i][0], ctx->normalize_gcd);
+ if (isl_int_is_zero(rem))
+ continue;
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ break;
+ isl_int_sub(bset->ineq[i][0], bset->ineq[i][0], rem);
+ }
+ isl_int_clear(rem);
+
+ return uset_gist_full(bset, ineq, context);
+error:
+ isl_mat_free(ineq);
+ isl_basic_set_free(context);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Project "bset" onto the variables that are involved in "template".
+ */
+static __isl_give isl_basic_set *project_onto_involved(
+ __isl_take isl_basic_set *bset, __isl_keep isl_basic_set *template)
+{
+ int i, n;
+
+ if (!bset || !template)
+ return isl_basic_set_free(bset);
+
+ n = isl_basic_set_dim(template, isl_dim_set);
+
+ for (i = 0; i < n; ++i) {
+ isl_bool involved;
+
+ involved = isl_basic_set_involves_dims(template,
+ isl_dim_set, i, 1);
+ if (involved < 0)
+ return isl_basic_set_free(bset);
+ if (involved)
+ continue;
+ bset = isl_basic_set_eliminate_vars(bset, i, 1);
+ }
+
+ return bset;
+}
+
/* Remove all information from bset that is redundant in the context
* of context. In particular, equalities that are linear combinations
* of those in context are removed. Then the inequalities that are
@@ -2130,9 +2728,11 @@ error:
* that are irrelevant for computing the gist of "bset".
* Alternatively, we could factorize the intersection of "context" and "bset".
*
- * We first compute the integer affine hull of the intersection,
- * compute the gist inside this affine hull and then add back
- * those equalities that are not implied by the context.
+ * We first compute the intersection of the integer affine hulls
+ * of "bset" and "context",
+ * compute the gist inside this intersection and then reduce
+ * the constraints with respect to the equalities of the context
+ * that only involve variables already involved in the input.
*
* If two constraints are mutually redundant, then uset_gist_full
* will remove the second of those constraints. We therefore first
@@ -2145,7 +2745,7 @@ static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
__isl_take isl_basic_set *context)
{
isl_mat *eq;
- isl_mat *T, *T2;
+ isl_mat *T;
isl_basic_set *aff;
isl_basic_set *aff_context;
unsigned total;
@@ -2155,9 +2755,13 @@ static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
context = drop_irrelevant_constraints(context, bset);
+ bset = isl_basic_set_detect_equalities(bset);
aff = isl_basic_set_copy(bset);
- aff = isl_basic_set_intersect(aff, isl_basic_set_copy(context));
- aff = isl_basic_set_affine_hull(aff);
+ aff = isl_basic_set_plain_affine_hull(aff);
+ context = isl_basic_set_detect_equalities(context);
+ aff_context = isl_basic_set_copy(context);
+ aff_context = isl_basic_set_plain_affine_hull(aff_context);
+ aff = isl_basic_set_intersect(aff, aff_context);
if (!aff)
goto error;
if (isl_basic_set_plain_is_empty(aff)) {
@@ -2168,28 +2772,23 @@ static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
bset = isl_basic_set_sort_constraints(bset);
if (aff->n_eq == 0) {
isl_basic_set_free(aff);
- return uset_gist_full(bset, context);
+ return uset_gist_uncompressed(bset, context);
}
total = isl_basic_set_total_dim(bset);
eq = isl_mat_sub_alloc6(bset->ctx, aff->eq, 0, aff->n_eq, 0, 1 + total);
eq = isl_mat_cow(eq);
- T = isl_mat_variable_compression(eq, &T2);
+ T = isl_mat_variable_compression(eq, NULL);
+ isl_basic_set_free(aff);
if (T && T->n_col == 0) {
isl_mat_free(T);
- isl_mat_free(T2);
isl_basic_set_free(context);
- isl_basic_set_free(aff);
return isl_basic_set_set_to_empty(bset);
}
aff_context = isl_basic_set_affine_hull(isl_basic_set_copy(context));
+ aff_context = project_onto_involved(aff_context, bset);
- bset = isl_basic_set_preimage(bset, isl_mat_copy(T));
- context = isl_basic_set_preimage(context, T);
-
- bset = uset_gist_full(bset, context);
- bset = isl_basic_set_preimage(bset, T2);
- bset = isl_basic_set_intersect(bset, aff);
+ bset = uset_gist_compressed(bset, context, T);
bset = isl_basic_set_reduce_using_equalities(bset, aff_context);
if (bset) {
@@ -2204,46 +2803,6 @@ error:
return NULL;
}
-/* Normalize the divs in "bmap" in the context of the equalities in "context".
- * We simply add the equalities in context to bmap and then do a regular
- * div normalizations. Better results can be obtained by normalizing
- * only the divs in bmap than do not also appear in context.
- * We need to be careful to reduce the divs using the equalities
- * so that later calls to isl_basic_map_overlying_set wouldn't introduce
- * spurious constraints.
- */
-static struct isl_basic_map *normalize_divs_in_context(
- struct isl_basic_map *bmap, struct isl_basic_map *context)
-{
- int i;
- unsigned total_context;
- int div_eq;
-
- div_eq = n_pure_div_eq(bmap);
- if (div_eq == 0)
- return bmap;
-
- bmap = isl_basic_map_cow(bmap);
- if (context->n_div > 0)
- bmap = isl_basic_map_align_divs(bmap, context);
-
- total_context = isl_basic_map_total_dim(context);
- bmap = isl_basic_map_extend_constraints(bmap, context->n_eq, 0);
- for (i = 0; i < context->n_eq; ++i) {
- int k;
- k = isl_basic_map_alloc_equality(bmap);
- if (k < 0)
- return isl_basic_map_free(bmap);
- isl_seq_cpy(bmap->eq[k], context->eq[i], 1 + total_context);
- isl_seq_clr(bmap->eq[k] + 1 + total_context,
- isl_basic_map_total_dim(bmap) - total_context);
- }
- bmap = isl_basic_map_gauss(bmap, NULL);
- bmap = normalize_divs(bmap, NULL);
- bmap = isl_basic_map_gauss(bmap, NULL);
- return bmap;
-}
-
/* Return a basic map that has the same intersection with "context" as "bmap"
* and that is as "simple" as possible.
*
@@ -2265,7 +2824,7 @@ struct isl_basic_map *isl_basic_map_gist(struct isl_basic_map *bmap,
{
isl_basic_set *bset, *eq;
isl_basic_map *eq_bmap;
- unsigned n_div, n_eq, n_ineq;
+ unsigned total, n_div, extra, n_eq, n_ineq;
if (!bmap || !context)
goto error;
@@ -2290,15 +2849,16 @@ struct isl_basic_map *isl_basic_map_gist(struct isl_basic_map *bmap,
if (!context)
goto error;
- if (context->n_eq)
- bmap = normalize_divs_in_context(bmap, context);
-
context = isl_basic_map_align_divs(context, bmap);
- bmap = isl_basic_map_align_divs(bmap, context);
- n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ n_div = isl_basic_map_dim(context, isl_dim_div);
+ total = isl_basic_map_dim(bmap, isl_dim_all);
+ extra = n_div - isl_basic_map_dim(bmap, isl_dim_div);
- bset = uset_gist(isl_basic_map_underlying_set(isl_basic_map_copy(bmap)),
+ bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
+ bset = isl_basic_set_add_dims(bset, isl_dim_set, extra);
+ bset = uset_gist(bset,
isl_basic_map_underlying_set(isl_basic_map_copy(context)));
+ bset = isl_basic_set_project_out(bset, isl_dim_set, total, extra);
if (!bset || bset->n_eq == 0 || n_div == 0 ||
isl_basic_set_plain_is_empty(bset)) {
@@ -2375,6 +2935,230 @@ error:
return NULL;
}
+/* Drop all inequalities from "bmap" that also appear in "context".
+ * "context" is assumed to have only known local variables and
+ * the initial local variables of "bmap" are assumed to be the same
+ * as those of "context".
+ * The constraints of both "bmap" and "context" are assumed
+ * to have been sorted using isl_basic_map_sort_constraints.
+ *
+ * Run through the inequality constraints of "bmap" and "context"
+ * in sorted order.
+ * If a constraint of "bmap" involves variables not in "context",
+ * then it cannot appear in "context".
+ * If a matching constraint is found, it is removed from "bmap".
+ */
+static __isl_give isl_basic_map *drop_inequalities(
+ __isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context)
+{
+ int i1, i2;
+ unsigned total, extra;
+
+ if (!bmap || !context)
+ return isl_basic_map_free(bmap);
+
+ total = isl_basic_map_total_dim(context);
+ extra = isl_basic_map_total_dim(bmap) - total;
+
+ i1 = bmap->n_ineq - 1;
+ i2 = context->n_ineq - 1;
+ while (bmap && i1 >= 0 && i2 >= 0) {
+ int cmp;
+
+ if (isl_seq_first_non_zero(bmap->ineq[i1] + 1 + total,
+ extra) != -1) {
+ --i1;
+ continue;
+ }
+ cmp = isl_basic_map_constraint_cmp(context, bmap->ineq[i1],
+ context->ineq[i2]);
+ if (cmp < 0) {
+ --i2;
+ continue;
+ }
+ if (cmp > 0) {
+ --i1;
+ continue;
+ }
+ if (isl_int_eq(bmap->ineq[i1][0], context->ineq[i2][0])) {
+ bmap = isl_basic_map_cow(bmap);
+ if (isl_basic_map_drop_inequality(bmap, i1) < 0)
+ bmap = isl_basic_map_free(bmap);
+ }
+ --i1;
+ --i2;
+ }
+
+ return bmap;
+}
+
+/* Drop all equalities from "bmap" that also appear in "context".
+ * "context" is assumed to have only known local variables and
+ * the initial local variables of "bmap" are assumed to be the same
+ * as those of "context".
+ *
+ * Run through the equality constraints of "bmap" and "context"
+ * in sorted order.
+ * If a constraint of "bmap" involves variables not in "context",
+ * then it cannot appear in "context".
+ * If a matching constraint is found, it is removed from "bmap".
+ */
+static __isl_give isl_basic_map *drop_equalities(
+ __isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context)
+{
+ int i1, i2;
+ unsigned total, extra;
+
+ if (!bmap || !context)
+ return isl_basic_map_free(bmap);
+
+ total = isl_basic_map_total_dim(context);
+ extra = isl_basic_map_total_dim(bmap) - total;
+
+ i1 = bmap->n_eq - 1;
+ i2 = context->n_eq - 1;
+
+ while (bmap && i1 >= 0 && i2 >= 0) {
+ int last1, last2;
+
+ if (isl_seq_first_non_zero(bmap->eq[i1] + 1 + total,
+ extra) != -1)
+ break;
+ last1 = isl_seq_last_non_zero(bmap->eq[i1] + 1, total);
+ last2 = isl_seq_last_non_zero(context->eq[i2] + 1, total);
+ if (last1 > last2) {
+ --i2;
+ continue;
+ }
+ if (last1 < last2) {
+ --i1;
+ continue;
+ }
+ if (isl_seq_eq(bmap->eq[i1], context->eq[i2], 1 + total)) {
+ bmap = isl_basic_map_cow(bmap);
+ if (isl_basic_map_drop_equality(bmap, i1) < 0)
+ bmap = isl_basic_map_free(bmap);
+ }
+ --i1;
+ --i2;
+ }
+
+ return bmap;
+}
+
+/* Remove the constraints in "context" from "bmap".
+ * "context" is assumed to have explicit representations
+ * for all local variables.
+ *
+ * First align the divs of "bmap" to those of "context" and
+ * sort the constraints. Then drop all constraints from "bmap"
+ * that appear in "context".
+ */
+__isl_give isl_basic_map *isl_basic_map_plain_gist(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_map *context)
+{
+ isl_bool done, known;
+
+ done = isl_basic_map_is_universe(context);
+ if (done == isl_bool_false)
+ done = isl_basic_map_is_universe(bmap);
+ if (done == isl_bool_false)
+ done = isl_basic_map_plain_is_empty(context);
+ if (done == isl_bool_false)
+ done = isl_basic_map_plain_is_empty(bmap);
+ if (done < 0)
+ goto error;
+ if (done) {
+ isl_basic_map_free(context);
+ return bmap;
+ }
+ known = isl_basic_map_divs_known(context);
+ if (known < 0)
+ goto error;
+ if (!known)
+ isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+ "context has unknown divs", goto error);
+
+ bmap = isl_basic_map_align_divs(bmap, context);
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ bmap = isl_basic_map_sort_constraints(bmap);
+ context = isl_basic_map_sort_constraints(context);
+
+ bmap = drop_inequalities(bmap, context);
+ bmap = drop_equalities(bmap, context);
+
+ isl_basic_map_free(context);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ isl_basic_map_free(context);
+ return NULL;
+}
+
+/* Replace "map" by the disjunct at position "pos" and free "context".
+ */
+static __isl_give isl_map *replace_by_disjunct(__isl_take isl_map *map,
+ int pos, __isl_take isl_basic_map *context)
+{
+ isl_basic_map *bmap;
+
+ bmap = isl_basic_map_copy(map->p[pos]);
+ isl_map_free(map);
+ isl_basic_map_free(context);
+ return isl_map_from_basic_map(bmap);
+}
+
+/* Remove the constraints in "context" from "map".
+ * If any of the disjuncts in the result turns out to be the universe,
+ * the return this universe.
+ * "context" is assumed to have explicit representations
+ * for all local variables.
+ */
+__isl_give isl_map *isl_map_plain_gist_basic_map(__isl_take isl_map *map,
+ __isl_take isl_basic_map *context)
+{
+ int i;
+ isl_bool univ, known;
+
+ univ = isl_basic_map_is_universe(context);
+ if (univ < 0)
+ goto error;
+ if (univ) {
+ isl_basic_map_free(context);
+ return map;
+ }
+ known = isl_basic_map_divs_known(context);
+ if (known < 0)
+ goto error;
+ if (!known)
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "context has unknown divs", goto error);
+
+ map = isl_map_cow(map);
+ if (!map)
+ goto error;
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_plain_gist(map->p[i],
+ isl_basic_map_copy(context));
+ univ = isl_basic_map_is_universe(map->p[i]);
+ if (univ < 0)
+ goto error;
+ if (univ && map->n > 1)
+ return replace_by_disjunct(map, i, context);
+ }
+
+ isl_basic_map_free(context);
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ if (map->n > 1)
+ ISL_F_CLR(map, ISL_MAP_DISJOINT);
+ return map;
+error:
+ isl_map_free(map);
+ isl_basic_map_free(context);
+ return NULL;
+}
+
/* Return a map that has the same intersection with "context" as "map"
* and that is as "simple" as possible.
*
@@ -2766,6 +3550,13 @@ isl_bool isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
return isl_map_is_disjoint(set1, set2);
}
+/* Is "v" equal to 0, 1 or -1?
+ */
+static int is_zero_or_one(isl_int v)
+{
+ return isl_int_is_zero(v) || isl_int_is_one(v) || isl_int_is_negone(v);
+}
+
/* Check if we can combine a given div with lower bound l and upper
* bound u with some other div and if so return that other div.
* Otherwise return -1.
@@ -2791,6 +3582,8 @@ isl_bool isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
*
* e + f (a + m b) >= 0
*
+ * Furthermore, in the constraints that only contain b, the coefficient
+ * of b should be equal to 1 or -1.
* If so, we return b so that "a + m b" can be replaced by
* a single div "c = a + m b".
*/
@@ -2847,8 +3640,11 @@ static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs,
int valid;
if (j == l || j == u)
continue;
- if (isl_int_is_zero(bmap->ineq[j][1 + dim + div]))
- continue;
+ if (isl_int_is_zero(bmap->ineq[j][1 + dim + div])) {
+ if (is_zero_or_one(bmap->ineq[j][1 + dim + i]))
+ continue;
+ break;
+ }
if (isl_int_is_zero(bmap->ineq[j][1 + dim + i]))
break;
isl_int_mul(bmap->ineq[j][1 + dim + div],
@@ -2903,23 +3699,23 @@ static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs,
* f_l e_u + f_u e_l + f_l - 1 + f_u - 1 + 1 >= f_u f_l g
*/
static void construct_test_ineq(struct isl_basic_map *bmap, int i,
- int l, int u, isl_int *ineq, isl_int g, isl_int fl, isl_int fu)
+ int l, int u, isl_int *ineq, isl_int *g, isl_int *fl, isl_int *fu)
{
unsigned dim;
dim = isl_space_dim(bmap->dim, isl_dim_all);
- isl_int_gcd(g, bmap->ineq[l][1 + dim + i], bmap->ineq[u][1 + dim + i]);
- isl_int_divexact(fl, bmap->ineq[l][1 + dim + i], g);
- isl_int_divexact(fu, bmap->ineq[u][1 + dim + i], g);
- isl_int_neg(fu, fu);
- isl_seq_combine(ineq, fl, bmap->ineq[u], fu, bmap->ineq[l],
+ isl_int_gcd(*g, bmap->ineq[l][1 + dim + i], bmap->ineq[u][1 + dim + i]);
+ isl_int_divexact(*fl, bmap->ineq[l][1 + dim + i], *g);
+ isl_int_divexact(*fu, bmap->ineq[u][1 + dim + i], *g);
+ isl_int_neg(*fu, *fu);
+ isl_seq_combine(ineq, *fl, bmap->ineq[u], *fu, bmap->ineq[l],
1 + dim + bmap->n_div);
- isl_int_add(ineq[0], ineq[0], fl);
- isl_int_add(ineq[0], ineq[0], fu);
+ isl_int_add(ineq[0], ineq[0], *fl);
+ isl_int_add(ineq[0], ineq[0], *fu);
isl_int_sub_ui(ineq[0], ineq[0], 1);
- isl_int_mul(g, g, fl);
- isl_int_mul(g, g, fu);
- isl_int_sub(ineq[0], ineq[0], g);
+ isl_int_mul(*g, *g, *fl);
+ isl_int_mul(*g, *g, *fu);
+ isl_int_sub(ineq[0], ineq[0], *g);
}
/* Remove more kinds of divs that are not strictly needed.
@@ -2972,7 +3768,7 @@ static struct isl_basic_map *drop_more_redundant_divs(
if (!isl_int_is_neg(bmap->ineq[u][1 + dim + i]))
continue;
construct_test_ineq(bmap, i, l, u,
- vec->el, g, fl, fu);
+ vec->el, &g, &fl, &fu);
res = isl_tab_min(tab, vec->el,
bmap->ctx->one, &g, NULL, 0);
if (res == isl_lp_error)
@@ -3020,8 +3816,8 @@ error:
return NULL;
}
-/* Given a pair of divs div1 and div2 such that, expect for the lower bound l
- * and the upper bound u, div1 always occurs together with div2 in the form
+/* Given a pair of divs div1 and div2 such that, except for the lower bound l
+ * and the upper bound u, div1 always occurs together with div2 in the form
* (div1 + m div2), where m is the constant range on the variable div1
* allowed by l and u, replace the pair div1 and div2 by a single
* div that is equal to div1 + m div2.
@@ -3029,6 +3825,7 @@ error:
* The new div will appear in the location that contains div2.
* We need to modify all constraints that contain
* div2 = (div - div1) / m
+ * The coefficient of div2 is known to be equal to 1 or -1.
* (If a constraint does not contain div2, it will also not contain div1.)
* If the constraint also contains div1, then we know they appear
* as f (div1 + m div2) and we can simply replace (div1 + m div2) by div,
@@ -3045,20 +3842,19 @@ error:
*
* A lower bound on div2
*
- * n div2 + t >= 0
+ * div2 + t >= 0
*
* can be replaced by
*
- * (n * (m div 2 + div1) + m t + n f)/g >= 0
+ * m div2 + div1 + m t + f >= 0
*
- * with g = gcd(m,n).
* An upper bound
*
- * -n div2 + t >= 0
+ * -div2 + t >= 0
*
* can be replaced by
*
- * (-n * (m div2 + div1) + m t + n f')/g >= 0
+ * -(m div2 + div1) + m t + f' >= 0
*
* These constraint are those that we would obtain from eliminating
* div1 using Fourier-Motzkin.
@@ -3069,17 +3865,16 @@ error:
static struct isl_basic_map *coalesce_divs(struct isl_basic_map *bmap,
unsigned div1, unsigned div2, unsigned l, unsigned u)
{
- isl_int a;
- isl_int b;
+ isl_ctx *ctx;
isl_int m;
unsigned dim, total;
int i;
+ ctx = isl_basic_map_get_ctx(bmap);
+
dim = isl_space_dim(bmap->dim, isl_dim_all);
total = 1 + dim + bmap->n_div;
- isl_int_init(a);
- isl_int_init(b);
isl_int_init(m);
isl_int_add(m, bmap->ineq[l][0], bmap->ineq[u][0]);
isl_int_add_ui(m, m, 1);
@@ -3089,26 +3884,14 @@ static struct isl_basic_map *coalesce_divs(struct isl_basic_map *bmap,
continue;
if (isl_int_is_zero(bmap->ineq[i][1 + dim + div2]))
continue;
- if (isl_int_is_zero(bmap->ineq[i][1 + dim + div1])) {
- isl_int_gcd(b, m, bmap->ineq[i][1 + dim + div2]);
- isl_int_divexact(a, m, b);
- isl_int_divexact(b, bmap->ineq[i][1 + dim + div2], b);
- if (isl_int_is_pos(b)) {
- isl_seq_combine(bmap->ineq[i], a, bmap->ineq[i],
- b, bmap->ineq[l], total);
- } else {
- isl_int_neg(b, b);
- isl_seq_combine(bmap->ineq[i], a, bmap->ineq[i],
- b, bmap->ineq[u], total);
- }
- }
+ if (isl_int_is_zero(bmap->ineq[i][1 + dim + div1]))
+ isl_seq_combine(bmap->ineq[i], m, bmap->ineq[i],
+ ctx->one, bmap->ineq[l], total);
isl_int_set(bmap->ineq[i][1 + dim + div2],
bmap->ineq[i][1 + dim + div1]);
isl_int_set_si(bmap->ineq[i][1 + dim + div1], 0);
}
- isl_int_clear(a);
- isl_int_clear(b);
isl_int_clear(m);
if (l > u) {
isl_basic_map_drop_inequality(bmap, l);
@@ -3479,7 +4262,10 @@ error:
return isl_basic_map_free(bmap);
}
-/* Shift the integer division at position "div" of "bmap" by "shift".
+/* Shift the integer division at position "div" of "bmap"
+ * by "shift" times the variable at position "pos".
+ * "pos" is as determined by isl_basic_map_offset, i.e., pos == 0
+ * corresponds to the constant term.
*
* That is, if the integer division has the form
*
@@ -3487,10 +4273,10 @@ error:
*
* then replace it by
*
- * floor((f(x) + shift * d)/d) - shift
+ * floor((f(x) + shift * d * x_pos)/d) - shift * x_pos
*/
__isl_give isl_basic_map *isl_basic_map_shift_div(
- __isl_take isl_basic_map *bmap, int div, isl_int shift)
+ __isl_take isl_basic_map *bmap, int div, int pos, isl_int shift)
{
int i;
unsigned total;
@@ -3501,18 +4287,18 @@ __isl_give isl_basic_map *isl_basic_map_shift_div(
total = isl_basic_map_dim(bmap, isl_dim_all);
total -= isl_basic_map_dim(bmap, isl_dim_div);
- isl_int_addmul(bmap->div[div][1], shift, bmap->div[div][0]);
+ isl_int_addmul(bmap->div[div][1 + pos], shift, bmap->div[div][0]);
for (i = 0; i < bmap->n_eq; ++i) {
if (isl_int_is_zero(bmap->eq[i][1 + total + div]))
continue;
- isl_int_submul(bmap->eq[i][0],
+ isl_int_submul(bmap->eq[i][pos],
shift, bmap->eq[i][1 + total + div]);
}
for (i = 0; i < bmap->n_ineq; ++i) {
if (isl_int_is_zero(bmap->ineq[i][1 + total + div]))
continue;
- isl_int_submul(bmap->ineq[i][0],
+ isl_int_submul(bmap->ineq[i][pos],
shift, bmap->ineq[i][1 + total + div]);
}
for (i = 0; i < bmap->n_div; ++i) {
@@ -3520,7 +4306,7 @@ __isl_give isl_basic_map *isl_basic_map_shift_div(
continue;
if (isl_int_is_zero(bmap->div[i][1 + 1 + total + div]))
continue;
- isl_int_submul(bmap->div[i][1],
+ isl_int_submul(bmap->div[i][1 + pos],
shift, bmap->div[i][1 + 1 + total + div]);
}
diff --git a/isl_mat.c b/isl_mat.c
index f859601e..0cb67723 100644
--- a/isl_mat.c
+++ b/isl_mat.c
@@ -1123,7 +1123,7 @@ static int preimage(struct isl_ctx *ctx, isl_int **q, unsigned n,
* M the matrix mat.
*
* If there are fewer variables x' then there are x, then we perform
- * the transformation in place, which that, in principle,
+ * the transformation in place, which means that, in principle,
* this frees up some extra variables as the number
* of columns remains constant, but we would have to extend
* the div array too as the number of rows in this array is assumed
diff --git a/isl_morph.c b/isl_morph.c
index 9c14c80a..92215af6 100644
--- a/isl_morph.c
+++ b/isl_morph.c
@@ -398,7 +398,7 @@ static __isl_give isl_basic_set *copy_equalities(__isl_keep isl_basic_set *bset,
k = isl_basic_set_alloc_equality(eq);
if (k < 0)
goto error;
- isl_seq_cpy(eq->eq[k], bset->eq[first + k], 1 + total);
+ isl_seq_cpy(eq->eq[k], bset->eq[first + i], 1 + total);
}
return eq;
diff --git a/isl_multi_coalesce.c b/isl_multi_coalesce.c
new file mode 100644
index 00000000..aef59e88
--- /dev/null
+++ b/isl_multi_coalesce.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl_multi_macro.h>
+
+/* Coalesce the elements of "multi".
+ *
+ * Note that such coalescing does not change the meaning of "multi"
+ * so there is no need to cow. We do need to be careful not to
+ * destroy any other copies of "multi" in case of failure.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),coalesce)(__isl_take MULTI(BASE) *multi)
+{
+ int i;
+
+ if (!multi)
+ return NULL;
+
+ for (i = 0; i < multi->n; ++i) {
+ EL *el = FN(EL,copy)(multi->p[i]);
+ el = FN(EL,coalesce)(el);
+ if (!el)
+ return FN(MULTI(BASE),free)(multi);
+ FN(EL,free)(multi->p[i]);
+ multi->p[i] = el;
+ }
+
+ return multi;
+}
diff --git a/isl_multi_templ.c b/isl_multi_templ.c
index b7efbc1b..f8924dd8 100644
--- a/isl_multi_templ.c
+++ b/isl_multi_templ.c
@@ -869,6 +869,30 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_range)(
return multi;
}
+/* Given a function [B -> C], extract the function C.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)(
+ __isl_take MULTI(BASE) *multi)
+{
+ isl_space *space;
+ int total, keep;
+
+ if (!multi)
+ return NULL;
+ if (!isl_space_is_wrapping(multi->space))
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "not a product", return FN(MULTI(BASE),free)(multi));
+
+ space = FN(MULTI(BASE),get_space)(multi);
+ total = isl_space_dim(space, isl_dim_out);
+ space = isl_space_factor_range(space);
+ keep = isl_space_dim(space, isl_dim_out);
+ multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
+ multi = FN(MULTI(BASE),reset_space)(multi, space);
+
+ return multi;
+}
+
#ifndef NO_PRODUCT
/* Given two MULTI(BASE)s A -> B and C -> D,
* construct a MULTI(BASE) [A -> C] -> [B -> D].
@@ -1092,6 +1116,25 @@ error:
return NULL;
}
+/* Add "multi2" from "multi1" and return the result.
+ *
+ * The parameters of "multi1" and "multi2" are assumed to have been aligned.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),add_aligned)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
+{
+ return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,add));
+}
+
+/* Add "multi2" from "multi1" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),add)(__isl_take MULTI(BASE) *multi1,
+ __isl_take MULTI(BASE) *multi2)
+{
+ return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
+ &FN(MULTI(BASE),add_aligned));
+}
+
/* Subtract "multi2" from "multi1" and return the result.
*
* The parameters of "multi1" and "multi2" are assumed to have been aligned.
@@ -1205,7 +1248,7 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
- return NULL;
+ goto error;
for (i = 0; i < multi->n; ++i) {
isl_val *v;
diff --git a/isl_output.c b/isl_output.c
index 8ebe10ef..a0a57877 100644
--- a/isl_output.c
+++ b/isl_output.c
@@ -30,6 +30,7 @@
#include <isl_val_private.h>
#include <isl/ast_build.h>
#include <isl_sort.h>
+#include <isl_output_private.h>
static const char *s_to[2] = { " -> ", " \\to " };
static const char *s_and[2] = { " and ", " \\wedge " };
@@ -174,7 +175,10 @@ static int count_same_name(__isl_keep isl_space *dim,
return count;
}
-static __isl_give isl_printer *print_name(__isl_keep isl_space *dim,
+/* Print the name of the variable of type "type" and position "pos"
+ * in "space" to "p".
+ */
+static __isl_give isl_printer *print_name(__isl_keep isl_space *space,
__isl_take isl_printer *p, enum isl_dim_type type, unsigned pos,
int latex)
{
@@ -182,7 +186,8 @@ static __isl_give isl_printer *print_name(__isl_keep isl_space *dim,
char buffer[20];
int primes;
- name = type == isl_dim_div ? NULL : isl_space_get_dim_name(dim, type, pos);
+ name = type == isl_dim_div ? NULL
+ : isl_space_get_dim_name(space, type, pos);
if (!name) {
const char *prefix;
@@ -190,14 +195,14 @@ static __isl_give isl_printer *print_name(__isl_keep isl_space *dim,
prefix = s_param_prefix[latex];
else if (type == isl_dim_div)
prefix = s_div_prefix[latex];
- else if (isl_space_is_set(dim) || type == isl_dim_in)
+ else if (isl_space_is_set(space) || type == isl_dim_in)
prefix = s_input_prefix[latex];
else
prefix = s_output_prefix[latex];
snprintf(buffer, sizeof(buffer), "%s%d", prefix, pos);
name = buffer;
}
- primes = count_same_name(dim, name == buffer ? isl_dim_div : type,
+ primes = count_same_name(space, name == buffer ? isl_dim_div : type,
pos, name);
p = isl_printer_print_str(p, name);
while (primes-- > 0)
@@ -229,10 +234,27 @@ static enum isl_dim_type pos2type(__isl_keep isl_space *dim, unsigned *pos)
return type;
}
+/* Can the div expression of the integer division at position "row" of "div"
+ * be printed?
+ * In particular, are the div expressions available and does the selected
+ * variable have a known explicit representation?
+ * Furthermore, the Omega format does not allow and div expressions
+ * to be printed.
+ */
+static isl_bool can_print_div_expr(__isl_keep isl_printer *p,
+ __isl_keep isl_mat *div, int pos)
+{
+ if (p->output_format == ISL_FORMAT_OMEGA)
+ return isl_bool_false;
+ if (!div)
+ return isl_bool_false;
+ return !isl_int_is_zero(div->row[pos][0]);
+}
+
static __isl_give isl_printer *print_div(__isl_keep isl_space *dim,
__isl_keep isl_mat *div, int pos, __isl_take isl_printer *p);
-static __isl_give isl_printer *print_term(__isl_keep isl_space *dim,
+static __isl_give isl_printer *print_term(__isl_keep isl_space *space,
__isl_keep isl_mat *div,
isl_int c, unsigned pos, __isl_take isl_printer *p, int latex)
{
@@ -242,9 +264,8 @@ static __isl_give isl_printer *print_term(__isl_keep isl_space *dim,
if (pos == 0)
return isl_printer_print_isl_int(p, c);
- type = pos2type(dim, &pos);
- print_div_def = type == isl_dim_div && div &&
- !isl_int_is_zero(div->row[pos][0]);
+ type = pos2type(space, &pos);
+ print_div_def = type == isl_dim_div && can_print_div_expr(p, div, pos);
if (isl_int_is_one(c))
;
@@ -256,9 +277,9 @@ static __isl_give isl_printer *print_term(__isl_keep isl_space *dim,
p = isl_printer_print_str(p, "*");
}
if (print_div_def)
- p = print_div(dim, div, pos, p);
+ p = print_div(space, div, pos, p);
else
- p = print_name(dim, p, type, pos, latex);
+ p = print_name(space, p, type, pos, latex);
return p;
}
@@ -291,34 +312,18 @@ static __isl_give isl_printer *print_affine_of_len(__isl_keep isl_space *dim,
return p;
}
+/* Print an affine expression "c" corresponding to a constraint in "bmap"
+ * to "p", with the variable names taken from "space" and
+ * the integer division definitions taken from "div".
+ */
static __isl_give isl_printer *print_affine(__isl_keep isl_basic_map *bmap,
- __isl_keep isl_space *dim, __isl_take isl_printer *p, isl_int *c)
+ __isl_keep isl_space *space, __isl_keep isl_mat *div,
+ __isl_take isl_printer *p, isl_int *c)
{
unsigned len = 1 + isl_basic_map_total_dim(bmap);
- return print_affine_of_len(dim, NULL, p, c, len);
+ return print_affine_of_len(space, div, p, c, len);
}
-/* Internal data structure for print_space.
- *
- * latex is set if that is the output format.
- * print_dim (if not NULL) is called on each dimension.
- * user is set by the caller of print_space and may be used inside print_dim.
- *
- * space is the global space that is being printed. This field is set by
- * print_space.
- * type is the tuple of the global space that is currently being printed.
- * This field is set by print_space.
- */
-struct isl_print_space_data {
- int latex;
- __isl_give isl_printer *(*print_dim)(__isl_take isl_printer *p,
- struct isl_print_space_data *data, unsigned pos);
- void *user;
-
- isl_space *space;
- enum isl_dim_type type;
-};
-
/* offset is the offset of local_dim inside data->type of data->space.
*/
static __isl_give isl_printer *print_nested_var_list(__isl_take isl_printer *p,
@@ -407,20 +412,20 @@ static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
return p;
}
-static __isl_give isl_printer *print_space(__isl_keep isl_space *dim,
+__isl_give isl_printer *isl_print_space(__isl_keep isl_space *space,
__isl_take isl_printer *p, int rational,
struct isl_print_space_data *data)
{
if (rational && !data->latex)
p = isl_printer_print_str(p, "rat: ");
- if (isl_space_is_params(dim))
+ if (isl_space_is_params(space))
;
- else if (isl_space_is_set(dim))
- p = print_tuple(dim, p, isl_dim_set, data);
+ else if (isl_space_is_set(space))
+ p = print_tuple(space, p, isl_dim_set, data);
else {
- p = print_tuple(dim, p, isl_dim_in, data);
+ p = print_tuple(space, p, isl_dim_in, data);
p = isl_printer_print_str(p, s_to[data->latex]);
- p = print_tuple(dim, p, isl_dim_out, data);
+ p = print_tuple(space, p, isl_dim_out, data);
}
return p;
@@ -440,8 +445,91 @@ static __isl_give isl_printer *print_omega_parameters(__isl_keep isl_space *dim,
return p;
}
+/* Does the inequality constraint following "i" in "bmap"
+ * have an opposite value for the same last coefficient?
+ * "last" is the position of the last coefficient of inequality "i".
+ * If the next constraint is a div constraint, then it is ignored
+ * since div constraints are not printed.
+ */
+static int next_is_opposite(__isl_keep isl_basic_map *bmap, int i, int last)
+{
+ unsigned total = isl_basic_map_total_dim(bmap);
+ unsigned o_div = isl_basic_map_offset(bmap, isl_dim_div);
+
+ if (i + 1 >= bmap->n_ineq)
+ return 0;
+ if (isl_seq_last_non_zero(bmap->ineq[i + 1], 1 + total) != last)
+ return 0;
+ if (last >= o_div &&
+ isl_basic_map_is_div_constraint(bmap, bmap->ineq[i + 1],
+ last - o_div))
+ return 0;
+ return isl_int_abs_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]) &&
+ !isl_int_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]);
+}
+
+/* Return a string representation of the operator used when
+ * printing a constraint where the LHS is greater than or equal to the LHS
+ * (sign > 0) or smaller than or equal to the LHS (sign < 0).
+ * If "strict" is set, then return the strict version of the comparison
+ * operator.
+ */
+static const char *constraint_op(int sign, int strict, int latex)
+{
+ if (strict)
+ return sign < 0 ? "<" : ">";
+ if (sign < 0)
+ return s_le[latex];
+ else
+ return s_ge[latex];
+}
+
+/* Print one side of a constraint "c" from "bmap" to "p", with
+ * the variable names taken from "space" and the integer division definitions
+ * taken from "div".
+ * "last" is the position of the last non-zero coefficient.
+ * Let c' be the result of zeroing out this coefficient, then
+ * the partial constraint
+ *
+ * c' op
+ *
+ * is printed.
+ * "first_constraint" is set if this is the first constraint
+ * in the conjunction.
+ */
+static __isl_give isl_printer *print_half_constraint(struct isl_basic_map *bmap,
+ __isl_keep isl_space *space, __isl_keep isl_mat *div,
+ __isl_take isl_printer *p, isl_int *c, int last, const char *op,
+ int first_constraint, int latex)
+{
+ if (!first_constraint)
+ p = isl_printer_print_str(p, s_and[latex]);
+
+ isl_int_set_si(c[last], 0);
+ p = print_affine(bmap, space, div, p, c);
+
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_str(p, op);
+ p = isl_printer_print_str(p, " ");
+
+ return p;
+}
+
+/* Print a constraint "c" from "bmap" to "p", with the variable names
+ * taken from "space" and the integer division definitions taken from "div".
+ * "last" is the position of the last non-zero coefficient, which is
+ * moreover assumed to be negative.
+ * Let c' be the result of zeroing out this coefficient, then
+ * the constraint is printed in the form
+ *
+ * -c[last] op c'
+ *
+ * "first_constraint" is set if this is the first constraint
+ * in the conjunction.
+ */
static __isl_give isl_printer *print_constraint(struct isl_basic_map *bmap,
- __isl_keep isl_space *dim, __isl_take isl_printer *p,
+ __isl_keep isl_space *space, __isl_keep isl_mat *div,
+ __isl_take isl_printer *p,
isl_int *c, int last, const char *op, int first_constraint, int latex)
{
if (!first_constraint)
@@ -449,24 +537,74 @@ static __isl_give isl_printer *print_constraint(struct isl_basic_map *bmap,
isl_int_abs(c[last], c[last]);
- p = print_term(dim, NULL, c[last], last, p, latex);
+ p = print_term(space, div, c[last], last, p, latex);
p = isl_printer_print_str(p, " ");
p = isl_printer_print_str(p, op);
p = isl_printer_print_str(p, " ");
isl_int_set_si(c[last], 0);
- p = print_affine(bmap, dim, p, c);
+ p = print_affine(bmap, space, div, p, c);
return p;
}
+/* Print the constraints of "bmap" to "p".
+ * The names of the variables are taken from "space" and
+ * the integer division definitions are taken from "div".
+ * Div constraints are only printed in "dump" mode.
+ * The constraints are sorted prior to printing (except in "dump" mode).
+ *
+ * If x is the last variable with a non-zero coefficient,
+ * then a lower bound
+ *
+ * f - a x >= 0
+ *
+ * is printed as
+ *
+ * a x <= f
+ *
+ * while an upper bound
+ *
+ * f + a x >= 0
+ *
+ * is printed as
+ *
+ * a x >= -f
+ *
+ * If the next constraint has an opposite sign for the same last coefficient,
+ * then it is printed as
+ *
+ * f >= a x
+ *
+ * or
+ *
+ * -f <= a x
+ *
+ * instead. In fact, the "a x" part is not printed explicitly, but
+ * reused from the next constraint, which is therefore treated as
+ * a first constraint in the conjunction.
+ *
+ * If the constant term of "f" is -1, then "f" is replaced by "f + 1" and
+ * the comparison operator is replaced by the strict variant.
+ * Essentially, ">= 1" is replaced by "> 0".
+ */
static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
- __isl_keep isl_space *dim, __isl_take isl_printer *p, int latex)
+ __isl_keep isl_space *space, __isl_keep isl_mat *div,
+ __isl_take isl_printer *p, int latex)
{
int i;
- struct isl_vec *c;
+ isl_vec *c = NULL;
+ int rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
unsigned total = isl_basic_map_total_dim(bmap);
+ unsigned o_div = isl_basic_map_offset(bmap, isl_dim_div);
+ int first = 1;
+
+ bmap = isl_basic_map_copy(bmap);
+ if (!p->dump)
+ bmap = isl_basic_map_sort_constraints(bmap);
+ if (!bmap)
+ goto error;
c = isl_vec_alloc(bmap->ctx, 1 + total);
if (!c)
@@ -484,29 +622,48 @@ static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
isl_seq_cpy(c->el, bmap->eq[i], 1 + total);
else
isl_seq_neg(c->el, bmap->eq[i], 1 + total);
- p = print_constraint(bmap, dim, p, c->el, l,
- "=", i == bmap->n_eq - 1, latex);
+ p = print_constraint(bmap, space, div, p, c->el, l,
+ "=", first, latex);
+ first = 0;
}
for (i = 0; i < bmap->n_ineq; ++i) {
int l = isl_seq_last_non_zero(bmap->ineq[i], 1 + total);
+ int strict;
int s;
const char *op;
if (l < 0)
continue;
+ if (!p->dump && l >= o_div &&
+ isl_basic_map_is_div_constraint(bmap, bmap->ineq[i],
+ l - o_div))
+ continue;
s = isl_int_sgn(bmap->ineq[i][l]);
+ strict = !rational && isl_int_is_negone(bmap->ineq[i][0]);
if (s < 0)
isl_seq_cpy(c->el, bmap->ineq[i], 1 + total);
else
isl_seq_neg(c->el, bmap->ineq[i], 1 + total);
- op = s < 0 ? s_le[latex] : s_ge[latex];
- p = print_constraint(bmap, dim, p, c->el, l,
- op, !bmap->n_eq && !i, latex);
+ if (strict)
+ isl_int_set_si(c->el[0], 0);
+ if (!p->dump && next_is_opposite(bmap, i, l)) {
+ op = constraint_op(-s, strict, latex);
+ p = print_half_constraint(bmap, space, div, p, c->el, l,
+ op, first, latex);
+ first = 1;
+ } else {
+ op = constraint_op(s, strict, latex);
+ p = print_constraint(bmap, space, div, p, c->el, l,
+ op, first, latex);
+ first = 0;
+ }
}
+ isl_basic_map_free(bmap);
isl_vec_free(c);
return p;
error:
+ isl_basic_map_free(bmap);
isl_vec_free(c);
isl_printer_free(p);
return NULL;
@@ -515,7 +672,12 @@ error:
static __isl_give isl_printer *print_div(__isl_keep isl_space *dim,
__isl_keep isl_mat *div, int pos, __isl_take isl_printer *p)
{
- int c = p->output_format == ISL_FORMAT_C;
+ int c;
+
+ if (!p || !div)
+ return isl_printer_free(p);
+
+ c = p->output_format == ISL_FORMAT_C;
p = isl_printer_print_str(p, c ? "floord(" : "floor((");
p = print_affine_of_len(dim, div, p,
div->row[pos] + 1, div->n_col - 1);
@@ -525,13 +687,17 @@ static __isl_give isl_printer *print_div(__isl_keep isl_space *dim,
return p;
}
-/* Print a comma separated list of div names, with their definitions
- * (provided that they have a definition and we are printing in isl format).
+/* Print a comma separated list of div names, except those that have
+ * a definition that can be printed.
+ * If "print_defined_divs" is set, then those div names are printed
+ * as well, along with their definitions.
*/
static __isl_give isl_printer *print_div_list(__isl_take isl_printer *p,
- __isl_keep isl_space *space, __isl_keep isl_mat *div, int latex)
+ __isl_keep isl_space *space, __isl_keep isl_mat *div, int latex,
+ int print_defined_divs)
{
int i;
+ int first = 1;
unsigned n_div;
if (!p || !space || !div)
@@ -540,11 +706,13 @@ static __isl_give isl_printer *print_div_list(__isl_take isl_printer *p,
n_div = isl_mat_rows(div);
for (i = 0; i < n_div; ++i) {
- if (i)
+ if (!print_defined_divs && can_print_div_expr(p, div, i))
+ continue;
+ if (!first)
p = isl_printer_print_str(p, ", ");
p = print_name(space, p, isl_dim_div, i, latex);
- if (p->output_format != ISL_FORMAT_ISL ||
- isl_int_is_zero(div->row[i][0]))
+ first = 0;
+ if (!can_print_div_expr(p, div, i))
continue;
p = isl_printer_print_str(p, " = ");
p = print_div(space, div, i, p);
@@ -553,25 +721,52 @@ static __isl_give isl_printer *print_div_list(__isl_take isl_printer *p,
return p;
}
+/* Does printing "bmap" require an "exists" clause?
+ * That is, are there any local variables without an explicit representation?
+ */
+static isl_bool need_exists(__isl_keep isl_printer *p,
+ __isl_keep isl_basic_map *bmap, __isl_keep isl_mat *div)
+{
+ int i;
+
+ if (!p || !bmap)
+ return isl_bool_error;
+ if (bmap->n_div == 0)
+ return isl_bool_false;
+ for (i = 0; i < bmap->n_div; ++i)
+ if (!can_print_div_expr(p, div, i))
+ return isl_bool_true;
+ return isl_bool_false;
+}
+
+/* Print the constraints of "bmap" to "p".
+ * The names of the variables are taken from "space".
+ * "latex" is set if the constraints should be printed in LaTeX format.
+ * Do not print inline explicit div representations in "dump" mode.
+ */
static __isl_give isl_printer *print_disjunct(__isl_keep isl_basic_map *bmap,
- __isl_keep isl_space *dim, __isl_take isl_printer *p, int latex)
+ __isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
{
- if (bmap->n_div > 0) {
- isl_space *space;
- isl_mat *div;
+ isl_mat *div;
+ isl_bool exists;
- space = isl_basic_map_get_space(bmap);
- div = isl_basic_map_get_divs(bmap);
+ div = isl_basic_map_get_divs(bmap);
+ if (p->dump)
+ exists = bmap->n_div > 0;
+ else
+ exists = need_exists(p, bmap, div);
+ if (exists >= 0 && exists) {
p = isl_printer_print_str(p, s_open_exists[latex]);
- p = print_div_list(p, space, div, latex);
- isl_space_free(space);
- isl_mat_free(div);
+ p = print_div_list(p, space, div, latex, p->dump);
p = isl_printer_print_str(p, ": ");
}
- p = print_constraints(bmap, dim, p, latex);
+ if (p->dump)
+ div = isl_mat_free(div);
+ p = print_constraints(bmap, space, div, p, latex);
+ isl_mat_free(div);
- if (bmap->n_div > 0)
+ if (exists >= 0 && exists)
p = isl_printer_print_str(p, s_close_exists[latex]);
return p;
}
@@ -656,22 +851,22 @@ static __isl_give isl_printer *isl_basic_map_print_isl(
p = isl_printer_print_str(p, " -> ");
}
p = isl_printer_print_str(p, "{ ");
- p = print_space(bmap->dim, p, rational, &data);
+ p = isl_print_space(bmap->dim, p, rational, &data);
p = isl_printer_print_str(p, " : ");
p = print_disjunct(bmap, bmap->dim, p, latex);
p = isl_printer_print_str(p, " }");
return p;
}
-static __isl_give isl_printer *print_disjuncts(__isl_keep isl_map *map,
- __isl_take isl_printer *p, int latex)
+/* Print the disjuncts of a map (or set) "map" to "p".
+ * The names of the variables are taken from "space".
+ * "latex" is set if the constraints should be printed in LaTeX format.
+ */
+static __isl_give isl_printer *print_disjuncts_core(__isl_keep isl_map *map,
+ __isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
{
int i;
- if (isl_map_plain_is_universe(map))
- return p;
-
- p = isl_printer_print_str(p, s_such_that[latex]);
if (map->n == 0)
p = isl_printer_print_str(p, "1 = 0");
for (i = 0; i < map->n; ++i) {
@@ -679,25 +874,96 @@ static __isl_give isl_printer *print_disjuncts(__isl_keep isl_map *map,
p = isl_printer_print_str(p, s_or[latex]);
if (map->n > 1 && map->p[i]->n_eq + map->p[i]->n_ineq > 1)
p = isl_printer_print_str(p, "(");
- p = print_disjunct(map->p[i], map->dim, p, latex);
+ p = print_disjunct(map->p[i], space, p, latex);
if (map->n > 1 && map->p[i]->n_eq + map->p[i]->n_ineq > 1)
p = isl_printer_print_str(p, ")");
}
return p;
}
+/* Print the disjuncts of a map (or set) "map" to "p".
+ * The names of the variables are taken from "space".
+ * "hull" describes constraints shared by all disjuncts of "map".
+ * "latex" is set if the constraints should be printed in LaTeX format.
+ *
+ * Print the disjuncts as a conjunction of "hull" and
+ * the result of removing the constraints of "hull" from "map".
+ * If this result turns out to be the universe, then simply print "hull".
+ */
+static __isl_give isl_printer *print_disjuncts_in_hull(__isl_keep isl_map *map,
+ __isl_keep isl_space *space, __isl_take isl_basic_map *hull,
+ __isl_take isl_printer *p, int latex)
+{
+ isl_bool is_universe;
+
+ p = print_disjunct(hull, space, p, latex);
+ map = isl_map_plain_gist_basic_map(isl_map_copy(map), hull);
+ is_universe = isl_map_plain_is_universe(map);
+ if (is_universe < 0)
+ goto error;
+ if (!is_universe) {
+ p = isl_printer_print_str(p, s_and[latex]);
+ p = isl_printer_print_str(p, "(");
+ p = print_disjuncts_core(map, space, p, latex);
+ p = isl_printer_print_str(p, ")");
+ }
+ isl_map_free(map);
+
+ return p;
+error:
+ isl_map_free(map);
+ isl_printer_free(p);
+ return NULL;
+}
+
+/* Print the disjuncts of a map (or set) "map" to "p".
+ * The names of the variables are taken from "space".
+ * "latex" is set if the constraints should be printed in LaTeX format.
+ *
+ * If there are at least two disjuncts and "dump" mode is not turned out,
+ * check for any shared constraints among all disjuncts.
+ * If there are any, then print them separately in print_disjuncts_in_hull.
+ */
+static __isl_give isl_printer *print_disjuncts(__isl_keep isl_map *map,
+ __isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
+{
+ if (isl_map_plain_is_universe(map))
+ return p;
+
+ p = isl_printer_print_str(p, s_such_that[latex]);
+
+ if (!p->dump && map->n >= 2) {
+ isl_basic_map *hull;
+ isl_bool is_universe;
+
+ hull = isl_map_plain_unshifted_simple_hull(isl_map_copy(map));
+ is_universe = isl_basic_map_is_universe(hull);
+ if (is_universe < 0)
+ p = isl_printer_free(p);
+ else if (!is_universe)
+ return print_disjuncts_in_hull(map, space, hull,
+ p, latex);
+ isl_basic_map_free(hull);
+ }
+
+ return print_disjuncts_core(map, space, p, latex);
+}
+
/* Print the disjuncts of a map (or set).
+ * The names of the variables are taken from "space".
+ * "latex" is set if the constraints should be printed in LaTeX format.
+ *
* If the map turns out to be a universal parameter domain, then
* we need to print the colon. Otherwise, the output looks identical
* to the empty set.
*/
static __isl_give isl_printer *print_disjuncts_map(__isl_keep isl_map *map,
- __isl_take isl_printer *p, int latex)
+ __isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
{
if (isl_map_plain_is_universe(map) && isl_space_is_params(map->dim))
return isl_printer_print_str(p, s_such_that[latex]);
else
- return print_disjuncts(map, p, latex);
+ return print_disjuncts(map, space, p, latex);
}
struct isl_aff_split {
@@ -888,7 +1154,7 @@ static __isl_give isl_printer *print_dim_eq(__isl_take isl_printer *p,
}
static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p,
- struct isl_aff_split *split, int n)
+ struct isl_aff_split *split, int n, __isl_keep isl_space *space)
{
struct isl_print_space_data data = { 0 };
int i;
@@ -896,18 +1162,15 @@ static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p,
data.print_dim = &print_dim_eq;
for (i = 0; i < n; ++i) {
- isl_space *dim;
-
if (!split[i].map)
break;
- dim = split[i].map->dim;
rational = split[i].map->n > 0 &&
ISL_F_ISSET(split[i].map->p[0], ISL_BASIC_MAP_RATIONAL);
if (i)
p = isl_printer_print_str(p, "; ");
data.user = split[i].aff;
- p = print_space(dim, p, rational, &data);
- p = print_disjuncts_map(split[i].map, p, 0);
+ p = isl_print_space(space, p, rational, &data);
+ p = print_disjuncts_map(split[i].map, space, p, 0);
}
return p;
@@ -920,15 +1183,15 @@ static __isl_give isl_printer *isl_map_print_isl_body(__isl_keep isl_map *map,
struct isl_aff_split *split = NULL;
int rational;
- if (map->n > 0)
+ if (!p->dump && map->n > 0)
split = split_aff(map);
if (split) {
- p = print_split_map(p, split, map->n);
+ p = print_split_map(p, split, map->n, map->dim);
} else {
rational = map->n > 0 &&
ISL_F_ISSET(map->p[0], ISL_BASIC_MAP_RATIONAL);
- p = print_space(map->dim, p, rational, &data);
- p = print_disjuncts_map(map, p, 0);
+ p = isl_print_space(map->dim, p, rational, &data);
+ p = print_disjuncts_map(map, map->dim, p, 0);
}
free_split(split, map->n);
return p;
@@ -962,8 +1225,8 @@ static __isl_give isl_printer *print_latex_map(__isl_keep isl_map *map,
p = isl_printer_print_str(p, s_open_set[1]);
data.print_dim = &print_dim_eq;
data.user = aff;
- p = print_space(map->dim, p, 0, &data);
- p = print_disjuncts_map(map, p, 1);
+ p = isl_print_space(map->dim, p, 0, &data);
+ p = print_disjuncts_map(map, map->dim, p, 1);
p = isl_printer_print_str(p, s_close_set[1]);
return p;
@@ -1333,7 +1596,7 @@ static __isl_give isl_printer *print_qpolynomial_isl(__isl_take isl_printer *p,
}
p = isl_printer_print_str(p, "{ ");
if (!isl_space_is_params(qp->dim)) {
- p = print_space(qp->dim, p, 0, &data);
+ p = isl_print_space(qp->dim, p, 0, &data);
p = isl_printer_print_str(p, " -> ");
}
p = print_qpolynomial(p, qp);
@@ -1447,14 +1710,18 @@ static __isl_give isl_printer *isl_pwqp_print_isl_body(
int i = 0;
for (i = 0; i < pwqp->n; ++i) {
+ isl_space *space;
+
if (i)
p = isl_printer_print_str(p, "; ");
- if (!isl_space_is_params(pwqp->p[i].set->dim)) {
- p = print_space(pwqp->p[i].set->dim, p, 0, &data);
+ space = isl_qpolynomial_get_domain_space(pwqp->p[i].qp);
+ if (!isl_space_is_params(space)) {
+ p = isl_print_space(space, p, 0, &data);
p = isl_printer_print_str(p, " -> ");
}
p = print_qpolynomial(p, pwqp->p[i].qp);
- p = print_disjuncts((isl_map *)pwqp->p[i].set, p, 0);
+ p = print_disjuncts((isl_map *)pwqp->p[i].set, space, p, 0);
+ isl_space_free(space);
}
return p;
@@ -1510,14 +1777,18 @@ static __isl_give isl_printer *isl_pwf_print_isl_body(
int i = 0;
for (i = 0; i < pwf->n; ++i) {
+ isl_space *space;
+
if (i)
p = isl_printer_print_str(p, "; ");
- if (!isl_space_is_params(pwf->p[i].set->dim)) {
- p = print_space(pwf->p[i].set->dim, p, 0, &data);
+ space = isl_qpolynomial_fold_get_domain_space(pwf->p[i].fold);
+ if (!isl_space_is_params(space)) {
+ p = isl_print_space(space, p, 0, &data);
p = isl_printer_print_str(p, " -> ");
}
p = qpolynomial_fold_print(pwf->p[i].fold, p);
- p = print_disjuncts((isl_map *)pwf->p[i].set, p, 0);
+ p = print_disjuncts((isl_map *)pwf->p[i].set, space, p, 0);
+ isl_space_free(space);
}
return p;
@@ -1968,23 +2239,23 @@ error:
}
static __isl_give isl_printer *isl_printer_print_space_isl(
- __isl_take isl_printer *p, __isl_keep isl_space *dim)
+ __isl_take isl_printer *p, __isl_keep isl_space *space)
{
struct isl_print_space_data data = { 0 };
- if (!dim)
+ if (!space)
goto error;
- if (isl_space_dim(dim, isl_dim_param) > 0) {
- p = print_tuple(dim, p, isl_dim_param, &data);
+ if (isl_space_dim(space, isl_dim_param) > 0) {
+ p = print_tuple(space, p, isl_dim_param, &data);
p = isl_printer_print_str(p, " -> ");
}
p = isl_printer_print_str(p, "{ ");
- if (isl_space_is_params(dim))
+ if (isl_space_is_params(space))
p = isl_printer_print_str(p, s_such_that[0]);
else
- p = print_space(dim, p, 0, &data);
+ p = isl_print_space(space, p, 0, &data);
p = isl_printer_print_str(p, " }");
return p;
@@ -2022,12 +2293,13 @@ __isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
p = isl_printer_print_str(p, " -> ");
}
p = isl_printer_print_str(p, "{ ");
- p = print_space(ls->dim, p, 0, &data);
+ p = isl_print_space(ls->dim, p, 0, &data);
n_div = isl_local_space_dim(ls, isl_dim_div);
if (n_div > 0) {
p = isl_printer_print_str(p, " : ");
p = isl_printer_print_str(p, s_open_exists[0]);
- p = print_div_list(p, ls->dim, ls->div, 0);
+ p = print_div_list(p, ls->dim, ls->div, 0, 1);
+ p = isl_printer_print_str(p, s_close_exists[0]);
} else if (isl_space_is_params(ls->dim))
p = isl_printer_print_str(p, s_such_that[0]);
p = isl_printer_print_str(p, " }");
@@ -2110,10 +2382,14 @@ static __isl_give isl_printer *print_pw_aff_body(
return isl_printer_free(p);
for (i = 0; i < pa->n; ++i) {
+ isl_space *space;
+
if (i)
p = isl_printer_print_str(p, "; ");
p = print_aff(p, pa->p[i].aff);
- p = print_disjuncts((isl_map *)pa->p[i].set, p, 0);
+ space = isl_aff_get_domain_space(pa->p[i].aff);
+ p = print_disjuncts((isl_map *)pa->p[i].set, space, p, 0);
+ isl_space_free(space);
}
return p;
@@ -2402,7 +2678,7 @@ static __isl_give isl_printer *print_multi_aff(__isl_take isl_printer *p,
data.print_dim = &print_dim_ma;
data.user = maff;
- return print_space(maff->space, p, 0, &data);
+ return isl_print_space(maff->space, p, 0, &data);
}
static __isl_give isl_printer *print_multi_aff_isl(__isl_take isl_printer *p,
@@ -2450,10 +2726,14 @@ static __isl_give isl_printer *print_pw_multi_aff_body(
goto error;
for (i = 0; i < pma->n; ++i) {
+ isl_space *space;
+
if (i)
p = isl_printer_print_str(p, "; ");
p = print_multi_aff(p, pma->p[i].maff);
- p = print_disjuncts((isl_map *)pma->p[i].set, p, 0);
+ space = isl_multi_aff_get_domain_space(pma->p[i].maff);
+ p = print_disjuncts((isl_map *)pma->p[i].set, space, p, 0);
+ isl_space_free(space);
}
return p;
error:
@@ -2628,10 +2908,14 @@ static __isl_give isl_printer *print_dim_mpa(__isl_take isl_printer *p,
if (need_parens)
p = isl_printer_print_str(p, "(");
for (i = 0; i < pa->n; ++i) {
+ isl_space *space;
+
if (i)
p = isl_printer_print_str(p, "; ");
p = print_aff_body(p, pa->p[i].aff);
- p = print_disjuncts(pa->p[i].set, p, 0);
+ space = isl_aff_get_domain_space(pa->p[i].aff);
+ p = print_disjuncts(pa->p[i].set, space, p, 0);
+ isl_space_free(space);
}
if (need_parens)
p = isl_printer_print_str(p, ")");
@@ -2656,7 +2940,7 @@ static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p,
p = isl_printer_print_str(p, "{ ");
data.print_dim = &print_dim_mpa;
data.user = mpa;
- p = print_space(mpa->space, p, 0, &data);
+ p = isl_print_space(mpa->space, p, 0, &data);
p = isl_printer_print_str(p, " }");
return p;
}
@@ -2708,7 +2992,7 @@ static __isl_give isl_printer *print_multi_val_isl(__isl_take isl_printer *p,
p = isl_printer_print_str(p, "{ ");
data.print_dim = &print_dim_mv;
data.user = mv;
- p = print_space(mv->space, p, 0, &data);
+ p = isl_print_space(mv->space, p, 0, &data);
p = isl_printer_print_str(p, " }");
return p;
}
@@ -2768,7 +3052,7 @@ static __isl_give isl_printer *print_multi_union_pw_aff_isl(
data.print_dim = &print_union_pw_aff_dim;
data.user = mupa;
- p = print_space(space, p, 0, &data);
+ p = isl_print_space(space, p, 0, &data);
isl_space_free(space);
return p;
diff --git a/isl_output_private.h b/isl_output_private.h
new file mode 100644
index 00000000..2e4701dd
--- /dev/null
+++ b/isl_output_private.h
@@ -0,0 +1,27 @@
+#include <isl/space.h>
+#include <isl/printer.h>
+
+/* Internal data structure for isl_print_space.
+ *
+ * latex is set if that is the output format.
+ * print_dim (if not NULL) is called on each dimension.
+ * user is set by the caller of print_space and may be used inside print_dim.
+ *
+ * space is the global space that is being printed. This field is set by
+ * print_space.
+ * type is the tuple of the global space that is currently being printed.
+ * This field is set by print_space.
+ */
+struct isl_print_space_data {
+ int latex;
+ __isl_give isl_printer *(*print_dim)(__isl_take isl_printer *p,
+ struct isl_print_space_data *data, unsigned pos);
+ void *user;
+
+ isl_space *space;
+ enum isl_dim_type type;
+};
+
+__isl_give isl_printer *isl_print_space(__isl_keep isl_space *space,
+ __isl_take isl_printer *p, int rational,
+ struct isl_print_space_data *data);
diff --git a/isl_point.c b/isl_point.c
index a78662fe..3e832a8e 100644
--- a/isl_point.c
+++ b/isl_point.c
@@ -1,12 +1,14 @@
#include <isl_map_private.h>
#include <isl_point_private.h>
#include <isl/set.h>
+#include <isl/union_set.h>
#include <isl_sample.h>
#include <isl_scan.h>
#include <isl_seq.h>
#include <isl_space_private.h>
#include <isl_val_private.h>
#include <isl_vec_private.h>
+#include <isl_output_private.h>
#include <isl/deprecated/point_int.h>
isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt)
@@ -445,6 +447,24 @@ __isl_give isl_set *isl_set_from_point(__isl_take isl_point *pnt)
return isl_set_from_basic_set(bset);
}
+/* Construct a union set, containing the single element "pnt".
+ * If "pnt" is void, then return an empty union set.
+ */
+__isl_give isl_union_set *isl_union_set_from_point(__isl_take isl_point *pnt)
+{
+ if (!pnt)
+ return NULL;
+ if (isl_point_is_void(pnt)) {
+ isl_space *space;
+
+ space = isl_point_get_space(pnt);
+ isl_point_free(pnt);
+ return isl_union_set_empty(space);
+ }
+
+ return isl_union_set_from_set(isl_set_from_point(pnt));
+}
+
__isl_give isl_basic_set *isl_basic_set_box_from_points(
__isl_take isl_point *pnt1, __isl_take isl_point *pnt2)
{
@@ -537,9 +557,26 @@ __isl_give isl_set *isl_set_box_from_points(__isl_take isl_point *pnt1,
return isl_set_from_basic_set(bset);
}
+/* Print the coordinate at position "pos" of the point "pnt".
+ */
+static __isl_give isl_printer *print_coordinate(__isl_take isl_printer *p,
+ struct isl_print_space_data *data, unsigned pos)
+{
+ isl_point *pnt = data->user;
+
+ p = isl_printer_print_isl_int(p, pnt->vec->el[1 + pos]);
+ if (!isl_int_is_one(pnt->vec->el[0])) {
+ p = isl_printer_print_str(p, "/");
+ p = isl_printer_print_isl_int(p, pnt->vec->el[0]);
+ }
+
+ return p;
+}
+
__isl_give isl_printer *isl_printer_print_point(
__isl_take isl_printer *p, __isl_keep isl_point *pnt)
{
+ struct isl_print_space_data data = { 0 };
int i;
unsigned nparam;
unsigned dim;
@@ -573,16 +610,10 @@ __isl_give isl_printer *isl_printer_print_point(
p = isl_printer_print_str(p, "]");
p = isl_printer_print_str(p, " -> ");
}
- p = isl_printer_print_str(p, "[");
- for (i = 0; i < dim; ++i) {
- if (i)
- p = isl_printer_print_str(p, ", ");
- p = isl_printer_print_isl_int(p, pnt->vec->el[1 + nparam + i]);
- if (!isl_int_is_one(pnt->vec->el[0])) {
- p = isl_printer_print_str(p, "/");
- p = isl_printer_print_isl_int(p, pnt->vec->el[0]);
- }
- }
- p = isl_printer_print_str(p, "]");
+ data.print_dim = &print_coordinate;
+ data.user = pnt;
+ p = isl_printer_print_str(p, "{ ");
+ p = isl_print_space(pnt->dim, p, 0, &data);
+ p = isl_printer_print_str(p, " }");
return p;
}
diff --git a/isl_polynomial.c b/isl_polynomial.c
index 414e7c0b..277912ad 100644
--- a/isl_polynomial.c
+++ b/isl_polynomial.c
@@ -2817,7 +2817,9 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_qpolynomial(
#undef PARTS
#define PARTS pw_qpolynomial
-#include <isl_union_templ.c>
+#include <isl_union_single.c>
+#include <isl_union_eval.c>
+#include <isl_union_neg.c>
int isl_pw_qpolynomial_is_one(__isl_keep isl_pw_qpolynomial *pwqp)
{
@@ -4770,31 +4772,19 @@ error:
return NULL;
}
-static isl_stat poly_entry(void **entry, void *user)
+static __isl_give isl_pw_qpolynomial *poly_entry(
+ __isl_take isl_pw_qpolynomial *pwqp, void *user)
{
int *sign = user;
- isl_pw_qpolynomial **pwqp = (isl_pw_qpolynomial **)entry;
- *pwqp = isl_pw_qpolynomial_to_polynomial(*pwqp, *sign);
-
- return *pwqp ? isl_stat_ok : isl_stat_error;
+ return isl_pw_qpolynomial_to_polynomial(pwqp, *sign);
}
__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_to_polynomial(
__isl_take isl_union_pw_qpolynomial *upwqp, int sign)
{
- upwqp = isl_union_pw_qpolynomial_cow(upwqp);
- if (!upwqp)
- return NULL;
-
- if (isl_hash_table_foreach(upwqp->space->ctx, &upwqp->table,
- &poly_entry, &sign) < 0)
- goto error;
-
- return upwqp;
-error:
- isl_union_pw_qpolynomial_free(upwqp);
- return NULL;
+ return isl_union_pw_qpolynomial_transform_inplace(upwqp,
+ &poly_entry, &sign);
}
__isl_give isl_basic_map *isl_basic_map_from_qpolynomial(
diff --git a/isl_printer.c b/isl_printer.c
index a0b3823e..0c9b75ae 100644
--- a/isl_printer.c
+++ b/isl_printer.c
@@ -384,6 +384,20 @@ int isl_printer_get_output_format(__isl_keep isl_printer *p)
return p->output_format;
}
+/* Keep track of whether the printing to "p" is being performed from
+ * an isl_*_dump function as specified by "dump".
+ */
+__isl_give isl_printer *isl_printer_set_dump(__isl_take isl_printer *p,
+ int dump)
+{
+ if (!p)
+ return NULL;
+
+ p->dump = dump;
+
+ return p;
+}
+
/* Set the YAML style of "p" to "yaml_style" and return the updated printer.
*/
__isl_give isl_printer *isl_printer_set_yaml_style(__isl_take isl_printer *p,
diff --git a/isl_printer_private.h b/isl_printer_private.h
index 29f3db57..7af8aae6 100644
--- a/isl_printer_private.h
+++ b/isl_printer_private.h
@@ -1,3 +1,6 @@
+#ifndef ISL_PRINTER_PRIVATE_H
+#define ISL_PRINTER_PRIVATE_H
+
#include <isl/printer.h>
#include <isl_yaml.h>
@@ -5,6 +8,8 @@ struct isl_printer_ops;
/* A printer to a file or a string.
*
+ * "dump" is set if the printing is performed from an isl_*_dump function.
+ *
* yaml_style is the YAML style in which the next elements should
* be printed and may be either ISL_YAML_STYLE_BLOCK or ISL_YAML_STYLE_FLOW,
* with ISL_YAML_STYLE_FLOW being the default.
@@ -22,6 +27,7 @@ struct isl_printer {
char *buf;
int indent;
int output_format;
+ int dump;
char *indent_prefix;
char *prefix;
char *suffix;
@@ -32,3 +38,8 @@ struct isl_printer {
int yaml_size;
enum isl_yaml_state *yaml_state;
};
+
+__isl_give isl_printer *isl_printer_set_dump(__isl_take isl_printer *p,
+ int dump);
+
+#endif
diff --git a/isl_range.c b/isl_range.c
index 1bf81ed7..a23a6332 100644
--- a/isl_range.c
+++ b/isl_range.c
@@ -137,16 +137,24 @@ error:
return -2;
}
+/* Return a positive ("sign" > 0) or negative ("sign" < 0) infinite polynomial
+ * with domain space "space".
+ */
+static __isl_give isl_qpolynomial *signed_infty(__isl_take isl_space *space,
+ int sign)
+{
+ if (sign > 0)
+ return isl_qpolynomial_infty_on_domain(space);
+ else
+ return isl_qpolynomial_neginfty_on_domain(space);
+}
+
static __isl_give isl_qpolynomial *bound2poly(__isl_take isl_constraint *bound,
- __isl_take isl_space *dim, unsigned pos, int sign)
+ __isl_take isl_space *space, unsigned pos, int sign)
{
- if (!bound) {
- if (sign > 0)
- return isl_qpolynomial_infty_on_domain(dim);
- else
- return isl_qpolynomial_neginfty_on_domain(dim);
- }
- isl_space_free(dim);
+ if (!bound)
+ return signed_infty(space, sign);
+ isl_space_free(space);
return isl_qpolynomial_from_constraint(bound, isl_dim_set, pos);
}
@@ -270,6 +278,52 @@ static isl_stat add_guarded_poly(__isl_take isl_basic_set *bset,
return isl_stat_ok;
}
+/* Plug in "sub" for the variable at position "pos" in "poly".
+ *
+ * If "sub" is an infinite polynomial and if the variable actually
+ * appears in "poly", then calling isl_qpolynomial_substitute
+ * to perform the substitution may result in a NaN result.
+ * In such cases, return positive or negative infinity instead,
+ * depending on whether an upper bound or a lower bound is being computed,
+ * and mark the result as not being tight.
+ */
+static __isl_give isl_qpolynomial *plug_in_at_pos(
+ __isl_take isl_qpolynomial *poly, int pos,
+ __isl_take isl_qpolynomial *sub, struct range_data *data)
+{
+ isl_bool involves, infty;
+
+ involves = isl_qpolynomial_involves_dims(poly, isl_dim_in, pos, 1);
+ if (involves < 0)
+ goto error;
+ if (!involves) {
+ isl_qpolynomial_free(sub);
+ return poly;
+ }
+
+ infty = isl_qpolynomial_is_infty(sub);
+ if (infty >= 0 && !infty)
+ infty = isl_qpolynomial_is_neginfty(sub);
+ if (infty < 0)
+ goto error;
+ if (infty) {
+ isl_space *space = isl_qpolynomial_get_domain_space(poly);
+ data->tight = 0;
+ isl_qpolynomial_free(poly);
+ isl_qpolynomial_free(sub);
+ return signed_infty(space, data->sign);
+ }
+
+ poly = isl_qpolynomial_substitute(poly, isl_dim_in, pos, 1, &sub);
+ isl_qpolynomial_free(sub);
+
+ return poly;
+error:
+ isl_qpolynomial_free(poly);
+ isl_qpolynomial_free(sub);
+ return NULL;
+}
+
/* Given a lower and upper bound on the final variable and constraints
* on the remaining variables where these bounds are active,
* eliminate the variable from data->poly based on these bounds.
@@ -312,10 +366,8 @@ static isl_stat propagate_on_bound_pair(__isl_take isl_constraint *lower,
isl_constraint_free(upper);
}
poly = isl_qpolynomial_copy(data->poly);
- poly = isl_qpolynomial_substitute(poly, isl_dim_in, nvar, 1, &sub);
+ poly = plug_in_at_pos(poly, nvar, sub, data);
poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, nvar, 1);
-
- isl_qpolynomial_free(sub);
} else {
isl_qpolynomial *l, *u;
isl_qpolynomial *pos, *neg;
@@ -331,14 +383,11 @@ static isl_stat propagate_on_bound_pair(__isl_take isl_constraint *lower,
pos = isl_qpolynomial_terms_of_sign(data->poly, data->signs, sign);
neg = isl_qpolynomial_terms_of_sign(data->poly, data->signs, -sign);
- pos = isl_qpolynomial_substitute(pos, isl_dim_in, nvar, 1, &u);
- neg = isl_qpolynomial_substitute(neg, isl_dim_in, nvar, 1, &l);
+ pos = plug_in_at_pos(pos, nvar, u, data);
+ neg = plug_in_at_pos(neg, nvar, l, data);
poly = isl_qpolynomial_add(pos, neg);
poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, nvar, 1);
-
- isl_qpolynomial_free(u);
- isl_qpolynomial_free(l);
}
if (isl_basic_set_dim(bset, isl_dim_set) == 0)
diff --git a/isl_schedule.c b/isl_schedule.c
index 62b45836..6d98af37 100644
--- a/isl_schedule.c
+++ b/isl_schedule.c
@@ -478,6 +478,36 @@ error:
return NULL;
}
+/* Replace the domain of the schedule "schedule" with the gist
+ * of the original domain with respect to the parameter domain "context".
+ */
+__isl_give isl_schedule *isl_schedule_gist_domain_params(
+ __isl_take isl_schedule *schedule, __isl_take isl_set *context)
+{
+ enum isl_schedule_node_type root_type;
+ isl_schedule_node *node;
+
+ if (!schedule || !context)
+ goto error;
+
+ root_type = isl_schedule_tree_get_type(schedule->root);
+ if (root_type != isl_schedule_node_domain)
+ isl_die(isl_schedule_get_ctx(schedule), isl_error_invalid,
+ "root node must be a domain node", goto error);
+
+ node = isl_schedule_get_root(schedule);
+ isl_schedule_free(schedule);
+ node = isl_schedule_node_domain_gist_params(node, context);
+ schedule = isl_schedule_node_get_schedule(node);
+ isl_schedule_node_free(node);
+
+ return schedule;
+error:
+ isl_schedule_free(schedule);
+ isl_set_free(context);
+ return NULL;
+}
+
/* Return an isl_union_map representation of the schedule.
* If we still have access to the schedule tree, then we return
* an isl_union_map corresponding to the subtree schedule of the child
@@ -1102,3 +1132,23 @@ void isl_schedule_dump(__isl_keep isl_schedule *schedule)
isl_printer_free(printer);
}
+
+/* Return a string representation of "schedule".
+ * Print the schedule in flow format.
+ */
+__isl_give char *isl_schedule_to_str(__isl_keep isl_schedule *schedule)
+{
+ isl_printer *printer;
+ char *s;
+
+ if (!schedule)
+ return NULL;
+
+ printer = isl_printer_to_str(isl_schedule_get_ctx(schedule));
+ printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_FLOW);
+ printer = isl_printer_print_schedule(printer, schedule);
+ s = isl_printer_get_str(printer);
+ isl_printer_free(printer);
+
+ return s;
+}
diff --git a/isl_schedule_band.c b/isl_schedule_band.c
index 42d1564e..c25d7738 100644
--- a/isl_schedule_band.c
+++ b/isl_schedule_band.c
@@ -950,6 +950,61 @@ error:
return NULL;
}
+/* Reduce the partial schedule of "band" modulo the factors in "mv".
+ */
+__isl_give isl_schedule_band *isl_schedule_band_mod(
+ __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
+{
+ band = isl_schedule_band_cow(band);
+ if (!band || !mv)
+ goto error;
+ band->mupa = isl_multi_union_pw_aff_mod_multi_val(band->mupa, mv);
+ if (!band->mupa)
+ return isl_schedule_band_free(band);
+ return band;
+error:
+ isl_schedule_band_free(band);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Shift the partial schedule of "band" by "shift" after checking
+ * that the domain of the partial schedule would not be affected
+ * by this shift.
+ */
+__isl_give isl_schedule_band *isl_schedule_band_shift(
+ __isl_take isl_schedule_band *band,
+ __isl_take isl_multi_union_pw_aff *shift)
+{
+ isl_union_set *dom1, *dom2;
+ isl_bool subset;
+
+ band = isl_schedule_band_cow(band);
+ if (!band || !shift)
+ goto error;
+ dom1 = isl_multi_union_pw_aff_domain(
+ isl_multi_union_pw_aff_copy(band->mupa));
+ dom2 = isl_multi_union_pw_aff_domain(
+ isl_multi_union_pw_aff_copy(shift));
+ subset = isl_union_set_is_subset(dom1, dom2);
+ isl_union_set_free(dom1);
+ isl_union_set_free(dom2);
+ if (subset < 0)
+ goto error;
+ if (!subset)
+ isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
+ "domain of shift needs to include domain of "
+ "partial schedule", goto error);
+ band->mupa = isl_multi_union_pw_aff_add(band->mupa, shift);
+ if (!band->mupa)
+ return isl_schedule_band_free(band);
+ return band;
+error:
+ isl_schedule_band_free(band);
+ isl_multi_union_pw_aff_free(shift);
+ return NULL;
+}
+
/* Given the schedule of a band, construct the corresponding
* schedule for the tile loops based on the given tile sizes
* and return the result.
diff --git a/isl_schedule_band.h b/isl_schedule_band.h
index bb86fcac..bc58fbf5 100644
--- a/isl_schedule_band.h
+++ b/isl_schedule_band.h
@@ -94,11 +94,16 @@ __isl_give isl_schedule_band *isl_schedule_band_scale(
__isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv);
__isl_give isl_schedule_band *isl_schedule_band_scale_down(
__isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_band *isl_schedule_band_mod(
+ __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv);
__isl_give isl_schedule_band *isl_schedule_band_tile(
__isl_take isl_schedule_band *band, __isl_take isl_multi_val *sizes);
__isl_give isl_schedule_band *isl_schedule_band_point(
__isl_take isl_schedule_band *band, __isl_keep isl_schedule_band *tile,
__isl_take isl_multi_val *sizes);
+__isl_give isl_schedule_band *isl_schedule_band_shift(
+ __isl_take isl_schedule_band *band,
+ __isl_take isl_multi_union_pw_aff *shift);
__isl_give isl_schedule_band *isl_schedule_band_drop(
__isl_take isl_schedule_band *band, int pos, int n);
__isl_give isl_schedule_band *isl_schedule_band_gist(
diff --git a/isl_schedule_node.c b/isl_schedule_node.c
index 2540d15e..7c369e77 100644
--- a/isl_schedule_node.c
+++ b/isl_schedule_node.c
@@ -772,7 +772,7 @@ __isl_give isl_union_map *isl_schedule_node_get_prefix_schedule_union_map(
* there is also a filter ancestor that filters out all the extended
* domain elements.
*
- * Essentially, this functions intersected the domain of the output
+ * Essentially, this function intersects the domain of the output
* of isl_schedule_node_get_prefix_schedule_union_map with the output
* of isl_schedule_node_get_domain, except that it only traverses
* the ancestors of "node" once.
@@ -1764,6 +1764,91 @@ error:
return NULL;
}
+/* Reduce the partial schedule of the band node "node"
+ * modulo the factors in "mv".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_band_mod(
+ __isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv)
+{
+ isl_schedule_tree *tree;
+ isl_bool anchored;
+
+ if (!node || !mv)
+ goto error;
+ if (check_space_multi_val(node, mv) < 0)
+ goto error;
+ anchored = isl_schedule_node_is_subtree_anchored(node);
+ if (anchored < 0)
+ goto error;
+ if (anchored)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "cannot perform mod on band node with anchored subtree",
+ goto error);
+
+ tree = isl_schedule_node_get_tree(node);
+ tree = isl_schedule_tree_band_mod(tree, mv);
+ return isl_schedule_node_graft_tree(node, tree);
+error:
+ isl_multi_val_free(mv);
+ isl_schedule_node_free(node);
+ return NULL;
+}
+
+/* Make sure that that spaces of "node" and "mupa" are the same.
+ * Return isl_stat_error on error, reporting the error to the user.
+ */
+static isl_stat check_space_multi_union_pw_aff(
+ __isl_keep isl_schedule_node *node,
+ __isl_keep isl_multi_union_pw_aff *mupa)
+{
+ isl_space *node_space, *mupa_space;
+ isl_bool equal;
+
+ node_space = isl_schedule_node_band_get_space(node);
+ mupa_space = isl_multi_union_pw_aff_get_space(mupa);
+ equal = isl_space_tuple_is_equal(node_space, isl_dim_set,
+ mupa_space, isl_dim_set);
+ isl_space_free(mupa_space);
+ isl_space_free(node_space);
+ if (equal < 0)
+ return isl_stat_error;
+ if (!equal)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "spaces don't match", return isl_stat_error);
+
+ return isl_stat_ok;
+}
+
+/* Shift the partial schedule of the band node "node" by "shift".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_band_shift(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_union_pw_aff *shift)
+{
+ isl_schedule_tree *tree;
+ int anchored;
+
+ if (!node || !shift)
+ goto error;
+ if (check_space_multi_union_pw_aff(node, shift) < 0)
+ goto error;
+ anchored = isl_schedule_node_is_subtree_anchored(node);
+ if (anchored < 0)
+ goto error;
+ if (anchored)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "cannot shift band node with anchored subtree",
+ goto error);
+
+ tree = isl_schedule_node_get_tree(node);
+ tree = isl_schedule_tree_band_shift(tree, shift);
+ return isl_schedule_node_graft_tree(node, tree);
+error:
+ isl_multi_union_pw_aff_free(shift);
+ isl_schedule_node_free(node);
+ return NULL;
+}
+
/* Tile "node" with tile sizes "sizes".
*
* The current node is replaced by two nested nodes corresponding
@@ -2003,6 +2088,39 @@ error:
return NULL;
}
+/* Intersect the filter of filter node "node" with "filter".
+ *
+ * If the filter of the node is already a subset of "filter",
+ * then leave the node unchanged.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_filter_intersect_filter(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *filter)
+{
+ isl_union_set *node_filter = NULL;
+ isl_bool subset;
+
+ if (!node || !filter)
+ goto error;
+
+ node_filter = isl_schedule_node_filter_get_filter(node);
+ subset = isl_union_set_is_subset(node_filter, filter);
+ if (subset < 0)
+ goto error;
+ if (subset) {
+ isl_union_set_free(node_filter);
+ isl_union_set_free(filter);
+ return node;
+ }
+ node_filter = isl_union_set_intersect(node_filter, filter);
+ node = isl_schedule_node_filter_set_filter(node, node_filter);
+ return node;
+error:
+ isl_schedule_node_free(node);
+ isl_union_set_free(node_filter);
+ isl_union_set_free(filter);
+ return NULL;
+}
+
/* Return the guard of the guard node "node".
*/
__isl_give isl_set *isl_schedule_node_guard_get_guard(
@@ -2053,6 +2171,50 @@ error:
return NULL;
}
+/* Given a sequence node "node", with a child at position "pos" that
+ * is also a sequence node, attach the children of that node directly
+ * as children of "node" at that position, replacing the original child.
+ *
+ * The filters of these children are intersected with the filter
+ * of the child at position "pos".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_sequence_splice_child(
+ __isl_take isl_schedule_node *node, int pos)
+{
+ int i, n;
+ isl_union_set *filter;
+ isl_schedule_node *child;
+ isl_schedule_tree *tree;
+
+ if (!node)
+ return NULL;
+ if (isl_schedule_node_get_type(node) != isl_schedule_node_sequence)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "not a sequence node", isl_schedule_node_free(node));
+ node = isl_schedule_node_child(node, pos);
+ node = isl_schedule_node_child(node, 0);
+ if (isl_schedule_node_get_type(node) != isl_schedule_node_sequence)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "not a sequence node", isl_schedule_node_free(node));
+ child = isl_schedule_node_copy(node);
+ node = isl_schedule_node_parent(node);
+ filter = isl_schedule_node_filter_get_filter(node);
+ n = isl_schedule_node_n_children(child);
+ for (i = 0; i < n; ++i) {
+ child = isl_schedule_node_child(child, i);
+ child = isl_schedule_node_filter_intersect_filter(child,
+ isl_union_set_copy(filter));
+ child = isl_schedule_node_parent(child);
+ }
+ isl_union_set_free(filter);
+ tree = isl_schedule_node_get_tree(child);
+ isl_schedule_node_free(child);
+ node = isl_schedule_node_parent(node);
+ node = isl_schedule_node_sequence_splice(node, pos, tree);
+
+ return node;
+}
+
/* Update the ancestors of "node" to point to the tree that "node"
* now points to.
* That is, replace the child in the original parent that corresponds
@@ -2333,6 +2495,8 @@ __isl_give isl_schedule_node *isl_schedule_node_insert_mark(
* with filters described by "filters", attach this sequence
* of filter tree nodes as children to a new tree of type "type" and
* replace the original subtree of "node" by this new tree.
+ * Each copy of the original subtree is simplified with respect
+ * to the corresponding filter.
*/
static __isl_give isl_schedule_node *isl_schedule_node_insert_children(
__isl_take isl_schedule_node *node,
@@ -2354,11 +2518,16 @@ static __isl_give isl_schedule_node *isl_schedule_node_insert_children(
n = isl_union_set_list_n_union_set(filters);
list = isl_schedule_tree_list_alloc(ctx, n);
for (i = 0; i < n; ++i) {
+ isl_schedule_node *node_i;
isl_schedule_tree *tree;
isl_union_set *filter;
- tree = isl_schedule_node_get_tree(node);
filter = isl_union_set_list_get_union_set(filters, i);
+ node_i = isl_schedule_node_copy(node);
+ node_i = isl_schedule_node_gist(node_i,
+ isl_union_set_copy(filter));
+ tree = isl_schedule_node_get_tree(node_i);
+ isl_schedule_node_free(node_i);
tree = isl_schedule_tree_insert_filter(tree, filter);
list = isl_schedule_tree_list_add(list, tree);
}
@@ -3333,6 +3502,31 @@ error:
return NULL;
}
+/* Replace the domain of domain node "node" with the gist
+ * of the original domain with respect to the parameter domain "context".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_domain_gist_params(
+ __isl_take isl_schedule_node *node, __isl_take isl_set *context)
+{
+ isl_union_set *domain;
+ isl_schedule_tree *tree;
+
+ if (!node || !context)
+ goto error;
+
+ tree = isl_schedule_tree_copy(node->tree);
+ domain = isl_schedule_tree_domain_get_domain(node->tree);
+ domain = isl_union_set_gist_params(domain, context);
+ tree = isl_schedule_tree_domain_set_domain(tree, domain);
+ node = isl_schedule_node_graft_tree(node, tree);
+
+ return node;
+error:
+ isl_schedule_node_free(node);
+ isl_set_free(context);
+ return NULL;
+}
+
/* Internal data structure for isl_schedule_node_get_subtree_expansion.
* "expansions" contains a list of accumulated expansions
* for each outer expansion, set or sequence node. The first element
@@ -4096,7 +4290,8 @@ __isl_give isl_schedule_node *isl_schedule_node_graft_after(
/* Split the domain elements that reach "node" into those that satisfy
* "filter" and those that do not. Arrange for the first subset to be
- * executed after the second subset.
+ * executed before or after the second subset, depending on the value
+ * of "before".
* Return a pointer to the tree corresponding to the second subset,
* except when this subset is empty in which case the original pointer
* is returned.
@@ -4107,8 +4302,9 @@ __isl_give isl_schedule_node *isl_schedule_node_graft_after(
* The children in the sequence are copies of the original subtree,
* simplified with respect to their filters.
*/
-__isl_give isl_schedule_node *isl_schedule_node_order_after(
- __isl_take isl_schedule_node *node, __isl_take isl_union_set *filter)
+static __isl_give isl_schedule_node *isl_schedule_node_order_before_or_after(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *filter,
+ int before)
{
enum isl_schedule_node_type ancestors[] =
{ isl_schedule_node_filter, isl_schedule_node_sequence };
@@ -4152,9 +4348,14 @@ __isl_give isl_schedule_node *isl_schedule_node_order_after(
isl_schedule_node_free(node2);
tree1 = isl_schedule_tree_insert_filter(tree1, node_filter);
tree2 = isl_schedule_tree_insert_filter(tree2, filter);
- tree1 = isl_schedule_tree_sequence_pair(tree1, tree2);
- node = graft_or_splice(node, tree1, 0);
+ if (before) {
+ tree1 = isl_schedule_tree_sequence_pair(tree2, tree1);
+ node = graft_or_splice(node, tree1, 1);
+ } else {
+ tree1 = isl_schedule_tree_sequence_pair(tree1, tree2);
+ node = graft_or_splice(node, tree1, 0);
+ }
return node;
error:
@@ -4164,6 +4365,32 @@ error:
return NULL;
}
+/* Split the domain elements that reach "node" into those that satisfy
+ * "filter" and those that do not. Arrange for the first subset to be
+ * executed before the second subset.
+ * Return a pointer to the tree corresponding to the second subset,
+ * except when this subset is empty in which case the original pointer
+ * is returned.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_order_before(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *filter)
+{
+ return isl_schedule_node_order_before_or_after(node, filter, 1);
+}
+
+/* Split the domain elements that reach "node" into those that satisfy
+ * "filter" and those that do not. Arrange for the first subset to be
+ * executed after the second subset.
+ * Return a pointer to the tree corresponding to the second subset,
+ * except when this subset is empty in which case the original pointer
+ * is returned.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_order_after(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *filter)
+{
+ return isl_schedule_node_order_before_or_after(node, filter, 0);
+}
+
/* Reset the user pointer on all identifiers of parameters and tuples
* in the schedule node "node".
*/
@@ -4318,3 +4545,24 @@ void isl_schedule_node_dump(__isl_keep isl_schedule_node *node)
isl_printer_free(printer);
}
+
+/* Return a string representation of "node".
+ * Print the schedule node in block format as it would otherwise
+ * look identical to the entire schedule.
+ */
+__isl_give char *isl_schedule_node_to_str(__isl_keep isl_schedule_node *node)
+{
+ isl_printer *printer;
+ char *s;
+
+ if (!node)
+ return NULL;
+
+ printer = isl_printer_to_str(isl_schedule_node_get_ctx(node));
+ printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_BLOCK);
+ printer = isl_printer_print_schedule_node(printer, node);
+ s = isl_printer_get_str(printer);
+ isl_printer_free(printer);
+
+ return s;
+}
diff --git a/isl_schedule_node_private.h b/isl_schedule_node_private.h
index e89bcacb..17f74d75 100644
--- a/isl_schedule_node_private.h
+++ b/isl_schedule_node_private.h
@@ -3,6 +3,7 @@
#include <isl/schedule_node.h>
#include <isl_schedule_band.h>
+#include <isl_schedule_tree.h>
/* An isl_schedule_node points to a particular location in a schedule tree.
*
@@ -42,8 +43,13 @@ __isl_give isl_schedule_node *isl_schedule_node_pullback_union_pw_multi_aff(
__isl_take isl_schedule_node *node,
__isl_take isl_union_pw_multi_aff *upma);
+__isl_give isl_schedule_node *isl_schedule_node_gist(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *context);
+
__isl_give isl_schedule_node *isl_schedule_node_domain_intersect_domain(
__isl_take isl_schedule_node *node, __isl_take isl_union_set *domain);
+__isl_give isl_schedule_node *isl_schedule_node_domain_gist_params(
+ __isl_take isl_schedule_node *node, __isl_take isl_set *context);
__isl_give isl_schedule_node *isl_schedule_node_insert_expansion(
__isl_take isl_schedule_node *node,
diff --git a/isl_schedule_tree.c b/isl_schedule_tree.c
index 7b83f005..b6214fde 100644
--- a/isl_schedule_tree.c
+++ b/isl_schedule_tree.c
@@ -2032,6 +2032,60 @@ error:
return NULL;
}
+/* Reduce the partial schedule of the band root node of "tree"
+ * modulo the factors in "mv".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_band_mod(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
+{
+ if (!tree || !mv)
+ goto error;
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", goto error);
+
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree)
+ goto error;
+
+ tree->band = isl_schedule_band_mod(tree->band, mv);
+ if (!tree->band)
+ return isl_schedule_tree_free(tree);
+
+ return tree;
+error:
+ isl_schedule_tree_free(tree);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Shift the partial schedule of the band root node of "tree" by "shift".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_band_shift(
+ __isl_take isl_schedule_tree *tree,
+ __isl_take isl_multi_union_pw_aff *shift)
+{
+ if (!tree || !shift)
+ goto error;
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", goto error);
+
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree)
+ goto error;
+
+ tree->band = isl_schedule_band_shift(tree->band, shift);
+ if (!tree->band)
+ return isl_schedule_tree_free(tree);
+
+ return tree;
+error:
+ isl_schedule_tree_free(tree);
+ isl_multi_union_pw_aff_free(shift);
+ return NULL;
+}
+
/* Given two trees with sequence roots, replace the child at position
* "pos" of "tree" with the children of "child".
*/
diff --git a/isl_schedule_tree.h b/isl_schedule_tree.h
index 4c18e956..2ae2f0f5 100644
--- a/isl_schedule_tree.h
+++ b/isl_schedule_tree.h
@@ -223,8 +223,13 @@ __isl_give isl_schedule_tree *isl_schedule_tree_band_scale(
__isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv);
__isl_give isl_schedule_tree *isl_schedule_tree_band_scale_down(
__isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_tree *isl_schedule_tree_band_mod(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv);
__isl_give isl_schedule_tree *isl_schedule_tree_band_tile(
__isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *sizes);
+__isl_give isl_schedule_tree *isl_schedule_tree_band_shift(
+ __isl_take isl_schedule_tree *tree,
+ __isl_take isl_multi_union_pw_aff *shift);
__isl_give isl_schedule_tree *isl_schedule_tree_band_split(
__isl_take isl_schedule_tree *tree, int pos);
__isl_give isl_schedule_tree *isl_schedule_tree_band_gist(
diff --git a/isl_scheduler.c b/isl_scheduler.c
index 156eb419..a214e1c3 100644
--- a/isl_scheduler.c
+++ b/isl_scheduler.c
@@ -45,7 +45,8 @@ enum isl_edge_type {
isl_edge_condition,
isl_edge_conditional_validity,
isl_edge_proximity,
- isl_edge_last = isl_edge_proximity
+ isl_edge_last = isl_edge_proximity,
+ isl_edge_local
};
/* The constraints that need to be satisfied by a schedule on "domain".
@@ -267,6 +268,17 @@ isl_ctx *isl_schedule_constraints_get_ctx(
return sc ? isl_union_set_get_ctx(sc->domain) : NULL;
}
+/* Return the domain of "sc".
+ */
+__isl_give isl_union_set *isl_schedule_constraints_get_domain(
+ __isl_keep isl_schedule_constraints *sc)
+{
+ if (!sc)
+ return NULL;
+
+ return isl_union_set_copy(sc->domain);
+}
+
/* Return the validity constraints of "sc".
*/
__isl_give isl_union_map *isl_schedule_constraints_get_validity(
@@ -468,6 +480,8 @@ static int node_scc_at_least(struct isl_sched_node *node, int scc)
* If these fields are NULL, then they represent the empty relation.
* src is the source node
* dst is the sink node
+ *
+ * types is a bit vector containing the types of this edge.
* validity is set if the edge is used to ensure correctness
* coincidence is used to enforce zero dependence distances
* proximity is set if the edge is used to minimize dependence distances
@@ -490,17 +504,96 @@ struct isl_sched_edge {
struct isl_sched_node *src;
struct isl_sched_node *dst;
- unsigned validity : 1;
- unsigned coincidence : 1;
- unsigned proximity : 1;
- unsigned local : 1;
- unsigned condition : 1;
- unsigned conditional_validity : 1;
+ unsigned types;
int start;
int end;
};
+/* Is "edge" marked as being of type "type"?
+ */
+static int is_type(struct isl_sched_edge *edge, enum isl_edge_type type)
+{
+ return ISL_FL_ISSET(edge->types, 1 << type);
+}
+
+/* Mark "edge" as being of type "type".
+ */
+static void set_type(struct isl_sched_edge *edge, enum isl_edge_type type)
+{
+ ISL_FL_SET(edge->types, 1 << type);
+}
+
+/* No longer mark "edge" as being of type "type"?
+ */
+static void clear_type(struct isl_sched_edge *edge, enum isl_edge_type type)
+{
+ ISL_FL_CLR(edge->types, 1 << type);
+}
+
+/* Is "edge" marked as a validity edge?
+ */
+static int is_validity(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_validity);
+}
+
+/* Mark "edge" as a validity edge.
+ */
+static void set_validity(struct isl_sched_edge *edge)
+{
+ set_type(edge, isl_edge_validity);
+}
+
+/* Is "edge" marked as a proximity edge?
+ */
+static int is_proximity(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_proximity);
+}
+
+/* Is "edge" marked as a local edge?
+ */
+static int is_local(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_local);
+}
+
+/* Mark "edge" as a local edge.
+ */
+static void set_local(struct isl_sched_edge *edge)
+{
+ set_type(edge, isl_edge_local);
+}
+
+/* No longer mark "edge" as a local edge.
+ */
+static void clear_local(struct isl_sched_edge *edge)
+{
+ clear_type(edge, isl_edge_local);
+}
+
+/* Is "edge" marked as a coincidence edge?
+ */
+static int is_coincidence(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_coincidence);
+}
+
+/* Is "edge" marked as a condition edge?
+ */
+static int is_condition(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_condition);
+}
+
+/* Is "edge" marked as a conditional validity edge?
+ */
+static int is_conditional_validity(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_conditional_validity);
+}
+
/* Internal information about the dependence graph used during
* the construction of the schedule.
*
@@ -534,7 +627,9 @@ struct isl_sched_edge {
* and sink spaces; there is one such table for each type;
* a given edge may be referenced from more than one table
* if the corresponding relation appears in more than one of the
- * sets of dependences
+ * sets of dependences; however, for each type there is only
+ * a single edge between a given pair of source and sink space
+ * in the entire graph
*
* node_table contains pointers into the node array, hashed on the space
*
@@ -1058,23 +1153,17 @@ struct isl_extract_edge_data {
};
/* Merge edge2 into edge1, freeing the contents of edge2.
- * "type" is the type of the schedule constraint from which edge2 was
- * extracted.
* Return 0 on success and -1 on failure.
*
* edge1 and edge2 are assumed to have the same value for the map field.
*/
-static int merge_edge(enum isl_edge_type type, struct isl_sched_edge *edge1,
+static int merge_edge(struct isl_sched_edge *edge1,
struct isl_sched_edge *edge2)
{
- edge1->validity |= edge2->validity;
- edge1->coincidence |= edge2->coincidence;
- edge1->proximity |= edge2->proximity;
- edge1->condition |= edge2->condition;
- edge1->conditional_validity |= edge2->conditional_validity;
+ edge1->types |= edge2->types;
isl_map_free(edge2->map);
- if (type == isl_edge_condition) {
+ if (is_condition(edge2)) {
if (!edge1->tagged_condition)
edge1->tagged_condition = edge2->tagged_condition;
else
@@ -1083,7 +1172,7 @@ static int merge_edge(enum isl_edge_type type, struct isl_sched_edge *edge1,
edge2->tagged_condition);
}
- if (type == isl_edge_conditional_validity) {
+ if (is_conditional_validity(edge2)) {
if (!edge1->tagged_validity)
edge1->tagged_validity = edge2->tagged_validity;
else
@@ -1092,9 +1181,9 @@ static int merge_edge(enum isl_edge_type type, struct isl_sched_edge *edge1,
edge2->tagged_validity);
}
- if (type == isl_edge_condition && !edge1->tagged_condition)
+ if (is_condition(edge2) && !edge1->tagged_condition)
return -1;
- if (type == isl_edge_conditional_validity && !edge1->tagged_validity)
+ if (is_conditional_validity(edge2) && !edge1->tagged_validity)
return -1;
return 0;
@@ -1173,6 +1262,38 @@ static __isl_give isl_map *map_intersect_domains(__isl_take isl_map *tagged,
return tagged;
}
+/* Return a pointer to the node that lives in the domain space of "map"
+ * or NULL if there is no such node.
+ */
+static struct isl_sched_node *find_domain_node(isl_ctx *ctx,
+ struct isl_sched_graph *graph, __isl_keep isl_map *map)
+{
+ struct isl_sched_node *node;
+ isl_space *space;
+
+ space = isl_space_domain(isl_map_get_space(map));
+ node = graph_find_node(ctx, graph, space);
+ isl_space_free(space);
+
+ return node;
+}
+
+/* Return a pointer to the node that lives in the range space of "map"
+ * or NULL if there is no such node.
+ */
+static struct isl_sched_node *find_range_node(isl_ctx *ctx,
+ struct isl_sched_graph *graph, __isl_keep isl_map *map)
+{
+ struct isl_sched_node *node;
+ isl_space *space;
+
+ space = isl_space_range(isl_map_get_space(map));
+ node = graph_find_node(ctx, graph, space);
+ isl_space_free(space);
+
+ return node;
+}
+
/* Add a new edge to the graph based on the given map
* and add it to data->graph->edge_table[data->type].
* If a dependence relation of a given type happens to be identical
@@ -1202,7 +1323,6 @@ static isl_stat extract_edge(__isl_take isl_map *map, void *user)
struct isl_extract_edge_data *data = user;
struct isl_sched_graph *graph = data->graph;
struct isl_sched_node *src, *dst;
- isl_space *dim;
struct isl_sched_edge *edge;
isl_map *tagged = NULL;
@@ -1216,12 +1336,8 @@ static isl_stat extract_edge(__isl_take isl_map *map, void *user)
}
}
- dim = isl_space_domain(isl_map_get_space(map));
- src = graph_find_node(ctx, graph, dim);
- isl_space_free(dim);
- dim = isl_space_range(isl_map_get_space(map));
- dst = graph_find_node(ctx, graph, dim);
- isl_space_free(dim);
+ src = find_domain_node(ctx, graph, map);
+ dst = find_range_node(ctx, graph, map);
if (!src || !dst) {
isl_map_free(map);
@@ -1240,30 +1356,16 @@ static isl_stat extract_edge(__isl_take isl_map *map, void *user)
graph->edge[graph->n_edge].src = src;
graph->edge[graph->n_edge].dst = dst;
graph->edge[graph->n_edge].map = map;
- graph->edge[graph->n_edge].validity = 0;
- graph->edge[graph->n_edge].coincidence = 0;
- graph->edge[graph->n_edge].proximity = 0;
- graph->edge[graph->n_edge].condition = 0;
- graph->edge[graph->n_edge].local = 0;
- graph->edge[graph->n_edge].conditional_validity = 0;
+ graph->edge[graph->n_edge].types = 0;
graph->edge[graph->n_edge].tagged_condition = NULL;
graph->edge[graph->n_edge].tagged_validity = NULL;
- if (data->type == isl_edge_validity)
- graph->edge[graph->n_edge].validity = 1;
- if (data->type == isl_edge_coincidence)
- graph->edge[graph->n_edge].coincidence = 1;
- if (data->type == isl_edge_proximity)
- graph->edge[graph->n_edge].proximity = 1;
- if (data->type == isl_edge_condition) {
- graph->edge[graph->n_edge].condition = 1;
+ set_type(&graph->edge[graph->n_edge], data->type);
+ if (data->type == isl_edge_condition)
graph->edge[graph->n_edge].tagged_condition =
isl_union_map_from_map(tagged);
- }
- if (data->type == isl_edge_conditional_validity) {
- graph->edge[graph->n_edge].conditional_validity = 1;
+ if (data->type == isl_edge_conditional_validity)
graph->edge[graph->n_edge].tagged_validity =
isl_union_map_from_map(tagged);
- }
edge = graph_find_matching_edge(graph, &graph->edge[graph->n_edge]);
if (!edge) {
@@ -1274,12 +1376,70 @@ static isl_stat extract_edge(__isl_take isl_map *map, void *user)
return graph_edge_table_add(ctx, graph, data->type,
&graph->edge[graph->n_edge++]);
- if (merge_edge(data->type, edge, &graph->edge[graph->n_edge]) < 0)
+ if (merge_edge(edge, &graph->edge[graph->n_edge]) < 0)
return -1;
return graph_edge_table_add(ctx, graph, data->type, edge);
}
+/* Initialize the schedule graph "graph" from the schedule constraints "sc".
+ *
+ * The context is included in the domain before the nodes of
+ * the graphs are extracted in order to be able to exploit
+ * any possible additional equalities.
+ * Note that this intersection is only performed locally here.
+ */
+static isl_stat graph_init(struct isl_sched_graph *graph,
+ __isl_keep isl_schedule_constraints *sc)
+{
+ isl_ctx *ctx;
+ isl_union_set *domain;
+ struct isl_extract_edge_data data;
+ enum isl_edge_type i;
+ isl_stat r;
+
+ if (!sc)
+ return isl_stat_error;
+
+ ctx = isl_schedule_constraints_get_ctx(sc);
+
+ domain = isl_schedule_constraints_get_domain(sc);
+ graph->n = isl_union_set_n_set(domain);
+ isl_union_set_free(domain);
+
+ if (graph_alloc(ctx, graph, graph->n,
+ isl_schedule_constraints_n_map(sc)) < 0)
+ return isl_stat_error;
+
+ if (compute_max_row(graph, sc) < 0)
+ return isl_stat_error;
+ graph->root = 1;
+ graph->n = 0;
+ domain = isl_schedule_constraints_get_domain(sc);
+ domain = isl_union_set_intersect_params(domain,
+ isl_set_copy(sc->context));
+ r = isl_union_set_foreach_set(domain, &extract_node, graph);
+ isl_union_set_free(domain);
+ if (r < 0)
+ return isl_stat_error;
+ if (graph_init_table(ctx, graph) < 0)
+ return isl_stat_error;
+ for (i = isl_edge_first; i <= isl_edge_last; ++i)
+ graph->max_edge[i] = isl_union_map_n_map(sc->constraint[i]);
+ if (graph_init_edge_tables(ctx, graph) < 0)
+ return isl_stat_error;
+ graph->n_edge = 0;
+ data.graph = graph;
+ for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+ data.type = i;
+ if (isl_union_map_foreach_map(sc->constraint[i],
+ &extract_edge, &data) < 0)
+ return isl_stat_error;
+ }
+
+ return isl_stat_ok;
+}
+
/* Check whether there is any dependence from node[j] to node[i]
* or from node[i] to node[j].
*/
@@ -1821,8 +1981,9 @@ static int add_all_validity_constraints(struct isl_sched_graph *graph,
struct isl_sched_edge *edge= &graph->edge[i];
int local;
- local = edge->local || (edge->coincidence && use_coincidence);
- if (!edge->validity && !local)
+ local = is_local(edge) ||
+ (is_coincidence(edge) && use_coincidence);
+ if (!is_validity(edge) && !local)
continue;
if (edge->src != edge->dst)
continue;
@@ -1834,8 +1995,9 @@ static int add_all_validity_constraints(struct isl_sched_graph *graph,
struct isl_sched_edge *edge = &graph->edge[i];
int local;
- local = edge->local || (edge->coincidence && use_coincidence);
- if (!edge->validity && !local)
+ local = is_local(edge) ||
+ (is_coincidence(edge) && use_coincidence);
+ if (!is_validity(edge) && !local)
continue;
if (edge->src == edge->dst)
continue;
@@ -1867,8 +2029,9 @@ static int add_all_proximity_constraints(struct isl_sched_graph *graph,
struct isl_sched_edge *edge= &graph->edge[i];
int local;
- local = edge->local || (edge->coincidence && use_coincidence);
- if (!edge->proximity && !local)
+ local = is_local(edge) ||
+ (is_coincidence(edge) && use_coincidence);
+ if (!is_proximity(edge) && !local)
continue;
if (edge->src == edge->dst &&
add_intra_proximity_constraints(graph, edge, 1, local) < 0)
@@ -1876,7 +2039,7 @@ static int add_all_proximity_constraints(struct isl_sched_graph *graph,
if (edge->src != edge->dst &&
add_inter_proximity_constraints(graph, edge, 1, local) < 0)
return -1;
- if (edge->validity || local)
+ if (is_validity(edge) || local)
continue;
if (edge->src == edge->dst &&
add_intra_proximity_constraints(graph, edge, -1, 0) < 0)
@@ -1951,15 +2114,15 @@ static int node_update_cmap(struct isl_sched_node *node)
static int edge_multiplicity(struct isl_sched_edge *edge, int carry,
int use_coincidence)
{
- if (carry && !edge->validity && !edge->conditional_validity)
+ if (carry && !is_validity(edge) && !is_conditional_validity(edge))
return 0;
if (carry)
return 1;
- if (edge->proximity || edge->local)
+ if (is_proximity(edge) || is_local(edge))
return 2;
- if (use_coincidence && edge->coincidence)
+ if (use_coincidence && is_coincidence(edge))
return 2;
- if (edge->validity)
+ if (is_validity(edge))
return 1;
return 0;
}
@@ -2230,7 +2393,7 @@ static int check_conflict(int con, void *user)
return 0;
for (i = 0; i < graph->n_edge; ++i) {
- if (!graph->edge[i].validity)
+ if (!is_validity(&graph->edge[i]))
continue;
if (graph->edge[i].src == graph->edge[i].dst)
continue;
@@ -2628,9 +2791,9 @@ static int unconditionalize_adjacent_validity(struct isl_sched_graph *graph,
int adjacent;
isl_union_map *validity;
- if (!graph->edge[i].conditional_validity)
+ if (!is_conditional_validity(&graph->edge[i]))
continue;
- if (graph->edge[i].validity)
+ if (is_validity(&graph->edge[i]))
continue;
validity = graph->edge[i].tagged_validity;
@@ -2642,7 +2805,7 @@ static int unconditionalize_adjacent_validity(struct isl_sched_graph *graph,
if (!adjacent)
continue;
- graph->edge[i].validity = 1;
+ set_validity(&graph->edge[i]);
}
isl_union_set_free(condition_source);
@@ -2680,9 +2843,9 @@ static int update_edges(isl_ctx *ctx, struct isl_sched_graph *graph)
isl_union_set *uset;
isl_union_map *umap;
- if (!graph->edge[i].condition)
+ if (!is_condition(&graph->edge[i]))
continue;
- if (graph->edge[i].local)
+ if (is_local(&graph->edge[i]))
continue;
local = is_condition_false(&graph->edge[i]);
if (local < 0)
@@ -2776,7 +2939,7 @@ static __isl_give isl_union_set_list *extract_sccs(isl_ctx *ctx,
}
/* Return a list of two unions of universe domains, one for the SCCs up
- * to and including graph->src_scc and another for the other SCCS.
+ * to and including graph->src_scc and another for the other SCCs.
*/
static __isl_give isl_union_set_list *extract_split(isl_ctx *ctx,
struct isl_sched_graph *graph)
@@ -2866,7 +3029,7 @@ static int copy_edges(isl_ctx *ctx, struct isl_sched_graph *dst,
dst_src = graph_find_node(ctx, dst, edge->src->space);
dst_dst = graph_find_node(ctx, dst, edge->dst->space);
if (!dst_src || !dst_dst) {
- if (edge->validity || edge->conditional_validity)
+ if (is_validity(edge) || is_conditional_validity(edge))
isl_die(ctx, isl_error_internal,
"backward (conditional) validity edge",
return -1);
@@ -2882,12 +3045,7 @@ static int copy_edges(isl_ctx *ctx, struct isl_sched_graph *dst,
dst->edge[dst->n_edge].map = map;
dst->edge[dst->n_edge].tagged_condition = tagged_condition;
dst->edge[dst->n_edge].tagged_validity = tagged_validity;
- dst->edge[dst->n_edge].validity = edge->validity;
- dst->edge[dst->n_edge].proximity = edge->proximity;
- dst->edge[dst->n_edge].coincidence = edge->coincidence;
- dst->edge[dst->n_edge].condition = edge->condition;
- dst->edge[dst->n_edge].conditional_validity =
- edge->conditional_validity;
+ dst->edge[dst->n_edge].types = edge->types;
dst->n_edge++;
if (edge->tagged_condition && !tagged_condition)
@@ -2941,9 +3099,7 @@ static __isl_give isl_schedule_node *compute_schedule_wcc(
/* Compute a schedule for a subgraph of "graph". In particular, for
* the graph composed of nodes that satisfy node_pred and edges that
- * that satisfy edge_pred. The caller should precompute the number
- * of nodes and edges that satisfy these predicates and pass them along
- * as "n" and "n_edge".
+ * that satisfy edge_pred.
* If the subgraph is known to consist of a single component, then wcc should
* be set and then we call compute_schedule_wcc on the constructed subgraph.
* Otherwise, we call compute_schedule, which will check whether the subgraph
@@ -2954,14 +3110,21 @@ static __isl_give isl_schedule_node *compute_schedule_wcc(
*/
static __isl_give isl_schedule_node *compute_sub_schedule(
__isl_take isl_schedule_node *node, isl_ctx *ctx,
- struct isl_sched_graph *graph, int n, int n_edge,
+ struct isl_sched_graph *graph,
int (*node_pred)(struct isl_sched_node *node, int data),
int (*edge_pred)(struct isl_sched_edge *edge, int data),
int data, int wcc)
{
struct isl_sched_graph split = { 0 };
+ int i, n = 0, n_edge = 0;
int t;
+ for (i = 0; i < graph->n; ++i)
+ if (node_pred(&graph->node[i], data))
+ ++n;
+ for (i = 0; i < graph->n_edge; ++i)
+ if (edge_pred(&graph->edge[i], data))
+ ++n_edge;
if (graph_alloc(ctx, &split, n, n_edge) < 0)
goto error;
if (copy_nodes(&split, graph, node_pred, data) < 0)
@@ -3036,8 +3199,10 @@ static int reset_band(struct isl_sched_graph *graph)
/* Split the current graph into two parts and compute a schedule for each
* part individually. In particular, one part consists of all SCCs up
* to and including graph->src_scc, while the other part contains the other
- * SCCS. The split is enforced by a sequence node inserted at position "node"
+ * SCCs. The split is enforced by a sequence node inserted at position "node"
* in the schedule tree. Return the updated schedule node.
+ * If either of these two parts consists of a sequence, then it is spliced
+ * into the sequence containing the two parts.
*
* The current band is reset. It would be possible to reuse
* the previously computed rows as the first rows in the next
@@ -3047,7 +3212,7 @@ static int reset_band(struct isl_sched_graph *graph)
static __isl_give isl_schedule_node *compute_split_schedule(
__isl_take isl_schedule_node *node, struct isl_sched_graph *graph)
{
- int i, n, e1, e2;
+ int is_seq;
isl_ctx *ctx;
isl_union_set_list *filters;
@@ -3057,42 +3222,32 @@ static __isl_give isl_schedule_node *compute_split_schedule(
if (reset_band(graph) < 0)
return isl_schedule_node_free(node);
- n = 0;
- for (i = 0; i < graph->n; ++i) {
- struct isl_sched_node *node = &graph->node[i];
- int before = node->scc <= graph->src_scc;
-
- if (before)
- n++;
- }
-
- e1 = e2 = 0;
- for (i = 0; i < graph->n_edge; ++i) {
- if (graph->edge[i].dst->scc <= graph->src_scc)
- e1++;
- if (graph->edge[i].src->scc > graph->src_scc)
- e2++;
- }
-
next_band(graph);
ctx = isl_schedule_node_get_ctx(node);
filters = extract_split(ctx, graph);
node = isl_schedule_node_insert_sequence(node, filters);
- node = isl_schedule_node_child(node, 0);
+ node = isl_schedule_node_child(node, 1);
node = isl_schedule_node_child(node, 0);
- node = compute_sub_schedule(node, ctx, graph, n, e1,
- &node_scc_at_most, &edge_dst_scc_at_most,
- graph->src_scc, 0);
- node = isl_schedule_node_parent(node);
- node = isl_schedule_node_next_sibling(node);
- node = isl_schedule_node_child(node, 0);
- node = compute_sub_schedule(node, ctx, graph, graph->n - n, e2,
+ node = compute_sub_schedule(node, ctx, graph,
&node_scc_at_least, &edge_src_scc_at_least,
graph->src_scc + 1, 0);
+ is_seq = isl_schedule_node_get_type(node) == isl_schedule_node_sequence;
+ node = isl_schedule_node_parent(node);
+ node = isl_schedule_node_parent(node);
+ if (is_seq)
+ node = isl_schedule_node_sequence_splice_child(node, 1);
+ node = isl_schedule_node_child(node, 0);
+ node = isl_schedule_node_child(node, 0);
+ node = compute_sub_schedule(node, ctx, graph,
+ &node_scc_at_most, &edge_dst_scc_at_most,
+ graph->src_scc, 0);
+ is_seq = isl_schedule_node_get_type(node) == isl_schedule_node_sequence;
node = isl_schedule_node_parent(node);
node = isl_schedule_node_parent(node);
+ if (is_seq)
+ node = isl_schedule_node_sequence_splice_child(node, 0);
return node;
}
@@ -3303,7 +3458,7 @@ static int add_all_constraints(struct isl_sched_graph *graph)
for (i = 0; i < graph->n_edge; ++i) {
struct isl_sched_edge *edge= &graph->edge[i];
- if (!edge->validity && !edge->conditional_validity)
+ if (!is_validity(edge) && !is_conditional_validity(edge))
continue;
for (j = 0; j < edge->map->n; ++j) {
@@ -3668,6 +3823,11 @@ static int is_any_trivial(struct isl_sched_graph *graph,
/* Construct a schedule row for each node such that as many dependences
* as possible are carried and then continue with the next band.
*
+ * Note that despite the fact that the problem is solved using a rational
+ * solver, the solution is guaranteed to be integral.
+ * Specifically, the dependence distance lower bounds e_i (and therefore
+ * also their sum) are integers. See Lemma 5 of [1].
+ *
* If the computed schedule row turns out to be trivial on one or
* more nodes where it should not be trivial, then we throw it away
* and try again on each component separately.
@@ -3684,6 +3844,10 @@ static int is_any_trivial(struct isl_sched_graph *graph,
* of the schedule tree and continue with the construction of the schedule.
* This insertion and the continued construction is performed by split_scaled
* after optionally checking for non-trivial common divisors.
+ *
+ * [1] P. Feautrier, Some Efficient Solutions to the Affine Scheduling
+ * Problem, Part II: Multi-Dimensional Time.
+ * In Intl. Journal of Parallel Programming, 1992.
*/
static __isl_give isl_schedule_node *carry_dependences(
__isl_take isl_schedule_node *node, struct isl_sched_graph *graph)
@@ -3802,8 +3966,8 @@ static int has_validity_edges(struct isl_sched_graph *graph)
return -1;
if (empty)
continue;
- if (graph->edge[i].validity ||
- graph->edge[i].conditional_validity)
+ if (is_validity(&graph->edge[i]) ||
+ is_conditional_validity(&graph->edge[i]))
return 1;
}
@@ -3846,8 +4010,8 @@ static void clear_local_edges(struct isl_sched_graph *graph)
int i;
for (i = 0; i < graph->n_edge; ++i)
- if (graph->edge[i].condition)
- graph->edge[i].local = 0;
+ if (is_condition(&graph->edge[i]))
+ clear_local(&graph->edge[i]);
}
/* Does "graph" have both condition and conditional validity edges?
@@ -3859,9 +4023,9 @@ static int need_condition_check(struct isl_sched_graph *graph)
int any_conditional_validity = 0;
for (i = 0; i < graph->n_edge; ++i) {
- if (graph->edge[i].condition)
+ if (is_condition(&graph->edge[i]))
any_condition = 1;
- if (graph->edge[i].conditional_validity)
+ if (is_conditional_validity(&graph->edge[i]))
any_conditional_validity = 1;
}
@@ -3875,7 +4039,7 @@ static int has_any_coincidence(struct isl_sched_graph *graph)
int i;
for (i = 0; i < graph->n_edge; ++i)
- if (graph->edge[i].coincidence)
+ if (is_coincidence(&graph->edge[i]))
return 1;
return 0;
@@ -3943,9 +4107,9 @@ static int has_adjacent_true_conditions(struct isl_sched_graph *graph,
int adjacent, local;
isl_union_map *condition;
- if (!graph->edge[i].condition)
+ if (!is_condition(&graph->edge[i]))
continue;
- if (graph->edge[i].local)
+ if (is_local(&graph->edge[i]))
continue;
condition = graph->edge[i].tagged_condition;
@@ -3958,7 +4122,7 @@ static int has_adjacent_true_conditions(struct isl_sched_graph *graph,
if (!adjacent)
continue;
- graph->edge[i].local = 1;
+ set_local(&graph->edge[i]);
local = is_condition_false(&graph->edge[i]);
if (local < 0)
@@ -3998,7 +4162,7 @@ static int has_violated_conditional_constraint(isl_ctx *ctx,
isl_union_map *umap;
int violated;
- if (!graph->edge[i].conditional_validity)
+ if (!is_conditional_validity(&graph->edge[i]))
continue;
violated = is_violated(graph, i);
@@ -4182,8 +4346,7 @@ static __isl_give isl_schedule_node *compute_component_schedule(
__isl_take isl_schedule_node *node, struct isl_sched_graph *graph,
int wcc)
{
- int component, i;
- int n, n_edge;
+ int component;
isl_ctx *ctx;
isl_union_set_list *filters;
@@ -4198,19 +4361,9 @@ static __isl_give isl_schedule_node *compute_component_schedule(
node = isl_schedule_node_insert_sequence(node, filters);
for (component = 0; component < graph->scc; ++component) {
- n = 0;
- for (i = 0; i < graph->n; ++i)
- if (graph->node[i].scc == component)
- n++;
- n_edge = 0;
- for (i = 0; i < graph->n_edge; ++i)
- if (graph->edge[i].src->scc == component &&
- graph->edge[i].dst->scc == component)
- n_edge++;
-
node = isl_schedule_node_child(node, component);
node = isl_schedule_node_child(node, 0);
- node = compute_sub_schedule(node, ctx, graph, n, n_edge,
+ node = compute_sub_schedule(node, ctx, graph,
&node_scc_exactly,
&edge_scc_exactly, component, wcc);
node = isl_schedule_node_parent(node);
@@ -4267,12 +4420,6 @@ static __isl_give isl_schedule_node *compute_schedule(isl_schedule_node *node,
* then the conditional validity dependences may be violated inside
* a tilable band, provided they have no adjacent non-local
* condition dependences.
- *
- * The context is included in the domain before the nodes of
- * the graphs are extracted in order to be able to exploit
- * any possible additional equalities.
- * However, the returned schedule contains the original domain
- * (before this intersection).
*/
__isl_give isl_schedule *isl_schedule_constraints_compute_schedule(
__isl_take isl_schedule_constraints *sc)
@@ -4282,65 +4429,29 @@ __isl_give isl_schedule *isl_schedule_constraints_compute_schedule(
isl_schedule *sched;
isl_schedule_node *node;
isl_union_set *domain;
- struct isl_extract_edge_data data;
- enum isl_edge_type i;
- int r;
sc = isl_schedule_constraints_align_params(sc);
- if (!sc)
- return NULL;
- graph.n = isl_union_set_n_set(sc->domain);
- if (graph.n == 0) {
- isl_union_set *domain = isl_union_set_copy(sc->domain);
- sched = isl_schedule_from_domain(domain);
- goto done;
- }
- if (graph_alloc(ctx, &graph, graph.n,
- isl_schedule_constraints_n_map(sc)) < 0)
- goto error;
- if (compute_max_row(&graph, sc) < 0)
- goto error;
- graph.root = 1;
- graph.n = 0;
- domain = isl_union_set_copy(sc->domain);
- domain = isl_union_set_intersect_params(domain,
- isl_set_copy(sc->context));
- r = isl_union_set_foreach_set(domain, &extract_node, &graph);
- isl_union_set_free(domain);
- if (r < 0)
- goto error;
- if (graph_init_table(ctx, &graph) < 0)
- goto error;
- for (i = isl_edge_first; i <= isl_edge_last; ++i)
- graph.max_edge[i] = isl_union_map_n_map(sc->constraint[i]);
- if (graph_init_edge_tables(ctx, &graph) < 0)
- goto error;
- graph.n_edge = 0;
- data.graph = &graph;
- for (i = isl_edge_first; i <= isl_edge_last; ++i) {
- data.type = i;
- if (isl_union_map_foreach_map(sc->constraint[i],
- &extract_edge, &data) < 0)
- goto error;
+ domain = isl_schedule_constraints_get_domain(sc);
+ if (isl_union_set_n_set(domain) == 0) {
+ isl_schedule_constraints_free(sc);
+ return isl_schedule_from_domain(domain);
}
- node = isl_schedule_node_from_domain(isl_union_set_copy(sc->domain));
+ if (graph_init(&graph, sc) < 0)
+ domain = isl_union_set_free(domain);
+
+ node = isl_schedule_node_from_domain(domain);
node = isl_schedule_node_child(node, 0);
if (graph.n > 0)
node = compute_schedule(node, &graph);
sched = isl_schedule_node_get_schedule(node);
isl_schedule_node_free(node);
-done:
graph_free(ctx, &graph);
isl_schedule_constraints_free(sc);
return sched;
-error:
- graph_free(ctx, &graph);
- isl_schedule_constraints_free(sc);
- return NULL;
}
/* Compute a schedule for the given union of domains that respects
diff --git a/isl_space.c b/isl_space.c
index 128eddfa..2e1b1e19 100644
--- a/isl_space.c
+++ b/isl_space.c
@@ -1288,15 +1288,6 @@ __isl_give isl_space *isl_space_factor_domain(__isl_take isl_space *space)
return space;
}
-/* Given a space of the form [A -> B] -> [C -> D], return the space B -> D.
- */
-__isl_give isl_space *isl_space_factor_range(__isl_take isl_space *space)
-{
- space = isl_space_domain_factor_range(space);
- space = isl_space_range_factor_range(space);
- return space;
-}
-
/* Given a space of the form [A -> B] -> C, return the space A -> C.
*/
__isl_give isl_space *isl_space_domain_factor_domain(
@@ -1413,19 +1404,18 @@ error:
return NULL;
}
-/* Given a space of the form A -> [B -> C], return the space A -> C.
+/* Internal function that selects the range of the map that is
+ * embedded in either a set space or the range of a map space.
+ * In particular, given a space of the form [A -> B], return the space B.
+ * Given a space of the form A -> [B -> C], return the space A -> C.
*/
-__isl_give isl_space *isl_space_range_factor_range(
- __isl_take isl_space *space)
+static __isl_give isl_space *range_factor_range(__isl_take isl_space *space)
{
isl_space *nested;
isl_space *range;
if (!space)
return NULL;
- if (!isl_space_range_is_wrapping(space))
- isl_die(isl_space_get_ctx(space), isl_error_invalid,
- "range not a product", return isl_space_free(space));
nested = space->nested[1];
range = isl_space_copy(space);
@@ -1451,6 +1441,47 @@ error:
return NULL;
}
+/* Given a space of the form A -> [B -> C], return the space A -> C.
+ */
+__isl_give isl_space *isl_space_range_factor_range(
+ __isl_take isl_space *space)
+{
+ if (!space)
+ return NULL;
+ if (!isl_space_range_is_wrapping(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "range not a product", return isl_space_free(space));
+
+ return range_factor_range(space);
+}
+
+/* Given a space of the form [A -> B], return the space B.
+ */
+static __isl_give isl_space *set_factor_range(__isl_take isl_space *space)
+{
+ if (!space)
+ return NULL;
+ if (!isl_space_is_wrapping(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "not a product", return isl_space_free(space));
+
+ return range_factor_range(space);
+}
+
+/* Given a space of the form [A -> B] -> [C -> D], return the space B -> D.
+ * Given a space of the form [A -> B], return the space B.
+ */
+__isl_give isl_space *isl_space_factor_range(__isl_take isl_space *space)
+{
+ if (!space)
+ return NULL;
+ if (isl_space_is_set(space))
+ return set_factor_range(space);
+ space = isl_space_domain_factor_range(space);
+ space = isl_space_range_factor_range(space);
+ return space;
+}
+
__isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *dim)
{
isl_ctx *ctx;
@@ -1866,30 +1897,64 @@ int isl_space_compatible(__isl_keep isl_space *dim1,
dim1->n_in + dim1->n_out == dim2->n_in + dim2->n_out;
}
-static uint32_t isl_hash_dim(uint32_t hash, __isl_keep isl_space *dim)
+/* Update "hash" by hashing in "space".
+ * Changes in this function should be reflected in isl_hash_space_domain.
+ */
+static uint32_t isl_hash_space(uint32_t hash, __isl_keep isl_space *space)
{
int i;
isl_id *id;
- if (!dim)
+ if (!space)
return hash;
- isl_hash_byte(hash, dim->nparam % 256);
- isl_hash_byte(hash, dim->n_in % 256);
- isl_hash_byte(hash, dim->n_out % 256);
+ isl_hash_byte(hash, space->nparam % 256);
+ isl_hash_byte(hash, space->n_in % 256);
+ isl_hash_byte(hash, space->n_out % 256);
- for (i = 0; i < dim->nparam; ++i) {
- id = get_id(dim, isl_dim_param, i);
+ for (i = 0; i < space->nparam; ++i) {
+ id = get_id(space, isl_dim_param, i);
hash = isl_hash_id(hash, id);
}
- id = tuple_id(dim, isl_dim_in);
+ id = tuple_id(space, isl_dim_in);
+ hash = isl_hash_id(hash, id);
+ id = tuple_id(space, isl_dim_out);
hash = isl_hash_id(hash, id);
- id = tuple_id(dim, isl_dim_out);
+
+ hash = isl_hash_space(hash, space->nested[0]);
+ hash = isl_hash_space(hash, space->nested[1]);
+
+ return hash;
+}
+
+/* Update "hash" by hashing in the domain of "space".
+ * The result of this function is equal to the result of applying
+ * isl_hash_space to the domain of "space".
+ */
+static uint32_t isl_hash_space_domain(uint32_t hash,
+ __isl_keep isl_space *space)
+{
+ int i;
+ isl_id *id;
+
+ if (!space)
+ return hash;
+
+ isl_hash_byte(hash, space->nparam % 256);
+ isl_hash_byte(hash, 0);
+ isl_hash_byte(hash, space->n_in % 256);
+
+ for (i = 0; i < space->nparam; ++i) {
+ id = get_id(space, isl_dim_param, i);
+ hash = isl_hash_id(hash, id);
+ }
+
+ hash = isl_hash_id(hash, &isl_id_none);
+ id = tuple_id(space, isl_dim_in);
hash = isl_hash_id(hash, id);
- hash = isl_hash_dim(hash, dim->nested[0]);
- hash = isl_hash_dim(hash, dim->nested[1]);
+ hash = isl_hash_space(hash, space->nested[0]);
return hash;
}
@@ -1902,7 +1967,24 @@ uint32_t isl_space_get_hash(__isl_keep isl_space *dim)
return 0;
hash = isl_hash_init();
- hash = isl_hash_dim(hash, dim);
+ hash = isl_hash_space(hash, dim);
+
+ return hash;
+}
+
+/* Return the hash value of the domain of "space".
+ * That is, isl_space_get_domain_hash(space) is equal to
+ * isl_space_get_hash(isl_space_domain(space)).
+ */
+uint32_t isl_space_get_domain_hash(__isl_keep isl_space *space)
+{
+ uint32_t hash;
+
+ if (!space)
+ return 0;
+
+ hash = isl_hash_init();
+ hash = isl_hash_space_domain(hash, space);
return hash;
}
@@ -2199,6 +2281,45 @@ error:
return NULL;
}
+/* Can isl_space_range_curry be applied to "space"?
+ * That is, does it have a nested relation in its range,
+ * the domain of which is itself a nested relation?
+ */
+isl_bool isl_space_can_range_curry(__isl_keep isl_space *space)
+{
+ isl_bool can;
+
+ if (!space)
+ return isl_bool_error;
+ can = isl_space_range_is_wrapping(space);
+ if (can < 0 || !can)
+ return can;
+ return isl_space_can_curry(space->nested[1]);
+}
+
+/* Given a space A -> ((B -> C) -> D), return the corresponding space
+ * A -> (B -> (C -> D)).
+ */
+__isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space)
+{
+ if (!space)
+ return NULL;
+
+ if (!isl_space_can_range_curry(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "space range cannot be curried",
+ return isl_space_free(space));
+
+ space = isl_space_cow(space);
+ if (!space)
+ return NULL;
+ space->nested[1] = isl_space_curry(space->nested[1]);
+ if (!space->nested[1])
+ return isl_space_free(space);
+
+ return space;
+}
+
/* Can we apply isl_space_uncurry to "space"?
* That is, does it have a nested relation in its range?
*/
diff --git a/isl_space_private.h b/isl_space_private.h
index a07acea7..6ceba076 100644
--- a/isl_space_private.h
+++ b/isl_space_private.h
@@ -28,6 +28,7 @@ __isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
unsigned n_div);
uint32_t isl_space_get_hash(__isl_keep isl_space *dim);
+uint32_t isl_space_get_domain_hash(__isl_keep isl_space *space);
isl_bool isl_space_is_domain_internal(__isl_keep isl_space *space1,
__isl_keep isl_space *space2);
diff --git a/isl_stream.c b/isl_stream.c
index ee62aca5..cf1fd5e7 100644
--- a/isl_stream.c
+++ b/isl_stream.c
@@ -9,7 +9,6 @@
#include <ctype.h>
#include <string.h>
-#include <strings.h>
#include <isl/ctx.h>
#include <isl_stream_private.h>
#include <isl/map.h>
diff --git a/isl_tab.c b/isl_tab.c
index 47abea1f..908b7934 100644
--- a/isl_tab.c
+++ b/isl_tab.c
@@ -616,21 +616,21 @@ static int min_is_manifestly_unbounded(struct isl_tab *tab,
return 1;
}
-static int row_cmp(struct isl_tab *tab, int r1, int r2, int c, isl_int t)
+static int row_cmp(struct isl_tab *tab, int r1, int r2, int c, isl_int *t)
{
unsigned off = 2 + tab->M;
if (tab->M) {
int s;
- isl_int_mul(t, tab->mat->row[r1][2], tab->mat->row[r2][off+c]);
- isl_int_submul(t, tab->mat->row[r2][2], tab->mat->row[r1][off+c]);
- s = isl_int_sgn(t);
+ isl_int_mul(*t, tab->mat->row[r1][2], tab->mat->row[r2][off+c]);
+ isl_int_submul(*t, tab->mat->row[r2][2], tab->mat->row[r1][off+c]);
+ s = isl_int_sgn(*t);
if (s)
return s;
}
- isl_int_mul(t, tab->mat->row[r1][1], tab->mat->row[r2][off + c]);
- isl_int_submul(t, tab->mat->row[r2][1], tab->mat->row[r1][off + c]);
- return isl_int_sgn(t);
+ isl_int_mul(*t, tab->mat->row[r1][1], tab->mat->row[r2][off + c]);
+ isl_int_submul(*t, tab->mat->row[r2][1], tab->mat->row[r1][off + c]);
+ return isl_int_sgn(*t);
}
/* Given the index of a column "c", return the index of a row
@@ -673,7 +673,7 @@ static int pivot_row(struct isl_tab *tab,
r = j;
continue;
}
- tsgn = sgn * row_cmp(tab, r, j, c, t);
+ tsgn = sgn * row_cmp(tab, r, j, c, &t);
if (tsgn < 0 || (tsgn == 0 &&
tab->row_var[j] < tab->row_var[r]))
r = j;
@@ -1883,6 +1883,7 @@ int isl_tab_add_ineq(struct isl_tab *tab, isl_int *ineq)
}
if (tab->cone) {
isl_int_init(cst);
+ isl_int_set_si(cst, 0);
isl_int_swap(ineq[0], cst);
}
r = isl_tab_add_row(tab, ineq);
@@ -2064,6 +2065,7 @@ int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
if (tab->cone) {
isl_int_init(cst);
+ isl_int_set_si(cst, 0);
isl_int_swap(eq[0], cst);
}
r = isl_tab_add_row(tab, eq);
@@ -2363,6 +2365,7 @@ struct isl_tab *isl_tab_from_recession_cone(__isl_keep isl_basic_set *bset,
tab->cone = 1;
isl_int_init(cst);
+ isl_int_set_si(cst, 0);
for (i = 0; i < bset->n_eq; ++i) {
isl_int_swap(bset->eq[i][offset], cst);
if (offset > 0) {
diff --git a/isl_test.c b/isl_test.c
index 4ec7deb5..81e9a70b 100644
--- a/isl_test.c
+++ b/isl_test.c
@@ -21,6 +21,7 @@
#include <isl_ctx_private.h>
#include <isl_map_private.h>
#include <isl_aff_private.h>
+#include <isl_space_private.h>
#include <isl/set.h>
#include <isl/flow.h>
#include <isl_constraint_private.h>
@@ -118,8 +119,79 @@ static int test_parse_multi_val(isl_ctx *ctx, const char *str)
return mv ? 0 : -1;
}
+/* Pairs of binary relation representations that should represent
+ * the same binary relations.
+ */
+struct {
+ const char *map1;
+ const char *map2;
+} parse_map_equal_tests[] = {
+ { "{ [x,y] : [([x/2]+y)/3] >= 1 }",
+ "{ [x, y] : 2y >= 6 - x }" },
+ { "{ [x,y] : x <= min(y, 2*y+3) }",
+ "{ [x,y] : x <= y, 2*y + 3 }" },
+ { "{ [x,y] : x >= min(y, 2*y+3) }",
+ "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }" },
+ { "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }",
+ "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }" },
+ { "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }",
+ "{ [i,j] -> [min(i,j)] }" },
+ { "{ [i,j] : i != j }",
+ "{ [i,j] : i < j or i > j }" },
+ { "{ [i,j] : (i+1)*2 >= j }",
+ "{ [i, j] : j <= 2 + 2i }" },
+ { "{ [i] -> [i > 0 ? 4 : 5] }",
+ "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }" },
+ { "[N=2,M] -> { [i=[(M+N)/4]] }",
+ "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }" },
+ { "{ [x] : x >= 0 }",
+ "{ [x] : x-0 >= 0 }" },
+ { "{ [i] : ((i > 10)) }",
+ "{ [i] : i >= 11 }" },
+ { "{ [i] -> [0] }",
+ "{ [i] -> [0 * i] }" },
+ { "{ [a] -> [b] : (not false) }",
+ "{ [a] -> [b] : true }" },
+ { "{ [i] : i/2 <= 5 }",
+ "{ [i] : i <= 10 }" },
+ { "{Sym=[n] [i] : i <= n }",
+ "[n] -> { [i] : i <= n }" },
+ { "{ [*] }",
+ "{ [a] }" },
+ { "{ [i] : 2*floor(i/2) = i }",
+ "{ [i] : exists a : i = 2 a }" },
+ { "{ [a] -> [b] : a = 5 implies b = 5 }",
+ "{ [a] -> [b] : a != 5 or b = 5 }" },
+ { "{ [a] -> [a - 1 : a > 0] }",
+ "{ [a] -> [a - 1] : a > 0 }" },
+ { "{ [a] -> [a - 1 : a > 0; a : a <= 0] }",
+ "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }" },
+ { "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }",
+ "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
+ { "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }",
+ "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
+ { "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }",
+ "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
+ { "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }",
+ "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },
+ { "{ [a,b] -> [i,j] : a,b << i,j }",
+ "{ [a,b] -> [i,j] : a < i or (a = i and b < j) }" },
+ { "{ [a,b] -> [i,j] : a,b <<= i,j }",
+ "{ [a,b] -> [i,j] : a < i or (a = i and b <= j) }" },
+ { "{ [a,b] -> [i,j] : a,b >> i,j }",
+ "{ [a,b] -> [i,j] : a > i or (a = i and b > j) }" },
+ { "{ [a,b] -> [i,j] : a,b >>= i,j }",
+ "{ [a,b] -> [i,j] : a > i or (a = i and b >= j) }" },
+ { "{ [n] -> [i] : exists (a, b, c: 8b <= i - 32a and "
+ "8b >= -7 + i - 32 a and b >= 0 and b <= 3 and "
+ "8c < n - 32a and i < n and c >= 0 and "
+ "c <= 3 and c >= -4a) }",
+ "{ [n] -> [i] : 0 <= i < n }" },
+};
+
int test_parse(struct isl_ctx *ctx)
{
+ int i;
isl_map *map, *map2;
const char *str, *str2;
@@ -144,18 +216,12 @@ int test_parse(struct isl_ctx *ctx)
test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : "
"p1 = 1 && (y1 <= y2 || y2 = 0) }");
- str = "{ [x,y] : [([x/2]+y)/3] >= 1 }";
- str2 = "{ [x, y] : 2y >= 6 - x }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
- if (test_parse_map_equal(ctx, "{ [x,y] : x <= min(y, 2*y+3) }",
- "{ [x,y] : x <= y, 2*y + 3 }") < 0)
- return -1;
- str = "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }";
- if (test_parse_map_equal(ctx, "{ [x,y] : x >= min(y, 2*y+3) }",
- str) < 0)
- return -1;
+ for (i = 0; i < ARRAY_SIZE(parse_map_equal_tests); ++i) {
+ str = parse_map_equal_tests[i].map1;
+ str2 = parse_map_equal_tests[i].map2;
+ if (test_parse_map_equal(ctx, str, str2) < 0)
+ return -1;
+ }
str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
map = isl_map_read_from_str(ctx, str);
@@ -176,103 +242,11 @@ int test_parse(struct isl_ctx *ctx)
isl_map_free(map);
isl_map_free(map2);
- str = "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }";
- str2 = "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
- str = "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }";
- str2 = "{ [i,j] -> [min(i,j)] }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
- str = "{ [i,j] : i != j }";
- str2 = "{ [i,j] : i < j or i > j }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
- str = "{ [i,j] : (i+1)*2 >= j }";
- str2 = "{ [i, j] : j <= 2 + 2i }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
- str = "{ [i] -> [i > 0 ? 4 : 5] }";
- str2 = "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
- str = "[N=2,M] -> { [i=[(M+N)/4]] }";
- str2 = "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
- str = "{ [x] : x >= 0 }";
- str2 = "{ [x] : x-0 >= 0 }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
- str = "{ [i] : ((i > 10)) }";
- str2 = "{ [i] : i >= 11 }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
- str = "{ [i] -> [0] }";
- str2 = "{ [i] -> [0 * i] }";
- if (test_parse_map_equal(ctx, str, str2) < 0)
- return -1;
-
test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }");
test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }");
test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }");
test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }");
- if (test_parse_map_equal(ctx, "{ [a] -> [b] : (not false) }",
- "{ [a] -> [b] : true }") < 0)
- return -1;
-
- if (test_parse_map_equal(ctx, "{ [i] : i/2 <= 5 }",
- "{ [i] : i <= 10 }") < 0)
- return -1;
-
- if (test_parse_map_equal(ctx, "{Sym=[n] [i] : i <= n }",
- "[n] -> { [i] : i <= n }") < 0)
- return -1;
-
- if (test_parse_map_equal(ctx, "{ [*] }", "{ [a] }") < 0)
- return -1;
-
- if (test_parse_map_equal(ctx, "{ [i] : 2*floor(i/2) = i }",
- "{ [i] : exists a : i = 2 a }") < 0)
- return -1;
-
- if (test_parse_map_equal(ctx, "{ [a] -> [b] : a = 5 implies b = 5 }",
- "{ [a] -> [b] : a != 5 or b = 5 }") < 0)
- return -1;
-
- if (test_parse_map_equal(ctx, "{ [a] -> [a - 1 : a > 0] }",
- "{ [a] -> [a - 1] : a > 0 }") < 0)
- return -1;
- if (test_parse_map_equal(ctx,
- "{ [a] -> [a - 1 : a > 0; a : a <= 0] }",
- "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }") < 0)
- return -1;
- if (test_parse_map_equal(ctx,
- "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }",
- "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }") < 0)
- return -1;
- if (test_parse_map_equal(ctx,
- "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }",
- "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }") < 0)
- return -1;
- if (test_parse_map_equal(ctx,
- "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }",
- "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }") < 0)
- return -1;
- if (test_parse_map_equal(ctx,
- "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }",
- "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }") < 0)
- return -1;
-
return 0;
}
@@ -1104,6 +1078,76 @@ int test_affine_hull(struct isl_ctx *ctx)
return 0;
}
+/* Pairs of maps and the corresponding expected results of
+ * isl_map_plain_unshifted_simple_hull.
+ */
+struct {
+ const char *map;
+ const char *hull;
+} plain_unshifted_simple_hull_tests[] = {
+ { "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
+ "{ [i] -> [j] : i >= 1 }" },
+ { "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
+ "(j mod 4 = 2 and k mod 6 = n) }",
+ "{ [n] -> [i,j,k] : j mod 4 = 2 }" },
+};
+
+/* Basic tests for isl_map_plain_unshifted_simple_hull.
+ */
+static int test_plain_unshifted_simple_hull(isl_ctx *ctx)
+{
+ int i;
+ isl_map *map;
+ isl_basic_map *hull, *expected;
+ isl_bool equal;
+
+ for (i = 0; i < ARRAY_SIZE(plain_unshifted_simple_hull_tests); ++i) {
+ const char *str;
+ str = plain_unshifted_simple_hull_tests[i].map;
+ map = isl_map_read_from_str(ctx, str);
+ str = plain_unshifted_simple_hull_tests[i].hull;
+ expected = isl_basic_map_read_from_str(ctx, str);
+ hull = isl_map_plain_unshifted_simple_hull(map);
+ equal = isl_basic_map_is_equal(hull, expected);
+ isl_basic_map_free(hull);
+ isl_basic_map_free(expected);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected hull",
+ return -1);
+ }
+
+ return 0;
+}
+
+static int test_simple_hull(struct isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_basic_set *bset;
+ isl_bool is_empty;
+
+ str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"
+ "[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";
+ set = isl_set_read_from_str(ctx, str);
+ bset = isl_set_simple_hull(set);
+ is_empty = isl_basic_set_is_empty(bset);
+ isl_basic_set_free(bset);
+
+ if (is_empty == isl_bool_error)
+ return -1;
+
+ if (is_empty == isl_bool_false)
+ isl_die(ctx, isl_error_unknown, "Empty set should be detected",
+ return -1);
+
+ if (test_plain_unshifted_simple_hull(ctx) < 0)
+ return -1;
+
+ return 0;
+}
+
void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
{
char *filename;
@@ -1233,6 +1277,55 @@ void test_gist_case(struct isl_ctx *ctx, const char *name)
fclose(input);
}
+/* Inputs to isl_map_plain_gist_basic_map, along with the expected output.
+ */
+struct {
+ const char *map;
+ const char *context;
+ const char *gist;
+} plain_gist_tests[] = {
+ { "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",
+ "{ [i] -> [j] : i >= 1 }",
+ "{ [i] -> [j] : j >= 1 or i >= 2 and j <= 10 }" },
+ { "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "
+ "(j mod 4 = 2 and k mod 6 = n) }",
+ "{ [n] -> [i,j,k] : j mod 4 = 2 }",
+ "{ [n] -> [i,j,k] : (i mod 3 = 2) or (k mod 6 = n) }" },
+ { "{ [i] -> [j] : i > j and (exists a,b : i <= 2a + 5b <= 2) }",
+ "{ [i] -> [j] : i > j }",
+ "{ [i] -> [j] : exists a,b : i <= 2a + 5b <= 2 }" },
+};
+
+/* Basic tests for isl_map_plain_gist_basic_map.
+ */
+static int test_plain_gist(isl_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(plain_gist_tests); ++i) {
+ const char *str;
+ int equal;
+ isl_map *map, *gist;
+ isl_basic_map *context;
+
+ map = isl_map_read_from_str(ctx, plain_gist_tests[i].map);
+ str = plain_gist_tests[i].context;
+ context = isl_basic_map_read_from_str(ctx, str);
+ map = isl_map_plain_gist_basic_map(map, context);
+ gist = isl_map_read_from_str(ctx, plain_gist_tests[i].gist);
+ equal = isl_map_is_equal(map, gist);
+ isl_map_free(map);
+ isl_map_free(gist);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "incorrect gist result", return -1);
+ }
+
+ return 0;
+}
+
struct {
const char *set;
const char *context;
@@ -1252,6 +1345,41 @@ struct {
"(n >= 1 and a >= 0 and b <= 2148 - n - a and "
"b >= 0) }",
"{ [m, n, ku, kl] }" },
+ { "{ [a, a, b] : a >= 10 }",
+ "{ [a, b, c] : c >= a and c <= b and c >= 2 }",
+ "{ [a, a, b] : a >= 10 }" },
+ { "{ [i, j] : i >= 0 and i + j >= 0 }", "{ [i, j] : i <= 0 }",
+ "{ [0, j] : j >= 0 }" },
+ /* Check that no constraints on i6 are introduced in the gist */
+ { "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
+ "20e0 <= 1530 - 4t1 - 5i4 and 20e0 >= 1511 - 4t1 - 5i4 and "
+ "5e0 <= 381 - t1 and i4 <= 1) }",
+ "[t1] -> { [i4, i6] : exists (e0 = floor((-t1 + i6)/5): "
+ "5e0 = -t1 + i6 and i6 <= 6 and i6 >= 3) }",
+ "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "
+ "i4 <= 1 and 5e0 <= 381 - t1 and 20e0 <= 1530 - 4t1 - 5i4 and "
+ "20e0 >= 1511 - 4t1 - 5i4) }" },
+ /* Check that no constraints on i6 are introduced in the gist */
+ { "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((1 + i4)/2), "
+ "e1 = floor((1530 - 4t1 - 5i4)/20), "
+ "e2 = floor((-4t1 - 5i4 + 10*floor((1 + i4)/2))/20), "
+ "e3 = floor((-1 + i4)/2): t2 = 0 and 2e3 = -1 + i4 and "
+ "20e2 >= -19 - 4t1 - 5i4 + 10e0 and 5e2 <= 1 - t1 and "
+ "2e0 <= 1 + i4 and 2e0 >= i4 and "
+ "20e1 <= 1530 - 4t1 - 5i4 and "
+ "20e1 >= 1511 - 4t1 - 5i4 and i4 <= 1 and "
+ "5e1 <= 381 - t1 and 20e2 <= -4t1 - 5i4 + 10e0) }",
+ "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((-17 + i4)/2), "
+ "e1 = floor((-t1 + i6)/5): 5e1 = -t1 + i6 and "
+ "2e0 <= -17 + i4 and 2e0 >= -18 + i4 and "
+ "10e0 <= -91 + 5i4 + 4i6 and "
+ "10e0 >= -105 + 5i4 + 4i6) }",
+ "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((381 - t1)/5), "
+ "e1 = floor((-1 + i4)/2): t2 = 0 and 2e1 = -1 + i4 and "
+ "i4 <= 1 and 5e0 <= 381 - t1 and 20e0 >= 1511 - 4t1 - 5i4) }" },
+ { "{ [0, 0, q, p] : -5 <= q <= 5 and p >= 0 }",
+ "{ [a, b, q, p] : b >= 1 + a }",
+ "{ [a, b, q, p] : false }" },
};
static int test_gist(struct isl_ctx *ctx)
@@ -1337,6 +1465,9 @@ static int test_gist(struct isl_ctx *ctx)
isl_map_free(map1); return -1);
isl_map_free(map1);
+ if (test_plain_gist(ctx) < 0)
+ return -1;
+
return 0;
}
@@ -1597,6 +1728,11 @@ struct {
"32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "
"32e0 <= 31 + i0)) or "
"i0 >= 0 }" },
+ { 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },
+ { 1, "{ [a, a, b, c] : 32*floor((a)/32) = a and 2*floor((b)/2) = b and "
+ "2*floor((c)/2) = c and 0 <= a <= 192;"
+ "[224, 224, b, c] : 2*floor((b)/2) = b and 2*floor((c)/2) = c }"
+ },
};
/* A specialized coalescing test case that would result
@@ -1661,13 +1797,55 @@ static int test_coalesce(struct isl_ctx *ctx)
return 0;
}
-static int test_closure(isl_ctx *ctx)
+/* Construct a representation of the graph on the right of Figure 1
+ * in "Computing the Transitive Closure of a Union of
+ * Affine Integer Tuple Relations".
+ */
+static __isl_give isl_map *cocoa_fig_1_right_graph(isl_ctx *ctx)
{
- const char *str;
isl_set *dom;
isl_map *up, *right;
+
+ dom = isl_set_read_from_str(ctx,
+ "{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "
+ "2 x - 3 y + 3 >= 0 }");
+ right = isl_map_read_from_str(ctx,
+ "{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");
+ up = isl_map_read_from_str(ctx,
+ "{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");
+ right = isl_map_intersect_domain(right, isl_set_copy(dom));
+ right = isl_map_intersect_range(right, isl_set_copy(dom));
+ up = isl_map_intersect_domain(up, isl_set_copy(dom));
+ up = isl_map_intersect_range(up, dom);
+ return isl_map_union(up, right);
+}
+
+/* Construct a representation of the power of the graph
+ * on the right of Figure 1 in "Computing the Transitive Closure of
+ * a Union of Affine Integer Tuple Relations".
+ */
+static __isl_give isl_map *cocoa_fig_1_right_power(isl_ctx *ctx)
+{
+ return isl_map_read_from_str(ctx,
+ "{ [1] -> [[0,0] -> [0,1]]; [2] -> [[0,0] -> [1,1]]; "
+ " [1] -> [[0,1] -> [1,1]]; [1] -> [[2,2] -> [3,2]]; "
+ " [2] -> [[2,2] -> [3,3]]; [1] -> [[3,2] -> [3,3]] }");
+}
+
+/* Construct a representation of the transitive closure of the graph
+ * on the right of Figure 1 in "Computing the Transitive Closure of
+ * a Union of Affine Integer Tuple Relations".
+ */
+static __isl_give isl_map *cocoa_fig_1_right_tc(isl_ctx *ctx)
+{
+ return isl_set_unwrap(isl_map_range(cocoa_fig_1_right_power(ctx)));
+}
+
+static int test_closure(isl_ctx *ctx)
+{
+ const char *str;
isl_map *map, *map2;
- int exact;
+ int exact, equal;
/* COCOA example 1 */
map = isl_map_read_from_str(ctx,
@@ -1776,28 +1954,27 @@ static int test_closure(isl_ctx *ctx)
isl_map_free(map2);
isl_map_free(map);
- /* COCOA Fig.1 right */
- dom = isl_set_read_from_str(ctx,
- "{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "
- "2 x - 3 y + 3 >= 0 }");
- right = isl_map_read_from_str(ctx,
- "{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");
- up = isl_map_read_from_str(ctx,
- "{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");
- right = isl_map_intersect_domain(right, isl_set_copy(dom));
- right = isl_map_intersect_range(right, isl_set_copy(dom));
- up = isl_map_intersect_domain(up, isl_set_copy(dom));
- up = isl_map_intersect_range(up, dom);
- map = isl_map_union(up, right);
+ map = cocoa_fig_1_right_graph(ctx);
map = isl_map_transitive_closure(map, &exact);
assert(exact);
- map2 = isl_map_read_from_str(ctx,
- "{ [0,0] -> [0,1]; [0,0] -> [1,1]; [0,1] -> [1,1]; "
- " [2,2] -> [3,2]; [2,2] -> [3,3]; [3,2] -> [3,3] }");
+ map2 = cocoa_fig_1_right_tc(ctx);
assert(isl_map_is_equal(map, map2));
isl_map_free(map2);
isl_map_free(map);
+ map = cocoa_fig_1_right_graph(ctx);
+ map = isl_map_power(map, &exact);
+ map2 = cocoa_fig_1_right_power(ctx);
+ equal = isl_map_is_equal(map, map2);
+ isl_map_free(map2);
+ isl_map_free(map);
+ if (equal < 0)
+ return -1;
+ if (!exact)
+ isl_die(ctx, isl_error_unknown, "power not exact", return -1);
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected power", return -1);
+
/* COCOA Theorem 1 counter example */
map = isl_map_read_from_str(ctx,
"{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "
@@ -2606,33 +2783,30 @@ static int test_union(isl_ctx *ctx)
/* Check that computing a bound of a non-zero polynomial over an unbounded
* domain does not produce a rational value.
- * Ideally, we want the value to be infinity, but we accept NaN for now.
- * We certainly do not want to obtain the value zero.
+ * In particular, check that the upper bound is infinity.
*/
static int test_bound_unbounded_domain(isl_ctx *ctx)
{
const char *str;
- isl_set *dom;
- isl_point *pnt;
isl_pw_qpolynomial *pwqp;
- isl_pw_qpolynomial_fold *pwf;
- isl_val *v;
- int is_rat;
+ isl_pw_qpolynomial_fold *pwf, *pwf2;
+ isl_bool equal;
str = "{ [m,n] -> -m * n }";
pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
- dom = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf));
- pnt = isl_set_sample_point(dom);
- v = isl_pw_qpolynomial_fold_eval(pwf, pnt);
- is_rat = isl_val_is_rat(v);
- isl_val_free(v);
+ str = "{ infty }";
+ pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+ pwf2 = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
+ equal = isl_pw_qpolynomial_fold_plain_is_equal(pwf, pwf2);
+ isl_pw_qpolynomial_fold_free(pwf);
+ isl_pw_qpolynomial_fold_free(pwf2);
- if (is_rat < 0)
+ if (equal < 0)
return -1;
- if (is_rat)
+ if (!equal)
isl_die(ctx, isl_error_unknown,
- "unexpected rational value", return -1);
+ "expecting infinite polynomial bound", return -1);
return 0;
}
@@ -2800,6 +2974,31 @@ static int test_subtract(isl_ctx *ctx)
return 0;
}
+/* Check that intersecting the empty basic set with another basic set
+ * does not increase the number of constraints. In particular,
+ * the empty basic set should maintain its canonical representation.
+ */
+static int test_intersect(isl_ctx *ctx)
+{
+ int n1, n2;
+ isl_basic_set *bset1, *bset2;
+
+ bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }");
+ bset2 = isl_basic_set_read_from_str(ctx, "{ [1,2,3] }");
+ n1 = isl_basic_set_n_constraint(bset1);
+ bset1 = isl_basic_set_intersect(bset1, bset2);
+ n2 = isl_basic_set_n_constraint(bset1);
+ isl_basic_set_free(bset1);
+ if (!bset1)
+ return -1;
+ if (n1 != n2)
+ isl_die(ctx, isl_error_unknown,
+ "number of constraints of empty set changed",
+ return -1);
+
+ return 0;
+}
+
int test_factorize(isl_ctx *ctx)
{
const char *str;
@@ -3898,6 +4097,17 @@ struct {
{ &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",
"{ B[x] -> [2] : x >= 0 }",
"{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },
+ { &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,
+ "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",
+ "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",
+ "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "
+ "D[i] -> B[2] : i >= 5 }" },
+ { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
+ "{ B[x] -> C[2] : x > 0 }",
+ "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },
+ { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
+ "{ B[x] -> A[2] : x >= 0 }",
+ "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },
};
/* Perform some basic tests of binary operations on
@@ -3930,6 +4140,47 @@ static int test_bin_upma(isl_ctx *ctx)
return 0;
}
+struct {
+ __isl_give isl_union_pw_multi_aff *(*fn)(
+ __isl_take isl_union_pw_multi_aff *upma1,
+ __isl_take isl_union_pw_multi_aff *upma2);
+ const char *arg1;
+ const char *arg2;
+} upma_bin_fail_tests[] = {
+ { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
+ "{ B[x] -> C[2] : x >= 0 }" },
+};
+
+/* Perform some basic tests of binary operations on
+ * isl_union_pw_multi_aff objects that are expected to fail.
+ */
+static int test_bin_upma_fail(isl_ctx *ctx)
+{
+ int i, n;
+ isl_union_pw_multi_aff *upma1, *upma2;
+ int on_error;
+
+ on_error = isl_options_get_on_error(ctx);
+ isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
+ n = ARRAY_SIZE(upma_bin_fail_tests);
+ for (i = 0; i < n; ++i) {
+ upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
+ upma_bin_fail_tests[i].arg1);
+ upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
+ upma_bin_fail_tests[i].arg2);
+ upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);
+ isl_union_pw_multi_aff_free(upma1);
+ if (upma1)
+ break;
+ }
+ isl_options_set_on_error(ctx, on_error);
+ if (i < n)
+ isl_die(ctx, isl_error_unknown,
+ "operation not expected to succeed", return -1);
+
+ return 0;
+}
+
int test_aff(isl_ctx *ctx)
{
const char *str;
@@ -3943,6 +4194,8 @@ int test_aff(isl_ctx *ctx)
return -1;
if (test_bin_upma(ctx) < 0)
return -1;
+ if (test_bin_upma_fail(ctx) < 0)
+ return -1;
space = isl_space_set_alloc(ctx, 0, 1);
ls = isl_local_space_from_space(space);
@@ -4387,6 +4640,35 @@ int test_union_pw(isl_ctx *ctx)
return 0;
}
+/* Test that isl_union_pw_qpolynomial_eval picks up the function
+ * defined over the correct domain space.
+ */
+static int test_eval(isl_ctx *ctx)
+{
+ const char *str;
+ isl_point *pnt;
+ isl_set *set;
+ isl_union_pw_qpolynomial *upwqp;
+ isl_val *v;
+ int cmp;
+
+ str = "{ A[x] -> x^2; B[x] -> -x^2 }";
+ upwqp = isl_union_pw_qpolynomial_read_from_str(ctx, str);
+ str = "{ A[6] }";
+ set = isl_set_read_from_str(ctx, str);
+ pnt = isl_set_sample_point(set);
+ v = isl_union_pw_qpolynomial_eval(upwqp, pnt);
+ cmp = isl_val_cmp_si(v, 36);
+ isl_val_free(v);
+
+ if (!v)
+ return -1;
+ if (cmp != 0)
+ isl_die(ctx, isl_error_unknown, "unexpected value", return -1);
+
+ return 0;
+}
+
int test_output(isl_ctx *ctx)
{
char *s;
@@ -4668,6 +4950,9 @@ const char *set_conversion_tests[] = {
"[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
"[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
"[N] -> { [3*floor(N/2) + 5*floor(N/3)] }",
+ "[a, b] -> { [c, d] : (4*floor((-a + c)/4) = -a + c and "
+ "32*floor((-b + d)/32) = -b + d and 5 <= c <= 8 and "
+ "-3 + c <= d <= 28 + c) }",
};
/* Check that converting from isl_set to isl_pw_multi_aff and back
@@ -4700,32 +4985,41 @@ static int test_set_conversion(isl_ctx *ctx)
return 0;
}
+const char *conversion_tests[] = {
+ "{ [a, b, c, d] -> s0[a, b, e, f] : "
+ "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
+ "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
+ "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
+ "9e <= -2 - 2a) }",
+ "{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "
+ "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
+ "{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
+};
+
/* Check that converting from isl_map to isl_pw_multi_aff and back
* to isl_map produces the original isl_map.
*/
static int test_map_conversion(isl_ctx *ctx)
{
- const char *str;
+ int i;
isl_map *map1, *map2;
isl_pw_multi_aff *pma;
int equal;
- str = "{ [a, b, c, d] -> s0[a, b, e, f] : "
- "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
- "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
- "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
- "9e <= -2 - 2a) }";
- map1 = isl_map_read_from_str(ctx, str);
- pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));
- map2 = isl_map_from_pw_multi_aff(pma);
- equal = isl_map_is_equal(map1, map2);
- isl_map_free(map1);
- isl_map_free(map2);
+ for (i = 0; i < ARRAY_SIZE(conversion_tests); ++i) {
+ map1 = isl_map_read_from_str(ctx, conversion_tests[i]);
+ pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));
+ map2 = isl_map_from_pw_multi_aff(pma);
+ equal = isl_map_is_equal(map1, map2);
+ isl_map_free(map1);
+ isl_map_free(map2);
- if (equal < 0)
- return -1;
- if (!equal)
- isl_die(ctx, isl_error_unknown, "bad conversion", return -1);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "bad conversion",
+ return -1);
+ }
return 0;
}
@@ -5888,10 +6182,37 @@ static int test_tile(isl_ctx *ctx)
return 0;
}
+/* Check that the domain hash of a space is equal to the hash
+ * of the domain of the space.
+ */
+static int test_domain_hash(isl_ctx *ctx)
+{
+ isl_map *map;
+ isl_space *space;
+ uint32_t hash1, hash2;
+
+ map = isl_map_read_from_str(ctx, "[n] -> { A[B[x] -> C[]] -> D[] }");
+ space = isl_map_get_space(map);
+ isl_map_free(map);
+ hash1 = isl_space_get_domain_hash(space);
+ space = isl_space_domain(space);
+ hash2 = isl_space_get_hash(space);
+ isl_space_free(space);
+
+ if (!space)
+ return -1;
+ if (hash1 != hash2)
+ isl_die(ctx, isl_error_unknown,
+ "domain hash not equal to hash of domain", return -1);
+
+ return 0;
+}
+
struct {
const char *name;
int (*fn)(isl_ctx *ctx);
} tests [] = {
+ { "domain hash", &test_domain_hash },
{ "dual", &test_dual },
{ "dependence analysis", &test_flow },
{ "val", &test_val },
@@ -5928,13 +6249,16 @@ struct {
{ "schedule tree grouping", &test_schedule_tree_group },
{ "tile", &test_tile },
{ "union_pw", &test_union_pw },
+ { "eval", &test_eval },
{ "parse", &test_parse },
{ "single-valued", &test_sv },
{ "affine hull", &test_affine_hull },
+ { "simple_hull", &test_simple_hull },
{ "coalesce", &test_coalesce },
{ "factorize", &test_factorize },
{ "subset", &test_subset },
{ "subtract", &test_subtract },
+ { "intersect", &test_intersect },
{ "lexmin", &test_lexmin },
{ "min", &test_min },
{ "gist", &test_gist },
diff --git a/isl_test_imath.c b/isl_test_imath.c
new file mode 100644
index 00000000..fdb07774
--- /dev/null
+++ b/isl_test_imath.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2015 INRIA Paris-Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Michael Kruse, INRIA Paris-Rocquencourt,
+ * Domaine de Voluceau, Rocquenqourt, B.P. 105,
+ * 78153 Le Chesnay Cedex France
+ */
+
+#include <limits.h>
+#include <assert.h>
+#include <isl_imath.h>
+
+/* This constant is not defined in limits.h, but IMath uses it */
+#define ULONG_MIN 0ul
+
+/* Test the IMath internals assumed by the imath implementation of isl_int.
+ *
+ * In particular, we test the ranges of IMath-defined types.
+ *
+ * Also, isl uses the existence and function of imath's struct
+ * fields. The digits are stored with less significant digits at lower array
+ * indices. Where they are stored (on the heap or in the field 'single') does
+ * not matter.
+ */
+int test_imath_internals()
+{
+ mpz_t val;
+ mp_result retval;
+
+ assert(sizeof(mp_small) == sizeof(long));
+ assert(MP_SMALL_MIN == LONG_MIN);
+ assert(MP_SMALL_MAX == LONG_MAX);
+
+ assert(sizeof(mp_usmall) == sizeof(unsigned long));
+ assert(MP_USMALL_MIN == ULONG_MIN);
+ assert(MP_USMALL_MAX == ULONG_MAX);
+
+ retval = mp_int_init_value(&val, 0);
+ assert(retval == MP_OK);
+ assert(val.alloc >= val.used);
+ assert(val.used == 1);
+ assert(val.sign == MP_ZPOS);
+ assert(val.digits[0] == 0);
+
+ retval = mp_int_set_value(&val, -1);
+ assert(retval == MP_OK);
+ assert(val.alloc >= val.used);
+ assert(val.used == 1);
+ assert(val.sign == MP_NEG);
+ assert(val.digits[0] == 1);
+
+ retval = mp_int_set_value(&val, 1);
+ assert(retval == MP_OK);
+ assert(val.alloc >= val.used);
+ assert(val.used == 1);
+ assert(val.sign == MP_ZPOS);
+ assert(val.digits[0] == 1);
+
+ retval = mp_int_mul_pow2(&val, sizeof(mp_digit) * CHAR_BIT, &val);
+ assert(retval == MP_OK);
+ assert(val.alloc >= val.used);
+ assert(val.used == 2);
+ assert(val.sign == MP_ZPOS);
+ assert(val.digits[0] == 0);
+ assert(val.digits[1] == 1);
+
+ mp_int_clear(&val);
+ return 0;
+}
+
+int main()
+{
+ if (test_imath_internals() < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/isl_test_int.c b/isl_test_int.c
new file mode 100644
index 00000000..09884b1f
--- /dev/null
+++ b/isl_test_int.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright 2015 INRIA Paris-Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Michael Kruse, INRIA Paris-Rocquencourt,
+ * Domaine de Voluceau, Rocquenqourt, B.P. 105,
+ * 78153 Le Chesnay Cedex France
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <isl_int.h>
+
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
+
+#ifdef USE_SMALL_INT_OPT
+/* Test whether small and big representation of the same number have the same
+ * hash.
+ */
+static void int_test_hash(isl_int val)
+{
+ uint32_t demotedhash, promotedhash;
+ isl_int demoted, promoted;
+
+ isl_int_init(demoted);
+ isl_int_set(demoted, val);
+
+ isl_int_init(promoted);
+ isl_int_set(promoted, val);
+
+ isl_sioimath_try_demote(demoted);
+ isl_sioimath_promote(promoted);
+
+ assert(isl_int_eq(demoted, promoted));
+
+ demotedhash = isl_int_hash(demoted, 0);
+ promotedhash = isl_int_hash(promoted, 0);
+ assert(demotedhash == promotedhash);
+}
+
+struct {
+ void (*fn)(isl_int);
+ char *val;
+} int_single_value_tests[] = {
+ { &int_test_hash, "0" },
+ { &int_test_hash, "1" },
+ { &int_test_hash, "-1" },
+ { &int_test_hash, "23" },
+ { &int_test_hash, "-23" },
+ { &int_test_hash, "107" },
+ { &int_test_hash, "32768" },
+ { &int_test_hash, "2147483647" },
+ { &int_test_hash, "-2147483647" },
+ { &int_test_hash, "2147483648" },
+ { &int_test_hash, "-2147483648" },
+};
+
+static void int_test_single_value()
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(int_single_value_tests); i += 1) {
+ isl_int val;
+
+ isl_int_init(val);
+ isl_int_read(val, int_single_value_tests[i].val);
+
+ (*int_single_value_tests[i].fn)(val);
+
+ isl_int_clear(val);
+ }
+}
+
+static void invoke_alternate_representations_2args(char *arg1, char *arg2,
+ void (*fn)(isl_int, isl_int))
+{
+ int j;
+ isl_int int1, int2;
+
+ isl_int_init(int1);
+ isl_int_init(int2);
+
+ for (j = 0; j < 4; ++j) {
+ isl_int_read(int1, arg1);
+ isl_int_read(int2, arg2);
+
+ if (j & 1)
+ isl_sioimath_promote(int1);
+ else
+ isl_sioimath_try_demote(int1);
+
+ if (j & 2)
+ isl_sioimath_promote(int2);
+ else
+ isl_sioimath_try_demote(int2);
+
+ (*fn)(int1, int2);
+ }
+
+ isl_int_clear(int1);
+ isl_int_clear(int2);
+}
+
+static void invoke_alternate_representations_3args(char *arg1, char *arg2,
+ char *arg3, void (*fn)(isl_int, isl_int, isl_int))
+{
+ int j;
+ isl_int int1, int2, int3;
+
+ isl_int_init(int1);
+ isl_int_init(int2);
+ isl_int_init(int3);
+
+ for (j = 0; j < 8; ++j) {
+ isl_int_read(int1, arg1);
+ isl_int_read(int2, arg2);
+ isl_int_read(int3, arg3);
+
+ if (j & 1)
+ isl_sioimath_promote(int1);
+ else
+ isl_sioimath_try_demote(int1);
+
+ if (j & 2)
+ isl_sioimath_promote(int2);
+ else
+ isl_sioimath_try_demote(int2);
+
+ if (j & 4)
+ isl_sioimath_promote(int3);
+ else
+ isl_sioimath_try_demote(int3);
+
+ (*fn)(int1, int2, int3);
+ }
+
+ isl_int_clear(int1);
+ isl_int_clear(int2);
+ isl_int_clear(int3);
+}
+#else /* USE_SMALL_INT_OPT */
+
+static void int_test_single_value()
+{
+}
+
+static void invoke_alternate_representations_2args(char *arg1, char *arg2,
+ void (*fn)(isl_int, isl_int))
+{
+ isl_int int1, int2;
+
+ isl_int_init(int1);
+ isl_int_init(int2);
+
+ isl_int_read(int1, arg1);
+ isl_int_read(int2, arg2);
+
+ (*fn)(int1, int2);
+
+ isl_int_clear(int1);
+ isl_int_clear(int2);
+}
+
+static void invoke_alternate_representations_3args(char *arg1, char *arg2,
+ char *arg3, void (*fn)(isl_int, isl_int, isl_int))
+{
+ isl_int int1, int2, int3;
+
+ isl_int_init(int1);
+ isl_int_init(int2);
+ isl_int_init(int3);
+
+ isl_int_read(int1, arg1);
+ isl_int_read(int2, arg2);
+ isl_int_read(int3, arg3);
+
+ (*fn)(int1, int2, int3);
+
+ isl_int_clear(int1);
+ isl_int_clear(int2);
+ isl_int_clear(int3);
+}
+#endif /* USE_SMALL_INT_OPT */
+
+static void int_test_neg(isl_int expected, isl_int arg)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_neg(result, arg);
+ assert(isl_int_eq(result, expected));
+
+ isl_int_neg(result, expected);
+ assert(isl_int_eq(result, arg));
+
+ isl_int_clear(result);
+}
+
+static void int_test_abs(isl_int expected, isl_int arg)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_abs(result, arg);
+ assert(isl_int_eq(result, expected));
+
+ isl_int_clear(result);
+}
+
+struct {
+ void (*fn)(isl_int, isl_int);
+ char *expected, *arg;
+} int_unary_tests[] = {
+ { &int_test_neg, "0", "0" },
+ { &int_test_neg, "-1", "1" },
+ { &int_test_neg, "-2147483647", "2147483647" },
+ { &int_test_neg, "-2147483648", "2147483648" },
+ { &int_test_neg, "-9223372036854775807", "9223372036854775807" },
+ { &int_test_neg, "-9223372036854775808", "9223372036854775808" },
+
+ { &int_test_abs, "0", "0" },
+ { &int_test_abs, "1", "1" },
+ { &int_test_abs, "1", "-1" },
+ { &int_test_abs, "2147483647", "2147483647" },
+ { &int_test_abs, "2147483648", "-2147483648" },
+ { &int_test_abs, "9223372036854775807", "9223372036854775807" },
+ { &int_test_abs, "9223372036854775808", "-9223372036854775808" },
+};
+
+static void int_test_divexact(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ isl_int result;
+ unsigned long rhsulong;
+
+ if (isl_int_sgn(rhs) == 0)
+ return;
+
+ isl_int_init(result);
+
+ isl_int_divexact(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_tdiv_q(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_fdiv_q(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_cdiv_q(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ if (isl_int_fits_ulong(rhs)) {
+ rhsulong = isl_int_get_ui(rhs);
+
+ isl_int_divexact_ui(result, lhs, rhsulong);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_fdiv_q_ui(result, lhs, rhsulong);
+ assert(isl_int_eq(expected, result));
+ }
+
+ isl_int_clear(result);
+}
+
+static void int_test_mul(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_mul(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ if (isl_int_fits_ulong(rhs)) {
+ unsigned long rhsulong = isl_int_get_ui(rhs);
+
+ isl_int_mul_ui(result, lhs, rhsulong);
+ assert(isl_int_eq(expected, result));
+ }
+
+ if (isl_int_fits_slong(rhs)) {
+ unsigned long rhsslong = isl_int_get_si(rhs);
+
+ isl_int_mul_si(result, lhs, rhsslong);
+ assert(isl_int_eq(expected, result));
+ }
+
+ isl_int_clear(result);
+}
+
+/* Use a triple that satisfies 'product = factor1 * factor2' to check the
+ * operations mul, divexact, tdiv, fdiv and cdiv.
+ */
+static void int_test_product(isl_int product, isl_int factor1, isl_int factor2)
+{
+ int_test_divexact(factor1, product, factor2);
+ int_test_divexact(factor2, product, factor1);
+
+ int_test_mul(product, factor1, factor2);
+ int_test_mul(product, factor2, factor1);
+}
+
+static void int_test_add(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_add(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_clear(result);
+}
+
+static void int_test_sub(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_sub(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_clear(result);
+}
+
+/* Use a triple that satisfies 'sum = term1 + term2' to check the operations add
+ * and sub.
+ */
+static void int_test_sum(isl_int sum, isl_int term1, isl_int term2)
+{
+ int_test_sub(term1, sum, term2);
+ int_test_sub(term2, sum, term1);
+
+ int_test_add(sum, term1, term2);
+ int_test_add(sum, term2, term1);
+}
+
+static void int_test_fdiv(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ unsigned long rhsulong;
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_fdiv_q(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ if (isl_int_fits_ulong(rhs)) {
+ rhsulong = isl_int_get_ui(rhs);
+
+ isl_int_fdiv_q_ui(result, lhs, rhsulong);
+ assert(isl_int_eq(expected, result));
+ }
+
+ isl_int_clear(result);
+}
+
+static void int_test_cdiv(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_cdiv_q(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_clear(result);
+}
+
+static void int_test_tdiv(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_tdiv_q(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_clear(result);
+}
+
+static void int_test_fdiv_r(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_fdiv_r(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_clear(result);
+}
+
+static void int_test_gcd(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_gcd(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_gcd(result, rhs, lhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_clear(result);
+}
+
+static void int_test_lcm(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ isl_int result;
+ isl_int_init(result);
+
+ isl_int_lcm(result, lhs, rhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_lcm(result, rhs, lhs);
+ assert(isl_int_eq(expected, result));
+
+ isl_int_clear(result);
+}
+
+static int sgn(int val)
+{
+ if (val > 0)
+ return 1;
+ if (val < 0)
+ return -1;
+ return 0;
+}
+
+static void int_test_cmp(int exp, isl_int lhs, isl_int rhs)
+{
+ long rhslong;
+
+ assert(exp == sgn(isl_int_cmp(lhs, rhs)));
+
+ if (isl_int_fits_slong(rhs)) {
+ rhslong = isl_int_get_si(rhs);
+ assert(exp == sgn(isl_int_cmp_si(lhs, rhslong)));
+ }
+}
+
+/* Test the comparison relations over two numbers.
+ * expected is the sign (1, 0 or -1) of 'lhs - rhs'.
+ */
+static void int_test_cmps(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ int exp;
+ isl_int diff;
+
+ exp = isl_int_get_si(expected);
+
+ isl_int_init(diff);
+ isl_int_sub(diff, lhs, rhs);
+ assert(exp == isl_int_sgn(diff));
+ isl_int_clear(diff);
+
+ int_test_cmp(exp, lhs, rhs);
+ int_test_cmp(-exp, rhs, lhs);
+}
+
+static void int_test_abs_cmp(isl_int expected, isl_int lhs, isl_int rhs)
+{
+ int exp;
+
+ exp = isl_int_get_si(expected);
+ assert(exp == sgn(isl_int_abs_cmp(lhs, rhs)));
+ assert(-exp == sgn(isl_int_abs_cmp(rhs, lhs)));
+}
+
+struct {
+ void (*fn)(isl_int, isl_int, isl_int);
+ char *expected, *lhs, *rhs;
+} int_binary_tests[] = {
+ { &int_test_sum, "0", "0", "0" },
+ { &int_test_sum, "1", "1", "0" },
+ { &int_test_sum, "2", "1", "1" },
+ { &int_test_sum, "-1", "0", "-1" },
+ { &int_test_sum, "-2", "-1", "-1" },
+
+ { &int_test_sum, "2147483647", "1073741823", "1073741824" },
+ { &int_test_sum, "-2147483648", "-1073741824", "-1073741824" },
+
+ { &int_test_sum, "2147483648", "2147483647", "1" },
+ { &int_test_sum, "-2147483648", "-2147483647", "-1" },
+
+ { &int_test_product, "0", "0", "0" },
+ { &int_test_product, "0", "0", "1" },
+ { &int_test_product, "1", "1", "1" },
+
+ { &int_test_product, "6", "2", "3" },
+ { &int_test_product, "-6", "2", "-3" },
+ { &int_test_product, "-6", "-2", "3" },
+ { &int_test_product, "6", "-2", "-3" },
+
+ { &int_test_product, "2147483648", "65536", "32768" },
+ { &int_test_product, "-2147483648", "65536", "-32768" },
+
+ { &int_test_product,
+ "4611686014132420609", "2147483647", "2147483647" },
+ { &int_test_product,
+ "-4611686014132420609", "-2147483647", "2147483647" },
+
+ { &int_test_product,
+ "4611686016279904256", "2147483647", "2147483648" },
+ { &int_test_product,
+ "-4611686016279904256", "-2147483647", "2147483648" },
+ { &int_test_product,
+ "-4611686016279904256", "2147483647", "-2147483648" },
+ { &int_test_product,
+ "4611686016279904256", "-2147483647", "-2147483648" },
+
+ { &int_test_product, "85070591730234615847396907784232501249",
+ "9223372036854775807", "9223372036854775807" },
+ { &int_test_product, "-85070591730234615847396907784232501249",
+ "-9223372036854775807", "9223372036854775807" },
+
+ { &int_test_product, "85070591730234615856620279821087277056",
+ "9223372036854775807", "9223372036854775808" },
+ { &int_test_product, "-85070591730234615856620279821087277056",
+ "-9223372036854775807", "9223372036854775808" },
+ { &int_test_product, "-85070591730234615856620279821087277056",
+ "9223372036854775807", "-9223372036854775808" },
+ { &int_test_product, "85070591730234615856620279821087277056",
+ "-9223372036854775807", "-9223372036854775808" },
+
+ { &int_test_product, "340282366920938463426481119284349108225",
+ "18446744073709551615", "18446744073709551615" },
+ { &int_test_product, "-340282366920938463426481119284349108225",
+ "-18446744073709551615", "18446744073709551615" },
+
+ { &int_test_product, "340282366920938463444927863358058659840",
+ "18446744073709551615", "18446744073709551616" },
+ { &int_test_product, "-340282366920938463444927863358058659840",
+ "-18446744073709551615", "18446744073709551616" },
+ { &int_test_product, "-340282366920938463444927863358058659840",
+ "18446744073709551615", "-18446744073709551616" },
+ { &int_test_product, "340282366920938463444927863358058659840",
+ "-18446744073709551615", "-18446744073709551616" },
+
+ { &int_test_fdiv, "0", "1", "2" },
+ { &int_test_fdiv_r, "1", "1", "3" },
+ { &int_test_fdiv, "-1", "-1", "2" },
+ { &int_test_fdiv_r, "2", "-1", "3" },
+ { &int_test_fdiv, "-1", "1", "-2" },
+ { &int_test_fdiv_r, "-2", "1", "-3" },
+ { &int_test_fdiv, "0", "-1", "-2" },
+ { &int_test_fdiv_r, "-1", "-1", "-3" },
+
+ { &int_test_cdiv, "1", "1", "2" },
+ { &int_test_cdiv, "0", "-1", "2" },
+ { &int_test_cdiv, "0", "1", "-2" },
+ { &int_test_cdiv, "1", "-1", "-2" },
+
+ { &int_test_tdiv, "0", "1", "2" },
+ { &int_test_tdiv, "0", "-1", "2" },
+ { &int_test_tdiv, "0", "1", "-2" },
+ { &int_test_tdiv, "0", "-1", "-2" },
+
+ { &int_test_gcd, "0", "0", "0" },
+ { &int_test_lcm, "0", "0", "0" },
+ { &int_test_gcd, "7", "0", "7" },
+ { &int_test_lcm, "0", "0", "7" },
+ { &int_test_gcd, "1", "1", "1" },
+ { &int_test_lcm, "1", "1", "1" },
+ { &int_test_gcd, "1", "1", "-1" },
+ { &int_test_lcm, "1", "1", "-1" },
+ { &int_test_gcd, "1", "-1", "-1" },
+ { &int_test_lcm, "1", "-1", "-1" },
+ { &int_test_gcd, "3", "6", "9" },
+ { &int_test_lcm, "18", "6", "9" },
+ { &int_test_gcd, "1", "14", "2147483647" },
+ { &int_test_lcm, "15032385529", "7", "2147483647" },
+ { &int_test_gcd, "2", "6", "-2147483648" },
+ { &int_test_lcm, "6442450944", "6", "-2147483648" },
+ { &int_test_gcd, "1", "6", "9223372036854775807" },
+ { &int_test_lcm, "55340232221128654842", "6", "9223372036854775807" },
+ { &int_test_gcd, "2", "6", "-9223372036854775808" },
+ { &int_test_lcm, "27670116110564327424", "6", "-9223372036854775808" },
+ { &int_test_gcd, "1", "18446744073709551616", "18446744073709551615" },
+ { &int_test_lcm, "340282366920938463444927863358058659840",
+ "18446744073709551616", "18446744073709551615" },
+
+ { &int_test_cmps, "0", "0", "0" },
+ { &int_test_abs_cmp, "0", "0", "0" },
+ { &int_test_cmps, "1", "1", "0" },
+ { &int_test_abs_cmp, "1", "1", "0" },
+ { &int_test_cmps, "-1", "-1", "0" },
+ { &int_test_abs_cmp, "1", "-1", "0" },
+ { &int_test_cmps, "-1", "-1", "1" },
+ { &int_test_abs_cmp, "0", "-1", "1" },
+
+ { &int_test_cmps, "-1", "5", "2147483647" },
+ { &int_test_abs_cmp, "-1", "5", "2147483647" },
+ { &int_test_cmps, "1", "5", "-2147483648" },
+ { &int_test_abs_cmp, "-1", "5", "-2147483648" },
+ { &int_test_cmps, "-1", "5", "9223372036854775807" },
+ { &int_test_abs_cmp, "-1", "5", "9223372036854775807" },
+ { &int_test_cmps, "1", "5", "-9223372036854775809" },
+ { &int_test_abs_cmp, "-1", "5", "-9223372036854775809" },
+};
+
+/* Tests the isl_int_* function to give the expected results. Tests are
+ * grouped by the number of arguments they take.
+ *
+ * If small integer optimization is enabled, we also test whether the results
+ * are the same in small and big representation.
+ */
+int main()
+{
+ int i;
+
+ int_test_single_value();
+
+ for (i = 0; i < ARRAY_SIZE(int_unary_tests); i += 1) {
+ invoke_alternate_representations_2args(
+ int_unary_tests[i].expected, int_unary_tests[i].arg,
+ int_unary_tests[i].fn);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(int_binary_tests); i += 1) {
+ invoke_alternate_representations_3args(
+ int_binary_tests[i].expected, int_binary_tests[i].lhs,
+ int_binary_tests[i].rhs, int_binary_tests[i].fn);
+ }
+
+ return 0;
+}
diff --git a/isl_transitive_closure.c b/isl_transitive_closure.c
index f031f67a..7ef84d48 100644
--- a/isl_transitive_closure.c
+++ b/isl_transitive_closure.c
@@ -1608,7 +1608,7 @@ static __isl_give isl_map *floyd_warshall_with_groups(__isl_take isl_space *dim,
floyd_warshall_iterate(grid, n, exact);
- app = isl_map_empty(isl_map_get_space(map));
+ app = isl_map_empty(isl_map_get_space(grid[0][0]));
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
diff --git a/isl_union_eval.c b/isl_union_eval.c
new file mode 100644
index 00000000..3daab3fc
--- /dev/null
+++ b/isl_union_eval.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010 INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
+ * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
+ * 91893 Orsay, France
+ */
+
+#include <isl_union_macro.h>
+
+/* Is the domain space of "entry" equal to "space"?
+ */
+static int FN(UNION,has_domain_space)(const void *entry, const void *val)
+{
+ PART *part = (PART *)entry;
+ isl_space *space = (isl_space *) val;
+
+ if (isl_space_is_params(space))
+ return isl_space_is_set(part->dim);
+
+ return isl_space_tuple_is_equal(part->dim, isl_dim_in,
+ space, isl_dim_set);
+}
+
+__isl_give isl_val *FN(UNION,eval)(__isl_take UNION *u,
+ __isl_take isl_point *pnt)
+{
+ uint32_t hash;
+ struct isl_hash_table_entry *entry;
+ isl_space *space;
+ isl_val *v;
+
+ if (!u || !pnt)
+ goto error;
+
+ space = isl_space_copy(pnt->dim);
+ if (!space)
+ goto error;
+ hash = isl_space_get_hash(space);
+ entry = isl_hash_table_find(u->space->ctx, &u->table,
+ hash, &FN(UNION,has_domain_space),
+ space, 0);
+ isl_space_free(space);
+ if (!entry) {
+ v = isl_val_zero(isl_point_get_ctx(pnt));
+ isl_point_free(pnt);
+ } else {
+ v = FN(PART,eval)(FN(PART,copy)(entry->data), pnt);
+ }
+ FN(UNION,free)(u);
+ return v;
+error:
+ FN(UNION,free)(u);
+ isl_point_free(pnt);
+ return NULL;
+}
diff --git a/isl_union_macro.h b/isl_union_macro.h
new file mode 100644
index 00000000..f445df67
--- /dev/null
+++ b/isl_union_macro.h
@@ -0,0 +1,4 @@
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xS(TYPE,NAME) struct TYPE ## _ ## NAME
+#define S(TYPE,NAME) xS(TYPE,NAME)
diff --git a/isl_union_map.c b/isl_union_map.c
index 2cae0bc4..cf616c9e 100644
--- a/isl_union_map.c
+++ b/isl_union_map.c
@@ -2087,6 +2087,31 @@ __isl_give isl_union_map *isl_union_map_domain_factor_range(
return cond_un_op(umap, &domain_factor_range_entry);
}
+/* If "map" is of the form A -> [B -> C], then add A -> B to "res".
+ */
+static isl_stat range_factor_domain_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_range_is_wrapping(map))
+ return isl_stat_ok;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_range_factor_domain(isl_map_copy(map)));
+
+ return *res ? isl_stat_ok : isl_stat_error;
+}
+
+/* For each map in "umap" of the form A -> [B -> C],
+ * construct the map A -> B and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_range_factor_domain(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &range_factor_domain_entry);
+}
+
/* If "map" is of the form A -> [B -> C], then add A -> C to "res".
*/
static isl_stat range_factor_range_entry(void **entry, void *user)
@@ -2419,6 +2444,14 @@ __isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset)
return (isl_basic_set *)isl_union_map_sample(uset);
}
+/* Return an element in "uset" in the form of an isl_point.
+ * Return a void isl_point if "uset" is empty.
+ */
+__isl_give isl_point *isl_union_set_sample_point(__isl_take isl_union_set *uset)
+{
+ return isl_basic_set_sample_point(isl_union_set_sample(uset));
+}
+
struct isl_forall_data {
isl_bool res;
isl_bool (*fn)(__isl_keep isl_map *map);
@@ -2930,6 +2963,32 @@ __isl_give isl_union_map *isl_union_map_curry(__isl_take isl_union_map *umap)
return cond_un_op(umap, &curry_entry);
}
+/* If *entry is of the form A -> ((B -> C) -> D), then apply
+ * isl_map_range_curry to it and add the result to *res.
+ */
+static isl_stat range_curry_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_can_range_curry(map))
+ return isl_stat_ok;
+
+ map = isl_map_range_curry(isl_map_copy(map));
+ *res = isl_union_map_add_map(*res, map);
+
+ return isl_stat_ok;
+}
+
+/* Given a union map, take the maps of the form A -> ((B -> C) -> D) and
+ * return the union of the corresponding maps A -> (B -> (C -> D)).
+ */
+__isl_give isl_union_map *isl_union_map_range_curry(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &range_curry_entry);
+}
+
static isl_stat lift_entry(void **entry, void *user)
{
isl_set *set = *entry;
diff --git a/isl_union_multi.c b/isl_union_multi.c
new file mode 100644
index 00000000..e78e36bf
--- /dev/null
+++ b/isl_union_multi.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2013 Ecole Normale Superieure
+ * Copyright 2015 INRIA Paris-Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
+ * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
+ * 91893 Orsay, France
+ * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ * and INRIA Paris-Rocquencourt, Domaine de Voluceau, Rocquenqourt, B.P. 105,
+ * 78153 Le Chesnay Cedex France
+ */
+
+#include <isl_hash_private.h>
+#include <isl_union_macro.h>
+
+/* A group of expressions defined over the same domain space "domain_space".
+ * The entries of "part_table" are the individual expressions,
+ * keyed on the entire space of the expression.
+ *
+ * Each UNION has its own groups, so there can only ever be a single
+ * reference to each group.
+ */
+S(UNION,group) {
+ isl_space *domain_space;
+ struct isl_hash_table part_table;
+};
+
+/* A union of expressions defined over different disjoint domains.
+ * "space" describes the parameters.
+ * The entries of "table" are keyed on the domain space of the entry and
+ * contain groups of expressions that are defined over the same domain space.
+ */
+struct UNION {
+ int ref;
+ isl_space *space;
+
+ struct isl_hash_table table;
+};
+
+/* Internal data structure for isl_union_*_foreach_group.
+ * "fn" is the function that needs to be called on each group.
+ */
+S(UNION,foreach_group_data)
+{
+ isl_stat (*fn)(__isl_keep S(UNION,group) *group, void *user);
+ void *user;
+};
+
+/* Call data->fn on the group stored at *entry.
+ */
+static isl_stat FN(UNION,call_on_group)(void **entry, void *user)
+{
+ S(UNION,group) *group = *entry;
+ S(UNION,foreach_group_data) *data;
+
+ data = (S(UNION,foreach_group_data) *) user;
+ return data->fn(group, data->user);
+}
+
+/* Call "fn" on each group of expressions in "u".
+ */
+static isl_stat FN(UNION,foreach_group)(__isl_keep UNION *u,
+ isl_stat (*fn)(__isl_keep S(UNION,group) *group, void *user),
+ void *user)
+{
+ S(UNION,foreach_group_data) data = { fn, user };
+
+ if (!u)
+ return isl_stat_error;
+
+ return isl_hash_table_foreach(u->space->ctx, &u->table,
+ &FN(UNION,call_on_group), &data);
+}
+
+/* A isl_union_*_foreach_group callback for counting the total number
+ * of expressions in a UNION. Add the number of expressions in "group"
+ * to *n.
+ */
+static isl_stat FN(UNION,count_part)(__isl_keep S(UNION,group) *group,
+ void *user)
+{
+ int *n = user;
+
+ if (!group)
+ return isl_stat_error;
+
+ *n += group->part_table.n;
+ return isl_stat_ok;
+}
+
+/* Return the number of base expressions in "u".
+ */
+int FN(FN(UNION,n),PARTS)(__isl_keep UNION *u)
+{
+ int n;
+
+ n = 0;
+ if (FN(UNION,foreach_group)(u, &FN(UNION,count_part), &n) < 0)
+ n = -1;
+ return n;
+}
+
+/* Free an entry in a group of expressions.
+ * Each entry in such a group is a single expression.
+ */
+static isl_stat FN(UNION,free_group_entry)(void **entry, void *user)
+{
+ PART *part = *entry;
+
+ FN(PART,free)(part);
+ return isl_stat_ok;
+}
+
+/* Free all memory allocated for "group" and return NULL.
+ */
+static __isl_null S(UNION,group) *FN(UNION,group_free)(
+ __isl_take S(UNION,group) *group)
+{
+ isl_ctx *ctx;
+
+ if (!group)
+ return NULL;
+
+ ctx = isl_space_get_ctx(group->domain_space);
+ isl_hash_table_foreach(ctx, &group->part_table,
+ &FN(UNION,free_group_entry), NULL);
+ isl_hash_table_clear(&group->part_table);
+ isl_space_free(group->domain_space);
+ free(group);
+ return NULL;
+}
+
+/* Allocate a group of expressions defined over the same domain space
+ * with domain space "domain_space" and initial size "size".
+ */
+static __isl_give S(UNION,group) *FN(UNION,group_alloc)(
+ __isl_take isl_space *domain_space, int size)
+{
+ isl_ctx *ctx;
+ S(UNION,group) *group;
+
+ if (!domain_space)
+ return NULL;
+ ctx = isl_space_get_ctx(domain_space);
+ group = isl_calloc_type(ctx, S(UNION,group));
+ if (!group)
+ goto error;
+ group->domain_space = domain_space;
+ if (isl_hash_table_init(ctx, &group->part_table, size) < 0)
+ return FN(UNION,group_free)(group);
+
+ return group;
+error:
+ isl_space_free(domain_space);
+ return NULL;
+}
+
+/* Is the space of "entry" equal to "space"?
+ */
+static int FN(UNION,has_space)(const void *entry, const void *val)
+{
+ PART *part = (PART *) entry;
+ isl_space *space = (isl_space *) val;
+
+ return isl_space_is_equal(part->dim, space);
+}
+
+/* Return a group equal to "group", but with a single reference.
+ * Since all groups have only a single reference, simply return "group".
+ */
+static __isl_give S(UNION,group) *FN(UNION,group_cow)(
+ __isl_take S(UNION,group) *group)
+{
+ return group;
+}
+
+S(UNION,foreach_data)
+{
+ isl_stat (*fn)(__isl_take PART *part, void *user);
+ void *user;
+};
+
+static isl_stat FN(UNION,call_on_copy)(void **entry, void *user)
+{
+ PART *part = *entry;
+ S(UNION,foreach_data) *data = (S(UNION,foreach_data) *) user;
+
+ part = FN(PART,copy)(part);
+ if (!part)
+ return isl_stat_error;
+ return data->fn(part, data->user);
+}
+
+/* Call data->fn on a copy of each expression in "group".
+ */
+static isl_stat FN(UNION,group_call_on_copy)(__isl_keep S(UNION,group) *group,
+ void *user)
+{
+ isl_ctx *ctx;
+
+ if (!group)
+ return isl_stat_error;
+
+ ctx = isl_space_get_ctx(group->domain_space);
+ return isl_hash_table_foreach(ctx, &group->part_table,
+ &FN(UNION,call_on_copy), user);
+}
+
+isl_stat FN(FN(UNION,foreach),PARTS)(__isl_keep UNION *u,
+ isl_stat (*fn)(__isl_take PART *part, void *user), void *user)
+{
+ S(UNION,foreach_data) data = { fn, user };
+
+ if (!u)
+ return isl_stat_error;
+
+ return FN(UNION,foreach_group)(u, &FN(UNION,group_call_on_copy), &data);
+}
+
+/* Is the domain space of the group of expressions at "entry"
+ * equal to "space"?
+ */
+static int FN(UNION,group_has_domain_space)(const void *entry, const void *val)
+{
+ S(UNION,group) *group = (S(UNION,group) *) entry;
+ isl_space *space = (isl_space *) val;
+
+ return isl_space_is_domain_internal(group->domain_space, space);
+}
+
+/* Return the entry, if any, in "u" that lives in "space".
+ * If "reserve" is set, then an entry is created if it does not exist yet.
+ * Return NULL on error and isl_hash_table_entry_none if no entry was found.
+ * Note that when "reserve" is set, the function will never return
+ * isl_hash_table_entry_none.
+ *
+ * First look for the group of expressions with the same domain space,
+ * creating one if needed.
+ * Then look for the expression living in the specified space in that group.
+ */
+static struct isl_hash_table_entry *FN(UNION,find_part_entry)(
+ __isl_keep UNION *u, __isl_keep isl_space *space, int reserve)
+{
+ isl_ctx *ctx;
+ uint32_t hash;
+ struct isl_hash_table_entry *group_entry, *part_entry;
+ S(UNION,group) *group;
+
+ if (!u || !space)
+ return NULL;
+
+ ctx = FN(UNION,get_ctx)(u);
+ hash = isl_space_get_domain_hash(space);
+ group_entry = isl_hash_table_find(ctx, &u->table, hash,
+ &FN(UNION,group_has_domain_space), space, reserve);
+ if (!group_entry)
+ return reserve ? NULL : isl_hash_table_entry_none;
+ if (reserve && !group_entry->data) {
+ isl_space *domain = isl_space_domain(isl_space_copy(space));
+ group = FN(UNION,group_alloc)(domain, 1);
+ group_entry->data = group;
+ } else {
+ group = group_entry->data;
+ if (reserve)
+ group = FN(UNION,group_cow)(group);
+ }
+ if (!group)
+ return NULL;
+ hash = isl_space_get_hash(space);
+ part_entry = isl_hash_table_find(ctx, &group->part_table, hash,
+ &FN(UNION,has_space), space, reserve);
+ if (!reserve && !part_entry)
+ return isl_hash_table_entry_none;
+ return part_entry;
+}
+
+/* Remove "part_entry" from the hash table of "u".
+ *
+ * First look the group_entry in "u" holding the group that
+ * contains "part_entry". Remove "part_entry" from that group.
+ * If the group becomes empty, then also remove the group_entry from "u".
+ */
+static __isl_give UNION *FN(UNION,remove_part_entry)(__isl_take UNION *u,
+ struct isl_hash_table_entry *part_entry)
+{
+ isl_ctx *ctx;
+ uint32_t hash;
+ PART *part;
+ struct isl_hash_table_entry *group_entry;
+ S(UNION,group) *group;
+
+ if (!u || !part_entry)
+ return FN(UNION,free)(u);
+
+ part = part_entry->data;
+ ctx = FN(UNION,get_ctx)(u);
+ hash = isl_space_get_domain_hash(part->dim);
+ group_entry = isl_hash_table_find(ctx, &u->table, hash,
+ &FN(UNION,group_has_domain_space), part->dim, 0);
+ if (!group_entry)
+ isl_die(ctx, isl_error_internal, "missing group",
+ return FN(UNION,free)(u));
+ group = group_entry->data;
+ isl_hash_table_remove(ctx, &group->part_table, part_entry);
+ FN(PART,free)(part);
+
+ if (group->part_table.n != 0)
+ return u;
+
+ isl_hash_table_remove(ctx, &u->table, group_entry);
+ FN(UNION,group_free)(group);
+
+ return u;
+}
+
+/* Are the domains of "part1" and "part2" disjoint?
+ */
+static isl_bool FN(UNION,disjoint_domain)(__isl_keep PART *part1,
+ __isl_keep PART *part2)
+{
+ isl_set *dom1, *dom2;
+ isl_bool disjoint;
+
+ if (!part1 || !part2)
+ return isl_bool_error;
+ dom1 = FN(PART,domain)(FN(PART,copy)(part1));
+ dom2 = FN(PART,domain)(FN(PART,copy)(part2));
+ disjoint = isl_set_is_disjoint(dom1, dom2);
+ isl_set_free(dom1);
+ isl_set_free(dom2);
+
+ return disjoint;
+}
+
+/* Check that the expression at *entry has a domain that is disjoint
+ * from that of "part", unless they also have the same target space.
+ */
+static isl_stat FN(UNION,check_disjoint_domain_entry)(void **entry, void *user)
+{
+ PART *part = user;
+ PART *other = *entry;
+ isl_bool equal;
+ isl_bool disjoint;
+
+ equal = isl_space_is_equal(part->dim, other->dim);
+ if (equal < 0)
+ return isl_stat_error;
+ if (equal)
+ return isl_stat_ok;
+
+ disjoint = FN(UNION,disjoint_domain)(part, other);
+ if (disjoint < 0)
+ return isl_stat_error;
+ if (!disjoint)
+ isl_die(FN(PART,get_ctx)(part), isl_error_invalid,
+ "overlapping domain with other part",
+ return isl_stat_error);
+ return isl_stat_ok;
+}
+
+/* Check that the domain of "part" is disjoint from the domain of the entries
+ * in "u" that are defined on the same domain space, but have a different
+ * target space.
+ * If there is no group of expressions in "u" with the same domain space,
+ * then everything is fine. Otherwise, check the individual expressions
+ * in that group.
+ */
+static isl_stat FN(UNION,check_disjoint_domain_other)(__isl_keep UNION *u,
+ __isl_keep PART *part)
+{
+ isl_ctx *ctx;
+ uint32_t hash;
+ struct isl_hash_table_entry *group_entry;
+ S(UNION,group) *group;
+
+ if (!u || !part)
+ return isl_stat_error;
+ ctx = FN(UNION,get_ctx)(u);
+ hash = isl_space_get_domain_hash(part->dim);
+ group_entry = isl_hash_table_find(ctx, &u->table, hash,
+ &FN(UNION,group_has_domain_space), part->dim, 0);
+ if (!group_entry)
+ return isl_stat_ok;
+ group = group_entry->data;
+ return isl_hash_table_foreach(ctx, &group->part_table,
+ &FN(UNION,check_disjoint_domain_entry), part);
+}
+
+/* Check that the domain of "part1" is disjoint from the domain of "part2".
+ * This check is performed before "part2" is added to a UNION to ensure
+ * that the UNION expression remains a function.
+ */
+static isl_stat FN(UNION,check_disjoint_domain)(__isl_keep PART *part1,
+ __isl_keep PART *part2)
+{
+ isl_bool disjoint;
+
+ disjoint = FN(UNION,disjoint_domain)(part1, part2);
+ if (disjoint < 0)
+ return isl_stat_error;
+ if (!disjoint)
+ isl_die(FN(PART,get_ctx)(part1), isl_error_invalid,
+ "domain of additional part should be disjoint",
+ return isl_stat_error);
+ return isl_stat_ok;
+}
+
+/* Internal data structure for isl_union_*_foreach_inplace.
+ * "fn" is the function that needs to be called on each entry.
+ */
+S(UNION,foreach_inplace_data)
+{
+ isl_stat (*fn)(void **entry, void *user);
+ void *user;
+};
+
+/* isl_union_*_foreach_group callback for calling data->fn on
+ * each part entry in the group.
+ */
+static isl_stat FN(UNION,group_call_inplace)(__isl_keep S(UNION,group) *group,
+ void *user)
+{
+ isl_ctx *ctx;
+ S(UNION,foreach_inplace_data) *data;
+
+ if (!group)
+ return isl_stat_error;
+
+ data = (S(UNION,foreach_inplace_data) *) user;
+ ctx = isl_space_get_ctx(group->domain_space);
+ return isl_hash_table_foreach(ctx, &group->part_table,
+ data->fn, data->user);
+}
+
+/* Call "fn" on each part entry of "u".
+ */
+static isl_stat FN(UNION,foreach_inplace)(__isl_keep UNION *u,
+ isl_stat (*fn)(void **part, void *user), void *user)
+{
+ S(UNION,foreach_inplace_data) data = { fn, user };
+
+ return FN(UNION,foreach_group)(u, &FN(UNION,group_call_inplace), &data);
+}
+
+/* Does "u" have a single reference?
+ * That is, can we change "u" inplace?
+ */
+static isl_bool FN(UNION,has_single_reference)(__isl_keep UNION *u)
+{
+ if (!u)
+ return isl_bool_error;
+ return u->ref == 1;
+}
+
+static isl_stat FN(UNION,free_u_entry)(void **entry, void *user)
+{
+ S(UNION,group) *group = *entry;
+ FN(UNION,group_free)(group);
+ return isl_stat_ok;
+}
+
+#include <isl_union_templ.c>
diff --git a/isl_union_neg.c b/isl_union_neg.c
new file mode 100644
index 00000000..386b8dcd
--- /dev/null
+++ b/isl_union_neg.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
+ * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
+ * 91893 Orsay, France
+ */
+
+#include <isl_union_macro.h>
+
+/* Return the opposite of "part".
+ */
+static __isl_give PART *FN(UNION,neg_entry)(__isl_take PART *part, void *user)
+{
+ return FN(PART,neg)(part);
+}
+
+/* Return the opposite of "u".
+ */
+__isl_give UNION *FN(UNION,neg)(__isl_take UNION *u)
+{
+ return FN(UNION,transform_inplace)(u, &FN(UNION,neg_entry), NULL);
+}
diff --git a/isl_union_single.c b/isl_union_single.c
new file mode 100644
index 00000000..d365aae7
--- /dev/null
+++ b/isl_union_single.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
+ * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
+ * 91893 Orsay, France
+ * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl_hash_private.h>
+#include <isl_union_macro.h>
+
+/* A union of expressions defined over different domain spaces.
+ * "space" describes the parameters.
+ * The entries of "table" are keyed on the domain space of the entry.
+ */
+struct UNION {
+ int ref;
+#ifdef HAS_TYPE
+ enum isl_fold type;
+#endif
+ isl_space *space;
+
+ struct isl_hash_table table;
+};
+
+/* Return the number of base expressions in "u".
+ */
+int FN(FN(UNION,n),PARTS)(__isl_keep UNION *u)
+{
+ return u ? u->table.n : 0;
+}
+
+S(UNION,foreach_data)
+{
+ isl_stat (*fn)(__isl_take PART *part, void *user);
+ void *user;
+};
+
+static isl_stat FN(UNION,call_on_copy)(void **entry, void *user)
+{
+ PART *part = *entry;
+ S(UNION,foreach_data) *data = (S(UNION,foreach_data) *)user;
+
+ part = FN(PART,copy)(part);
+ if (!part)
+ return isl_stat_error;
+ return data->fn(part, data->user);
+}
+
+isl_stat FN(FN(UNION,foreach),PARTS)(__isl_keep UNION *u,
+ isl_stat (*fn)(__isl_take PART *part, void *user), void *user)
+{
+ S(UNION,foreach_data) data = { fn, user };
+
+ if (!u)
+ return isl_stat_error;
+
+ return isl_hash_table_foreach(u->space->ctx, &u->table,
+ &FN(UNION,call_on_copy), &data);
+}
+
+/* Is the domain space of "entry" equal to the domain of "space"?
+ */
+static int FN(UNION,has_same_domain_space)(const void *entry, const void *val)
+{
+ PART *part = (PART *)entry;
+ isl_space *space = (isl_space *) val;
+
+ if (isl_space_is_set(space))
+ return isl_space_is_set(part->dim);
+
+ return isl_space_tuple_is_equal(part->dim, isl_dim_in,
+ space, isl_dim_in);
+}
+
+/* Return the entry, if any, in "u" that lives in "space".
+ * If "reserve" is set, then an entry is created if it does not exist yet.
+ * Return NULL on error and isl_hash_table_entry_none if no entry was found.
+ * Note that when "reserve" is set, the function will never return
+ * isl_hash_table_entry_none.
+ *
+ * First look for the entry (if any) with the same domain space.
+ * If it exists, then check if the range space also matches.
+ */
+static struct isl_hash_table_entry *FN(UNION,find_part_entry)(
+ __isl_keep UNION *u, __isl_keep isl_space *space, int reserve)
+{
+ isl_ctx *ctx;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry;
+ isl_bool equal;
+ PART *part;
+
+ if (!u || !space)
+ return NULL;
+
+ ctx = FN(UNION,get_ctx)(u);
+ hash = isl_space_get_domain_hash(space);
+ entry = isl_hash_table_find(ctx, &u->table, hash,
+ &FN(UNION,has_same_domain_space), space, reserve);
+ if (!entry)
+ return reserve ? NULL : isl_hash_table_entry_none;
+ if (reserve && !entry->data)
+ return entry;
+ part = entry->data;
+ equal = isl_space_tuple_is_equal(part->dim, isl_dim_out,
+ space, isl_dim_out);
+ if (equal < 0)
+ return NULL;
+ if (equal)
+ return entry;
+ if (!reserve)
+ return isl_hash_table_entry_none;
+ isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
+ "union expression can only contain a single "
+ "expression over a given domain", return NULL);
+}
+
+/* Remove "part_entry" from the hash table of "u".
+ */
+static __isl_give UNION *FN(UNION,remove_part_entry)(__isl_take UNION *u,
+ struct isl_hash_table_entry *part_entry)
+{
+ isl_ctx *ctx;
+
+ if (!u || !part_entry)
+ return FN(UNION,free)(u);
+
+ ctx = FN(UNION,get_ctx)(u);
+ isl_hash_table_remove(ctx, &u->table, part_entry);
+ FN(PART,free)(part_entry->data);
+
+ return u;
+}
+
+/* Check that the domain of "part" is disjoint from the domain of the entries
+ * in "u" that are defined on the same domain space, but have a different
+ * target space.
+ * Since a UNION with a single entry per domain space is not allowed
+ * to contain two entries with the same domain space, there cannot be
+ * any such other entry.
+ */
+static isl_stat FN(UNION,check_disjoint_domain_other)(__isl_keep UNION *u,
+ __isl_keep PART *part)
+{
+ return isl_stat_ok;
+}
+
+/* Check that the domain of "part1" is disjoint from the domain of "part2".
+ * This check is performed before "part2" is added to a UNION to ensure
+ * that the UNION expression remains a function.
+ * Since a UNION with a single entry per domain space is not allowed
+ * to contain two entries with the same domain space, fail unconditionally.
+ */
+static isl_stat FN(UNION,check_disjoint_domain)(__isl_keep PART *part1,
+ __isl_keep PART *part2)
+{
+ isl_die(FN(PART,get_ctx)(part1), isl_error_invalid,
+ "additional part should live on separate space",
+ return isl_stat_error);
+}
+
+/* Call "fn" on each part entry of "u".
+ */
+static isl_stat FN(UNION,foreach_inplace)(__isl_keep UNION *u,
+ isl_stat (*fn)(void **part, void *user), void *user)
+{
+ isl_ctx *ctx;
+
+ if (!u)
+ return isl_stat_error;
+ ctx = FN(UNION,get_ctx)(u);
+ return isl_hash_table_foreach(ctx, &u->table, fn, user);
+}
+
+/* Does "u" have a single reference?
+ * That is, can we change "u" inplace?
+ */
+static isl_bool FN(UNION,has_single_reference)(__isl_keep UNION *u)
+{
+ if (!u)
+ return isl_bool_error;
+ return u->ref == 1;
+}
+
+static isl_stat FN(UNION,free_u_entry)(void **entry, void *user)
+{
+ PART *part = *entry;
+ FN(PART,free)(part);
+ return isl_stat_ok;
+}
+
+#include <isl_union_templ.c>
diff --git a/isl_union_templ.c b/isl_union_templ.c
index f0fb6b38..66bbd2b0 100644
--- a/isl_union_templ.c
+++ b/isl_union_templ.c
@@ -10,21 +10,6 @@
* and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
-#define xFN(TYPE,NAME) TYPE ## _ ## NAME
-#define FN(TYPE,NAME) xFN(TYPE,NAME)
-#define xS(TYPE,NAME) struct TYPE ## _ ## NAME
-#define S(TYPE,NAME) xS(TYPE,NAME)
-
-struct UNION {
- int ref;
-#ifdef HAS_TYPE
- enum isl_fold type;
-#endif
- isl_space *space;
-
- struct isl_hash_table table;
-};
-
__isl_give UNION *FN(UNION,cow)(__isl_take UNION *u);
isl_ctx *FN(UNION,get_ctx)(__isl_keep UNION *u)
@@ -118,82 +103,6 @@ __isl_give UNION *FN(UNION,copy)(__isl_keep UNION *u)
return u;
}
-/* Return the number of base expressions in "u".
- */
-int FN(FN(UNION,n),PARTS)(__isl_keep UNION *u)
-{
- return u ? u->table.n : 0;
-}
-
-S(UNION,foreach_data)
-{
- isl_stat (*fn)(__isl_take PART *part, void *user);
- void *user;
-};
-
-static isl_stat FN(UNION,call_on_copy)(void **entry, void *user)
-{
- PART *part = *entry;
- S(UNION,foreach_data) *data = (S(UNION,foreach_data) *)user;
-
- return data->fn(FN(PART,copy)(part), data->user);
-}
-
-isl_stat FN(FN(UNION,foreach),PARTS)(__isl_keep UNION *u,
- isl_stat (*fn)(__isl_take PART *part, void *user), void *user)
-{
- S(UNION,foreach_data) data = { fn, user };
-
- if (!u)
- return isl_stat_error;
-
- return isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,call_on_copy), &data);
-}
-
-/* Is the space of "entry" equal to "space"?
- */
-static int FN(UNION,has_space)(const void *entry, const void *val)
-{
- PART *part = (PART *)entry;
- isl_space *space = (isl_space *) val;
-
- return isl_space_is_equal(part->dim, space);
-}
-
-/* This function is not currently used by isl_aff.c.
- */
-static int FN(UNION,has_domain_space)(const void *entry, const void *val)
- __attribute__ ((unused));
-
-/* Is the domain space of "entry" equal to "space"?
- */
-static int FN(UNION,has_domain_space)(const void *entry, const void *val)
-{
- PART *part = (PART *)entry;
- isl_space *space = (isl_space *) val;
-
- if (isl_space_is_params(space))
- return isl_space_is_set(part->dim);
-
- return isl_space_tuple_is_equal(part->dim, isl_dim_in,
- space, isl_dim_set);
-}
-
-/* Is the domain space of "entry" equal to the domain of "space"?
- */
-static int FN(UNION,has_same_domain_space)(const void *entry, const void *val)
-{
- PART *part = (PART *)entry;
- isl_space *space = (isl_space *) val;
-
- if (isl_space_is_set(space))
- return isl_space_is_set(part->dim);
-
- return isl_space_tuple_is_equal(part->dim, isl_dim_in,
- space, isl_dim_in);
-}
-
/* Extract the element of "u" living in "space" (ignoring parameters).
*
* Return the ZERO element if "u" does not contain any element
@@ -202,7 +111,6 @@ static int FN(UNION,has_same_domain_space)(const void *entry, const void *val)
__isl_give PART *FN(FN(UNION,extract),PARTS)(__isl_keep UNION *u,
__isl_take isl_space *space)
{
- uint32_t hash;
struct isl_hash_table_entry *entry;
if (!u || !space)
@@ -216,10 +124,10 @@ __isl_give PART *FN(FN(UNION,extract),PARTS)(__isl_keep UNION *u,
goto error;
}
- hash = isl_space_get_hash(space);
- entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
- &FN(UNION,has_space), space, 0);
+ entry = FN(UNION,find_part_entry)(u, space, 0);
if (!entry)
+ goto error;
+ if (entry == isl_hash_table_entry_none)
#ifdef HAS_TYPE
return FN(PART,ZERO)(space, u->type);
#else
@@ -234,7 +142,8 @@ error:
/* Add "part" to "u".
* If "disjoint" is set, then "u" is not allowed to already have
- * a part that is defined on the same space as "part".
+ * a part that is defined over a domain that overlaps with the domain
+ * of "part".
* Otherwise, compute the union sum of "part" and the part in "u"
* defined on the same space.
*/
@@ -242,7 +151,6 @@ static __isl_give UNION *FN(UNION,add_part_generic)(__isl_take UNION *u,
__isl_take PART *part, int disjoint)
{
int empty;
- uint32_t hash;
struct isl_hash_table_entry *entry;
if (!part)
@@ -264,26 +172,18 @@ static __isl_give UNION *FN(UNION,add_part_generic)(__isl_take UNION *u,
if (!u)
goto error;
- hash = isl_space_get_hash(part->dim);
- entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
- &FN(UNION,has_same_domain_space),
- part->dim, 1);
+ if (FN(UNION,check_disjoint_domain_other)(u, part) < 0)
+ goto error;
+ entry = FN(UNION,find_part_entry)(u, part->dim, 1);
if (!entry)
goto error;
if (!entry->data)
entry->data = part;
else {
- PART *entry_part = entry->data;
- if (disjoint)
- isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
- "additional part should live on separate "
- "space", goto error);
- if (!isl_space_tuple_is_equal(entry_part->dim, isl_dim_out,
- part->dim, isl_dim_out))
- isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
- "union expression can only contain a single "
- "expression over a given domain", goto error);
+ if (disjoint &&
+ FN(UNION,check_disjoint_domain)(entry->data, part) < 0)
+ goto error;
entry->data = FN(PART,union_add_)(entry->data,
FN(PART,copy)(part));
if (!entry->data)
@@ -291,10 +191,8 @@ static __isl_give UNION *FN(UNION,add_part_generic)(__isl_take UNION *u,
empty = FN(PART,IS_ZERO)(part);
if (empty < 0)
goto error;
- if (empty) {
- FN(PART,free)(entry->data);
- isl_hash_table_remove(u->space->ctx, &u->table, entry);
- }
+ if (empty)
+ u = FN(UNION,remove_part_entry)(u, entry);
FN(PART,free)(part);
}
@@ -314,33 +212,144 @@ __isl_give UNION *FN(FN(UNION,add),PARTS)(__isl_take UNION *u,
return FN(UNION,add_part_generic)(u, part, 1);
}
-static isl_stat FN(UNION,add_part)(__isl_take PART *part, void *user)
+#ifdef HAS_TYPE
+/* Allocate a UNION with the same type and the same size as "u" and
+ * with space "space".
+ */
+static __isl_give UNION *FN(UNION,alloc_same_size_on_space)(__isl_keep UNION *u,
+ __isl_take isl_space *space)
{
- UNION **u = (UNION **)user;
+ if (!u)
+ goto error;
+ return FN(UNION,alloc)(space, u->type, u->table.n);
+error:
+ isl_space_free(space);
+ return NULL;
+}
+#else
+/* Allocate a UNION with the same size as "u" and with space "space".
+ */
+static __isl_give UNION *FN(UNION,alloc_same_size_on_space)(__isl_keep UNION *u,
+ __isl_take isl_space *space)
+{
+ if (!u)
+ goto error;
+ return FN(UNION,alloc)(space, u->table.n);
+error:
+ isl_space_free(space);
+ return NULL;
+}
+#endif
+
+/* Allocate a UNION with the same space, the same type (if any) and
+ * the same size as "u".
+ */
+static __isl_give UNION *FN(UNION,alloc_same_size)(__isl_keep UNION *u)
+{
+ return FN(UNION,alloc_same_size_on_space)(u, FN(UNION,get_space)(u));
+}
+
+/* Internal data structure for isl_union_*_transform_space.
+ * "fn' is applied to each entry in the input.
+ * "res" collects the results.
+ */
+S(UNION,transform_data)
+{
+ __isl_give PART *(*fn)(__isl_take PART *part, void *user);
+ void *user;
- *u = FN(FN(UNION,add),PARTS)(*u, part);
+ UNION *res;
+};
+
+/* Apply data->fn to "part" and add the result to data->res.
+ */
+static isl_stat FN(UNION,transform_entry)(__isl_take PART *part, void *user)
+{
+ S(UNION,transform_data) *data = (S(UNION,transform_data) *)user;
+
+ part = data->fn(part, data->user);
+ data->res = FN(FN(UNION,add),PARTS)(data->res, part);
+ if (!data->res)
+ return isl_stat_error;
return isl_stat_ok;
}
-__isl_give UNION *FN(UNION,dup)(__isl_keep UNION *u)
+/* Return a UNION living in "space" that is obtained by applying "fn"
+ * to each of the entries in "u".
+ */
+static __isl_give UNION *FN(UNION,transform_space)(__isl_take UNION *u,
+ isl_space *space,
+ __isl_give PART *(*fn)(__isl_take PART *part, void *user), void *user)
{
- UNION *dup;
+ S(UNION,transform_data) data = { fn, user };
- if (!u)
- return NULL;
+ data.res = FN(UNION,alloc_same_size_on_space)(u, space);
+ if (FN(FN(UNION,foreach),PARTS)(u,
+ &FN(UNION,transform_entry), &data) < 0)
+ data.res = FN(UNION,free)(data.res);
+ FN(UNION,free)(u);
+ return data.res;
+}
-#ifdef HAS_TYPE
- dup = FN(UNION,ZERO)(isl_space_copy(u->space), u->type);
-#else
- dup = FN(UNION,ZERO)(isl_space_copy(u->space));
-#endif
- if (FN(FN(UNION,foreach),PARTS)(u, &FN(UNION,add_part), &dup) < 0)
- goto error;
- return dup;
-error:
- FN(UNION,free)(dup);
- return NULL;
+/* Return a UNION that lives in the same space as "u" and that is obtained
+ * by applying "fn" to each of the entries in "u".
+ */
+static __isl_give UNION *FN(UNION,transform)(__isl_take UNION *u,
+ __isl_give PART *(*fn)(__isl_take PART *part, void *user), void *user)
+{
+ return FN(UNION,transform_space)(u, FN(UNION,get_space)(u), fn, user);
+}
+
+/* Apply data->fn to *part and store the result back into *part.
+ */
+static isl_stat FN(UNION,transform_inplace_entry)(void **part, void *user)
+{
+ S(UNION,transform_data) *data = (S(UNION,transform_data) *) user;
+
+ *part = data->fn(*part, data->user);
+ if (!*part)
+ return isl_stat_error;
+ return isl_stat_ok;
+}
+
+/* Update "u" by applying "fn" to each entry.
+ * This operation is assumed not to change the number of entries nor
+ * the spaces of the entries.
+ *
+ * If there is only one reference to "u", then change "u" inplace.
+ * Otherwise, create a new UNION from "u" and discard the original.
+ */
+static __isl_give UNION *FN(UNION,transform_inplace)(__isl_take UNION *u,
+ __isl_give PART *(*fn)(__isl_take PART *part, void *user), void *user)
+{
+ isl_bool single_ref;
+
+ single_ref = FN(UNION,has_single_reference)(u);
+ if (single_ref < 0)
+ return FN(UNION,free)(u);
+ if (single_ref) {
+ S(UNION,transform_data) data = { fn, user };
+ if (FN(UNION,foreach_inplace)(u,
+ &FN(UNION,transform_inplace_entry), &data) < 0)
+ return FN(UNION,free)(u);
+ return u;
+ }
+ return FN(UNION,transform)(u, fn, user);
+}
+
+/* An isl_union_*_transform callback for use in isl_union_*_dup
+ * that simply returns "part".
+ */
+static __isl_give PART *FN(UNION,copy_part)(__isl_take PART *part, void *user)
+{
+ return part;
+}
+
+__isl_give UNION *FN(UNION,dup)(__isl_keep UNION *u)
+{
+ u = FN(UNION,copy)(u);
+ return FN(UNION,transform)(u, &FN(UNION,copy_part), NULL);
}
__isl_give UNION *FN(UNION,cow)(__isl_take UNION *u)
@@ -354,13 +363,6 @@ __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u)
return FN(UNION,dup)(u);
}
-static isl_stat FN(UNION,free_u_entry)(void **entry, void *user)
-{
- PART *part = *entry;
- FN(PART,free)(part);
- return isl_stat_ok;
-}
-
__isl_null UNION *FN(UNION,free)(__isl_take UNION *u)
{
if (!u)
@@ -377,23 +379,13 @@ __isl_null UNION *FN(UNION,free)(__isl_take UNION *u)
return NULL;
}
-S(UNION,align) {
- isl_reordering *exp;
- UNION *res;
-};
-
-static isl_stat FN(UNION,align_entry)(__isl_take PART *part, void *user)
+static __isl_give PART *FN(UNION,align_entry)(__isl_take PART *part, void *user)
{
- isl_reordering *exp;
- S(UNION,align) *data = user;
+ isl_reordering *exp = user;
- exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
+ exp = isl_reordering_extend_space(isl_reordering_copy(exp),
FN(PART,get_domain_space)(part));
-
- data->res = FN(FN(UNION,add),PARTS)(data->res,
- FN(PART,realign_domain)(part, exp));
-
- return isl_stat_ok;
+ return FN(PART,realign_domain)(part, exp);
}
/* Reorder the parameters of "u" according to the given reordering.
@@ -401,23 +393,15 @@ static isl_stat FN(UNION,align_entry)(__isl_take PART *part, void *user)
static __isl_give UNION *FN(UNION,realign_domain)(__isl_take UNION *u,
__isl_take isl_reordering *r)
{
- S(UNION,align) data = { NULL, NULL };
+ isl_space *space;
if (!u || !r)
goto error;
-#ifdef HAS_TYPE
- data.res = FN(UNION,alloc)(isl_space_copy(r->dim), u->type, u->table.n);
-#else
- data.res = FN(UNION,alloc)(isl_space_copy(r->dim), u->table.n);
-#endif
- data.exp = r;
- if (FN(FN(UNION,foreach),PARTS)(u, &FN(UNION,align_entry), &data) < 0)
- data.res = FN(UNION,free)(data.res);
-
- isl_reordering_free(data.exp);
- FN(UNION,free)(u);
- return data.res;
+ space = isl_space_copy(r->dim);
+ u = FN(UNION,transform_space)(u, space, &FN(UNION,align_entry), r);
+ isl_reordering_free(r);
+ return u;
error:
FN(UNION,free)(u);
isl_reordering_free(r);
@@ -522,36 +506,34 @@ S(UNION,match_bin_data) {
__isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *);
};
-/* Check if data->u2 has an element living in the same space as *entry.
+/* Check if data->u2 has an element living in the same space as "part".
* If so, call data->fn on the two elements and add the result to
* data->res.
*/
-static isl_stat FN(UNION,match_bin_entry)(void **entry, void *user)
+static isl_stat FN(UNION,match_bin_entry)(__isl_take PART *part, void *user)
{
S(UNION,match_bin_data) *data = user;
- uint32_t hash;
struct isl_hash_table_entry *entry2;
isl_space *space;
- PART *part = *entry;
PART *part2;
space = FN(PART,get_space)(part);
- hash = isl_space_get_hash(space);
- entry2 = isl_hash_table_find(data->u2->space->ctx, &data->u2->table,
- hash, &FN(UNION,has_same_domain_space),
- space, 0);
+ entry2 = FN(UNION,find_part_entry)(data->u2, space, 0);
isl_space_free(space);
if (!entry2)
+ goto error;
+ if (entry2 == isl_hash_table_entry_none) {
+ FN(PART,free)(part);
return isl_stat_ok;
+ }
part2 = entry2->data;
if (!isl_space_tuple_is_equal(part->dim, isl_dim_out,
part2->dim, isl_dim_out))
isl_die(FN(UNION,get_ctx)(data->u2), isl_error_invalid,
"entries should have the same range space",
- return isl_stat_error);
+ goto error);
- part = FN(PART, copy)(part);
part = data->fn(part, FN(PART, copy)(entry2->data));
data->res = FN(FN(UNION,add),PARTS)(data->res, part);
@@ -559,6 +541,9 @@ static isl_stat FN(UNION,match_bin_entry)(void **entry, void *user)
return isl_stat_error;
return isl_stat_ok;
+error:
+ FN(PART,free)(part);
+ return isl_stat_error;
}
/* This function is currently only used from isl_polynomial.c
@@ -584,13 +569,8 @@ static __isl_give UNION *FN(UNION,match_bin_op)(__isl_take UNION *u1,
goto error;
data.u2 = u2;
-#ifdef HAS_TYPE
- data.res = FN(UNION,alloc)(isl_space_copy(u1->space), u1->type,
- u1->table.n);
-#else
- data.res = FN(UNION,alloc)(isl_space_copy(u1->space), u1->table.n);
-#endif
- if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
+ data.res = FN(UNION,alloc_same_size)(u1);
+ if (FN(FN(UNION,foreach),PARTS)(u1,
&FN(UNION,match_bin_entry), &data) < 0)
goto error;
@@ -630,23 +610,15 @@ __isl_give UNION *FN(UNION,sub)(__isl_take UNION *u1, __isl_take UNION *u2)
S(UNION,any_set_data) {
isl_set *set;
- UNION *res;
__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
};
-static isl_stat FN(UNION,any_set_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,any_set_entry)(__isl_take PART *part,
+ void *user)
{
S(UNION,any_set_data) *data = user;
- PW *pw = *entry;
-
- pw = FN(PW,copy)(pw);
- pw = data->fn(pw, isl_set_copy(data->set));
-
- data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
- if (!data->res)
- return isl_stat_error;
- return isl_stat_ok;
+ return data->fn(part, isl_set_copy(data->set));
}
/* Update each element of "u" by calling "fn" on the element and "set".
@@ -655,7 +627,7 @@ static __isl_give UNION *FN(UNION,any_set_op)(__isl_take UNION *u,
__isl_take isl_set *set,
__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
{
- S(UNION,any_set_data) data = { NULL, NULL, fn };
+ S(UNION,any_set_data) data = { NULL, fn };
u = FN(UNION,align_params)(u, isl_set_get_space(set));
set = isl_set_align_params(set, FN(UNION,get_space)(u));
@@ -664,23 +636,12 @@ static __isl_give UNION *FN(UNION,any_set_op)(__isl_take UNION *u,
goto error;
data.set = set;
-#ifdef HAS_TYPE
- data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->type,
- u->table.n);
-#else
- data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
-#endif
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,any_set_entry), &data) < 0)
- goto error;
-
- FN(UNION,free)(u);
+ u = FN(UNION,transform)(u, &FN(UNION,any_set_entry), &data);
isl_set_free(set);
- return data.res;
+ return u;
error:
FN(UNION,free)(u);
isl_set_free(set);
- FN(UNION,free)(data.res);
return NULL;
}
@@ -716,29 +677,29 @@ static int FN(UNION,set_has_dim)(const void *entry, const void *val)
}
/* Find the set in data->uset that lives in the same space as the domain
- * of *entry, apply data->fn to *entry and this set (if any), and add
+ * of "part", apply data->fn to *entry and this set (if any), and add
* the result to data->res.
*/
-static isl_stat FN(UNION,match_domain_entry)(void **entry, void *user)
+static isl_stat FN(UNION,match_domain_entry)(__isl_take PART *part, void *user)
{
S(UNION,match_domain_data) *data = user;
uint32_t hash;
struct isl_hash_table_entry *entry2;
- PW *pw = *entry;
isl_space *space;
- space = FN(PW,get_domain_space)(pw);
+ space = FN(PART,get_domain_space)(part);
hash = isl_space_get_hash(space);
entry2 = isl_hash_table_find(data->uset->dim->ctx, &data->uset->table,
hash, &FN(UNION,set_has_dim), space, 0);
isl_space_free(space);
- if (!entry2)
+ if (!entry2) {
+ FN(PART,free)(part);
return isl_stat_ok;
+ }
- pw = FN(PW,copy)(pw);
- pw = data->fn(pw, isl_set_copy(entry2->data));
+ part = data->fn(part, isl_set_copy(entry2->data));
- data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
+ data->res = FN(FN(UNION,add),PARTS)(data->res, part);
if (!data->res)
return isl_stat_error;
@@ -762,13 +723,8 @@ static __isl_give UNION *FN(UNION,match_domain_op)(__isl_take UNION *u,
goto error;
data.uset = uset;
-#ifdef HAS_TYPE
- data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->type,
- u->table.n);
-#else
- data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
-#endif
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
+ data.res = FN(UNION,alloc_same_size)(u);
+ if (FN(FN(UNION,foreach),PARTS)(u,
&FN(UNION,match_domain_entry), &data) < 0)
goto error;
@@ -795,31 +751,20 @@ __isl_give UNION *FN(UNION,intersect_domain)(__isl_take UNION *u,
return FN(UNION,match_domain_op)(u, uset, &FN(PW,intersect_domain));
}
-/* Internal data structure for isl_union_*_subtract_domain.
- * uset is the set that needs to be removed from the domain.
- * res collects the results.
- */
-S(UNION,subtract_domain_data) {
- isl_union_set *uset;
- UNION *res;
-};
-
/* Take the set (which may be empty) in data->uset that lives
* in the same space as the domain of "pw", subtract it from the domain
- * of "pw" and add the result to data->res.
+ * of "part" and return the result.
*/
-static isl_stat FN(UNION,subtract_domain_entry)(__isl_take PW *pw, void *user)
+static __isl_give PART *FN(UNION,subtract_domain_entry)(__isl_take PART *part,
+ void *user)
{
- S(UNION,subtract_domain_data) *data = user;
+ isl_union_set *uset = user;
isl_space *space;
isl_set *set;
- space = FN(PW,get_domain_space)(pw);
- set = isl_union_set_extract_set(data->uset, space);
- pw = FN(PW,subtract_domain)(pw, set);
- data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
-
- return isl_stat_ok;
+ space = FN(PART,get_domain_space)(part);
+ set = isl_union_set_extract_set(uset, space);
+ return FN(PART,subtract_domain)(part, set);
}
/* Subtract "uset' from the domain of "u".
@@ -827,29 +772,9 @@ static isl_stat FN(UNION,subtract_domain_entry)(__isl_take PW *pw, void *user)
__isl_give UNION *FN(UNION,subtract_domain)(__isl_take UNION *u,
__isl_take isl_union_set *uset)
{
- S(UNION,subtract_domain_data) data;
-
- if (!u || !uset)
- goto error;
-
- data.uset = uset;
-#ifdef HAS_TYPE
- data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->type,
- u->table.n);
-#else
- data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
-#endif
- if (FN(FN(UNION,foreach),PARTS)(u,
- &FN(UNION,subtract_domain_entry), &data) < 0)
- data.res = FN(UNION,free)(data.res);
-
- FN(UNION,free)(u);
+ u = FN(UNION,transform)(u, &FN(UNION,subtract_domain_entry), uset);
isl_union_set_free(uset);
- return data.res;
-error:
- FN(UNION,free)(u);
- isl_union_set_free(uset);
- return NULL;
+ return u;
}
__isl_give UNION *FN(UNION,gist)(__isl_take UNION *u,
@@ -860,59 +785,28 @@ __isl_give UNION *FN(UNION,gist)(__isl_take UNION *u,
return FN(UNION,match_domain_op)(u, uset, &FN(PW,gist));
}
-#ifndef NO_EVAL
-__isl_give isl_val *FN(UNION,eval)(__isl_take UNION *u,
- __isl_take isl_point *pnt)
-{
- uint32_t hash;
- struct isl_hash_table_entry *entry;
- isl_space *space;
- isl_val *v;
-
- if (!u || !pnt)
- goto error;
-
- space = isl_space_copy(pnt->dim);
- if (!space)
- goto error;
- hash = isl_space_get_hash(space);
- entry = isl_hash_table_find(u->space->ctx, &u->table,
- hash, &FN(UNION,has_domain_space),
- space, 0);
- isl_space_free(space);
- if (!entry) {
- v = isl_val_zero(isl_point_get_ctx(pnt));
- isl_point_free(pnt);
- } else {
- v = FN(PART,eval)(FN(PART,copy)(entry->data), pnt);
- }
- FN(UNION,free)(u);
- return v;
-error:
- FN(UNION,free)(u);
- isl_point_free(pnt);
- return NULL;
-}
-#endif
-
+/* Coalesce an entry in a UNION. Coalescing is performed in-place.
+ * Since the UNION may have several references, the entry is only
+ * replaced if the coalescing is successful.
+ */
static isl_stat FN(UNION,coalesce_entry)(void **entry, void *user)
{
- PW **pw = (PW **)entry;
+ PART **part_p = (PART **) entry;
+ PART *part;
- *pw = FN(PW,coalesce)(*pw);
- if (!*pw)
+ part = FN(PART,copy)(*part_p);
+ part = FN(PW,coalesce)(part);
+ if (!part)
return isl_stat_error;
+ FN(PART,free)(*part_p);
+ *part_p = part;
return isl_stat_ok;
}
__isl_give UNION *FN(UNION,coalesce)(__isl_take UNION *u)
{
- if (!u)
- return NULL;
-
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,coalesce_entry), NULL) < 0)
+ if (FN(UNION,foreach_inplace)(u, &FN(UNION,coalesce_entry), NULL) < 0)
goto error;
return u;
@@ -947,16 +841,33 @@ error:
return NULL;
}
-static isl_stat FN(UNION,mul_isl_int_entry)(void **entry, void *user)
+#ifdef HAS_TYPE
+/* Negate the type of "u".
+ */
+static __isl_give UNION *FN(UNION,negate_type)(__isl_take UNION *u)
{
- PW **pw = (PW **)entry;
- isl_int *v = user;
+ u = FN(UNION,cow)(u);
+ if (!u)
+ return NULL;
+ u->type = isl_fold_type_negate(u->type);
+ return u;
+}
+#else
+/* Negate the type of "u".
+ * Since "u" does not have a type, do nothing.
+ */
+static __isl_give UNION *FN(UNION,negate_type)(__isl_take UNION *u)
+{
+ return u;
+}
+#endif
- *pw = FN(PW,mul_isl_int)(*pw, *v);
- if (!*pw)
- return isl_stat_error;
+static __isl_give PART *FN(UNION,mul_isl_int_entry)(__isl_take PART *part,
+ void *user)
+{
+ isl_int *v = user;
- return isl_stat_ok;
+ return FN(PW,mul_isl_int)(part, *v);
}
__isl_give UNION *FN(UNION,mul_isl_int)(__isl_take UNION *u, isl_int v)
@@ -976,38 +887,21 @@ __isl_give UNION *FN(UNION,mul_isl_int)(__isl_take UNION *u, isl_int v)
return zero;
}
- u = FN(UNION,cow)(u);
- if (!u)
- return NULL;
-
-#ifdef HAS_TYPE
+ u = FN(UNION,transform_inplace)(u, &FN(UNION,mul_isl_int_entry), &v);
if (isl_int_is_neg(v))
- u->type = isl_fold_type_negate(u->type);
-#endif
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,mul_isl_int_entry), &v) < 0)
- goto error;
+ u = FN(UNION,negate_type)(u);
return u;
-error:
- FN(UNION,free)(u);
- return NULL;
}
-/* Multiply *entry by the isl_val "user".
- *
- * Return 0 on success and -1 on error.
+/* Multiply "part" by the isl_val "user" and return the result.
*/
-static isl_stat FN(UNION,scale_val_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,scale_val_entry)(__isl_take PART *part,
+ void *user)
{
- PW **pw = (PW **)entry;
isl_val *v = user;
- *pw = FN(PW,scale_val)(*pw, isl_val_copy(v));
- if (!*pw)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return FN(PART,scale_val)(part, isl_val_copy(v));
}
/* Multiply "u" by "v" and return the result.
@@ -1039,17 +933,9 @@ __isl_give UNION *FN(UNION,scale_val)(__isl_take UNION *u,
isl_die(isl_val_get_ctx(v), isl_error_invalid,
"expecting rational factor", goto error);
- u = FN(UNION,cow)(u);
- if (!u)
- return NULL;
-
-#ifdef HAS_TYPE
+ u = FN(UNION,transform_inplace)(u, &FN(UNION,scale_val_entry), v);
if (isl_val_is_neg(v))
- u->type = isl_fold_type_negate(u->type);
-#endif
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,scale_val_entry), v) < 0)
- goto error;
+ u = FN(UNION,negate_type)(u);
isl_val_free(v);
return u;
@@ -1059,20 +945,14 @@ error:
return NULL;
}
-/* Divide *entry by the isl_val "user".
- *
- * Return 0 on success and -1 on error.
+/* Divide "part" by the isl_val "user" and return the result.
*/
-static isl_stat FN(UNION,scale_down_val_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,scale_down_val_entry)(__isl_take PART *part,
+ void *user)
{
- PW **pw = (PW **)entry;
isl_val *v = user;
- *pw = FN(PW,scale_down_val)(*pw, isl_val_copy(v));
- if (!*pw)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return FN(PART,scale_down_val)(part, isl_val_copy(v));
}
/* Divide "u" by "v" and return the result.
@@ -1094,17 +974,9 @@ __isl_give UNION *FN(UNION,scale_down_val)(__isl_take UNION *u,
isl_die(isl_val_get_ctx(v), isl_error_invalid,
"cannot scale down by zero", goto error);
- u = FN(UNION,cow)(u);
- if (!u)
- return NULL;
-
-#ifdef HAS_TYPE
+ u = FN(UNION,transform_inplace)(u, &FN(UNION,scale_down_val_entry), v);
if (isl_val_is_neg(v))
- u->type = isl_fold_type_negate(u->type);
-#endif
- if (isl_hash_table_foreach(FN(UNION,get_ctx)(u), &u->table,
- &FN(UNION,scale_down_val_entry), v) < 0)
- goto error;
+ u = FN(UNION,negate_type)(u);
isl_val_free(v);
return u;
@@ -1123,16 +995,15 @@ S(UNION,plain_is_equal_data)
static isl_stat FN(UNION,plain_is_equal_entry)(void **entry, void *user)
{
S(UNION,plain_is_equal_data) *data = user;
- uint32_t hash;
struct isl_hash_table_entry *entry2;
PW *pw = *entry;
- hash = isl_space_get_hash(pw->dim);
- entry2 = isl_hash_table_find(data->u2->space->ctx, &data->u2->table,
- hash, &FN(UNION,has_same_domain_space),
- pw->dim, 0);
- if (!entry2) {
- data->is_equal = isl_bool_false;
+ entry2 = FN(UNION,find_part_entry)(data->u2, pw->dim, 0);
+ if (!entry2 || entry2 == isl_hash_table_entry_none) {
+ if (!entry2)
+ data->is_equal = isl_bool_error;
+ else
+ data->is_equal = isl_bool_false;
return isl_stat_error;
}
@@ -1146,6 +1017,7 @@ static isl_stat FN(UNION,plain_is_equal_entry)(void **entry, void *user)
isl_bool FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
{
S(UNION,plain_is_equal_data) data = { NULL, isl_bool_true };
+ int n1, n2;
if (!u1 || !u2)
return isl_bool_error;
@@ -1153,6 +1025,12 @@ isl_bool FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
return isl_bool_true;
if (u1->table.n != u2->table.n)
return isl_bool_false;
+ n1 = FN(FN(UNION,n),PARTS)(u1);
+ n2 = FN(FN(UNION,n),PARTS)(u2);
+ if (n1 < 0 || n2 < 0)
+ return isl_bool_error;
+ if (n1 != n2)
+ return isl_bool_false;
u1 = FN(UNION,copy)(u1);
u2 = FN(UNION,copy)(u2);
@@ -1162,7 +1040,7 @@ isl_bool FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
goto error;
data.u2 = u2;
- if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
+ if (FN(UNION,foreach_inplace)(u1,
&FN(UNION,plain_is_equal_entry), &data) < 0 &&
data.is_equal)
goto error;
@@ -1177,61 +1055,23 @@ error:
return isl_bool_error;
}
-#ifndef NO_NEG
-/* Replace *entry by its opposite.
- *
- * Return 0 on success and -1 on error.
- */
-static isl_stat FN(UNION,neg_entry)(void **entry, void *user)
-{
- PW **pw = (PW **) entry;
-
- *pw = FN(PW,neg)(*pw);
-
- return *pw ? isl_stat_ok : isl_stat_error;
-}
-
-/* Return the opposite of "u".
- */
-__isl_give UNION *FN(UNION,neg)(__isl_take UNION *u)
-{
- u = FN(UNION,cow)(u);
- if (!u)
- return NULL;
-
- if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &FN(UNION,neg_entry), NULL) < 0)
- return FN(UNION,free)(u);
-
- return u;
-}
-#endif
-
/* Internal data structure for isl_union_*_drop_dims.
* type, first and n are passed to isl_*_drop_dims.
- * res collects the results.
*/
S(UNION,drop_dims_data) {
enum isl_dim_type type;
unsigned first;
unsigned n;
-
- UNION *res;
};
-/* Drop the parameters specified by "data" from "part" and
- * add the results to data->res.
+/* Drop the parameters specified by "data" from "part" and return the result.
*/
-static isl_stat FN(UNION,drop_dims_entry)(__isl_take PART *part, void *user)
+static __isl_give PART *FN(UNION,drop_dims_entry)(__isl_take PART *part,
+ void *user)
{
S(UNION,drop_dims_data) *data = user;
- part = FN(PART,drop_dims)(part, data->type, data->first, data->n);
- data->res = FN(FN(UNION,add),PARTS)(data->res, part);
- if (!data->res)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return FN(PART,drop_dims)(part, data->type, data->first, data->n);
}
/* Drop the specified parameters from "u".
@@ -1253,45 +1093,28 @@ __isl_give UNION *FN(UNION,drop_dims)( __isl_take UNION *u,
space = FN(UNION,get_space)(u);
space = isl_space_drop_dims(space, type, first, n);
-#ifdef HAS_TYPE
- data.res = FN(UNION,alloc)(space, u->type, u->table.n);
-#else
- data.res = FN(UNION,alloc)(space, u->table.n);
-#endif
- if (FN(FN(UNION,foreach),PARTS)(u,
- &FN(UNION,drop_dims_entry), &data) < 0)
- data.res = FN(UNION,free)(data.res);
-
- FN(UNION,free)(u);
-
- return data.res;
+ return FN(UNION,transform_space)(u, space, &FN(UNION,drop_dims_entry),
+ &data);
}
/* Internal data structure for isl_union_*_set_dim_name.
* pos is the position of the parameter that needs to be renamed.
* s is the new name.
- * res collects the results.
*/
S(UNION,set_dim_name_data) {
unsigned pos;
const char *s;
-
- UNION *res;
};
/* Change the name of the parameter at position data->pos of "part" to data->s
- * and add the result to data->res.
+ * and return the result.
*/
-static isl_stat FN(UNION,set_dim_name_entry)(__isl_take PART *part, void *user)
+static __isl_give PART *FN(UNION,set_dim_name_entry)(__isl_take PART *part,
+ void *user)
{
S(UNION,set_dim_name_data) *data = user;
- part = FN(PART,set_dim_name)(part, isl_dim_param, data->pos, data->s);
- data->res = FN(FN(UNION,add),PARTS)(data->res, part);
- if (!data->res)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return FN(PART,set_dim_name)(part, isl_dim_param, data->pos, data->s);
}
/* Change the name of the parameter at position "pos" to "s".
@@ -1313,34 +1136,17 @@ __isl_give UNION *FN(UNION,set_dim_name)(__isl_take UNION *u,
space = FN(UNION,get_space)(u);
space = isl_space_set_dim_name(space, type, pos, s);
-#ifdef HAS_TYPE
- data.res = FN(UNION,alloc)(space, u->type, u->table.n);
-#else
- data.res = FN(UNION,alloc)(space, u->table.n);
-#endif
-
- if (FN(FN(UNION,foreach),PARTS)(u,
- &FN(UNION,set_dim_name_entry), &data) < 0)
- data.res = FN(UNION,free)(data.res);
-
- FN(UNION,free)(u);
-
- return data.res;
+ return FN(UNION,transform_space)(u, space,
+ &FN(UNION,set_dim_name_entry), &data);
}
/* Reset the user pointer on all identifiers of parameters and tuples
- * of the space of "part" and add the result to *res.
+ * of the space of "part" and return the result.
*/
-static isl_stat FN(UNION,reset_user_entry)(__isl_take PART *part, void *user)
+static __isl_give PART *FN(UNION,reset_user_entry)(__isl_take PART *part,
+ void *user)
{
- UNION **res = user;
-
- part = FN(PART,reset_user)(part);
- *res = FN(FN(UNION,add),PARTS)(*res, part);
- if (!*res)
- return isl_stat_error;
-
- return isl_stat_ok;
+ return FN(PART,reset_user)(part);
}
/* Reset the user pointer on all identifiers of parameters and tuples
@@ -1349,23 +1155,9 @@ static isl_stat FN(UNION,reset_user_entry)(__isl_take PART *part, void *user)
__isl_give UNION *FN(UNION,reset_user)(__isl_take UNION *u)
{
isl_space *space;
- UNION *res;
-
- if (!u)
- return NULL;
space = FN(UNION,get_space)(u);
space = isl_space_reset_user(space);
-#ifdef HAS_TYPE
- res = FN(UNION,alloc)(space, u->type, u->table.n);
-#else
- res = FN(UNION,alloc)(space, u->table.n);
-#endif
- if (FN(FN(UNION,foreach),PARTS)(u,
- &FN(UNION,reset_user_entry), &res) < 0)
- res = FN(UNION,free)(res);
-
- FN(UNION,free)(u);
-
- return res;
+ return FN(UNION,transform_space)(u, space, &FN(UNION,reset_user_entry),
+ NULL);
}
diff --git a/isl_val.c b/isl_val.c
index d0dc6743..b6307612 100644
--- a/isl_val.c
+++ b/isl_val.c
@@ -323,6 +323,20 @@ long isl_val_get_den_si(__isl_keep isl_val *v)
return isl_int_get_si(v->d);
}
+/* Extract the denominator of a rational value "v" as an isl_val.
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+__isl_give isl_val *isl_val_get_den_val(__isl_keep isl_val *v)
+{
+ if (!v)
+ return NULL;
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational value", return NULL);
+ return isl_val_int_from_isl_int(isl_val_get_ctx(v), v->d);
+}
+
/* Return an approximation of "v" as a double.
*/
double isl_val_get_d(__isl_keep isl_val *v)
@@ -983,7 +997,7 @@ error:
/* Compute x, y and g such that g = gcd(a,b) and a*x+b*y = g.
*/
-static void isl_int_gcdext(isl_int g, isl_int x, isl_int y,
+static void isl_int_gcdext(isl_int *g, isl_int *x, isl_int *y,
isl_int a, isl_int b)
{
isl_int d, tmp;
@@ -995,27 +1009,27 @@ static void isl_int_gcdext(isl_int g, isl_int x, isl_int y,
isl_int_init(tmp);
isl_int_set(a_copy, a);
isl_int_set(b_copy, b);
- isl_int_abs(g, a_copy);
+ isl_int_abs(*g, a_copy);
isl_int_abs(d, b_copy);
- isl_int_set_si(x, 1);
- isl_int_set_si(y, 0);
+ isl_int_set_si(*x, 1);
+ isl_int_set_si(*y, 0);
while (isl_int_is_pos(d)) {
- isl_int_fdiv_q(tmp, g, d);
- isl_int_submul(x, tmp, y);
- isl_int_submul(g, tmp, d);
- isl_int_swap(g, d);
- isl_int_swap(x, y);
+ isl_int_fdiv_q(tmp, *g, d);
+ isl_int_submul(*x, tmp, *y);
+ isl_int_submul(*g, tmp, d);
+ isl_int_swap(*g, d);
+ isl_int_swap(*x, *y);
}
if (isl_int_is_zero(a_copy))
- isl_int_set_si(x, 0);
+ isl_int_set_si(*x, 0);
else if (isl_int_is_neg(a_copy))
- isl_int_neg(x, x);
+ isl_int_neg(*x, *x);
if (isl_int_is_zero(b_copy))
- isl_int_set_si(y, 0);
+ isl_int_set_si(*y, 0);
else {
- isl_int_mul(tmp, a_copy, x);
- isl_int_sub(tmp, g, tmp);
- isl_int_divexact(y, tmp, b_copy);
+ isl_int_mul(tmp, a_copy, *x);
+ isl_int_sub(tmp, *g, tmp);
+ isl_int_divexact(*y, tmp, b_copy);
}
isl_int_clear(d);
isl_int_clear(tmp);
@@ -1048,7 +1062,7 @@ __isl_give isl_val *isl_val_gcdext(__isl_take isl_val *v1,
b = isl_val_alloc(ctx);
if (!v1 || !a || !b)
goto error;
- isl_int_gcdext(v1->n, a->n, b->n, v1->n, v2->n);
+ isl_int_gcdext(&v1->n, &a->n, &b->n, v1->n, v2->n);
if (x) {
isl_int_set_si(a->d, 1);
*x = a;
diff --git a/isl_val_sioimath.c b/isl_val_sioimath.c
new file mode 100644
index 00000000..42f87e3c
--- /dev/null
+++ b/isl_val_sioimath.c
@@ -0,0 +1,68 @@
+#include <isl_val_private.h>
+
+/* Return a reference to an isl_val representing the unsigned
+ * integer value stored in the "n" chunks of size "size" at "chunks".
+ * The least significant chunk is assumed to be stored first.
+ */
+__isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n,
+ size_t size, const void *chunks)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ impz_import(isl_sioimath_reinit_big(v->n), n, -1, size, 0, 0, chunks);
+ isl_sioimath_try_demote(v->n);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* Store a representation of the absolute value of the numerator of "v"
+ * in terms of chunks of size "size" at "chunks".
+ * The least significant chunk is stored first.
+ * The number of chunks in the result can be obtained by calling
+ * isl_val_n_abs_num_chunks. The user is responsible for allocating
+ * enough memory to store the results.
+ *
+ * In the special case of a zero value, isl_val_n_abs_num_chunks will
+ * return one, while impz_export will not fill in any chunks. We therefore
+ * do it ourselves.
+ */
+int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
+ void *chunks)
+{
+ isl_sioimath_scratchspace_t scratch;
+
+ if (!v || !chunks)
+ return -1;
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational value", return -1);
+
+ impz_export(chunks, NULL, -1, size, 0, 0,
+ isl_sioimath_bigarg_src(*v->n, &scratch));
+ if (isl_val_is_zero(v))
+ memset(chunks, 0, size);
+
+ return 0;
+}
+
+/* Return the number of chunks of size "size" required to
+ * store the absolute value of the numerator of "v".
+ */
+size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
+{
+ if (!v)
+ return 0;
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational value", return 0);
+
+ size *= 8;
+ return (isl_sioimath_sizeinbase(*v->n, 2) + size - 1) / size;
+}
diff --git a/isl_version.c b/isl_version.c
index a7ddd9dc..114323d6 100644
--- a/isl_version.c
+++ b/isl_version.c
@@ -9,6 +9,9 @@ const char *isl_version(void)
#endif
#ifdef USE_IMATH_FOR_MP
"-IMath"
+#ifdef USE_SMALL_INT_OPT
+ "-32"
+#endif
#endif
"\n";
}
diff --git a/pip.c b/pip.c
index 449293bd..72b2bef6 100644
--- a/pip.c
+++ b/pip.c
@@ -9,7 +9,6 @@
#include <assert.h>
#include <string.h>
-#include <strings.h>
#include <isl_map_private.h>
#include <isl/aff.h>
#include <isl/set.h>
@@ -22,6 +21,7 @@
#include <isl_point_private.h>
#include <isl_vec_private.h>
#include <isl/options.h>
+#include <isl_config.h>
/* The input of this program is the same as that of the "example" program
* from the PipLib distribution, except that the "big parameter column"
diff --git a/print_templ.c b/print_templ.c
index f147fdc5..d6b0db76 100644
--- a/print_templ.c
+++ b/print_templ.c
@@ -1,3 +1,5 @@
+#include <isl_printer_private.h>
+
#define xCAT(A,B) A ## B
#define CAT(A,B) xCAT(A,B)
#undef TYPE
@@ -12,6 +14,7 @@ void FN(TYPE,dump)(__isl_keep TYPE *obj)
if (!obj)
return;
p = isl_printer_to_file(FN(TYPE,get_ctx)(obj), stderr);
+ p = isl_printer_set_dump(p, 1);
p = FN(isl_printer_print,BASE)(p, obj);
p = isl_printer_end_line(p);
isl_printer_free(p);
diff --git a/test_inputs/brisebarre.pip b/test_inputs/brisebarre.pip
index 5d25dae3..f3decadf 100644
--- a/test_inputs/brisebarre.pip
+++ b/test_inputs/brisebarre.pip
@@ -1,34 +1,34 @@
-# ---------------------- CONTEXT ----------------------
-1 2
-1 0
-
--1
-
-# ----------------------- DOMAIN ----------------------
-26 6
-1 3 0 0 0 -98300
-1 -3 0 0 0 98308
-1 432 36 6 1 -14757611
-1 -432 -36 -6 -1 14758510
-1 54 9 3 1 -1923190
-1 -54 -9 -3 -1 1923303
-1 48 12 6 3 -1782238
-1 -48 -12 -6 -3 1782339
-1 27 9 6 4 -1045164
-1 -27 -9 -6 -4 1045221
-1 432 180 150 125 -17434139
-1 -432 -180 -150 -125 17435038
-1 6 3 3 3 -252443
-1 -6 -3 -3 -3 252456
-1 432 252 294 343 -18949275
-1 -432 -252 -294 -343 18950174
-1 27 18 24 32 -1234720
-1 -27 -18 -24 -32 1234777
-1 48 36 54 81 -2288453
-1 -48 -36 -54 -81 2288554
-1 54 45 75 125 -2684050
-1 -54 -45 -75 -125 2684163
-1 432 396 726 1331 -22386005
-1 -432 -396 -726 -1331 22386904
-1 3 3 6 12 -162072
-1 -3 -3 -6 -12 162080
+# ---------------------- CONTEXT ----------------------
+1 2
+1 0
+
+-1
+
+# ----------------------- DOMAIN ----------------------
+26 6
+1 3 0 0 0 -98300
+1 -3 0 0 0 98308
+1 432 36 6 1 -14757611
+1 -432 -36 -6 -1 14758510
+1 54 9 3 1 -1923190
+1 -54 -9 -3 -1 1923303
+1 48 12 6 3 -1782238
+1 -48 -12 -6 -3 1782339
+1 27 9 6 4 -1045164
+1 -27 -9 -6 -4 1045221
+1 432 180 150 125 -17434139
+1 -432 -180 -150 -125 17435038
+1 6 3 3 3 -252443
+1 -6 -3 -3 -3 252456
+1 432 252 294 343 -18949275
+1 -432 -252 -294 -343 18950174
+1 27 18 24 32 -1234720
+1 -27 -18 -24 -32 1234777
+1 48 36 54 81 -2288453
+1 -48 -36 -54 -81 2288554
+1 54 45 75 125 -2684050
+1 -54 -45 -75 -125 2684163
+1 432 396 726 1331 -22386005
+1 -432 -396 -726 -1331 22386904
+1 3 3 6 12 -162072
+1 -3 -3 -6 -12 162080
diff --git a/test_inputs/codegen/cloog/dealII.c b/test_inputs/codegen/cloog/dealII.c
index 939a804a..99ac53ee 100644
--- a/test_inputs/codegen/cloog/dealII.c
+++ b/test_inputs/codegen/cloog/dealII.c
@@ -1,32 +1,18 @@
{
- if (T_67 == 0 && T_66 <= -1) {
- S1(0);
- } else if (T_2 >= 1 && T_67 >= 1 && T_66 <= -1) {
- S1(0);
- } else if (T_2 >= 1 && T_67 >= 1 && T_66 >= 0) {
- S1(0);
- S2(0);
- }
- for (int c0 = 1; c0 <= min(min(T_2 - 1, T_67 - 1), T_66); c0 += 1) {
+ for (int c0 = 0; c0 <= min(min(T_2 - 1, T_67 - 1), T_66); c0 += 1) {
S1(c0);
S2(c0);
}
- for (int c0 = max(1, T_66 + 1); c0 < min(T_2, T_67); c0 += 1)
+ for (int c0 = max(0, T_66 + 1); c0 < min(T_2, T_67); c0 += 1)
S1(c0);
- if (T_2 >= 1 && T_67 == 0 && T_66 >= 0) {
- S1(0);
- S2(0);
- }
- for (int c0 = max(1, T_67); c0 <= min(T_2 - 1, T_66); c0 += 1) {
+ for (int c0 = T_67; c0 <= min(T_2 - 1, T_66); c0 += 1) {
S1(c0);
S2(c0);
}
- for (int c0 = max(max(1, T_67), T_66 + 1); c0 < T_2; c0 += 1)
+ for (int c0 = max(T_67, T_66 + 1); c0 < T_2; c0 += 1)
S1(c0);
- if (T_2 == 0 && T_67 >= 1 && T_66 >= 0)
- S2(0);
- for (int c0 = max(1, T_2); c0 <= min(T_67 - 1, T_66); c0 += 1)
+ for (int c0 = T_2; c0 <= min(T_67 - 1, T_66); c0 += 1)
S2(c0);
- if (T_2 == 0 && T_67 == 0 && T_66 >= 0)
+ if (T_2 == 0 && T_67 == 0)
S1(0);
}
diff --git a/test_inputs/codegen/cloog/faber.c b/test_inputs/codegen/cloog/faber.c
index b100b7b3..984dafcf 100644
--- a/test_inputs/codegen/cloog/faber.c
+++ b/test_inputs/codegen/cloog/faber.c
@@ -85,17 +85,10 @@
for (int c2 = max(c1 + 24, -2 * c1 + 30); c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
S1(c0, c1, c2);
}
- if (c0 >= 79 && c0 % 14 >= 9) {
- for (int c2 = max((c0 - 70) / 14 + 24, (c0 - 70) / 14 - (3 * c0 + 14) / 14 + 49); c2 <= (c0 - 70) / 14 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+ if (c0 >= 70 && c0 % 14 >= 9)
+ for (int c2 = max(c0 / 14 + 19, -((3 * c0 + 14) / 14) + c0 / 14 + 44); c2 <= -((3 * c0 + 17) / 14) + c0 / 14 + 51; c2 += 1)
S1(c0, c0 / 14 - 5, c2);
- } else if (c0 <= 69 && c0 % 14 >= 9) {
- if (c0 <= 41)
- S7(c0, -3, 6);
- S6(c0, c0 / 14 - 5, 8);
- for (int c2 = -((-c0 + 83) / 14) - (3 * c0 + 14) / 14 + 49; c2 <= -((-c0 + 83) / 14) - (3 * c0 + 17) / 14 + 56; c2 += 1)
- S1(c0, c0 / 14 - 5, c2);
- }
- for (int c1 = (c0 + 5) / 14 - 5; c1 < 0; c1 += 1) {
+ for (int c1 = c0 / 14 - 5; c1 < 0; c1 += 1) {
if (7 * c1 + 114 >= 2 * c0)
S7(c0, c1, 6);
for (int c2 = max(8, c1 - (6 * c0 + 77) / 77 + 13); c2 <= c1 - (6 * c0 + 91) / 77 + 15; c2 += 1)
@@ -104,21 +97,21 @@
S1(c0, c1, c2);
}
for (int c1 = max(0, (c0 + 5) / 14 - 5); c1 < c0 / 14 - 2; c1 += 1) {
- for (int c2 = max(c1, -2 * c1 + 6); c2 <= min(min(-2 * c1 + 24, c1 - (6 * c0 + 91) / 77 + 15), (2 * c0 - 7 * c1 - 10) / 21 + 1); c2 += 1)
+ for (int c2 = max(c1, -2 * c1 + 6); c2 <= min(c1 + 5, -2 * c1 + 24); c2 += 1)
+ S9(c0, c1, c2);
+ for (int c2 = c1 + 6; c2 <= min((2 * c1 + 1) / 5 + 7, (2 * c0 - 7 * c1 - 10) / 21 + 1); c2 += 1)
S9(c0, c1, c2);
- if (c1 >= 1 && c1 <= 5 && 14 * c1 + 46 >= c0)
- S9(c0, c1, c1 + 5);
for (int c2 = max(c1 + 6, (2 * c0 - 7 * c1 - 10) / 21 + 2); c2 <= (2 * c1 + 1) / 5 + 7; c2 += 1) {
S7(c0, c1, c2);
S9(c0, c1, c2);
}
- if (c1 <= 3 && 7 * c1 + 21 * ((2 * c1 + 41) / 5) >= 2 * c0 + 12)
+ if (c1 <= 3)
S9(c0, c1, (2 * c1 + 1) / 5 + 8);
for (int c2 = (2 * c1 + 1) / 5 + 9; c2 <= c1 - (6 * c0 + 91) / 77 + 15; c2 += 1) {
S6(c0, c1, c2);
S9(c0, c1, c2);
}
- for (int c2 = c1 - (6 * c0 + 91) / 77 + 16; c2 <= -2 * c1 + 24; c2 += 1)
+ for (int c2 = max(max(c1 + 6, c1 - (6 * c0 + 91) / 77 + 16), (2 * c1 + 1) / 5 + 9); c2 <= -2 * c1 + 24; c2 += 1)
S9(c0, c1, c2);
for (int c2 = max(c1, -2 * c1 + 30); c2 <= min(c1 + 24, c1 - (3 * c0 + 17) / 14 + 47); c2 += 1)
S8(c0, c1, c2);
diff --git a/test_inputs/codegen/cloog/jacobi-shared.c b/test_inputs/codegen/cloog/jacobi-shared.c
index 50840a86..0deb1064 100644
--- a/test_inputs/codegen/cloog/jacobi-shared.c
+++ b/test_inputs/codegen/cloog/jacobi-shared.c
@@ -1,3 +1,3 @@
if (((t1 + 31) % 32) + g2 >= 2 && N >= ((t1 + 31) % 32) + g2 + 2 && (h0 - 1) % 2 == 0)
for (int c0 = max(((t0 + 15) % 16) + 1, ((g1 + t0 + 13) % 16) - g1 + 3); c0 <= min(32, N - g1 - 1); c0 += 16)
- S1(g1 + c0 - 1, ((t1 + 31) % 32) + g2);
+ S1(g1 + c0 - 1, -((g2 - t1 + 32) % 32) + g2 + 31);
diff --git a/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c b/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c
index 42547118..f9e59c1c 100644
--- a/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c
+++ b/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c
@@ -1,7 +1,7 @@
if (M >= 0 && N >= 0)
for (int c0 = -4; c0 <= 3 * M + N; c0 += 1) {
if (c0 >= 0 && 3 * M + 1 >= c0 && (c0 + 1) % 3 >= 1 && N + 1 >= (c0 + 1) % 3)
- S2((c0 + 1) / 3, ((c0 + 1) % 3) - 1);
+ S2((c0 + 3) / 3 - 1, c0 % 3);
for (int c1 = max(-3 * M + c0 - 2, (c0 + 4) % 3); c1 <= min(min(N - 2, c0 - 2), -3 * M + c0 + 3); c1 += 3)
S2((c0 - c1 - 2) / 3, c1 + 2);
for (int c1 = max(-3 * M + c0 + 4, (c0 + 4) % 3); c1 < min(N - 1, c0 - 1); c1 += 3) {
@@ -9,7 +9,7 @@ if (M >= 0 && N >= 0)
S2((c0 - c1 - 2) / 3, c1 + 2);
}
if (3 * M + N >= c0 + 4 && c0 >= N + 1 && ((-N + c0) % 3) + N >= 2 && (-N + c0) % 3 >= 1)
- S1((-N + c0 + 3) / 3 + 1, ((-N + c0) % 3) + N - 2);
+ S1((-N + c0 - 1) / 3 + 2, ((-N + c0 - 1) % 3) + N - 1);
for (int c1 = max(max(c0 + 1, -3 * M + c0 + 4), (c0 + 4) % 3); c1 <= min(N, c0 + 4); c1 += 3)
S1((c0 - c1 + 4) / 3, c1);
for (int c1 = max(-3 * M + c0, (c0 + 6) % 3); c1 <= min(N, c0); c1 += 3)
diff --git a/test_inputs/codegen/isolate2.c b/test_inputs/codegen/isolate2.c
index 2c9e15d0..fda80332 100644
--- a/test_inputs/codegen/isolate2.c
+++ b/test_inputs/codegen/isolate2.c
@@ -2,10 +2,12 @@ for (int c0 = 0; c0 <= 99; c0 += 1) {
if (c0 >= 4 && c0 <= 6) {
for (int c1 = 0; c1 <= 99; c1 += 1)
A(c0, c1);
- } else if (c0 >= 7) {
- for (int c1 = 0; c1 <= 99; c1 += 1)
- A(c0, c1);
- } else
- for (int c1 = 0; c1 <= 99; c1 += 1)
- A(c0, c1);
+ } else if (c0 >= 7 || c0 <= 3) {
+ if (c0 >= 7) {
+ for (int c1 = 0; c1 <= 99; c1 += 1)
+ A(c0, c1);
+ } else
+ for (int c1 = 0; c1 <= 99; c1 += 1)
+ A(c0, c1);
+ }
}
diff --git a/test_inputs/codegen/isolate7.c b/test_inputs/codegen/isolate7.c
new file mode 100644
index 00000000..d41ce090
--- /dev/null
+++ b/test_inputs/codegen/isolate7.c
@@ -0,0 +1,27 @@
+{
+ for (int c0 = 0; c0 < n - 31; c0 += 32)
+ for (int c1 = 0; c1 <= n; c1 += 32) {
+ if (n >= c1 + 32) {
+ for (int c2 = 0; c2 <= 31; c2 += 1)
+ for (int c3 = 0; c3 <= 31; c3 += 1)
+ S_1(c0 + c2, c1 + c3);
+ } else
+ for (int c2 = 0; c2 <= 31; c2 += 1) {
+ for (int c3 = 0; c3 < n - c1; c3 += 1)
+ S_1(c0 + c2, c1 + c3);
+ S_2(c0 + c2);
+ }
+ }
+ for (int c1 = 0; c1 < n; c1 += 32) {
+ if (n >= c1 + 32) {
+ for (int c2 = 0; c2 < (n + 32) % 32; c2 += 1)
+ for (int c3 = 0; c3 <= 31; c3 += 1)
+ S_1(-((n + 32) % 32) + n + c2, c1 + c3);
+ } else
+ for (int c2 = 0; c2 < n - c1; c2 += 1) {
+ for (int c3 = 0; c3 < n - c1; c3 += 1)
+ S_1(c1 + c2, c1 + c3);
+ S_2(c1 + c2);
+ }
+ }
+}
diff --git a/test_inputs/codegen/isolate7.st b/test_inputs/codegen/isolate7.st
new file mode 100644
index 00000000..673eb08b
--- /dev/null
+++ b/test_inputs/codegen/isolate7.st
@@ -0,0 +1,16 @@
+# Check that no expressions of the form ((-n + 2147483648) % 32) are produced.
+domain: "[n] -> { S_2[i] : i >= 0 and i <= -1 + n; S_1[i, j] : j >= 0 and j <= -1 + n and i >= 0 and i <= -1 + n }"
+child:
+ context: "[n] -> { [] : n <= 2147483647 and n >= 0 }"
+ child:
+ schedule: "[n] -> [{ S_1[i, j] -> [(32*floor((i)/32))]; S_2[i] -> [(32*floor((i)/32))] }, { S_1[i, j] -> [(32*floor((j)/32))]; S_2[i] -> [(32*floor((n)/32))] }]"
+ permutable: 1
+ options: "[n] -> { atomic[i0] : i0 >= 0 and i0 <= 1; isolate[[] -> [i0, i1]] : (exists (e0 = floor((i0)/32), e1 = floor((i1)/32): 32e0 = i0 and 32e1 = i1 and i0 >= 0 and i0 <= -32 + n and i1 >= 0 and i1 <= n)) or (exists (e0 = floor((i0)/32), e1 = floor((i1)/32): 32e0 = i0 and 32e1 = i1 and i0 >= 0 and i0 <= -32 + n and i1 >= -31 + n and i1 <= -31 + 2n)) }"
+ child:
+ schedule: "[n] -> [{ S_1[i, j] -> [(i - 32*floor((i)/32))]; S_2[i] -> [(i - 32*floor((i)/32))] }, { S_1[i, j] -> [(j - 32*floor((j)/32))]; S_2[i] -> [(n - 32*floor((n)/32))] }]"
+ permutable: 1
+ options: "{ separate[i0] : i0 >= 0 and i0 <= 1 }"
+ child:
+ sequence:
+ - filter: "[n] -> { S_1[i, j] }"
+ - filter: "[n] -> { S_2[i] }"
diff --git a/test_inputs/codegen/omega/dagstuhl1-1.c b/test_inputs/codegen/omega/dagstuhl1-1.c
index a3e4458f..98953fbd 100644
--- a/test_inputs/codegen/omega/dagstuhl1-1.c
+++ b/test_inputs/codegen/omega/dagstuhl1-1.c
@@ -1,2 +1,2 @@
for (int c0 = 0; c0 <= 99; c0 += 1)
- s0(c0, c0 % 10, (c0 + 10) / 10 - 1);
+ s0(c0, c0 % 10, c0 / 10);
diff --git a/test_inputs/codegen/omega/iter9-0.c b/test_inputs/codegen/omega/iter9-0.c
index 9b8522ba..d25a354a 100644
--- a/test_inputs/codegen/omega/iter9-0.c
+++ b/test_inputs/codegen/omega/iter9-0.c
@@ -6,6 +6,6 @@ for (int c0 = 1; c0 <= 15; c0 += 1) {
s2(c0);
s1(c0);
}
- if (((-exprVar1 + 15) % 8) + c0 <= 15 || (c0 >= exprVar1 + 1 && (exprVar1 - c0 + 1) % 8 == 0))
+ if (((-exprVar1 + 15) % 8) + c0 <= 15 || (exprVar1 - c0 + 1) % 8 == 0)
s5(c0);
}
diff --git a/test_inputs/codegen/omega/lefur03-0.c b/test_inputs/codegen/omega/lefur03-0.c
index 05ac73f3..e809849c 100644
--- a/test_inputs/codegen/omega/lefur03-0.c
+++ b/test_inputs/codegen/omega/lefur03-0.c
@@ -1,5 +1,5 @@
for (int c0 = 0; c0 <= 3; c0 += 1)
- for (int c1 = max(2 * c0 - 3, c0 / 2); c1 <= min(3, c0 + 1); c1 += 1)
+ for (int c1 = max(0, 2 * c0 - 3); c1 <= min(3, c0 + c0 / 2 + 1); c1 += 1)
for (int c2 = c0; c2 <= min(min(3, 2 * c0 - c1 + 1), 3 * c1 + 2); c2 += 1)
for (int c3 = max(max(max(0, c1 - (-c1 + 3) / 3), c0 - (-c2 + 3) / 3), c2 + floord(3 * c1 - c2 - 1, 6)); c3 <= min(3, c0 + 1); c3 += 1)
for (int c4 = max(max(max(max(-200 * c1 + 400 * c3 - 199, 250 * c3 + 1), 667 * c0 - 333 * c1 - (c0 + c1 + 3) / 3 - 332), 333 * c1 + c1 / 3), 333 * c2 + (c2 + 1) / 3); c4 <= min(min(min(min(1000, 500 * c0 + 499), -200 * c1 + 400 * c3 + 400), 333 * c2 - (-c2 + 3) / 3 + 333), 333 * c3 - (-c3 + 3) / 3 + 334); c4 += 1)
diff --git a/test_inputs/codegen/omega/lefur04-0.c b/test_inputs/codegen/omega/lefur04-0.c
index 124d0f15..749fa020 100644
--- a/test_inputs/codegen/omega/lefur04-0.c
+++ b/test_inputs/codegen/omega/lefur04-0.c
@@ -1,7 +1,7 @@
for (int c0 = 0; c0 <= 3; c0 += 1)
- for (int c1 = max(2 * c0 - 3, c0 / 2); c1 <= min(3, c0 + 1); c1 += 1)
- for (int c2 = c0; c2 <= min(min(3, 2 * c0 - c1 + 1), 3 * c1 + 2); c2 += 1)
- for (int c3 = max(max(max(c1 - (-c1 + 3) / 3, c0 - (-c2 + 3) / 3), c2 - (c2 + 2) / 3), c2 + floord(3 * c1 - c2 - 1, 6)); c3 <= min(3, c0 + c2 / 3 + 1); c3 += 1)
+ for (int c1 = max(0, 2 * c0 - 3); c1 <= min(c0 + 1, -c0 + 6); c1 += 1)
+ for (int c2 = c0; c2 <= min(min(3, 2 * c0 - c1 + 1), c0 + c0 / 2 + 1); c2 += 1)
+ for (int c3 = max(max(max(0, c1 - (-c1 + 3) / 3), c0 - (-c2 + 3) / 3), c2 + floord(3 * c1 - c2 - 1, 6)); c3 <= min(3, c0 + c2 / 3 + 1); c3 += 1)
for (int c5 = max(max(max(max(0, 2 * c3 - 4), c1 - (-c1 + 3) / 3), c2 - (c2 + 3) / 3), c3 - (c3 + 3) / 3); c5 <= min(min(c1 + 1, c3), -c2 + 2 * c3 - (c2 + 3) / 3 + 2); c5 += 1)
for (int c6 = max(max(max(max(max(-200 * c1 + 400 * c3 - 199, 250 * c3 + 1), 1000 * c0 - 500 * c5 - 501), 667 * c0 - 333 * c1 - (c0 + c1 + 3) / 3 - 332), 333 * c1 + c1 / 3), 333 * c2 + (c2 + 1) / 3); c6 <= min(min(min(min(min(min(1000, 500 * c0 + 499), -200 * c1 + 400 * c3 + 400), 500 * c5 + 501), 1000 * c0 - 500 * c5 + 997), 333 * c2 - (-c2 + 3) / 3 + 333), 333 * c3 - (-c3 + 3) / 3 + 334); c6 += 1)
for (int c7 = max(max(max(max(500 * c5 + 2, c6), 1000 * c0 - c6), 1000 * c3 - 2 * c6 + 2), 500 * c1 + (c6 + 1) / 2); c7 <= min(min(min(min(500 * c5 + 501, 2 * c6 + 1), 1000 * c0 - c6 + 999), 1000 * c3 - 2 * c6 + 1001), 500 * c1 + (c6 + 1) / 2 + 499); c7 += 1)
diff --git a/test_inputs/codegen/omega/p.delft2-0.c b/test_inputs/codegen/omega/p.delft2-0.c
index ad5a4cab..1740e4fe 100644
--- a/test_inputs/codegen/omega/p.delft2-0.c
+++ b/test_inputs/codegen/omega/p.delft2-0.c
@@ -4,7 +4,7 @@ if (P1 >= 0 && P1 <= 3 && P2 >= 0 && P2 <= 3)
for (int c3 = 0; c3 <= 7; c3 += 1)
if ((5 * P2 + 2 * c3) % 9 <= 3) {
if (P1 >= 1 && c0 + 1 == P1 && (5 * P1 + 2 * c2) % 9 <= 2) {
- s0(P1 - 1, P2, c2, c3, ((5 * P1 + 2 * c2) % 9) + 1, (-4 * P2 + 2 * c3 + 9) % 9);
+ s0(P1 - 1, P2, c2, c3, ((5 * P1 + 2 * c2 + 9) % 9) + 1, -4 * P2 + 2 * c3 - 9 * floord(-4 * P2 + 2 * c3, 9));
} else if (P1 == 0 && c0 == 3 && c2 % 4 == 0)
- s0(3, P2, c2, c3, (-c2 / 4) + 3, (-4 * P2 + 2 * c3 + 9) % 9);
+ s0(3, P2, c2, c3, (-c2 / 4) + 3, -4 * P2 + 2 * c3 - 9 * floord(-4 * P2 + 2 * c3, 9));
}
diff --git a/test_inputs/codegen/omega/ts1d-check0-0.c b/test_inputs/codegen/omega/ts1d-check0-0.c
index 5cf4bc9f..484bd1f6 100644
--- a/test_inputs/codegen/omega/ts1d-check0-0.c
+++ b/test_inputs/codegen/omega/ts1d-check0-0.c
@@ -8,6 +8,6 @@
s2(2, 1000 * c1 + c3 + 1, 0, -1000 * c1 + c2 - c3 - 1, 1);
}
if (2 * T >= c2 + 1 && 1000 * c1 + 999 >= c2)
- s1(2, -(c2 % 2) + c2, 0, c2 % 2, 1);
+ s1(2, ((c2 + 1) % 2) + c2 - 1, 0, -((c2 + 1) % 2) + 1, 1);
}
}
diff --git a/test_inputs/codegen/pldi2012/figure8_b.c b/test_inputs/codegen/pldi2012/figure8_b.c
index d7fa3cd8..94559693 100644
--- a/test_inputs/codegen/pldi2012/figure8_b.c
+++ b/test_inputs/codegen/pldi2012/figure8_b.c
@@ -3,6 +3,6 @@
s1(c0);
s0(c0 + 2);
}
- if (n >= 2 && n % 4 >= 2)
+ if (n >= 1 && n % 4 >= 2)
s1(-(n % 4) + n + 2);
}
diff --git a/test_inputs/codegen/redundant.c b/test_inputs/codegen/redundant.c
new file mode 100644
index 00000000..ab9b4686
--- /dev/null
+++ b/test_inputs/codegen/redundant.c
@@ -0,0 +1,18 @@
+for (int c0 = 0; c0 <= 2; c0 += 1) {
+ if (b0 <= 1) {
+ for (int c1 = 0; c1 <= 1; c1 += 1) {
+ if (b0 == 1 && 4 * c0 + c1 >= 1)
+ for (int c2 = 1; c2 <= 2; c2 += 1)
+ for (int c3 = 1; c3 <= 14; c3 += 1)
+ write(c0, c1, c2 + 3, c3);
+ for (int c2 = max(max(3, -8 * b0 + 6), 8 * c0 - 12); c2 <= min(7, 8 * c0 + 6); c2 += 1)
+ if (4 * c0 + c1 >= 2 * floord(2 * c1 + c2 - 5, 4) + 1 && 2 * ((2 * c1 + c2 - 1) / 4) + 7 >= 4 * c0 + c1 && 2 * c1 + c2 >= 4 * ((2 * c1 + c2 - 1) / 4) + 2 && ((-2 * c1 - c2 + 8) % 4) + 2 * c2 <= 14)
+ for (int c3 = 1; c3 <= 14; c3 += 1)
+ write(c0, c1, 8 * b0 + c2 - 5, c3);
+ }
+ } else
+ for (int c1 = max(0, -4 * c0 + 1); c1 <= 1; c1 += 1)
+ for (int c2 = 1; c2 <= 2; c2 += 1)
+ for (int c3 = 1; c3 <= 14; c3 += 1)
+ write(c0, c1, c2 + 11, c3);
+}
diff --git a/test_inputs/codegen/redundant.st b/test_inputs/codegen/redundant.st
new file mode 100644
index 00000000..e766f740
--- /dev/null
+++ b/test_inputs/codegen/redundant.st
@@ -0,0 +1,6 @@
+# Check that b1 >= 1 is not dropped by mistake in 4 * c0 + c1 >= 1 part
+domain: "[b0] -> { write[i0, o1, o2, o3] : ((exists (e0 = floor((4 + o2)/8), e1 = floor((5 + o2)/8), e2 = floor((4 + o2)/262144), e3, e4: o1 <= 1 and o1 >= 0 and o2 <= 12 and o2 >= 1 and o3 <= 14 and o3 >= 1 and 8e0 <= 4 + o2 and 8e1 <= 5 + o2 and 262144e2 <= 4 - 8b0 + o2 and 262144e2 >= -262139 + o2 and 262144e2 <= 4 + o2 and 262144e2 >= -3 - 8b0 + o2 and 4e4 <= 1 - 8i0 + 2o1 - o2 + 8e0 and 4e4 <= 4 - 8i0 + 2o1 + o2 - 8e0 and 4e4 >= 2o1 + o2 - 8e1 - 8e3 and 4e4 >= -3 + 2o1 + o2 - 8e0 - 8e3 and 4e4 >= -6 + 2o1 - o2 + 8e0 - 8e3 and 2e4 >= -9 + o1 and 2e4 <= -1 + o1 and 4e4 <= -6 + 2o1 - o2 + 8e1 - 8e3 and 4e4 >= -3 - 8i0 + 2o1 + o2 - 8e0 and 4e4 >= -6 - 8i0 + 2o1 - o2 + 8e0)) or (exists (e0 = floor((4 + o2)/8), e1 = floor((5 + o2)/8), e2 = floor((4 + o2)/262144), e3, e4: o1 <= 1 and o1 >= 0 and o2 <= 12 and o2 >= 1 and o3 <= 14 and o3 >= 1 and 8e0 <= 4 + o2 and 8e1 >= -2 + o2 and 262144e2 <= 4 - 8b0 + o2 and 262144e2 >= -262139 + o2 and 262144e2 <= 4 + o2 and 262144e2 >= -3 - 8b0 + o2 and 4e4 <= 1 - 8i0 + 2o1 - o2 + 8e0 and 4e4 <= 4 - 8i0 + 2o1 + o2 - 8e0 and 4e4 >= -3 + 2o1 + o2 - 8e0 - 8e3 and 4e4 >= -6 + 2o1 - o2 + 8e0 - 8e3 and 2e4 >= -9 + o1 and 2e4 <= -1 + o1 and 4e4 <= 1 + 2o1 - o2 + 8e0 - 8e3 and 4e4 <= 4 + 2o1 + o2 - 8e0 - 8e3 and 4e4 <= -1 + 2o1 + o2 - 8e1 - 8e3 and 4e4 >= -3 - 8i0 + 2o1 + o2 - 8e0 and 4e4 >= -6 - 8i0 + 2o1 - o2 + 8e0)) or (exists (e0 = floor((2 + o2)/8), e1 = floor((4 + o2)/8), e2 = floor((4 + o2)/262144), e3, e4: o1 <= 1 and o1 >= 0 and o2 <= 13 and o2 >= 3 and o3 <= 14 and o3 >= 1 and 8e0 >= -5 + o2 and 8e1 <= 4 + o2 and 262144e2 <= 4 - 8b0 + o2 and 262144e2 >= -262139 + o2 and 262144e2 <= 4 + o2 and 262144e2 >= -3 - 8b0 + o2 and 4e4 <= 1 - 8i0 + 2o1 - o2 + 8e1 and 4e4 <= 4 - 8i0 + 2o1 + o2 - 8e1 and 4e4 >= -3 + 2o1 + o2 - 8e1 - 8e3 and 4e4 >= -6 + 2o1 - o2 + 8e1 - 8e3 and 2e4 >= -9 + o1 and 2e4 <= -1 + o1 and 4e4 <= 1 + 2o1 - o2 + 8e1 - 8e3 and 4e4 <= -4 + 2o1 + o2 - 8e0 - 8e3 and 4e4 <= 4 + 2o1 + o2 - 8e1 - 8e3 and 4e4 >= -3 - 8i0 + 2o1 + o2 - 8e1 and 4e4 >= -6 - 8i0 + 2o1 - o2 + 8e1))) and b0 >= 0 and i0 <= 2 and i0 >= 0 and b0 <= 2 }"
+child:
+ context: "[b0] -> { [] : b0 <= 2 and b0 >= 0 }"
+ child:
+ schedule: "[b0] -> [{ write[i0, o1, o2, o3] -> [i0] }, { write[i0, i1, i2, i3] -> [(i1)] }, { write[i0, i1, i2, i3] -> [(5 - 8b0 + i2)] }, { write[i0,i1, i2, i3] -> [(i3)] }]"
diff --git a/test_inputs/codegen/roman.c b/test_inputs/codegen/roman.c
index 1dd43c52..d7e4077e 100644
--- a/test_inputs/codegen/roman.c
+++ b/test_inputs/codegen/roman.c
@@ -17,7 +17,7 @@
S_24(c1, c3);
S_19(c1, c3);
}
- if (np1 >= i && i + c1 <= 21) {
+ if (i + c1 <= 21) {
S_15(c1, i + c1 - 2);
for (int c5 = 0; c5 < i + c1 - 2; c5 += 1) {
S_16(c1, i + c1 - 2, c5);
diff --git a/test_inputs/codegen/separate2.c b/test_inputs/codegen/separate2.c
index 81668215..76ee58d9 100644
--- a/test_inputs/codegen/separate2.c
+++ b/test_inputs/codegen/separate2.c
@@ -1,9 +1,8 @@
-if ((length - 1) % 16 <= 14)
- for (int c0 = 0; c0 <= 1; c0 += 1)
- for (int c5 = 0; c5 <= 31; c5 += 1)
- for (int c6 = max(0, 2 * ((length - 1) % 16) + 2 * c5 - 60); c6 <= 30; c6 += 1) {
- if (length + c5 >= ((length - 1) % 32) + 2 && (length - 1) % 32 >= c5 && 2 * ((length - 1) % 32) + c6 >= 2 * c5 && 2 * c5 + 30 >= 2 * ((length - 1) % 32) + c6 && 2 * ((length - 1) % 32) + c6 == 2 * ((length - 1) % 16) + 2 * c5 && (2 * c5 - c6) % 32 == 0)
- S_3(c0, 0, (c6 / 2) - ((length - 1) % 16) + length - 1);
- if (length <= 16 && length >= c5 + 1 && c6 >= 1 && length >= c6)
- S_0(c0, c5, c6 - 1);
- }
+for (int c0 = 0; c0 <= 1; c0 += 1)
+ for (int c5 = 0; c5 <= 31; c5 += 1)
+ for (int c6 = max(0, 2 * (length % 16) + 2 * c5 - 62); c6 <= 30; c6 += 1) {
+ if (2 * length + c6 >= 2 * (length % 16) + 2 && c6 + 62 >= 2 * (length % 16) + 2 * c5 && 2 * (length % 16) >= c6 + 2 && 2 * (length % 16) + 2 * c5 >= c6 && 2 * (length % 32) + c6 == 2 * (length % 16) + 2 * c5 && (2 * c5 - c6) % 32 == 0)
+ S_3(c0, 0, (c6 / 2) - (length % 16) + length);
+ if (length <= 15 && length >= c5 + 1 && c6 >= 1 && length >= c6)
+ S_0(c0, c5, c6 - 1);
+ }
diff --git a/test_inputs/codegen/separation_class2.c b/test_inputs/codegen/separation_class2.c
index 0fdbc323..80be0a73 100644
--- a/test_inputs/codegen/separation_class2.c
+++ b/test_inputs/codegen/separation_class2.c
@@ -6,10 +6,10 @@
A(c0 + c2, c1 + c3);
for (int c2 = 0; c2 <= 7; c2 += 1)
for (int c3 = 0; c3 < n % 8; c3 += 1)
- A(c0 + c2, -((n - 1) % 8) + n + c3 - 1);
+ A(c0 + c2, -(n % 8) + n + c3);
}
for (int c1 = 0; c1 < n; c1 += 8)
for (int c2 = 0; c2 < n % 8; c2 += 1)
for (int c3 = 0; c3 <= min(7, n - c1 - 1); c3 += 1)
- A(-((n - 1) % 8) + n + c2 - 1, c1 + c3);
+ A(-(n % 8) + n + c2, c1 + c3);
}
diff --git a/test_inputs/codegen/unroll3.c b/test_inputs/codegen/unroll3.c
index 95a30ba7..f6f390d3 100644
--- a/test_inputs/codegen/unroll3.c
+++ b/test_inputs/codegen/unroll3.c
@@ -1,2 +1,2 @@
if ((t1 + 121) % 128 <= 123)
- write_shared_A(((t1 + 125) % 128) - 3);
+ write_shared_A(((t1 + 121) % 128) + 1);
diff --git a/test_inputs/codegen/unroll4.c b/test_inputs/codegen/unroll4.c
index 8e2ac05c..30b2ba8e 100644
--- a/test_inputs/codegen/unroll4.c
+++ b/test_inputs/codegen/unroll4.c
@@ -2,21 +2,15 @@
write_shared_A(3, ((t1 + 3) % 4) + 1, ((t2 + 31) % 32) + 1);
if (t2 >= 1 && t2 <= 2 && t1 % 3 == 0)
write_shared_A(3, (-t1 / 3) + 4, t2 + 32);
- {
- int c3 = t2 >= 2 && ((t1 + 3) % 4) + 1 >= t2 ? t2 + 32 : ((t2 + 30) % 32) + 2;
- if (c3 == t2 + 32 || (c3 == t2 && t2 >= ((t1 + 3) % 4) + ((t2 - 1) % 2) + 2))
- write_shared_A(3, ((t1 + 3) % 4) + 5, c3);
- }
+ if ((t1 >= 1 && t1 <= 2 && t2 >= 3 && t2 <= 4) || ((-((t1 + 3) % 4) + t2 + 30) % 32) + t1 >= -4 * ((-t1 + 4) / 4) + 4)
+ write_shared_A(3, ((t1 + 3) % 4) + 5, -((((t1 + 3) % 4) - t2 + 33) % 32) + t1 + 4 * ((-t1 + 4) / 4) + 32);
if (t1 >= 1 && t2 >= t1 + 1 && t2 <= 4)
write_shared_A(3, t1 + 4, t2 + 32);
write_shared_A(4, ((t1 + 3) % 4) + 1, ((t2 + 31) % 32) + 1);
if (t2 >= 1 && t2 <= 2 && t1 % 3 == 0)
write_shared_A(4, (-t1 / 3) + 4, t2 + 32);
- {
- int c3 = t2 >= 2 && ((t1 + 3) % 4) + 1 >= t2 ? t2 + 32 : ((t2 + 30) % 32) + 2;
- if (c3 == t2 + 32 || (c3 == t2 && t2 >= ((t1 + 3) % 4) + ((t2 - 1) % 2) + 2))
- write_shared_A(4, ((t1 + 3) % 4) + 5, c3);
- }
+ if ((t1 >= 1 && t1 <= 2 && t2 >= 3 && t2 <= 4) || ((-((t1 + 3) % 4) + t2 + 30) % 32) + t1 >= -4 * ((-t1 + 4) / 4) + 4)
+ write_shared_A(4, ((t1 + 3) % 4) + 5, -((((t1 + 3) % 4) - t2 + 33) % 32) + t1 + 4 * ((-t1 + 4) / 4) + 32);
if (t1 >= 1 && t2 >= t1 + 1 && t2 <= 4)
write_shared_A(4, t1 + 4, t2 + 32);
}